Best Practices for Overriding the New Tab Page With Your Extension

In Firefox 13 (actually, Firefox 12), Firefox introduced the ability to override the new tab page with the preference browser.newtab.url. For extension developers, this is great because it because it allows us to remove all of the different hacks we were using to add content to the new tab page. Unfortunately it can also create problems as various extensions stomp on each other trying to take over the new tab page.

I’ve added support for overriding the new tab page to three different extensions, so I’ve learned a great deal about using this new preference in a way that coexists with other extensions and does the right thing for the user. My goal with this post is to give some best practices for overriding the new tab page in your extension. The code samples in this post assume a basic knowledge of how Firefox extensions work, including preference observers. You probably won’t be able to just cut and paste them into your extension.

First and foremost, do NOT set the browser.newtab.url preference in your default preferences file. Currently there is no user interface for a user to reset the preference. By changing the default preferences, you remove the user’s ability to get back to the Firefox new tab page. In addition, if you want to use your old new tab page overriding code on older versions of Firefox (particular Firefox 10 which is still supported as the ESR), you’ll need a way to detect new versus old. Using the default preference is the best way I’ve found (more on that later).

You should have a simple checkbox preference in your add-on that enables or disables your new tab page. For our code samples, we’ll use extensions.OUREXTENSION.overrideNewTab. When a user checks this box, we take over the new tab page. When it is unchecked, we relinquish the new tab page.

At startup, if our new tab preference is set, we change the new tab page URL:

try {
if (Services.prefs.getBoolPref("extensions.OUREXTENSION.overrideNewTab"))
  Services.prefs.setCharPref("browser.newtab.url", OUR_NEWTAB_URL);
} catch (ex) {}

Whenever our override preference is changed, we update the new tab page. We either set it if the user is turning on our new tab page or clear it if they are turning off our new tab page AND the current new tab page URL is the same as our new tab page URL.

observe: function observe(subject, topic, data) {
  switch (topic) {
    case "nsPref:changed":
      if (data == "extensions.OUREXTENSION.overrideNewTab") {
        var useOurNewTab = Services.prefs.getBoolPref("extensions.OUREXTENSION.overrideNewTab");
        if (useOurNewTab) {
          Services.prefs.setCharPref("browser.newtab.url", OUR_NEWTAB_URL);
        } else {
          var newTabURL = Services.prefs.getCharPref("browser.newtab.url");
          if (newTabURL == OUR_NEWTAB_URL)
            Services.prefs.clearUserPref("browser.newtab.url");
        }
      }
      break;
  }

Whenever the browser.newtab.url preference is changed to a value OTHER than our URL, we turn off our overriding of the new tab page:

observe: function observe(subject, topic, data) {
  switch (topic) {
    case "nsPref:changed":
      if (data == "browser.newtab.url") {
        var newTabURL = Services.prefs.getCharPref("browser.newtab.url");
        if (newTabURL != OUR_NEWTAB_URL)
          Services.prefs.setBoolPref("extensions.OUREXTENSION.overrideNewTab", false);
      }
      break;
  }

This ensures that if a user or another add-on changes the new tab page, we no longer try to take it over. It also ensures that a user can re-enable our new tab page by simply turning the preference back on.

Because this code does the right thing on start up, we always want to clear the preference when our add-on shuts down. We’re doing this so that if our add-on is uninstalled or disabled, we don’t continue to take over the new tab page. This can especially be a problem if you specify a chrome URL for the new tab page:

observe: function observe(subject, topic, data) {
  switch (topic) {
    case "profile-before-change":
      /* IMPORTANT: REMOVE browser.newtab.url LISTENER SO WE DON'T RESET OUR PREFERENCE */
      var newTabURL = Services.prefs.getCharPref("browser.newtab.url");
      if (newTabURL == OUR_NEWTAB_URL)
        Services.prefs.clearUserPref("browser.newtab.url");
      break;
  }
}

You might have noticed that whenever you open a new tab page, focus is on the URL bar and the text is not selected. This can be pretty annoying when a user opens the new tab page and can’t type a URL. There’s a bug open for this, but in the mean time we can change this behavior by adding our new tab URL to gInitialPages. This will cause Firefox to display a blank URL bar whenever this URL is loaded. If the new tab URL is always the same URL, you can just add it to gIntialPages whenever any window is opened.

if (gInitialPages.indexOf(OUR_NEWTAB_URL) == -1) {
  gInitialPages.push(newTabURL);
}

Be very careful about adding URLs to gInitialPages. Any URL added to that array will display as blank in the URL bar. Not just chrome URLs.

We mentioned earlier that we might want to distinguish between version2 of Firefox that have support for setting the new tab preference and those that don’t. The easiest way to do this is by checking the default value of browser.newtab.url:

var hasNewTab = false;
try {
  var newTabURL = Services.prefs.getDefaultBranch("browser.newtab.url").getCharPref("");
  hasNewTab = true;
} catch(ex) {}

This will allow you to only run the new code when a user is running Firefox 12 or newer.

And that’s how to cleanly take over the new tab page. As always, comments and suggestions welcome.

Please note: I reserve the right to delete comments that are offensive or off-topic.

Leave a Reply

Your email address will not be published. Required fields are marked *

8 thoughts on “Best Practices for Overriding the New Tab Page With Your Extension

  1. Services.prefs.setCharPref is setting a user pref, which can be dangerous if the user crashes or otherwise shuts down unexpectedly, and I really don’t think you *need* a user pref there. Why not set that as a default pref instead? Default prefs never persist across runs:

    Services.prefs.getDefaultBranch(“”).setCharPref(“browser.newtab.url”, OUR_NEWTAB_URL);

  2. Do you have an extension that can be downloaded for overriding firefox’s new tab? I want to have a custom page that shows when the new tab is clicked but am having issues achieving this in firefox. It was easy in chrome but I can’t figure out the firefox extension for this.

    • You don’t need an extension to override the new tab.

      Type about:config in the URL bar. If you see a warning, click “I’ll be careful, I promise”

      Then in the filter box, search on browser.newtab.url. If you double click on this value, you can set it to any URL you want like https://google.com and that will be your new tab page.

      • Thanks but the extension we are making, we want to show a custom page of functionality instead of the default firefox new tab. I think I have figured it out with the addon sdk. It wasn’t as straight forward as chrome was. I didn’t want our users to do those steps, I wanted to handle it in the extension.

        • Sorry, I misunderstood. The same thing applies though.

          You can create a chrome page in your extensions:

          chrome://yourext/content/foo.xul and use that for the new tab page.

          And then just set the preference to that value. Honestly I’m not an SDK user, so I don’t know how the standalone XUL page would work in there.