Currently no way for WebExtensions add-ons to change about:newtab
That is the error you receive when the page into which you are attempting to inject does not match the match pattern, or can not be expressed as a match pattern (i.e. the URL must be able to be expressed as a match pattern, even if you didn't supply a match pattern). Match patterns must have a scheme that is one of http
, https
, file
, ftp
, or app
. The error you are seeing is a result of not checking the runtime.lastError
value in the callback function in tabs.insertCSS()
when the error is the one expected when you attempt to inject code or CSS into an about:*
page.
The MDN documentation is quite specific about not being able to use tabs.insertCSS()
with any of the about:*
pages (emphasis mine):
You can only inject CSS into pages whose URL can be expressed using a match pattern: meaning, its scheme must be one of "http", "https", "file", "ftp". This means that you can't inject CSS into any of the browser's built-in pages, such as about:debugging
, about:addons
, or the page that opens when you open a new empty tab [about:newtab
].
Future:
Chrome has the manifest.json key chrome_url_overrides
which allows overriding any of: bookmarks
, history
, or newtab
. It appears that Firefox support for this manifest.json key is a "maybe".
Alternatives:
It is possible to override the newtab page with other types of Firefox add-ons.
You can use WebExtensions to detect that a tab has changed its URL to about:newtab
and redirect the tab to a page of your choice.
Using tabs.insertCSS()
or tabs.executeScript()
for tabs, generally
If you are using tabs.insertCSS()
or tabs.executeScript()
in a situation where the tab normally contains a regular URL, but might be an about*:
(or chrome:*
scheme on Chrome) (e.g. a browser_action
button), you could handle the error with the following code (tested and working in both Firefox WebExtensions and Chrome):
function handleExecuteScriptAndInsertCSSErrors(tabId){
if(chrome.runtime.lastError){
let message = chrome.runtime.lastError.message;
let isFirefox = window.InstallTrigger?true:false;
let extraMessage = tabId ? 'in tab ' + tabId + '.' : 'on this page.';
if((!isFirefox && message.indexOf('Cannot access a chrome:') > -1) //Chrome
||(isFirefox && message.indexOf('No window matching') > -1) //Firefox
){
//The current tab is one into which we are not allowed to inject scripts.
// You should consider alternatives for informing the user that your extension
// does not work on a particular page/URL/tab.
// For example: For browser_actions, you should listen to chrome.tabs events
// and use use browserAction.disable()/enable() when the URL of the
// active tab is, or is not, one for which your add-on can operate.
// Alternately, you could use a page_action button.
//In other words, using a console.log() here in a released add-on is not a good
// idea, but works for examples/testing.
console.log('This extension, ' + chrome.runtime.id
+ ', does not work ' + extraMessage);
} else {
// Report the error
if(isFirefox){
//In Firefox, runtime.lastError is an Error Object including a stack trace.
console.error(chrome.runtime.lastError);
}else{
console.error(message);
}
}
}
}
You could then change your changeBackground()
code to:
function changeBackground(tabId) {
chrome.tabs.insertCSS( tabId, {
code: "body { border: 20px dotted pink; }"
}, handleExecuteScriptAndInsertCSSErrors.bind(null,tabId));
}
Obviously, changing your code like that won't actually allow you to change the background on the about:newtab
page.