mles
mles

Reputation: 3456

Execute Script of Chrome extension only once

I've made a Chrome script that modifies a specific login Page. It works as expected, but I can see in the console that it is always active, although it should only be applied on the login site.

My manifest file:

{
  "manifest_version": 2,
  "name": "Login Enhancer",
  "description": "Login without a hassle",
  "version": "1.0",
  "icons": {
    "16": "icon16.png",
    "48": "icon48.png",
    "128": "icon128.png"
  },
  "permissions": [
    "https://*.examplesite.io/subdomain/portal/#/login"
  ],
  "background": {
    "scripts": [
      "background.js"
    ]
  }
}

background.js:

chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
  if (changeInfo.status == 'complete' && tab.active) {

    chrome.tabs.executeScript(null, {file: 'script.js'});

  }
});

script.js

// delete useless Remember Me Function
document.querySelector('.remember-me').remove();

After I've logged in when I'm browsing on examplesite.io/subdomain the console says on every new page:

Uncaught TypeError: Cannot read property 'remove' of null
    at script.js:2

Obviously there is no more remember-me button to remove. This has probably to do with the Listener in my background.js File. What is the correct listener so the script.js is only executed once on https://*.examplesite.io/subdomain/portal/#/login and not everywhere on https://*.examplesite.io?

Upvotes: 4

Views: 3351

Answers (1)

Makyen
Makyen

Reputation: 33296

For what you have shown in the question, the best way to do this is to use a content_scripts entry in your manifest.json to load your content script instead of using chrome.tabs.executeScript() to do so. Doing it as a content_scripts entry will inject the script once whenever the specified page is loaded. It is significantly less complicated than using chrome.tabs.executeScript() for the purpose of loading a script when a URL matches a certain page. In general, chrome.tabs.executeScript() should be used when the interaction with the user begins with the user clicking on a browserAction or pageAction button (which you are not using), or when you want more detailed control over when the script is injected other than always once for pages matching a specific URL, or URL pattern (which you don't need for what you are doing).

In your case, you are wanting to inject the script once, every time a specific URL is loaded. This is exactly the use case for which the content_scripts key in manifest.json exists.

Given that your background script was doing nothing other than loading your content script, using a content_scripts entry means you do not need a background script. In addition, you don't need to explicitly specify permissions for that particular URL. Your extension is implicitly given permissions for the URLs which match the content_scripts matches key.

You could do this by changing your manifest.json to:

{
  "manifest_version": 2,
  "name": "Login Enhancer",
  "description": "Login without a hassle",
  "version": "1.0",
  "icons": {
    "16": "icon16.png",
    "48": "icon48.png",
    "128": "icon128.png"
  },

  "content_scripts": [
    {
      "matches": ["https://*.examplesite.io/subdomain/portal/#/login"],
      "js": ["script.js"]
    }
  ]
}

Upvotes: 8

Related Questions