Bug 1341458 - Move homepage to chrome_settings_overrides. r=mixedpuppy draft
authorMichael Kaply <mozilla@kaply.com>
Tue, 07 Mar 2017 10:31:43 -0600
changeset 498352 b8720b48de2ee859dad2f132d433e10d371d6ec6
parent 496930 07e53fffedbb77210a4474c96fbbcc69f347b0d2
child 498443 1e377cdef0522dcb3d9c7c4ce7dd686fd993413b
child 499305 3cb211d393f6909185975eac01a753d5bdc6e88e
push id49156
push usermozilla@kaply.com
push dateTue, 14 Mar 2017 16:09:28 +0000
reviewersmixedpuppy
bugs1341458
milestone55.0a1
Bug 1341458 - Move homepage to chrome_settings_overrides. r=mixedpuppy MozReview-Commit-ID: 5wtaUxXco8z
browser/components/extensions/ext-chrome-settings-overrides.js
browser/components/extensions/extensions-browser.manifest
browser/components/extensions/jar.mn
browser/components/extensions/schemas/chrome_settings_overrides.json
browser/components/extensions/schemas/jar.mn
browser/components/extensions/test/browser/browser-common.ini
browser/components/extensions/test/browser/browser_ext_url_overrides_home.js
browser/components/extensions/test/browser/head.js
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/ext-chrome-settings-overrides.js
@@ -0,0 +1,31 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "ExtensionPreferencesManager",
+                                  "resource://gre/modules/ExtensionPreferencesManager.jsm");
+
+/* eslint-disable mozilla/balanced-listeners */
+extensions.on("manifest_chrome_settings_overrides", (type, directive, extension, manifest) => {
+  if (manifest.chrome_settings_overrides.homepage) {
+    ExtensionPreferencesManager.setSetting(extension, "homepage_override",
+                                           manifest.chrome_settings_overrides.homepage);
+  }
+});
+/* eslint-enable mozilla/balanced-listeners */
+
+ExtensionPreferencesManager.addSetting("homepage_override", {
+  prefNames: [
+    "browser.startup.homepage",
+  ],
+  setCallback(value) {
+    return {
+      "browser.startup.homepage": value,
+    };
+  },
+});
--- a/browser/components/extensions/extensions-browser.manifest
+++ b/browser/components/extensions/extensions-browser.manifest
@@ -1,12 +1,13 @@
 # scripts
 category webextension-scripts bookmarks chrome://browser/content/ext-bookmarks.js
 category webextension-scripts browserAction chrome://browser/content/ext-browserAction.js
 category webextension-scripts browsingData chrome://browser/content/ext-browsingData.js
+category webextension-scripts chrome-settings-overrides chrome://browser/content/ext-chrome-settings-overrides.js
 category webextension-scripts commands chrome://browser/content/ext-commands.js
 category webextension-scripts contextMenus chrome://browser/content/ext-contextMenus.js
 category webextension-scripts desktop-runtime chrome://browser/content/ext-desktop-runtime.js
 category webextension-scripts devtools chrome://browser/content/ext-devtools.js
 category webextension-scripts devtools-inspectedWindow chrome://browser/content/ext-devtools-inspectedWindow.js
 category webextension-scripts devtools-network chrome://browser/content/ext-devtools-network.js
 category webextension-scripts devtools-panels chrome://browser/content/ext-devtools-panels.js
 category webextension-scripts history chrome://browser/content/ext-history.js
@@ -27,16 +28,17 @@ category webextension-scripts-devtools d
 category webextension-scripts-addon contextMenus chrome://browser/content/ext-c-contextMenus.js
 category webextension-scripts-addon omnibox chrome://browser/content/ext-c-omnibox.js
 category webextension-scripts-addon tabs chrome://browser/content/ext-c-tabs.js
 
 # schemas
 category webextension-schemas bookmarks chrome://browser/content/schemas/bookmarks.json
 category webextension-schemas browser_action chrome://browser/content/schemas/browser_action.json
 category webextension-schemas browsing_data chrome://browser/content/schemas/browsing_data.json
+category webextension-schemas chrome_settings_overrides chrome://browser/content/schemas/chrome_settings_overrides.json
 category webextension-schemas commands chrome://browser/content/schemas/commands.json
 category webextension-schemas context_menus chrome://browser/content/schemas/context_menus.json
 category webextension-schemas context_menus_internal chrome://browser/content/schemas/context_menus_internal.json
 category webextension-schemas devtools chrome://browser/content/schemas/devtools.json
 category webextension-schemas devtools_inspected_window chrome://browser/content/schemas/devtools_inspected_window.json
 category webextension-schemas devtools_network chrome://browser/content/schemas/devtools_network.json
 category webextension-schemas devtools_panels chrome://browser/content/schemas/devtools_panels.json
 category webextension-schemas history chrome://browser/content/schemas/history.json
--- a/browser/components/extensions/jar.mn
+++ b/browser/components/extensions/jar.mn
@@ -10,16 +10,17 @@ browser.jar:
 #endif
 #ifdef XP_WIN
     content/browser/extension-win-panel.css
 #endif
     content/browser/extension.svg
     content/browser/ext-bookmarks.js
     content/browser/ext-browserAction.js
     content/browser/ext-browsingData.js
+    content/browser/ext-chrome-settings-overrides.js
     content/browser/ext-commands.js
     content/browser/ext-contextMenus.js
     content/browser/ext-desktop-runtime.js
     content/browser/ext-devtools.js
     content/browser/ext-devtools-inspectedWindow.js
     content/browser/ext-devtools-network.js
     content/browser/ext-devtools-panels.js
     content/browser/ext-history.js
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/schemas/chrome_settings_overrides.json
@@ -0,0 +1,25 @@
+[
+  {
+    "namespace": "manifest",
+    "types": [
+      {
+        "$extend": "WebExtensionManifest",
+        "properties": {
+          "chrome_settings_overrides": {
+            "type": "object",
+            "optional": true,
+            "additionalProperties": { "$ref": "UnrecognizedProperty" },
+            "properties": {
+              "homepage": {
+                "type": "string",
+                "format": "url",
+                "optional": true,
+                "preprocess": "localize"
+              }
+            }
+          }
+        }
+      }
+    ]
+  }
+]
\ No newline at end of file
--- a/browser/components/extensions/schemas/jar.mn
+++ b/browser/components/extensions/schemas/jar.mn
@@ -1,16 +1,17 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 browser.jar:
     content/browser/schemas/bookmarks.json
     content/browser/schemas/browser_action.json
     content/browser/schemas/browsing_data.json
+    content/browser/schemas/chrome_settings_overrides.json
     content/browser/schemas/commands.json
     content/browser/schemas/context_menus.json
     content/browser/schemas/context_menus_internal.json
     content/browser/schemas/devtools.json
     content/browser/schemas/devtools_inspected_window.json
     content/browser/schemas/devtools_network.json
     content/browser/schemas/devtools_panels.json
     content/browser/schemas/history.json
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ b/browser/components/extensions/test/browser/browser-common.ini
@@ -114,16 +114,17 @@ support-files =
 [browser_ext_tabs_sendMessage.js]
 [browser_ext_tabs_cookieStoreId.js]
 [browser_ext_tabs_update.js]
 [browser_ext_tabs_zoom.js]
 [browser_ext_tabs_update_url.js]
 [browser_ext_themes_icons.js]
 [browser_ext_topwindowid.js]
 [browser_ext_url_overrides_newtab.js]
+[browser_ext_url_overrides_home.js]
 [browser_ext_webRequest.js]
 [browser_ext_webNavigation_frameId0.js]
 [browser_ext_webNavigation_getFrames.js]
 [browser_ext_webNavigation_onCreatedNavigationTarget.js]
 [browser_ext_webNavigation_onCreatedNavigationTarget_window_open.js]
 [browser_ext_webNavigation_urlbar_transitions.js]
 [browser_ext_windows.js]
 [browser_ext_windows_create.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_url_overrides_home.js
@@ -0,0 +1,184 @@
+/* -*- 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");
+XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
+                                  "resource://gre/modules/AddonManager.jsm");
+
+// Named this way so they correspond to the extensions
+const HOME_URI_2 = "http://example.com/";
+const HOME_URI_3 = "http://example.org/";
+const HOME_URI_4 = "http://example.net/";
+
+add_task(function* test_multiple_extensions_overriding_home_page() {
+  let defaultHomePage = Preferences.get("browser.startup.homepage");
+
+  let ext1 = ExtensionTestUtils.loadExtension({
+    manifest: {"chrome_settings_overrides": {}},
+    useAddonManager: "temporary",
+  });
+
+  let ext2 = ExtensionTestUtils.loadExtension({
+    manifest: {"chrome_settings_overrides": {homepage: HOME_URI_2}},
+    useAddonManager: "temporary",
+  });
+
+  let ext3 = ExtensionTestUtils.loadExtension({
+    manifest: {"chrome_settings_overrides": {homepage: HOME_URI_3}},
+    useAddonManager: "temporary",
+  });
+
+  let ext4 = ExtensionTestUtils.loadExtension({
+    manifest: {"chrome_settings_overrides": {homepage: HOME_URI_4}},
+    useAddonManager: "temporary",
+  });
+
+  yield ext1.startup();
+
+  is(Preferences.get("browser.startup.homepage"), defaultHomePage,
+     "Home url should be the default");
+
+  // Because we are expecting the pref to change when we start or unload, we
+  // need to wait on a pref change.  This is because the pref management is
+  // async and can happen after the startup/unload is finished.
+  let prefPromise = promisePrefChangeObserved("browser.startup.homepage");
+  yield ext2.startup();
+  yield prefPromise;
+
+  ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI_2),
+     "Home url should be overridden by the second extension.");
+
+  // Because we are unloading an earlier extension, browser.startup.homepage won't change
+  yield ext1.unload();
+
+  ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI_2),
+     "Home url should be overridden by the second extension.");
+
+  prefPromise = promisePrefChangeObserved("browser.startup.homepage");
+  yield ext3.startup();
+  yield prefPromise;
+
+  ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI_3),
+     "Home url should be overridden by the third extension.");
+
+  // Because we are unloading an earlier extension, browser.startup.homepage won't change
+  yield ext2.unload();
+
+  ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI_3),
+     "Home url should be overridden by the third extension.");
+
+  prefPromise = promisePrefChangeObserved("browser.startup.homepage");
+  yield ext4.startup();
+  yield prefPromise;
+
+  ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI_4),
+     "Home url should be overridden by the third extension.");
+
+
+  prefPromise = promisePrefChangeObserved("browser.startup.homepage");
+  yield ext4.unload();
+  yield prefPromise;
+
+  ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI_3),
+     "Home url should be overridden by the third extension.");
+
+  prefPromise = promisePrefChangeObserved("browser.startup.homepage");
+  yield ext3.unload();
+  yield prefPromise;
+
+  is(Preferences.get("browser.startup.homepage"), defaultHomePage,
+     "Home url should be reset to default");
+});
+
+const HOME_URI_1 = "http://example.com/";
+const USER_URI = "http://example.edu/";
+
+add_task(function* test_extension_setting_home_page_back() {
+  let defaultHomePage = Preferences.get("browser.startup.homepage");
+
+  Preferences.set("browser.startup.homepage", USER_URI);
+
+  is(Preferences.get("browser.startup.homepage"), USER_URI,
+     "Home url should be the user set value");
+
+  let ext1 = ExtensionTestUtils.loadExtension({
+    manifest: {"chrome_settings_overrides": {homepage: HOME_URI_1}},
+    useAddonManager: "temporary",
+  });
+
+  // Because we are expecting the pref to change when we start or unload, we
+  // need to wait on a pref change.  This is because the pref management is
+  // async and can happen after the startup/unload is finished.
+  let prefPromise = promisePrefChangeObserved("browser.startup.homepage");
+  yield ext1.startup();
+  yield prefPromise;
+
+  ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI_1),
+     "Home url should be overridden by the second extension.");
+
+  prefPromise = promisePrefChangeObserved("browser.startup.homepage");
+  yield ext1.unload();
+  yield prefPromise;
+
+  is(Preferences.get("browser.startup.homepage"), USER_URI,
+     "Home url should be the user set value");
+
+  Preferences.reset("browser.startup.homepage");
+
+  is(Preferences.get("browser.startup.homepage"), defaultHomePage,
+     "Home url should be the default");
+});
+
+add_task(function* test_disable() {
+  let defaultHomePage = Preferences.get("browser.startup.homepage");
+
+  const ID = "id@tests.mozilla.org";
+
+  let ext1 = ExtensionTestUtils.loadExtension({
+    manifest: {
+      applications: {
+        gecko: {
+          id: ID,
+        },
+      },
+      "chrome_settings_overrides": {
+        homepage: HOME_URI_1,
+      },
+    },
+    useAddonManager: "temporary",
+  });
+
+  let prefPromise = promisePrefChangeObserved("browser.startup.homepage");
+  yield ext1.startup();
+  yield prefPromise;
+
+  ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI_1),
+     "Home url should be overridden by the extension.");
+
+  let addon = yield AddonManager.getAddonByID(ID);
+  is(addon.id, ID);
+
+  prefPromise = promisePrefChangeObserved("browser.startup.homepage");
+  addon.userDisabled = true;
+  yield prefPromise;
+
+  is(Preferences.get("browser.startup.homepage"), defaultHomePage,
+     "Home url should be the default");
+
+  prefPromise = promisePrefChangeObserved("browser.startup.homepage");
+  addon.userDisabled = false;
+  yield prefPromise;
+
+  ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI_1),
+     "Home url should be overridden by the extension.");
+
+  prefPromise = promisePrefChangeObserved("browser.startup.homepage");
+  yield ext1.unload();
+  yield prefPromise;
+
+  is(Preferences.get("browser.startup.homepage"), defaultHomePage,
+     "Home url should be the default");
+});
--- a/browser/components/extensions/test/browser/head.js
+++ b/browser/components/extensions/test/browser/head.js
@@ -11,16 +11,17 @@
  *          openContextMenu closeContextMenu
  *          openExtensionContextMenu closeExtensionContextMenu
  *          openActionContextMenu openSubmenu closeActionContextMenu
  *          openTabContextMenu closeTabContextMenu
  *          imageBuffer imageBufferFromDataURI
  *          getListStyleImage getPanelForNode
  *          awaitExtensionPanel awaitPopupResize
  *          promiseContentDimensions alterContent
+ *          promisePrefChangeObserved
  */
 
 const {AppConstants} = Cu.import("resource://gre/modules/AppConstants.jsm", {});
 const {CustomizableUI} = Cu.import("resource:///modules/CustomizableUI.jsm", {});
 
 // We run tests under two different configurations, from browser.ini and
 // browser-remote.ini. When running from browser-remote.ini, the tests are
 // copied to the sub-directory "test-oop-extensions", which we detect here, and
@@ -343,8 +344,16 @@ function closePageAction(extension, win 
   if (node) {
     return promisePopupShown(node).then(() => {
       node.hidePopup();
     });
   }
 
   return Promise.resolve();
 }
+
+function promisePrefChangeObserved(pref) {
+  return new Promise((resolve, reject) =>
+    Preferences.observe(pref, function prefObserver() {
+      Preferences.ignore(pref, prefObserver);
+      resolve();
+    }));
+}