1

I am trying to change the background of about:newtab in Firefox using the new WebExtensions API. At the moment, I don't understand why I receive the following error message in the debug console:

Unchecked lastError value: Error: No window matching {"matchesHost":[]}

The code for my add-on is as follows:

manifest.json

{
    "background": {
        "scripts": ["background.js"]
    },
    "description": "Yourdomain description.",
    "homepage_url": "https://yourdomain.com",
    "icons": {
        "64": "icons/icon-64.png"
    },
    "manifest_version": 2,
    "name": "yourDomain",
    "permissions": [
        "tabs",
        "activeTab"
    ],
    "version": "2.0"
}

background.js:

var tabId;

function changeBackground() {
    chrome.tabs.insertCSS( tabId, {
        code: "body { border: 20px dotted pink; }"
    });
}

function handleCreated(tab) {
    if (tab.url == "about:newtab") {
        console.log(tab);
        tabId = tab.id;
        changeBackground();
    }
}

chrome.tabs.onCreated.addListener(handleCreated);
Makyen
  • 31,849
  • 12
  • 86
  • 121
Peter
  • 387
  • 1
  • 9
  • 21

1 Answers1

2

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.

Makyen
  • 31,849
  • 12
  • 86
  • 121
  • thanks @Makyen. When I insert your new function and modify my **changeBackground(tabId)** function I get the following message: `alert() is not supported in background windows; please use console.log instead.` So I changed the following line from `alert('This extension, ' + chrome.runtime.id + ', does not work ' + extraMessage);` to this: `console.log('This extension, ' + chrome.runtime.id + ', does not work ' + extraMessage);` As you already mentioned I can't change the about:newtab page with Web Extensions. – Peter Oct 27 '16 at 12:49
  • That is the [behavior I expected from `alert()` in a Firefox WebExtension background script](http://stackoverflow.com/a/39084633/3773011). Forcing the [Browser Console](https://developer.mozilla.org/en-US/docs/Tools/Browser_Console) open and having a line of text display is as close as we get to having an `alert()` in stock Firefox. [Although, I have written code which simulates an `alert()` modal window in a WebExtensions background script]. From your comment, it is clear the comment in the code that "this is automatically in the console, not an alert" was not sufficient. I will update it. – Makyen Oct 27 '16 at 16:17