Bug 1298950 - Add support for overriding about:home to chrome_url_overrides r?mixedpuppy,aswan
MozReview-Commit-ID: 4Bc2F0W7WqV
--- a/browser/components/extensions/ext-url-overrides.js
+++ b/browser/components/extensions/ext-url-overrides.js
@@ -3,47 +3,102 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
"@mozilla.org/browser/aboutnewtab-service;1",
"nsIAboutNewTabService");
+XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
+ "resource://gre/modules/Preferences.jsm");
// Bug 1320736 tracks creating a generic precedence manager for handling
// multiple addons modifying the same properties, and bug 1330494 has been filed
// to track utilizing this manager for chrome_url_overrides. Until those land,
// the edge cases surrounding multiple addons using chrome_url_overrides will
// be ignored and precedence will be first come, first serve.
let overrides = {
// A queue of extensions in line to override the newtab page (sorted oldest to newest).
newtab: [],
+ // A queue of extensions in line to override the home page (sorted oldest to newest).
+ home: [],
};
+/**
+ * Resets the specified page to its default value.
+ *
+ * @param {string} page The page to override. Accepted values are "newtab" and "home".
+ */
+function resetPage(page) {
+ switch (page) {
+ case "newtab":
+ aboutNewTabService.resetNewTabURL();
+ break;
+ case "home":
+ Preferences.reset("browser.startup.homepage");
+ break;
+ default:
+ throw new Error("Unrecognized override type");
+ }
+}
+
+/**
+ * Overrides the specified page to the specified URL.
+ *
+ * @param {string} page The page to override. Accepted values are "newtab" and "home".
+ * @param {string} url The resolved URL to use for the page override.
+ */
+function overridePage(page, url) {
+ switch (page) {
+ case "newtab":
+ aboutNewTabService.newTabURL = url;
+ break;
+ case "home":
+ Preferences.set("browser.startup.homepage", url);
+ break;
+ default:
+ throw new Error("Unrecognized override type");
+ }
+}
+
+/**
+ * Updates the page to the URL specified by the extension next in line. If no extensions
+ * are in line, the page is reset to its default value.
+ *
+ * @param {string} page The page to override.
+ */
+function updatePage(page) {
+ if (overrides[page].length) {
+ overridePage(page, overrides[page][0].url);
+ } else {
+ resetPage(page);
+ }
+}
+
/* eslint-disable mozilla/balanced-listeners */
extensions.on("manifest_chrome_url_overrides", (type, directive, extension, manifest) => {
- if (manifest.chrome_url_overrides.newtab) {
- let newtab = manifest.chrome_url_overrides.newtab;
- let url = extension.baseURI.resolve(newtab);
+ if (Object.keys(overrides).length > 1) {
+ extension.manifestError("Extensions can override only one page.");
+ }
- // Only set the newtab URL if no other extension is overriding it.
- if (!overrides.newtab.length) {
- aboutNewTabService.newTabURL = url;
+ for (let page of Object.keys(overrides)) {
+ if (manifest.chrome_url_overrides[page]) {
+ let relativeURL = manifest.chrome_url_overrides[page];
+ let url = extension.baseURI.resolve(relativeURL);
+ // Store the extension ID instead of a hard reference to the extension.
+ overrides[page].push({id: extension.id, url});
+ updatePage(page);
+ break;
}
-
- overrides.newtab.push({extension, url});
}
});
extensions.on("shutdown", (type, extension) => {
- let i = overrides.newtab.findIndex(o => o.extension === extension);
- if (i !== -1) {
- overrides.newtab.splice(i, 1);
-
- if (overrides.newtab.length) {
- aboutNewTabService.newTabURL = overrides.newtab[0].url;
- } else {
- aboutNewTabService.resetNewTabURL();
+ for (let page of Object.keys(overrides)) {
+ let i = overrides[page].findIndex(o => o.id === extension.id);
+ if (i !== -1) {
+ overrides[page].splice(i, 1);
+ updatePage(page);
}
}
});
/* eslint-enable mozilla/balanced-listeners */
--- a/browser/components/extensions/schemas/url_overrides.json
+++ b/browser/components/extensions/schemas/url_overrides.json
@@ -9,16 +9,21 @@
"type": "object",
"optional": true,
"properties": {
"newtab": {
"$ref": "ExtensionURL",
"optional": true,
"preprocess": "localize"
},
+ "home": {
+ "$ref": "ExtensionURL",
+ "optional": true,
+ "preprocess": "localize"
+ },
"bookmarks": {
"unsupported": true,
"$ref": "ExtensionURL",
"optional": true,
"preprocess": "localize"
},
"history": {
"unsupported": true,
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ b/browser/components/extensions/test/browser/browser-common.ini
@@ -109,17 +109,19 @@ support-files =
[browser_ext_tabs_cookieStoreId.js]
[browser_ext_tabs_update.js]
[browser_ext_tabs_zoom.js]
[browser_ext_tabs_update_url.js]
[browser_ext_themes_chromeparity.js]
[browser_ext_themes_dynamic_updates.js]
[browser_ext_themes_lwtsupport.js]
[browser_ext_topwindowid.js]
-[browser_ext_url_overrides.js]
+[browser_ext_url_overrides_all.js]
+[browser_ext_url_overrides_home.js]
+[browser_ext_url_overrides_newtab.js]
[browser_ext_webRequest.js]
[browser_ext_webNavigation_frameId0.js]
[browser_ext_webNavigation_getFrames.js]
[browser_ext_webNavigation_urlbar_transitions.js]
[browser_ext_windows.js]
[browser_ext_windows_create.js]
tags = fullscreen
[browser_ext_windows_create_params.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_url_overrides_all.js
@@ -0,0 +1,97 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+
+"use strict";
+
+XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
+ "@mozilla.org/browser/aboutnewtab-service;1",
+ "nsIAboutNewTabService");
+
+const NEWTAB_URI = "webext-newtab.html";
+const HOME_URI = "webext-home.html";
+
+add_task(function* test_extensions_overriding_different_pages() {
+ let defaultHomePage = Preferences.get("browser.startup.homepage");
+ let defaultNewtabPage = aboutNewTabService.newTabURL;
+
+ is(Preferences.get("browser.startup.homepage"), defaultHomePage,
+ `Default home url should be ${defaultHomePage}`);
+ is(aboutNewTabService.newTabURL, defaultNewtabPage,
+ `Default newtab url should be ${defaultNewtabPage}`);
+
+ let ext1 = ExtensionTestUtils.loadExtension({
+ manifest: {"chrome_url_overrides": {}},
+ });
+
+ let ext2 = ExtensionTestUtils.loadExtension({
+ manifest: {"chrome_url_overrides": {newtab: NEWTAB_URI}},
+ });
+
+ let ext3 = ExtensionTestUtils.loadExtension({
+ manifest: {"chrome_url_overrides": {home: HOME_URI}},
+ });
+
+ yield ext1.startup();
+
+ is(aboutNewTabService.newTabURL, defaultNewtabPage,
+ `Default newtab url should still be ${defaultNewtabPage}`);
+ is(Preferences.get("browser.startup.homepage"), defaultHomePage,
+ `Default home url should be ${defaultHomePage}`);
+
+ yield ext2.startup();
+
+ ok(aboutNewTabService.newTabURL.endsWith(NEWTAB_URI),
+ "Newtab url should be overriden by the second extension.");
+ is(Preferences.get("browser.startup.homepage"), defaultHomePage,
+ `Default home url should be ${defaultHomePage}`);
+
+ yield ext1.unload();
+
+ ok(aboutNewTabService.newTabURL.endsWith(NEWTAB_URI),
+ "Newtab url should still be overriden by the second extension.");
+ is(Preferences.get("browser.startup.homepage"), defaultHomePage,
+ `Default home url should be ${defaultHomePage}`);
+
+ yield ext3.startup();
+
+ ok(aboutNewTabService.newTabURL.endsWith(NEWTAB_URI),
+ "Newtab url should still be overriden by the second extension.");
+ ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI),
+ "Home url should be overriden by the third extension.");
+
+ yield ext2.unload();
+
+ is(aboutNewTabService.newTabURL, defaultNewtabPage,
+ `Newtab url should be reset to ${defaultNewtabPage}`);
+ ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI),
+ "Home url should still be overriden by the third extension.");
+
+ yield ext3.unload();
+
+ is(aboutNewTabService.newTabURL, defaultNewtabPage,
+ `Newtab url should be reset to ${defaultNewtabPage}`);
+ is(Preferences.get("browser.startup.homepage"), defaultHomePage,
+ `Home url should be reset to ${defaultHomePage}`);
+});
+
+add_task(function* test_extensions_with_multiple_overrides() {
+ let ext = ExtensionTestUtils.loadExtension({
+ manifest: {"chrome_url_overrides": {
+ newtab: NEWTAB_URI,
+ home: HOME_URI,
+ }},
+ });
+
+ SimpleTest.waitForExplicitFinish();
+ let waitForConsole = new Promise(resolve => {
+ SimpleTest.monitorConsole(resolve, [{
+ message: /Extensions can override only one page./,
+ }]);
+ });
+
+ yield ext.startup();
+ yield ext.unload();
+
+ SimpleTest.endMonitorConsole();
+ yield waitForConsole;
+});
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_url_overrides_home.js
@@ -0,0 +1,74 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+
+"use strict";
+
+XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
+ "resource://gre/modules/Preferences.jsm");
+
+const HOME_URI_1 = "webext-home-1.html";
+const HOME_URI_2 = "webext-home-2.html";
+const HOME_URI_3 = "webext-home-3.html";
+
+add_task(function* test_multiple_extensions_overriding_newtab_page() {
+ let defaultHomePage = Preferences.get("browser.startup.homepage");
+
+ is(Preferences.get("browser.startup.homepage"), defaultHomePage,
+ `Default home url should be ${defaultHomePage}`);
+
+ let ext1 = ExtensionTestUtils.loadExtension({
+ manifest: {"chrome_url_overrides": {}},
+ });
+
+ let ext2 = ExtensionTestUtils.loadExtension({
+ manifest: {"chrome_url_overrides": {home: HOME_URI_1}},
+ });
+
+ let ext3 = ExtensionTestUtils.loadExtension({
+ manifest: {"chrome_url_overrides": {home: HOME_URI_2}},
+ });
+
+ let ext4 = ExtensionTestUtils.loadExtension({
+ manifest: {"chrome_url_overrides": {home: HOME_URI_3}},
+ });
+
+ yield ext1.startup();
+
+ is(Preferences.get("browser.startup.homepage"), defaultHomePage,
+ `Default home url should still be ${defaultHomePage}`);
+
+ yield ext2.startup();
+
+ ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI_1),
+ "Home url should be overriden by the second extension.");
+
+ yield ext1.unload();
+
+ ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI_1),
+ "Home url should still be overriden by the second extension.");
+
+ yield ext3.startup();
+
+ ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI_1),
+ "Home url should still be overriden by the second extension.");
+
+ yield ext2.unload();
+
+ ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI_2),
+ "Home url should be overriden by the third extension.");
+
+ yield ext4.startup();
+
+ ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI_2),
+ "Home url should be overriden by the third extension.");
+
+ yield ext4.unload();
+
+ ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI_2),
+ "Home url should be overriden by the third extension.");
+
+ yield ext3.unload();
+
+ is(Preferences.get("browser.startup.homepage"), defaultHomePage,
+ `Home url should be reset to ${defaultHomePage}`);
+});
rename from browser/components/extensions/test/browser/browser_ext_url_overrides.js
rename to browser/components/extensions/test/browser/browser_ext_url_overrides_newtab.js
--- a/browser/components/extensions/test/browser/browser_ext_url_overrides.js
+++ b/browser/components/extensions/test/browser/browser_ext_url_overrides_newtab.js
@@ -71,21 +71,21 @@ add_task(function* test_multiple_extensi
is(aboutNewTabService.newTabURL, "about:newtab",
"Newtab url should be reset to about:newtab");
});
add_task(function* test_sending_message_from_newtab_page() {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"chrome_url_overrides": {
- newtab: NEWTAB_URI_2,
+ newtab: NEWTAB_URI_1,
},
},
files: {
- [NEWTAB_URI_2]: `
+ [NEWTAB_URI_1]: `
<!DOCTYPE html>
<head>
<meta charset="utf-8"/></head>
<html>
<body>
<script src="newtab.js"></script>
</body>
</html>