Bug 1426081 - Migrate legacy search engines to WebExtensions. r=florian a=gchang
authorMichael Kaply <mozilla@kaply.com>
Thu, 21 Dec 2017 12:58:56 -0600
changeset 445670 e47207b8927fc7ae26a77e6a6bb57f258b516946
parent 445669 dd18bd878644487d20fc5358d2fd924e1dda0825
child 445671 ae6c87e225d3820393a4b727be87a5a837205d72
push id1623
push userarchaeopteryx@coole-files.de
push dateMon, 15 Jan 2018 09:33:19 +0000
treeherdermozilla-release@4c230b89e05e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersflorian, gchang
bugs1426081
milestone58.0
Bug 1426081 - Migrate legacy search engines to WebExtensions. r=florian a=gchang MozReview-Commit-ID: JfSwJwMC46F
toolkit/components/search/nsSearchService.js
toolkit/components/search/tests/xpcshell/test_migrateWebExtensionEngine.js
toolkit/components/search/tests/xpcshell/xpcshell.ini
--- a/toolkit/components/search/nsSearchService.js
+++ b/toolkit/components/search/nsSearchService.js
@@ -3871,16 +3871,17 @@ SearchService.prototype = {
         return engine;
     }
     return null;
   },
 
   addEngineWithDetails: function SRCH_SVC_addEWD(aName, iconURL, alias,
                                                  description, method,
                                                  template, extensionID) {
+    let isCurrent = false;
     var params;
 
     if (iconURL && typeof iconURL == "object") {
       params = iconURL;
     } else {
       params = {
         iconURL,
         alias,
@@ -3891,26 +3892,38 @@ SearchService.prototype = {
       };
     }
 
     this._ensureInitialized();
     if (!aName)
       FAIL("Invalid name passed to addEngineWithDetails!");
     if (!params.template)
       FAIL("Invalid template passed to addEngineWithDetails!");
-    if (this._engines[aName])
-      FAIL("An engine with that name already exists!", Cr.NS_ERROR_FILE_ALREADY_EXISTS);
-
-    var engine = new Engine(sanitizeName(aName), false);
-    engine._initFromMetadata(aName, params);
-    engine._loadPath = "[other]addEngineWithDetails";
+    let existingEngine = this._engines[aName];
+    if (existingEngine) {
+      if (params.extensionID &&
+          existingEngine._loadPath.startsWith(`jar:[profile]/extensions/${params.extensionID}`)) {
+        // This is a legacy extension engine that needs to be migrated to WebExtensions.
+        isCurrent = this.currentEngine == existingEngine;
+        this.removeEngine(existingEngine);
+      } else {
+        FAIL("An engine with that name already exists!", Cr.NS_ERROR_FILE_ALREADY_EXISTS);
+      }
+    }
+
+    let newEngine = new Engine(sanitizeName(aName), false);
+    newEngine._initFromMetadata(aName, params);
+    newEngine._loadPath = "[other]addEngineWithDetails";
     if (params.extensionID) {
-      engine._loadPath += ":" + params.extensionID;
+      newEngine._loadPath += ":" + params.extensionID;
     }
-    this._addEngineToStore(engine);
+    this._addEngineToStore(newEngine);
+    if (isCurrent) {
+      this.currentEngine = newEngine;
+    }
   },
 
   addEngine: function SRCH_SVC_addEngine(aEngineURL, aDataType, aIconURL,
                                          aConfirm, aCallback, aExtensionID) {
     LOG("addEngine: Adding \"" + aEngineURL + "\".");
     this._ensureInitialized();
     try {
       var uri = makeURI(aEngineURL);
new file mode 100644
--- /dev/null
+++ b/toolkit/components/search/tests/xpcshell/test_migrateWebExtensionEngine.js
@@ -0,0 +1,37 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const kSearchEngineID = "addEngineWithDetails_test_engine";
+const kExtensionID = "test@example.com";
+
+const kSearchEngineDetails = {
+  template: "http://example.com/?search={searchTerms}",
+  description: "Test Description",
+  iconURL: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==",
+  suggestURL: "http://example.com/?suggest={searchTerms}",
+  alias: "alias_foo",
+  extensionID: kExtensionID,
+};
+
+
+add_task(async function test_migrateLegacyEngine() {
+  Assert.ok(!Services.search.isInitialized);
+
+  await asyncInit();
+
+  Services.search.addEngineWithDetails(kSearchEngineID, kSearchEngineDetails);
+
+  // Modify the loadpath so it looks like an legacy plugin loadpath
+  let engine = Services.search.getEngineByName(kSearchEngineID);
+  engine.wrappedJSObject._loadPath = `jar:[profile]/extensions/${kExtensionID}.xpi!/engine.xml`;
+  engine.wrappedJSObject._extensionID = null;
+
+  // This should replace the existing engine
+  Services.search.addEngineWithDetails(kSearchEngineID, kSearchEngineDetails);
+
+  engine = Services.search.getEngineByName(kSearchEngineID);
+  Assert.equal(engine.wrappedJSObject._loadPath, "[other]addEngineWithDetails:" + kExtensionID);
+  Assert.equal(engine.wrappedJSObject._extensionID, kExtensionID);
+});
--- a/toolkit/components/search/tests/xpcshell/xpcshell.ini
+++ b/toolkit/components/search/tests/xpcshell/xpcshell.ini
@@ -92,8 +92,9 @@ tags = addons
 [test_searchReset.js]
 [test_addEngineWithDetails.js]
 [test_addEngineWithDetailsObject.js]
 [test_addEngineWithExtensionID.js]
 [test_chromeresource_icon1.js]
 [test_chromeresource_icon2.js]
 [test_engineUpdate.js]
 [test_paramSubstitution.js]
+[test_migrateWebExtensionEngine.js]