50

I'm writing a simple Chrome extension that displays a JavaScript alert saying "Hello World". In this example I have specified that the extension will only run for google.com (by putting this in the permissions property within manifest.json).

Even after everything in the target page has loaded, the alert doesn't appear. Here is my script so far:

File: manifest.json

{
  "name": "Hello",
  "version": "1.0",
  "description": "Says hello to Google",
  "permissions": ["http://*.google.com/"]
  "browser_action": {
    "popup": "Hello.html"
  }
}

File: Hello.html

<script language="Javascript">
   alert("Hello World");
</script>
Noor
  • 19,638
  • 38
  • 136
  • 254

3 Answers3

79

You are adding a browser action popup, which adds a button to the top-right of your browser. (It's probably invisible because you haven't specified an image for it. There should be some empty space to the right of your address bar; try clicking it to see your Hello.html in a popup.)

What you want is a content script. Content scripts can get injected into every page that Chrome loads. You can use the matches and exclude_matches sub-items in your manifest file to specify which pages get your injected script.

{
  "name": "Hello",
  "version": "1.0",
  "description": "Says hello to Google",
  "permissions": ["tabs", "*://*.google.com/*"],
  "content_scripts": [
    {
      "matches": ["*://*.google.com/*"],
      "js": ["hello.js"]
    }
  ]
}

Make sure you rename Hello.html to hello.js (and get rid of the <script> tags).

Note also that I changed your http://*.google.com/ to *://*.google.com/* so that it will apply to Google over HTTP and HTTPS (and the trailing * ensures that it will apply to all pages on google.com, not just the main page).

apsillers
  • 112,806
  • 17
  • 235
  • 239
  • 1
    The `tabs` permission is unnecessary. In fact, all of the permissions are not needed, because `alert('Hello World!')` is not accessing the page's DOM. The URL patterns follow very strict rules, see [Match patterns](http://code.google.com/chrome/extensions/match_patterns.html). – Rob W May 03 '12 at 07:41
  • Whoops, those are permissions for something else; you indeed need no permissions to run content scripts. (Specific things that you do *within* a content script may require permissions, though.) – apsillers May 03 '12 at 12:32
  • The "get rid of ` – Xan Apr 16 '14 at 20:36
  • 1
    You are missing a comma on the fifth line after ...com/*"] – SoEzPz Feb 24 '15 at 22:04
  • 9
    Since you're updating the answer, you could also bump it to manifest version 2. – Xan Feb 24 '15 at 22:24
  • @apsillers what if in case of www.google.com.ph how to write a universal pattern that will cover the .ph domain? – Abdelsalam Shahlol Mar 12 '18 at 15:52
  • @AbdelsalamA.Shahlol If you want to cover `www.google.com.ph` instead of `www.google.com`, then simply use `*://*.google.com.ph/*` instead of `*://*.google.com/*` – apsillers Mar 12 '18 at 16:20
  • @AbdelsalamA.Shahlol If you mean you want to cover *all* `.ph` domain in the world, the match pattern would technically be `*://*.ph/*`, but I think Chrome rejects match patterns for all of a top-level domain like `.ph` (or "effective" top-level domain like `.com.ph`). If you need to do this, your best approach is to request `` and then have your content script decide whether `window.location.host` is one that the script wants to target. – apsillers Mar 12 '18 at 16:21
  • @apsillers sorry for the confusion. What I was trying to say is that I want a pattern that will detect different google sites even if there is top-level domain at the end like (.ph, .ly ,etc.) www.google.com.ph and www.google.com.ly but according to what you've mentioned in the previous comment it's not allowed by chrome so will just use JS. Many thanks – Abdelsalam Shahlol Mar 13 '18 at 09:04
  • 1
    Seems like this is an old answer in V3 of manifest this is not valid. – Raj Oberoi Jul 24 '21 at 06:46
6

I came across this answer trying to find a way to only enable the icon on certain pages this is how I did it. Docs

background.js

chrome.runtime.onInstalled.addListener(function() {
  chrome.tabs.onActivated.addListener(async info => {
    const tab = await chrome.tabs.get(info.tabId);
    
    const isGithub = tab.url.startsWith('https://github.com/');
    isGithub 
      ? chrome.action.enable(tab.tabId) 
      : chrome.action.disable(tab.tabId);
  });
});

make sure to add tabs permission in manifest

ihor.eth
  • 2,207
  • 20
  • 27
  • This is everything I ever wanted. TY! – BrandonReid May 22 '21 at 15:54
  • 1
    Yes, in manifest v3 we can only use background.js to achieve this, and don't forget `platform.tabs.onUpdated.addListener(async (tabId, changeInfo) => { var tab = await platform.tabs.get(tabId); if (tab.active && changeInfo.url) { /* Do something */ } });` . otherwise enable is not called when url changed – Wonson Jul 06 '21 at 15:51
2
First of all there are 2 types of extensions:

1. Browser Action - which work for multiple websites or almost all websites
2. Page Action - which work for specific websites or webpages [which is needed 
   in our case]

Follow these steps to show your extension only on google:

Step 1: Go to manifest.json file and add the below code snippet

        "background":{
           "scripts":["background.js"],
           "persistent":false
         }
         
         ***also make sure you have page action not browser action** 
        
         "page_action" : { "default_popup":"your_popup.html" }

Step 2: Now add permissions in manifest:
        
        "permissions":["declarativeContent"]

Step 3: Now create background.js in root folder of extension and add the 
        below code in it, this will let the extension to work only on 
        urls that contain google.com
        
        // When the extension is installed or upgraded ...
        chrome.runtime.onInstalled.addListener(function() {
         // Replace all rules ...
         chrome.declarativeContent.onPageChanged.removeRules(undefined, 
      function() {
         // With a new rule ...
         chrome.declarativeContent.onPageChanged.addRules([
         {
          // That fires when a page's URL contains a 'g' ...
          conditions: [
          new chrome.declarativeContent.PageStateMatcher({
            pageUrl: { urlContains: 'google.com' },
          })
         ],
          // And shows the extension's page action.
          actions: [ new chrome.declarativeContent.ShowPageAction() ]
        }
      ]);
    });
  });

Step 4: Now reload your extension, you'll find that your extension will work 
        only for google.com

Hope this solved your query, If Yes, then Upvote the answer Thanks! 

        
       
Rohit Sharma
  • 565
  • 3
  • 7