Chrome extension icon change issue - google-chrome-extension

I'm developing a Chrome extension and have a strange problem with icon change on-the-fly.
In my popup.html I have a button by clicking on which I want to change the icon of the extension in the browser. E.g. from colored one to black and white (when application is inactive).
So the function which is responsible for this:
function toggleActivated(){
localStorage.isActive = toBool(localStorage.isActive) ? false : true;
$('#activate-disactivate span').text(toBool(localStorage.isActive) == false ? 'Включить' : 'Выключить');
chrome.browserAction.setIcon({path: toBool(localStorage.isActive) ? '48.png' : '48_bw.png'});
//window.close();
}
But the problem is that I want to close popup after the icon changed. If I use the window.close() at the end - then the icon is not changed, but if it is commented out - then the icon is changed fine.
Why is there a conflict between chrome.browserAction.setIcon() and window.close()?

It sounds like chrome.browserAction.setIcon is getting fired asynchronously but the popup is getting closed before it finishes. You could try adding a 500ms setTimeout before closing.
You should also file a bug report at new.crbug.com.

I know this is old, but I was having the same problem and abraham was right when he said that chrome.browserAction.setIcon was being called asynchronously. But I don't think that setting a timeout is the best answer.
If you check the setIcon documentation you can see that this method takes a function callback as parameter. That's where you should call window.close(). Like this:
chrome.browserAction.setIcon({ path: icon_path }, function() {
window.close();
});
UPDATE:
As niraj.nijju pointed in the comment below, you can pass a tabId param to the setIcon function to limit the scope of the change.

Related

How do I add button in NetSuite client script and use it as trigger for script function?

I'm trying to add a button to the current record with the Client Script button definition on a script record, but for some reason it's not finding my function. I'm returning my function tryThisand there is a button on the page which I created on the script record with the function tryThis defined in the appropriate field, but the code doesn't run. Here's my script:
define (['N/currentRecord','N/search','N/record'] ,
function(currentRecord,search,record) {
function tryThis(context){
log.debug({
title: 'try this',
details: 'try this'
});
}
function pageInit(context) {
}
return {
pageInit: pageInit,
tryThis: tryThis
};
});
Nothing happens :(
Yes, the script is deployed.
How can I use this button on a client script??
This doesn't exactly answer your question directly, but I hope it may help. I tested this, and there appears to be nothing wrong with the way you've set it up - the only thing that seems to be not working is the log module, which I've come across before in client scripts.
Try running your function using a console.log() or alert() instead (both work for me).
Hopefully someone with more detailed knowledge of the N/log module's design and behavior will chip in, as the documentation seems to indicate that this should work.
At the bottom of your Client Script record in Edit mode you will find where you can easily set the button and function to call.

Only after restarting Chrome browser: chrome.runtime.sendMessage() not sent, or chrome.runtime.onMessage listener function not called

My extension (https://chrome.google.com/webstore/detail/asana2go/meaajmlecpkbjcofehfpjngpnpfpjlkd/related?hl=en-US) works fine...until I quit and restart Chrome.
After restarting Chrome, this line in my extension's content script:
chrome.runtime.sendMessage({msg: copyOrPrint, tasksOrSubtasks: tasksOrSubtasks, currentProjectIdOrSearch: currentProjectIdOrSearch, currentProjectName: currentProjectName, tasks: tasks});
is executed, I believe, because the prior line is a console.log() and I see its output in the console.
But because in my background script I have this:
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log('background listener function');
...
and I do not see 'background listener function' in the console, I'm concluding that either the sendMessage isn't getting through or the onMessage listener is not getting called.
Can you think of any places where I could look to debug this? I'm using the page's devtools, the Inspect Popup devtools, and the background script page's devtools windows, and I've narrowed down to this but now I'm stumped.
Again, after restarting Chrome and seeing this failure to send or receive, I can remedy simply by reinstalling the extension and all works fine and I know the message is both sent and received and continues to work fine--until I quit and restart Chrome again. (This same behavior occurs if I run locally with Load Unpacked or published.)
Since the extension reinstall clears up the problem, perhaps my chrome.runtime.onInstalled listener is relevant? Here is the start of it (which ends with the snippet from my background script already included above):
'use strict';
chrome.runtime.onInstalled.addListener(function() {
let md;
let outputTabId = null;
let messageObj = null;
let cssRules = null;
let requestMsg = null;
chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
chrome.declarativeContent.onPageChanged.addRules([{
conditions: [new chrome.declarativeContent.PageStateMatcher({
pageUrl: {hostEquals: 'app.asana.com'},
})
],
actions: [new chrome.declarativeContent.ShowPageAction()]
}]);
});
chrome.commands.onCommand.addListener(function(command) { // shortcut keys for copy, print
chrome.tabs.executeScript({code: `ContentScript.sendEls('${command}');`});
});
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log('background listener function');
...
(Background: this is my first extension and it's not trivial, so I may well have something wrong! I'm sorry not to include a minimal and complete verifiable example, but the common message passing examples with the extension documentation don't exhibit this problem, and my large extension does. You should be able to repeat my problem by installing the extension linked above, but you will also need to use asana.com since my extension is a page_action for Asana.)
Thank you very much for any leads/ideas!
Larry
My colleague solved this. The onMessage listener was incorrectly inside the onInstalled listener, as is shown in the last code block in the question.
I should have realized that when Chrome restarts each time (post initial installation of the extension) none of this code is executed/exists so there's no onMessage handler to run anymore. But I never saw it during weeks of development because I rarely close chrome! And since I have been in heavy development, I'm constantly doing re-installs of the extension and thus getting the onMessage listener defined in my unique case--not so for most users!
Thanks...

nightwatch - check for popup window, after each click event

Is there a way in nightwatch to check whether a popup window appears after each click event?
I have a problem that randomly an error message appear and I don't want to write for each click event the same callback function.
I have already tried out the after and afterEach commands in the Global.js but then the commands will only run after the whole test suite.
I also have tried it local within a test file, although it also does not cover all single click events, even though the official website writes "... while beforeEach and afterEach are ran before and after each testcase (test step)"?
Solution I'm looking for:
.waitForElementVisible('selector')
.click('selector')
.click('selector')
Solution I have come up with so far:
.waitForElementVisible('selector')
.click('selector', isPresent)
.click('selector', isPresent)
isPresent as a callback function, which does the checking and close the popup window if it appears.
Is there another way to write a function (with or without after and/or forEach), so that it will be called after each click event or after each command. Thus, I don't have to write the isPresent repetitive code?
You can insert something like this in your page object file:
var popupCommand = {
popupCheck:function(){
return this.waitForElementVisible('selector', 5000)
.click('selector', isPresent)
.click('selector', isPresent)
},
module.exports = {
commands:[popupCommand],
elements:{
firstElement: {selector: 'xpath',locateStrategy: 'xpath'},
secondElement: {selector: 'css'},
}
}
Where 'popupCommand' will be the name of your page object file, for example 'Popup'. And also you will have to insert your isPresent callback function here so you can use it.
I did my best to explain you as much as possible what and how to do that :)
you should yse .switchWindow() method.
Why don't you write your own custom command specific for that case, so that way you will avoid repetitive code?

How can I disable javascript for the page that's being opened?

I was up till 1 am last night trying to find an example of how to do this. My theory is that I'd write a function that would comment out all javascript.
The second option would be to add the url to the list of javascript settings.
Right now my extension is very simple:
function linkOnClick(info, tab) {
window.open(info.linkUrl)
}
chrome.contextMenus.create(
{title: "Load with no Javascript", contexts:["link"], onclick: linkOnClick});
This is my first extension and I'm kind of lost.
edit: let me know if I should also post the manifest.json.
edit: I can't mark this as solved for 2 days (why? who knows.), so I'll probably not remember to mark this as solved. So accept this as the official making: SOLVED.
chrome.contentSettings.javascript.set is the thing that disables javascript.
Here's the part that disables javascript.
(Google, here's what an actual example should look like):
chrome.contentSettings.javascript.set(
{'primaryPattern':AnyDomainName, /*this is a string with the domain*/
'setting': "block", /* block the domain. Can be switched to "allow" */
'scope':'regular'}, /*it's either regular or incognito*/
function(){
/*optional action you want to
take place AFTER something's been blocked'*/
});
Here's the script I used to import into my json script for my chrome extension.
var link=""
var pattern=""
function linkOnClick(info, tab) {
r = /:\/\/(.[^/]+)/;
link=info.linkUrl
pattern="http://"+link.match(r)[1]+"/*"
chrome.contentSettings.javascript.set(
{'primaryPattern':pattern,
'setting': "block",
'scope':'regular'},
function(){
window.open(link)
});
}
chrome.contextMenus.create({title: "Load with no Javascript", contexts:["link"], onclick: linkOnClick});
I couldn't tell how any of this worked by reading the developer.chrome.com page! They really need add complete working examples or allow a way for users to add examples. I can't even use it. The git hub link is what saved me.

How to close the current extension tab?

I'm trying to close the Options page of the extension.
I have a Cancel button and I'm using this code:
chrome.tabs.getCurrent(null, function(tab) {
chrome.tabs.remove(tab.id, function() {});
});
When I'm trying to use it, it always gives this error:
Uncaught TypeError: Cannot call method 'getCurrent' of undefined
What's wrong with the code?
It works for me with one little fix:
chrome.tabs.getCurrent(function(tab) {
chrome.tabs.remove(tab.id, function() { });
});
Just make sure you're really running this code in options page of your extension and not just some HTML page, because chrome.tabs API is available only for extensions.
Most likely you're running your code from a content script, where chrome.tabs is undefined. If this is the case, you can instead send a message to the background page and have the background page (which has access to chrome.tabs) make the call.
Note that from a background page, you would use chrome.tabs.getSelected since getCurrent will return undefined.
In the options page, you can just do:
window.close()
If you wanted to use chrome.tabs.getCurrent, do you have tabs defined in the permissions section within the manifest?
I have time to continue my extension after a very long time. I checked the documentation again. So it was a inline script, that I had probably blocked with Content Security Policy in the manifest, because I hadn't read the documentation precisely.
Now Chrome blocks inline scripts by default, so I'll have to fix it anyway.
Only this worked for me:
chrome.tabs.query({ active: true }, function(tabs) {
chrome.tabs.remove(tabs[0].id);
});

Resources