Bug 1426081 - Migrate legacy search engines to WebExtensions. r?florian draft
authorMichael Kaply <mozilla@kaply.com>
Thu, 21 Dec 2017 12:58:56 -0600
changeset 717300 2acbc26e135728653b12ac477b899ff76e896247
parent 716325 81362f7306fe413b19fdba27cd0e9a5525d902e1
child 745197 ba85e73e77f5dd936aff8d42634ca18ed0c86f4e
push id94612
push usermozilla@kaply.com
push dateMon, 08 Jan 2018 14:45:13 +0000
reviewersflorian
bugs1426081
milestone59.0a1
Bug 1426081 - Migrate legacy search engines to WebExtensions. r?florian 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]