Chrome extension: how do I change my icon on tab focus? - google-chrome

I want to be able to change the icon of my extension according to what site I am currently browsing. How can I listen for changes in tab focus?

I think I've figured this one out. You need two listeners. One to sense when the tab has been changed, one to sense when it's been updated. And then they both can trigger the same function too run. Here's what would be in the background file...
function changeIcon() {
//query the information on the active tab
chrome.tabs.query({active: true}, function(tab){
//pull the url from that information
var url=tab[0].url;
//do whatever you need to do with the URL
//alert(url);
//change the icon
chrome.browserAction.setIcon({path: 'pathToIcon'});
});
}
//listen for new tab to be activated
chrome.tabs.onActivated.addListener(function(activeInfo) {
changeIcon();
});
//listen for current tab to be changed
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
changeIcon();
});

Simply register for tab update notifications in your background page:
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab)
{
if (changeInfo.status == "loading")
{
var url = tab.url;
var iconPath = ???
chrome.pageAction.setIcon({tabId: tabId, path: iconPath});
}
});
This handler will be called whenever a tab changes location. You don't need to care which tab is currently selected because you will have defined a different icon for each tab. Still, if you want to do it - http://code.google.com/chrome/extensions/tabs.html#event-onSelectionChanged is the way to go.

Related

chrome ext many loads on update page

In app use content script for all pages, and send message to active page on complete loaded page, but I have many calls of script sometimes 2 and more:
You can see that here
Code implimentation:
chrome.tabs.onCreated.addListener(function (tabs) {
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
if(changeInfo.status === "complete") {
let tabid = tab.id;
console.log("Site is valid: url -> " + tab.url)
chrome.tabs.executeScript(tab.id, {
file: '/injections/mobile.bet365.com.js',
});
console.log(tab);
setTimeout(function () {
console.log("timeout was set")
chrome.tabs.query({}, function (tabs) {
let countOpenedTabsFrom = tabs.length;
let opener = 1;
// на целевой вкладке
chrome.tabs.sendMessage(tabid, {
message: "start_app",
opener: opener,
queuenumber: countOpenedTabsFrom
}, function (response) {
console.log(response);
});
});
}, 500);
}
And executed script have many queries too.
Why is this happen?
Every time onCreated event fires, you're adding a new onUpdated listener.
When, after that, onUpdated event fires, all of them are executed, leading to the behavior you're seeing.
You either need to de-register the handlers when they are done, or register the handler only once. See chrome.events docs (which describe common points of all event objects in other APIs) for ideas on how to implement that.
Note that the code inside chrome.tabs.onCreated listener does not use the tabs parameter at all, so it's not clear why do you even need to listen to onCreated.

chrome.tabs.executeScript doesn't work on load

I am trying to load content script from the background one. the execute function works in the icon click block, but i can't trigger the auto load part
var toggle = false;
//Works
chrome.browserAction.onClicked.addListener(function(tab) {
toggle = !toggle;
if (!toggle){
chrome.browserAction.setIcon({path: "enabled.png"});
}else{
chrome.browserAction.setIcon({path: "disabled.png"});
chrome.tabs.executeScript(null, { file: "script.js" });
// chrome.tabs.executeScript({file : "script.js"});
}
});
//Doesn't work
chrome.tabs.onUpdated.addListener(function(tab) {
chrome.tabs.executeScript(null,{
file: 'script.js'
});
});
The activeTab permission only grants access to to the currently active tab when the user invokes the extension - for example by clicking its browser action.
If you want to execute a script on any arbitrary tab without user intervention, then you'll need the <all_urls> permission.

How to toggle actions of a browser action?

I have created my first chrome extension which adds event handlers to all the anchor elements on the page on clicking. If the user clicks the icon second time the event handlers are reattached to the anchor elements and are executed twice.
What I need following
Click the browser action.
Add the events to the anchor elements
If possible give a visual cue in the browser action icon that the extension is active currently.
Clicking again on the extension should remove the event handlers and again shows the extension icon as disabled.
Is this possible?
Following is what I have tried till now.
manifest.json
{
"name":"NameExtension",
"version":"1.0",
"description":"Here goes the description",
"manifest_version":2,
"browser_action":{
"default_icon":"16x16.png"
},
"background":{
"scripts":["background.js"]
},
"permissions":[
"tabs","http://*/*","https://*/*"
]
}
background.js
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, {file: "contentscript.js"});
});
contentscript.js
var all = document.getElementsByTagName('a');
for(var i=0; i<all.length;i++){
all[i].addEventListener('click',myHandler, false);
}
myHandler = function(event){
alert(event.target.innerText);
}
I would want the above handler to be toggled on anchors as the extension_browser_action is clicked and re-clicked. Also if the extension_browser-action_icon can give some visual feedback regarding the state.
I was able to do this with following in my background.js where contentscript adds the handlers and togglecontentscript removes them.
var x = false;
disableBrowserAction();
function disableBrowserAction(){
chrome.browserAction.setIcon({path:"inactive.png"});
chrome.tabs.executeScript(null, {file: "togglecontentscript.js"})
}
function enableBrowserAction(){
chrome.browserAction.setIcon({path:"active.png"});
chrome.tabs.executeScript(null, {file: "contentscript.js"});
}
function updateState(){
if(x==false){
x=true;
enableBrowserAction();
}else{
x=false;
disableBrowserAction();
}
}
chrome.browserAction.onClicked.addListener(updateState);

pass dom element from background script to chrome.tabs.executeScript

I'm trying to pass the active dom element when the contextmenu is clicked from my background script to a script that is being called through chrome.tabs.executeScript. I can pass booleans and strings just fine, but i always get an error when i pass dom elements. I'm starting to think it's not possible.
//doScripts function called from browser action
chrome.browserAction.onClicked.addListener(function(tab) {
doScripts(true, null);
});
//doScripts function called from context menu click
function getClickHandler(info, tab) {
var currTarg = document.activeElement;
console.log("currTarg = " + currTarg);
doScripts(false, currTarg);
}
//i reference doingBrowserAction and contextTarg in myscript.js
function doScripts(context, targ){
chrome.tabs.executeScript(null, {code: "var doingBrowserAction = "+context+"; var contextTarg = "+targ+";"}, function(){
chrome.tabs.executeScript(null, {file: "js/myscript.js"}, function(){
//all injected
});
});
}
//setup context menu
chrome.contextMenus.create({
"title" : "DESTROY!",
"type" : "normal",
"contexts" : ["page","selection","link","editable","image","video","audio"],
"onclick" : getClickHandler
});
i reference doingBrowserAction and contextTarg in myscript.js. I know what i'm trying to do is possible because the adblock extension does it, but having a hard time figuring out how. thanks in advance.
You cannot get a direct reference to a content script's DOM element from the background page, because the background page runs in the extension's process, and the content script runs in the tab's process. See also https://code.google.com/p/chromium/issues/detail?id=39507.
The document.activeElement property in the background page refers to the active element in the background page's document. As you can imagine, this value is quite useless.
If you query the state of the currently right-clicked element, bind an event in the content script. In the next example, I've chosen the contextmenu event, because context menus can also be opened through the keyboard.
This example adds a context menu option that removes the last active element from the document.
// content script
var lastElementContext;
document.addEventListener('contextmenu', function(event) {
lastElementContext = event.target;
}, true);
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
if (lastElementContext && lastElementContext.parentNode) {
lastElementContext.parentNode.removeChild(lastElementContext);
lastElementContext = null;
}
});
Background script:
chrome.contextMenus.create({
title: 'DESTROY!',
contexts: ['page', 'link', 'editable', 'image', 'video', 'audio'],
onclick: function(info, tab) {
chrome.tabs.sendMessage(tab.id, 'doDestroy');
}
});

closing two successive tabs from google chrome extension

I'm writing an extension for Google Chrome.
When a search page is opened on the target site, a content script is injected which sends a request to the background page to open a detailPage in a new tab. When the detailPage is opened a content script is injected which sends a request to the background page to open the messagePage in a new tab. When the messagePage is opened a content script is injected that sends a message and closes the messagePage tab. So far, so good. Focus is returned to the detailPage tab.
But how to close the detailPage? The script that was in the messagePage is gone. The script in the detailPage is idle. I suppose background has to close both the detailPage tab and the messagePage tab. I tried two successive chrome.tabs.remove commands but this code just hangs:
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.cmd == "closeMessage") {
chrome.tabs.getSelected(null, function (tab) {
chrome.tabs.remove(tab.id);
chrome.tabs.getSelected(null, function (tab) {
chrome.tabs.remove(tab.id);
});
}
});
It seems to me this has to be a part of the action upon receiving the "closeMessage" cmd. But how? And if not, how?
I understand that the tab.id of the sender is returned as sender.tab.id. Can't I just access this and use it to close the detailPage?
When you create those two tabs from a background page - save their ids. Then you can easily close them later.
var detailTabId = null;
var msgTabId = null;
...
chrome.tabs.create({url: "detail.html"}, function(tab){
detailTabId = tab.id;
});
...
chrome.tabs.create({url: "message.html"}, function(tab){
msgTabId = tab.id;
});
...
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.cmd == "closeMessage") {
chrome.tabs.remove(detailTabId);
chrome.tabs.remove(msgTabId);
}
});