Modifying the built-in newtab page

I am not able to run my content script on the new tab page (where it is not assigned to any url).

I looked at various posts on the subject, ie, Does content script have access to newtab page? and What is the URL of the google chrome new tab page and how to exclude it from manifest.json

which seem to suggest it is possible.

I enabled chrome://flags/#extensions-on-chrome-urls

I have:

"permissions": [
    "http://*/*", 
    "https://*/*",
    "chrome://*/*"
],

(also tried "*://*/_/chrome/newtab*")

still no luck ... what am I missing ?

this answer Can you access chrome:// pages from an extension? mentsions "wildcards are not accepted". Is this true ? and if so how to specify the newtab page ?


Solution 1:

The problem is that Chrome 61 and newer explicitly forbids access to the contents of its built-in new tab page (NTP) via content scripts or any other API.

The solution is to create the entire replacement page as an html file in your extension and specify it in chrome_url_overrides.

As for why, here's quoting [source] rdevlin, one of the developers of chrome extensions API:

There's a few reasons for this change. One is to enforce policy, the other is for consistency.

  • We've had a public policy for awhile now that states that modification of the NTP through anything other than Chrome URL overrides isn't allowed (though we didn't begin enforcing this policy in many cases until July 1st). This is merely bringing chrome code more inline with that same policy to help prevent surprise if an extension is modifying the NTP and is taken down for policy violations.
  • This is also for consistency, since we've actually treated scripts on the NTP differently for years now, due to certain NTP magic. For example, the URL seen by the browser on the NTP is chrome://newtab, but the url in the renderer is https://www.google.com/_/chrome/newtab. Since chrome.tabs.executeScript checks the URL in the browser, the script would be denied, even though content scripts (checked in the renderer) would be allowed. In theory, these permissions should not be different. Similarly odd, if the user is using the local ntp (chrome-search://local-ntp/local-ntp.html), injection would already be disallowed in both the renderer and the browser. And, if we go waaaaay back, the NTP used to be pure WebUI with an URL of chrome://newtab, where injections were again disallowed. Rather than have inconsistent behavior depending on the type of script injection the extension uses, we want to have consistency throughout the system.

P.S. Please don't edit the quoted text.