103

How do I write a chrome extension such that every time a user clicks the icon, my script is run but no popup is opened? (I would look this up in the docs myself but for whatever reason they suddenly stopped working, 404ing every page, as I got to this point).

I'm assuming it's just setting up the manifest correctly. Here's what I have now:

{
  "name": "My Extension",
  "version": "0.1",
  "description": "Does some simple stuff",
  "browser_action": {
    "popup" : "mine.html",
    "default_icon": "logo.png"
  },
  "permissions": [
    "notifications"
  ]
}
Endophage
  • 21,038
  • 13
  • 59
  • 90

7 Answers7

114

Remove popup from your browser_action section of the manifest and use background pages along with browser Action in the background script.

chrome.browserAction.onClicked.addListener(function(tab) { alert('icon clicked')});
arunkumar
  • 32,803
  • 4
  • 32
  • 47
  • 11
    Where exactly do I put this. Without mine.html the only file in the extension is the manifest... well, and the icon. – Endophage Aug 24 '11 at 02:50
  • 3
    Take a look at background pages - http://code.google.com/chrome/extensions/background_pages.html. Thats where you place your long running code and code that is common across different pages. The link to the document above has an example with browserAction.onClicked – arunkumar Aug 24 '11 at 09:30
  • Ah got it. I tried a background page initially but wasn't aware of the browserAction.onClicked. – Endophage Aug 24 '11 at 16:21
  • 9
    If you don't have browser_action section in manifest.json then it will not work. You have to add empty browser_action in manifest.json: "browser_action": {} – Navidot Jun 19 '19 at 18:51
79

First, if you don't want to show a popup, remove "popup" : "mine.html" from your manifest.json (shown in your question).

Your manifest.json will look something like this:

{
  "name": "My Extension",
  "version": "0.1",
  "manifest_version" : 2,
  "description": "Does some simple stuff",
  "background" : {
    "scripts" : ["background.js"]
  },
  "browser_action": {
    "default_icon": "logo .png"
  },
  "permissions": ["activeTab"]
}
  • Note that manifest_version must be there and it must be 2.
  • Note that the activeTab permission has been added.
  • Note that you can only do one thing when the browser action button is clicked: either you can show a popup, or you can execute a script, but you can't do both.

Second, to execute a script when the icon is clicked, place the code below in your background.js file (the filename is specified in your manifest.json):

chrome.browserAction.onClicked.addListener(function(tab) {
   chrome.tabs.executeScript(null, {file: "testScript.js"});
});

Finally, testScript.js is where you should put the code you want to execute when the icon is clicked.

user3335966
  • 2,673
  • 4
  • 30
  • 33
yogesh kumar
  • 940
  • 6
  • 10
  • 7
    As of February 2017, this solution accomplishes exactly what was asked in the original question. – mjamore Feb 12 '17 at 17:03
  • 4
    Great, this work for me as June 2018. Worth the up vote! @kerzek Probly something like this: ```js function buttonClicked(tab) { var msg = { message: "user clicked!" } chrome.tabs.sendMessage(tab.id, msg); } ``` – K F Jun 11 '18 at 02:19
  • 4
    For clarity, the `onClicked` listener will **only** fire if you remove the popup. It's one or the other, not both. – HughHughTeotl Mar 01 '19 at 12:27
9

If you want to follow the manifest 3 then you should do:

chrome.action.onClicked.addListener(function (tab) {
    console.log("Hello")
});

Further note that you will not see the Hello in normal console, to see the hello go to extensions menu and click on inspect views in front of the specific extension menu.

R. Gurung
  • 1,356
  • 1
  • 14
  • 34
5

you need to add a background file. but firstly ou need to add an attribute in manifest.json like,

"background":{
    "scripts":["background.js"]
}

now name a file in your extension folder as background.js there is a way of sending objects from background to your content scripts suppose your content script is named content.js then what you need to do is write this code snippet in background.js file

chrome.browserAction.onClicked.addListener(sendfunc);
function sendfunc(tab){
    msg={txtt:"execute"};
    chrome.tabs.sendMessage(tab.id,msg);
}

what the above code is doing is sending an object named msg to content page and this msg object has a property txtt which is equal to "execute". what you need to do next is compare the values in content script as

chrome.runtime.onMessage.addListener(recievefunc);
function receivefunc(mssg,sender,sendResponse){
    if(mssg.txtt==="execute"){
      /*  
         your code of content script goes here
      */
    }
}

now whenever you click the extension icon an object named msg is sent from background to content. the function "recievefunc()" will compare its txtt property with string "execute" if it matches your rest of the code will run.

note: msg,txtt,sendfunc,receivefunc,mssg all are variables and not chrome keywords so you can use anything you want.

hope it helps.

:)

rishuverma
  • 79
  • 1
  • 7
5

Instead of specifying a popup page, use the chrome.browserAction.onClicked API, documented here.

Sudarshan
  • 18,140
  • 7
  • 53
  • 61
Boris Smus
  • 8,220
  • 2
  • 36
  • 33
4

In manifest 3 you might do it like this

// manifest.json

  "background": {
  "service_worker": "back.js"
},

// back.js

chrome.action.onClicked.addListener(tab => { 
chrome.tabs.create({
    url: 'index.html'
  });
 });
Sal7_one
  • 427
  • 2
  • 7
  • This is working fine but opening multiple tabs on subsequent clicks. How can I prevent this? – san Dec 18 '21 at 06:49
0

This was just what I needed but I should add this: If all you need is a one-time event like when a user clicks on the extension's icon, then Background Pages is a waste of resources as it will run in the background ALL the time. Use Event Pages instead:

"background": {
    "scripts": ["script.js"],
    "persistent": false
}
user3335966
  • 2,673
  • 4
  • 30
  • 33
JustAGuy
  • 5,151
  • 11
  • 41
  • 55
  • If this is true them you should use `content_script` instead and attach the script to your DOM. Using the function of running in background only once defeats the functionality concept of using background from the start. Just a thought and it doesn't mean this idea wouldn't work. – K F Jun 11 '18 at 02:25