Bug 1301315 - Add support for chrome_settings_overrides search engine. r=mixedpuppy
authorMichael Kaply <mozilla@kaply.com>
Fri, 02 Jun 2017 15:59:43 -0500
changeset 411152 faf77d75b2b079921f0067c92ee06a6636e63eed
parent 411151 5cb536ad2b36e2769546cce1707d11dbd7bacacc
child 411153 8344aaa080f46d8898a77d475503d8652a527daf
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmixedpuppy
bugs1301315
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1301315 - Add support for chrome_settings_overrides search engine. r=mixedpuppy MozReview-Commit-ID: IkpigS3wqs1
browser/components/extensions/ext-chrome-settings-overrides.js
browser/components/extensions/schemas/chrome_settings_overrides.json
browser/components/extensions/test/browser/browser-common.ini
browser/components/extensions/test/browser/browser_ext_settings_overrides_search.js
--- a/browser/components/extensions/ext-chrome-settings-overrides.js
+++ b/browser/components/extensions/ext-chrome-settings-overrides.js
@@ -2,25 +2,93 @@
  * 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";
 
 XPCOMUtils.defineLazyModuleGetter(this, "ExtensionPreferencesManager",
                                   "resource://gre/modules/ExtensionPreferencesManager.jsm");
 
+function searchInitialized() {
+  return new Promise(resolve => {
+    if (Services.search.isInitialized) {
+      resolve();
+    }
+    const SEARCH_SERVICE_TOPIC = "browser-search-service";
+    Services.obs.addObserver(function observer(subject, topic, data) {
+      if (data != "init-complete") {
+        return;
+      }
+
+      Services.obs.removeObserver(observer, SEARCH_SERVICE_TOPIC);
+      resolve();
+    }, SEARCH_SERVICE_TOPIC);
+  });
+}
+
 this.chrome_settings_overrides = class extends ExtensionAPI {
-  onManifestEntry(entryName) {
+  async onManifestEntry(entryName) {
     let {extension} = this;
     let {manifest} = extension;
 
     if (manifest.chrome_settings_overrides.homepage) {
       ExtensionPreferencesManager.setSetting(extension, "homepage_override",
                                              manifest.chrome_settings_overrides.homepage);
     }
+    if (manifest.chrome_settings_overrides.search_provider) {
+      await searchInitialized();
+      let searchProvider = manifest.chrome_settings_overrides.search_provider;
+      let isCurrent = false;
+      let index = -1;
+      if (extension.startupReason === "ADDON_UPGRADE") {
+        let engines = Services.search.getEnginesByExtensionID(extension.id);
+        if (engines.length > 0) {
+          // There can be only one engine right now
+          isCurrent = Services.search.currentEngine == engines[0];
+          // Get position of engine and store it
+          index = Services.search.getEngines().indexOf(engines[0]);
+          Services.search.removeEngine(engines[0]);
+        }
+      }
+      try {
+        Services.search.addEngineWithDetails(searchProvider.name.trim(),
+                                             searchProvider.favicon_url,
+                                             searchProvider.keyword, null,
+                                             "GET", searchProvider.search_url,
+                                             extension.id);
+        if (extension.startupReason === "ADDON_UPGRADE") {
+          let engine = Services.search.getEngineByName(searchProvider.name.trim());
+          if (isCurrent) {
+            Services.search.currentEngine = engine;
+          }
+          if (index != -1) {
+            Services.search.moveEngine(engine, index);
+          }
+        }
+      } catch (e) {
+        Components.utils.reportError(e);
+      }
+    }
+  }
+  async onShutdown(reason) {
+    let {extension} = this;
+    if (reason == "ADDON_DISABLE" ||
+        reason == "ADDON_UNINSTALL") {
+      if (extension.manifest.chrome_settings_overrides.search_provider) {
+        await searchInitialized();
+        let engines = Services.search.getEnginesByExtensionID(extension.id);
+        for (let engine of engines) {
+          try {
+            Services.search.removeEngine(engine);
+          } catch (e) {
+            Components.utils.reportError(e);
+          }
+        }
+      }
+    }
   }
 };
 
 ExtensionPreferencesManager.addSetting("homepage_override", {
   prefNames: [
     "browser.startup.homepage",
   ],
   setCallback(value) {
--- a/browser/components/extensions/schemas/chrome_settings_overrides.json
+++ b/browser/components/extensions/schemas/chrome_settings_overrides.json
@@ -10,16 +10,103 @@
             "optional": true,
             "additionalProperties": { "$ref": "UnrecognizedProperty" },
             "properties": {
               "homepage": {
                 "type": "string",
                 "format": "relativeUrl",
                 "optional": true,
                 "preprocess": "localize"
+              },
+             "search_provider": {
+                "type": "object",
+                "optional": true,
+                "additionalProperties": { "$ref": "UnrecognizedProperty" },
+                "properties": {
+                  "name": {
+                    "type": "string",
+                    "preprocess": "localize"
+                  },
+                  "keyword": {
+                    "type": "string",
+                    "optional": true,
+                    "preprocess": "localize"
+                  },
+                  "search_url": {
+                    "type": "string",
+                    "format": "url",
+                    "pattern": "^https://.*$",
+                    "preprocess": "localize"
+                  },
+                  "favicon_url": {
+                    "type": "string",
+                    "optional": true,
+                    "format": "url",
+                    "preprocess": "localize"
+                  },
+                  "suggest_url": {
+                    "type": "string",
+                    "optional": true,
+                    "format": "url",
+                    "preprocess": "localize",
+                    "deprecated": "Unsupported on Firefox at this time."
+                  },
+                  "instant_url": {
+                    "type": "string",
+                    "optional": true,
+                    "format": "url",
+                    "preprocess": "localize",
+                    "deprecated": "Unsupported on Firefox at this time."
+                  },
+                  "image_url": {
+                    "type": "string",
+                    "optional": true,
+                    "format": "url",
+                    "preprocess": "localize",
+                    "deprecated": "Unsupported on Firefox at this time."
+                  },
+                  "search_url_post_params": {
+                    "type": "string",
+                    "optional": true,
+                    "preprocess": "localize",
+                    "deprecated": "Unsupported on Firefox at this time."
+                  },
+                  "instant_url_post_params": {
+                    "type": "string",
+                    "optional": true,
+                    "preprocess": "localize",
+                    "deprecated": "Unsupported on Firefox at this time."
+                  },
+                  "image_url_post_params": {
+                    "type": "string",
+                    "optional": true,
+                    "preprocess": "localize",
+                    "deprecated": "Unsupported on Firefox at this time."
+                  },
+                  "alternate_urls": {
+                    "type": "array",
+                    "items": {
+                      "type": "string",
+                      "format": "url",
+                      "preprocess": "localize"
+                    },
+                    "optional": true,
+                    "deprecated": "Unsupported on Firefox at this time."
+                  },
+                  "prepopulated_id": {
+                    "type": "integer",
+                    "optional": true,
+                    "deprecated": "Unsupported on Firefox."
+                  },
+                  "is_default": {
+                    "type": "boolean",
+                    "optional": true,
+                    "deprecated": "Unsupported on Firefox at this time."
+                  }
+                }
               }
             }
           }
         }
       }
     ]
   }
 ]
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ b/browser/components/extensions/test/browser/browser-common.ini
@@ -91,16 +91,17 @@ skip-if = debug || asan # Bug 1354681
 [browser_ext_runtime_openOptionsPage_uninstall.js]
 [browser_ext_runtime_setUninstallURL.js]
 [browser_ext_sessions_forgetClosedTab.js]
 [browser_ext_sessions_forgetClosedWindow.js]
 [browser_ext_sessions_getRecentlyClosed.js]
 [browser_ext_sessions_getRecentlyClosed_private.js]
 [browser_ext_sessions_getRecentlyClosed_tabs.js]
 [browser_ext_sessions_restore.js]
+[browser_ext_settings_overrides_search.js]
 [browser_ext_sidebarAction.js]
 [browser_ext_sidebarAction_browser_style.js]
 [browser_ext_sidebarAction_context.js]
 [browser_ext_sidebarAction_contextMenu.js]
 [browser_ext_sidebarAction_tabs.js]
 [browser_ext_sidebarAction_windows.js]
 [browser_ext_simple.js]
 [browser_ext_tab_runtimeConnect.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_settings_overrides_search.js
@@ -0,0 +1,114 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+
+"use strict";
+
+add_task(async function test_extension_adding_engine() {
+  let ext1 = ExtensionTestUtils.loadExtension({
+    manifest: {
+      "chrome_settings_overrides": {
+        "search_provider": {
+             "name": "MozSearch",
+             "keyword": "MozSearch",
+             "search_url": "https://example.com/?q={searchTerms}",
+        },
+      },
+    },
+    useAddonManager: "temporary",
+  });
+
+  await ext1.startup();
+
+  let engine = Services.search.getEngineByName("MozSearch");
+  ok(engine, "Engine should exist.");
+
+  await ext1.unload();
+
+  engine = Services.search.getEngineByName("MozSearch");
+  ok(!engine, "Engine should not exist");
+});
+
+add_task(async function test_extension_adding_engine_with_spaces() {
+  let ext1 = ExtensionTestUtils.loadExtension({
+    manifest: {
+      "chrome_settings_overrides": {
+        "search_provider": {
+             "name": "MozSearch     ",
+             "keyword": "MozSearch",
+             "search_url": "https://example.com/?q={searchTerms}",
+        },
+      },
+    },
+    useAddonManager: "temporary",
+  });
+
+  await ext1.startup();
+
+  let engine = Services.search.getEngineByName("MozSearch");
+  ok(engine, "Engine should exist.");
+
+  await ext1.unload();
+
+  engine = Services.search.getEngineByName("MozSearch");
+  ok(!engine, "Engine should not exist");
+});
+
+
+add_task(async function test_upgrade_default_position_engine() {
+  let ext1 = ExtensionTestUtils.loadExtension({
+    manifest: {
+      "chrome_settings_overrides": {
+        "search_provider": {
+             "name": "MozSearch",
+             "keyword": "MozSearch",
+             "search_url": "https://example.com/?q={searchTerms}",
+        },
+      },
+      "applications": {
+        "gecko": {
+           "id": "testengine@mozilla.com",
+        },
+      },
+      "version": "0.1",
+    },
+    useAddonManager: "temporary",
+  });
+
+  let ext2 = ExtensionTestUtils.loadExtension({
+    manifest: {
+      "chrome_settings_overrides": {
+        "search_provider": {
+             "name": "MozSearch",
+             "keyword": "MozSearch",
+             "search_url": "https://example.com/?q={searchTerms}",
+        },
+      },
+      "applications": {
+        "gecko": {
+           "id": "testengine@mozilla.com",
+        },
+      },
+      "version": "0.2",
+    },
+    useAddonManager: "temporary",
+  });
+
+  await ext1.startup();
+
+  let engine = Services.search.getEngineByName("MozSearch");
+  Services.search.currentEngine = engine;
+  Services.search.moveEngine(engine, 1);
+
+  await ext2.startup();
+
+  engine = Services.search.getEngineByName("MozSearch");
+  is(Services.search.currentEngine, engine, "Default engine should still be MozSearch");
+  is(Services.search.getEngines().indexOf(engine), 1, "Engine is in position 1");
+
+  await ext2.unload();
+  await ext1.unload();
+
+  engine = Services.search.getEngineByName("MozSearch");
+  ok(!engine, "Engine should not exist");
+});
+