Bug 1492475 - Part 10: Update unit tests to be fully aware of the new, async signatures of the search service API and remove sync init flow tests. r=mkaply,florian
authorMike de Boer <mdeboer@mozilla.com>
Wed, 17 Oct 2018 11:09:34 +0200
changeset 452872 21b3aa17ee43dd0efd3c08564bbc7d747d4628b9
parent 452871 6c79eaf1d349638258d542ced0229d786f022683
child 452873 ce5ba6901957903ade31888cdc6a52e2b828dac0
push id2
push usermdeboer@mozilla.com
push dateTue, 08 Jan 2019 17:01:21 +0000
reviewersmkaply, florian
bugs1492475
milestone66.0a1
Bug 1492475 - Part 10: Update unit tests to be fully aware of the new, async signatures of the search service API and remove sync init flow tests. r=mkaply,florian Differential Revision: https://phabricator.services.mozilla.com/D9282
browser/base/content/test/about/browser_aboutHome_search_POST.js
browser/base/content/test/about/browser_aboutHome_search_composing.js
browser/base/content/test/about/browser_aboutHome_search_suggestion.js
browser/base/content/test/about/browser_aboutHome_search_telemetry.js
browser/base/content/test/about/head.js
browser/base/content/test/general/browser_contentSearchUI.js
browser/base/content/test/general/browser_keywordSearch.js
browser/base/content/test/general/browser_keywordSearch_postData.js
browser/base/content/test/general/browser_newTabDrop.js
browser/base/content/test/general/browser_newWindowDrop.js
browser/base/content/test/general/browser_tabDrop.js
browser/base/content/test/performance/browser_urlbar_keyed_search.js
browser/base/content/test/performance/browser_urlbar_search.js
browser/base/content/test/urlbar/browser_action_searchengine.js
browser/base/content/test/urlbar/browser_action_searchengine_alias.js
browser/base/content/test/urlbar/browser_autocomplete_a11y_label.js
browser/base/content/test/urlbar/browser_autocomplete_enter_race.js
browser/base/content/test/urlbar/browser_canonizeURL.js
browser/base/content/test/urlbar/browser_dragdropURL.js
browser/base/content/test/urlbar/browser_page_action_menu_add_search_engine.js
browser/base/content/test/urlbar/browser_search_favicon.js
browser/base/content/test/urlbar/browser_urlbarAddonIframe.js
browser/base/content/test/urlbar/browser_urlbarOneOffs.js
browser/base/content/test/urlbar/browser_urlbarOneOffs_searchSuggestions.js
browser/base/content/test/urlbar/browser_urlbarOneOffs_settings.js
browser/base/content/test/urlbar/browser_urlbarPlaceholder.js
browser/base/content/test/urlbar/browser_urlbarSearchSingleWordNotification.js
browser/base/content/test/urlbar/browser_urlbarSearchSuggestions.js
browser/base/content/test/urlbar/browser_urlbarSearchSuggestions_opt-out.js
browser/base/content/test/urlbar/browser_urlbarSearchTelemetry.js
browser/base/content/test/urlbar/browser_urlbarStopSearchOnSelection.js
browser/base/content/test/urlbar/browser_urlbarTokenAlias.js
browser/base/content/test/urlbar/browser_urlbar_search_speculative_connect_engine.js
browser/components/enterprisepolicies/tests/browser/browser_policy_search_engine.js
browser/components/enterprisepolicies/tests/browser/head.js
browser/components/extensions/test/browser/browser-common.ini
browser/components/extensions/test/browser/browser_ext_browserAction_contextMenu.js
browser/components/extensions/test/browser/browser_ext_omnibox.js
browser/components/extensions/test/browser/browser_ext_search.js
browser/components/extensions/test/browser/browser_ext_settings_overrides_default_search.js
browser/components/extensions/test/browser/browser_ext_webNavigation_urlbar_transitions.js
browser/components/extensions/test/xpcshell/test_ext_chrome_settings_overrides_update.js
browser/components/extensions/test/xpcshell/test_ext_settings_overrides_search.js
browser/components/extensions/test/xpcshell/test_ext_settings_overrides_search_mozParam.js
browser/components/newtab/test/browser/browser_asrouter_targeting.js
browser/components/newtab/test/unit/lib/TopSitesFeed.test.js
browser/components/preferences/in-content/tests/browser_engines.js
browser/components/preferences/in-content/tests/browser_extension_controlled.js
browser/components/search/test/browser/SearchTestUtils.jsm
browser/components/search/test/browser/browser_426329.js
browser/components/search/test/browser/browser_addEngine.js
browser/components/search/test/browser/browser_amazon.js
browser/components/search/test/browser/browser_bing.js
browser/components/search/test/browser/browser_contextmenu.js
browser/components/search/test/browser/browser_ddg.js
browser/components/search/test/browser/browser_eBay.js
browser/components/search/test/browser/browser_google.js
browser/components/search/test/browser/browser_google_behavior.js
browser/components/search/test/browser/browser_hiddenOneOffs_cleanup.js
browser/components/search/test/browser/browser_hiddenOneOffs_diacritics.js
browser/components/search/test/browser/browser_oneOffContextMenu_setDefault.js
browser/components/search/test/browser/browser_oneOffHeader.js
browser/components/search/test/browser/browser_searchEngine_behaviors.js
browser/components/search/test/browser/head.js
browser/components/tests/unit/test_distribution.js
browser/components/uitour/test/browser_UITour.js
browser/components/uitour/test/browser_UITour3.js
browser/components/urlbar/tests/unit/test_UrlbarUtils_getShortcutOrURIAndPostData.js
browser/modules/test/browser/browser_ContentSearch.js
browser/modules/test/browser/browser_UsageTelemetry_content.js
browser/modules/test/browser/browser_UsageTelemetry_content_aboutHome.js
browser/modules/test/browser/browser_UsageTelemetry_searchbar.js
browser/modules/test/browser/browser_UsageTelemetry_urlbar.js
docshell/test/browser/browser_search_notification.js
docshell/test/browser/browser_uriFixupIntegration.js
docshell/test/unit/test_nsDefaultURIFixup_info.js
docshell/test/unit/test_nsDefaultURIFixup_search.js
toolkit/components/places/tests/unifiedcomplete/head_autocomplete.js
toolkit/components/places/tests/unifiedcomplete/test_PlacesSearchAutocompleteProvider.js
toolkit/components/places/tests/unifiedcomplete/test_autofill_search_engine_aliases.js
toolkit/components/places/tests/unifiedcomplete/test_autofill_search_engines.js
toolkit/components/places/tests/unifiedcomplete/test_avoid_middle_complete.js
toolkit/components/places/tests/unifiedcomplete/test_search_engine_alias.js
toolkit/components/places/tests/unifiedcomplete/test_search_engine_current.js
toolkit/components/places/tests/unifiedcomplete/test_search_engine_host.js
toolkit/components/places/tests/unifiedcomplete/test_search_engine_restyle.js
toolkit/components/places/tests/unifiedcomplete/test_search_suggestions.js
toolkit/components/search/tests/xpcshell/head_search.js
toolkit/components/search/tests/xpcshell/test_645970.js
toolkit/components/search/tests/xpcshell/test_addEngineWithDetails.js
toolkit/components/search/tests/xpcshell/test_addEngineWithDetailsObject.js
toolkit/components/search/tests/xpcshell/test_addEngineWithExtensionID.js
toolkit/components/search/tests/xpcshell/test_addEngine_callback.js
toolkit/components/search/tests/xpcshell/test_async.js
toolkit/components/search/tests/xpcshell/test_async_addon.js
toolkit/components/search/tests/xpcshell/test_async_addon_no_override.js
toolkit/components/search/tests/xpcshell/test_async_disthidden.js
toolkit/components/search/tests/xpcshell/test_async_distribution.js
toolkit/components/search/tests/xpcshell/test_async_profile_engine.js
toolkit/components/search/tests/xpcshell/test_big_icon.js
toolkit/components/search/tests/xpcshell/test_currentEngine_fallback.js
toolkit/components/search/tests/xpcshell/test_defaultEngine.js
toolkit/components/search/tests/xpcshell/test_engineUpdate.js
toolkit/components/search/tests/xpcshell/test_engine_set_alias.js
toolkit/components/search/tests/xpcshell/test_hasEngineWithURL.js
toolkit/components/search/tests/xpcshell/test_hidden.js
toolkit/components/search/tests/xpcshell/test_identifiers.js
toolkit/components/search/tests/xpcshell/test_ignorelist.js
toolkit/components/search/tests/xpcshell/test_init_async_multiple.js
toolkit/components/search/tests/xpcshell/test_init_async_multiple_then_sync.js
toolkit/components/search/tests/xpcshell/test_invalid_engine_from_dir.js
toolkit/components/search/tests/xpcshell/test_json_cache.js
toolkit/components/search/tests/xpcshell/test_json_cache_ignorelist.js
toolkit/components/search/tests/xpcshell/test_list_json_locale.js
toolkit/components/search/tests/xpcshell/test_list_json_searchdefault_distro.js
toolkit/components/search/tests/xpcshell/test_list_json_searchorder.js
toolkit/components/search/tests/xpcshell/test_location.js
toolkit/components/search/tests/xpcshell/test_location_error.js
toolkit/components/search/tests/xpcshell/test_location_malformed_json.js
toolkit/components/search/tests/xpcshell/test_location_sync.js
toolkit/components/search/tests/xpcshell/test_location_timeout.js
toolkit/components/search/tests/xpcshell/test_location_timeout_xhr.js
toolkit/components/search/tests/xpcshell/test_migrateWebExtensionEngine.js
toolkit/components/search/tests/xpcshell/test_multipleIcons.js
toolkit/components/search/tests/xpcshell/test_nocache.js
toolkit/components/search/tests/xpcshell/test_nodb_pluschanges.js
toolkit/components/search/tests/xpcshell/test_parseSubmissionURL.js
toolkit/components/search/tests/xpcshell/test_purpose.js
toolkit/components/search/tests/xpcshell/test_remove_profile_engine.js
toolkit/components/search/tests/xpcshell/test_require_engines_in_cache.js
toolkit/components/search/tests/xpcshell/test_save_sorted_engines.js
toolkit/components/search/tests/xpcshell/test_selectedEngine.js
toolkit/components/search/tests/xpcshell/test_sendSubmissionURL.js
toolkit/components/search/tests/xpcshell/test_sync.js
toolkit/components/search/tests/xpcshell/test_sync_addon.js
toolkit/components/search/tests/xpcshell/test_sync_addon_no_override.js
toolkit/components/search/tests/xpcshell/test_sync_delay_fallback.js
toolkit/components/search/tests/xpcshell/test_sync_disthidden.js
toolkit/components/search/tests/xpcshell/test_sync_distribution.js
toolkit/components/search/tests/xpcshell/test_sync_fallback.js
toolkit/components/search/tests/xpcshell/test_sync_profile_engine.js
toolkit/components/search/tests/xpcshell/xpcshell.ini
toolkit/components/telemetry/tests/unit/head.js
toolkit/components/telemetry/tests/unit/test_SubsessionChaining.js
toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js
toolkit/components/telemetry/tests/unit/test_TelemetrySession.js
--- a/browser/base/content/test/about/browser_aboutHome_search_POST.js
+++ b/browser/base/content/test/about/browser_aboutHome_search_POST.js
@@ -5,34 +5,33 @@
 ignoreAllUncaughtExceptions();
 
 add_task(async function() {
   info("Check POST search engine support");
 
   await BrowserTestUtils.withNewTab({ gBrowser, url: "about:home" }, function(browser) {
     return new Promise(resolve => {
       let searchObserver = async function search_observer(subject, topic, data) {
-        let currEngine = Services.search.defaultEngine;
+        let currEngine = await Services.search.getDefault();
         let engine = subject.QueryInterface(Ci.nsISearchEngine);
         info("Observer: " + data + " for " + engine.name);
 
         if (data != "engine-added")
           return;
 
         if (engine.name != "POST Search")
           return;
 
         Services.obs.removeObserver(searchObserver, "browser-search-engine-modified");
 
         // Ready to execute the tests!
         let needle = "Search for something awesome.";
 
-        let p = promiseContentSearchChange(browser, engine.name);
-        Services.search.defaultEngine = engine;
-        await p;
+        await Promise.all([promiseContentSearchChange(browser, engine.name),
+          Services.search.setDefault(engine)]);
         let promise = BrowserTestUtils.browserLoaded(browser);
         await ContentTask.spawn(browser, { needle }, async function(args) {
           let doc = content.document;
           let el = doc.querySelector(["#searchText", "#newtab-search-text"]);
           el.value = args.needle;
           doc.getElementById("searchSubmit").click();
         });
 
@@ -41,19 +40,19 @@ add_task(async function() {
         // When the search results load, check them for correctness.
         await ContentTask.spawn(browser, { needle }, async function(args) {
           let loadedText = content.document.body.textContent;
           ok(loadedText, "search page loaded");
           is(loadedText, "searchterms=" + escape(args.needle.replace(/\s/g, "+")),
              "Search text should arrive correctly");
         });
 
-        Services.search.defaultEngine = currEngine;
+        await Services.search.setDefault(currEngine);
         try {
-          Services.search.removeEngine(engine);
+          await Services.search.removeEngine(engine);
         } catch (ex) {}
         resolve();
       };
       Services.obs.addObserver(searchObserver, "browser-search-engine-modified");
       Services.search.addEngine("http://test:80/browser/browser/base/content/test/about/POSTSearchEngine.xml",
                                 null, false);
     });
   });
--- a/browser/base/content/test/about/browser_aboutHome_search_composing.js
+++ b/browser/base/content/test/about/browser_aboutHome_search_composing.js
@@ -4,20 +4,20 @@
 
 ignoreAllUncaughtExceptions();
 
 add_task(async function() {
   info("Clicking suggestion list while composing");
 
   await BrowserTestUtils.withNewTab({ gBrowser, url: "about:home" }, async function(browser) {
     // Add a test engine that provides suggestions and switch to it.
-    let currEngine = Services.search.defaultEngine;
+    let currEngine = await Services.search.getDefault();
     let engine = await promiseNewEngine("searchSuggestionEngine.xml");
     let p = promiseContentSearchChange(browser, engine.name);
-    Services.search.defaultEngine = engine;
+    await Services.search.setDefault(engine);
     await p;
 
     await ContentTask.spawn(browser, null, async function() {
       // Start composition and type "x"
       let input = content.document.querySelector(["#searchText", "#newtab-search-text"]);
       input.focus();
     });
 
@@ -63,22 +63,21 @@ add_task(async function() {
       },
       caret: { start: 1, length: 0 },
     }, browser);
 
     info("Waiting for search suggestion table unhidden");
     await mutationPromise;
 
     // Click the second suggestion.
-    let expectedURL = Services.search.defaultEngine
-      .getSubmission("xbar", null, "homepage").uri.spec;
+    let expectedURL = (await Services.search.getDefault()).getSubmission("xbar", null, "homepage").uri.spec;
     let loadPromise = waitForDocLoadAndStopIt(expectedURL);
     await BrowserTestUtils.synthesizeMouseAtCenter("#TEMPID", {
       button: 0,
     }, browser);
     await loadPromise;
 
-    Services.search.defaultEngine = currEngine;
+    Services.search.setDefault(currEngine);
     try {
-      Services.search.removeEngine(engine);
+      await Services.search.removeEngine(engine);
     } catch (ex) { }
   });
 });
--- a/browser/base/content/test/about/browser_aboutHome_search_suggestion.js
+++ b/browser/base/content/test/about/browser_aboutHome_search_suggestion.js
@@ -5,21 +5,20 @@
 ignoreAllUncaughtExceptions();
 
 add_task(async function() {
   // See browser_contentSearchUI.js for comprehensive content search UI tests.
   info("Search suggestion smoke test");
 
   await BrowserTestUtils.withNewTab({ gBrowser, url: "about:home" }, async function(browser) {
     // Add a test engine that provides suggestions and switch to it.
-    let currEngine = Services.search.defaultEngine;
+    let currEngine = await Services.search.getDefault();
     let engine = await promiseNewEngine("searchSuggestionEngine.xml");
-    let p = promiseContentSearchChange(browser, engine.name);
-    Services.search.defaultEngine = engine;
-    await p;
+    await Promise.all([promiseContentSearchChange(browser, engine.name),
+      Services.search.setDefault(engine)]);
 
     await ContentTask.spawn(browser, null, async function() {
       // Type an X in the search input.
       let input = content.document.querySelector(["#searchText", "#newtab-search-text"]);
       input.focus();
     });
 
     await BrowserTestUtils.synthesizeKey("x", {}, browser);
@@ -49,14 +48,14 @@ add_task(async function() {
     await BrowserTestUtils.synthesizeKey("VK_DELETE", {}, browser);
 
     await ContentTask.spawn(browser, null, async function() {
       let table = content.document.getElementById("searchSuggestionTable");
       await ContentTaskUtils.waitForCondition(() => table.hidden,
         "Search suggestion table hidden");
     });
 
-    Services.search.defaultEngine = currEngine;
+    await Services.search.setDefault(currEngine);
     try {
-      Services.search.removeEngine(engine);
+      await Services.search.removeEngine(engine);
     } catch (ex) { }
   });
 });
--- a/browser/base/content/test/about/browser_aboutHome_search_telemetry.js
+++ b/browser/base/content/test/about/browser_aboutHome_search_telemetry.js
@@ -3,25 +3,24 @@
  */
 
 ignoreAllUncaughtExceptions();
 
 add_task(async function() {
   info("Check that performing a search fires a search event and records to Telemetry.");
 
   await BrowserTestUtils.withNewTab({ gBrowser, url: "about:home" }, async function(browser) {
-    let currEngine = Services.search.defaultEngine;
+    let currEngine = await Services.search.getDefault();
     let engine = await promiseNewEngine("searchSuggestionEngine.xml");
     // Make this actually work in healthreport by giving it an ID:
     Object.defineProperty(engine.wrappedJSObject, "identifier",
                           { value: "org.mozilla.testsearchsuggestions" });
 
-    let p = promiseContentSearchChange(browser, engine.name);
-    Services.search.defaultEngine = engine;
-    await p;
+    await Promise.all([promiseContentSearchChange(browser, engine.name),
+      Services.search.setDefault(engine)]);
 
     await ContentTask.spawn(browser, { expectedName: engine.name }, async function(args) {
       let engineName = content.wrappedJSObject.gContentSearchController.defaultEngine.name;
       is(engineName, args.expectedName, "Engine name in DOM should match engine we just added");
     });
 
     let numSearchesBefore = 0;
     // Get the current number of recorded searches.
@@ -32,18 +31,17 @@ add_task(async function() {
         numSearchesBefore = hs[histogramKey].sum;
       }
     } catch (ex) {
       // No searches performed yet, not a problem, |numSearchesBefore| is 0.
     }
 
     let searchStr = "a search";
 
-    let expectedURL = Services.search.defaultEngine
-      .getSubmission(searchStr, null, "homepage").uri.spec;
+    let expectedURL = (await Services.search.getDefault()).getSubmission(searchStr, null, "homepage").uri.spec;
     let promise = waitForDocLoadAndStopIt(expectedURL, browser);
 
     // Perform a search to increase the SEARCH_COUNT histogram.
     await ContentTask.spawn(browser, { searchStr }, async function(args) {
       let doc = content.document;
       info("Perform a search.");
       let el = doc.querySelector(["#searchText", "#newtab-search-text"]);
       el.value = args.searchStr;
@@ -53,14 +51,14 @@ add_task(async function() {
     await promise;
 
     // Make sure the SEARCH_COUNTS histogram has the right key and count.
     let hs = Services.telemetry.getKeyedHistogramById("SEARCH_COUNTS").snapshot();
     Assert.ok(histogramKey in hs, "histogram with key should be recorded");
     Assert.equal(hs[histogramKey].sum, numSearchesBefore + 1,
                  "histogram sum should be incremented");
 
-    Services.search.defaultEngine = currEngine;
+    await Services.search.setDefault(currEngine);
     try {
-      Services.search.removeEngine(engine);
+      await Services.search.removeEngine(engine);
     } catch (ex) {}
   });
 });
--- a/browser/base/content/test/about/head.js
+++ b/browser/base/content/test/about/head.js
@@ -222,29 +222,28 @@ function promiseContentSearchChange(brow
       });
     });
   });
 }
 
 /**
  * Wait for the search engine to be added.
  */
-function promiseNewEngine(basename) {
+async function promiseNewEngine(basename) {
   info("Waiting for engine to be added: " + basename);
-  return new Promise((resolve, reject) => {
-    let url = getRootDirectory(gTestPath) + basename;
-    Services.search.addEngine(url, "", false, {
-      onSuccess(engine) {
-        info("Search engine added: " + basename);
-        registerCleanupFunction(() => {
-          try {
-            Services.search.removeEngine(engine);
-          } catch (ex) { /* Can't remove the engine more than once */ }
-        });
-        resolve(engine);
-      },
-      onError(errCode) {
-        ok(false, "addEngine failed with error code " + errCode);
-        reject();
-      },
-    });
+  let url = getRootDirectory(gTestPath) + basename;
+  let engine;
+  try {
+    engine = await Services.search.addEngine(url, "", false);
+  } catch (errCode) {
+    ok(false, "addEngine failed with error code " + errCode);
+    throw errCode;
+  }
+
+  info("Search engine added: " + basename);
+  registerCleanupFunction(async () => {
+    try {
+      await Services.search.removeEngine(engine);
+    } catch (ex) { /* Can't remove the engine more than once */ }
   });
+
+  return engine;
 }
--- a/browser/base/content/test/general/browser_contentSearchUI.js
+++ b/browser/base/content/test/general/browser_contentSearchUI.js
@@ -732,26 +732,26 @@ function promiseMsg(name, type, msgMan) 
       }
     });
   });
 }
 
 function setUpEngines() {
   return (async function() {
     info("Removing default search engines");
-    let currentEngineName = Services.search.defaultEngine.name;
-    let currentEngines = Services.search.getVisibleEngines();
+    let currentEngineName = (await Services.search.getDefault()).name;
+    let currentEngines = await Services.search.getVisibleEngines();
     info("Adding test search engines");
     let rootDir = getRootDirectory(gTestPath);
     let engine1 = await SearchTestUtils.promiseNewSearchEngine(
       rootDir + TEST_ENGINE_BASENAME);
     await SearchTestUtils.promiseNewSearchEngine(
       rootDir + TEST_ENGINE_2_BASENAME);
-    Services.search.defaultEngine = engine1;
+    await Services.search.setDefault(engine1);
     for (let engine of currentEngines) {
-      Services.search.removeEngine(engine);
+      await Services.search.removeEngine(engine);
     }
-    registerCleanupFunction(() => {
+    registerCleanupFunction(async () => {
       Services.search.restoreDefaultEngines();
-      Services.search.defaultEngine = Services.search.getEngineByName(currentEngineName);
+      await Services.search.setDefault(Services.search.getEngineByName(currentEngineName));
     });
   })();
 }
--- a/browser/base/content/test/general/browser_keywordSearch.js
+++ b/browser/base/content/test/general/browser_keywordSearch.js
@@ -86,17 +86,17 @@ function test() {
 
   registerCleanupFunction(function() {
     Services.ww.unregisterNotification(windowObserver);
 
     gBrowser.removeProgressListener(listener);
     gBrowser.removeTab(tab);
   });
 
-  nextTest();
+  Services.search.init().then(nextTest);
 }
 
 var gCurrTest;
 function nextTest() {
   if (gTests.length) {
     gCurrTest = gTests.shift();
     doTest();
   } else {
--- a/browser/base/content/test/general/browser_keywordSearch_postData.js
+++ b/browser/base/content/test/general/browser_keywordSearch_postData.js
@@ -16,32 +16,32 @@ var gTests = [
   },
 ];
 
 add_task(async function setup() {
   let engineAddedPromise = TestUtils.topicObserved("browser-search-engine-modified", (subject, data) => {
     return data == "engine-added";
   });
 
-  Services.search.addEngine("http://test:80/browser/browser/base/content/test/general/POSTSearchEngine.xml",
-                            null, false);
+  const url = "http://test:80/browser/browser/base/content/test/general/POSTSearchEngine.xml";
+  await Services.search.addEngine(url, null, false);
 
   let [subject, data] = await engineAddedPromise;
 
   let engine = subject.QueryInterface(Ci.nsISearchEngine);
   info("Observer: " + data + " for " + engine.name);
 
   if (engine.name != "POST Search") {
     Assert.ok(false, "Wrong search engine added");
   }
 
-  Services.search.defaultEngine = engine;
+  await Services.search.setDefault(engine);
 
-  registerCleanupFunction(function() {
-    Services.search.removeEngine(engine);
+  registerCleanupFunction(async function() {
+    await Services.search.removeEngine(engine);
   });
 });
 
 add_task(async function() {
   for (let test of gTests) {
     let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
     let browser = tab.linkedBrowser;
 
--- a/browser/base/content/test/general/browser_newTabDrop.js
+++ b/browser/base/content/test/general/browser_newTabDrop.js
@@ -1,30 +1,30 @@
 const ANY_URL = undefined;
 
 registerCleanupFunction(async function cleanup() {
   while (gBrowser.tabs.length > 1) {
     BrowserTestUtils.removeTab(gBrowser.tabs[gBrowser.tabs.length - 1]);
   }
-  Services.search.defaultEngine = originalEngine;
+  await Services.search.setDefault(originalEngine);
   let engine = Services.search.getEngineByName("MozSearch");
-  Services.search.removeEngine(engine);
+  await Services.search.removeEngine(engine);
 });
 
 let originalEngine;
 add_task(async function test_setup() {
   // This test opens multiple tabs and some confirm dialogs, that takes long.
   requestLongerTimeout(2);
 
   // Stop search-engine loads from hitting the network
-  Services.search.addEngineWithDetails("MozSearch", "", "", "", "GET",
-                                       "http://example.com/?q={searchTerms}");
+  await Services.search.addEngineWithDetails("MozSearch", "", "", "", "GET",
+    "http://example.com/?q={searchTerms}");
   let engine = Services.search.getEngineByName("MozSearch");
-  originalEngine = Services.search.defaultEngine;
-  Services.search.defaultEngine = engine;
+  originalEngine = await Services.search.getDefault();
+  await Services.search.setDefault(engine);
 });
 
 // New Tab Button opens any link.
 add_task(async function single_url() {
   await dropText("mochi.test/first",
                  ["http://www.mochi.test/first"]);
 });
 add_task(async function single_javascript() {
--- a/browser/base/content/test/general/browser_newWindowDrop.js
+++ b/browser/base/content/test/general/browser_newWindowDrop.js
@@ -1,25 +1,25 @@
-registerCleanupFunction(function cleanup() {
-  Services.search.defaultEngine = originalEngine;
+registerCleanupFunction(async function cleanup() {
+  await Services.search.setDefault(originalEngine);
   let engine = Services.search.getEngineByName("MozSearch");
-  Services.search.removeEngine(engine);
+  await Services.search.removeEngine(engine);
 });
 
 let originalEngine;
 add_task(async function test_setup() {
   // Opening multiple windows on debug build takes too long time.
   requestLongerTimeout(10);
 
   // Stop search-engine loads from hitting the network
-  Services.search.addEngineWithDetails("MozSearch", "", "", "", "GET",
-                                       "http://example.com/?q={searchTerms}");
+  await Services.search.addEngineWithDetails("MozSearch", "", "", "", "GET",
+    "http://example.com/?q={searchTerms}");
   let engine = Services.search.getEngineByName("MozSearch");
-  originalEngine = Services.search.defaultEngine;
-  Services.search.defaultEngine = engine;
+  originalEngine = await Services.search.getDefault();
+  await Services.search.setDefault(engine);
 
   // Move New Window button to nav bar, to make it possible to drag and drop.
   let {CustomizableUI} = ChromeUtils.import("resource:///modules/CustomizableUI.jsm", {});
   let origPlacement = CustomizableUI.getPlacementOfWidget("new-window-button");
   if (!origPlacement || origPlacement.area != CustomizableUI.AREA_NAVBAR) {
     CustomizableUI.addWidgetToArea("new-window-button",
                                    CustomizableUI.AREA_NAVBAR,
                                    0);
--- a/browser/base/content/test/general/browser_tabDrop.js
+++ b/browser/base/content/test/general/browser_tabDrop.js
@@ -1,27 +1,27 @@
 const ANY_URL = undefined;
 
 registerCleanupFunction(async function cleanup() {
   while (gBrowser.tabs.length > 1) {
     BrowserTestUtils.removeTab(gBrowser.tabs[gBrowser.tabs.length - 1]);
   }
-  Services.search.defaultEngine = originalEngine;
+  await Services.search.setDefault(originalEngine);
   let engine = Services.search.getEngineByName("MozSearch");
-  Services.search.removeEngine(engine);
+  await Services.search.removeEngine(engine);
 });
 
 let originalEngine;
 add_task(async function test_setup() {
   // Stop search-engine loads from hitting the network
-  Services.search.addEngineWithDetails("MozSearch", "", "", "", "GET",
-                                       "http://example.com/?q={searchTerms}");
+  await Services.search.addEngineWithDetails("MozSearch", "", "", "", "GET",
+    "http://example.com/?q={searchTerms}");
   let engine = Services.search.getEngineByName("MozSearch");
-  originalEngine = Services.search.defaultEngine;
-  Services.search.defaultEngine = engine;
+  originalEngine = await Services.search.getDefault();
+  await Services.search.setDefault(engine);
 });
 
 add_task(async function single_url() {
   await dropText("mochi.test/first",
                  ["http://www.mochi.test/first"]);
 });
 add_task(async function single_javascript() {
   await dropText("javascript:'bad'", []);
--- a/browser/base/content/test/performance/browser_urlbar_keyed_search.js
+++ b/browser/base/content/test/performance/browser_urlbar_keyed_search.js
@@ -11,31 +11,33 @@ requestLongerTimeout(5);
  * be modifying your code to avoid the reflow.
  *
  * See https://developer.mozilla.org/en-US/Firefox/Performance_best_practices_for_Firefox_fe_engineers
  * for tips on how to do that.
  */
 
 /* These reflows happen only the first time the awesomebar panel opens. */
 const EXPECTED_REFLOWS_FIRST_OPEN = [];
-if (AppConstants.DEBUG ||
-    AppConstants.platform == "win" ||
-    AppConstants.platform == "macosx") {
+if (AppConstants.platform != "macosx" &&
+    (AppConstants.DEBUG ||
+     AppConstants.platform == "win")) {
   EXPECTED_REFLOWS_FIRST_OPEN.push({
     stack: [
       "_rebuild@chrome://browser/content/search/search-one-offs.js",
-      "set popup@chrome://browser/content/search/search-one-offs.js",
+      /* This is limited to a one-line stack, because the next item is an async
+         function and as such not supported on all trees, according to bug 1501761.
+      "async*set popup@chrome://browser/content/search/search-one-offs.js",
       "_syncOneOffSearchesEnabled@chrome://browser/content/urlbarBindings.xml",
       "toggleOneOffSearches@chrome://browser/content/urlbarBindings.xml",
       "_enableOrDisableOneOffSearches@chrome://browser/content/urlbarBindings.xml",
       "@chrome://browser/content/urlbarBindings.xml",
       "_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
       "openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
       "openPopup@chrome://global/content/bindings/autocomplete.xml",
-      "set_popupOpen@chrome://global/content/bindings/autocomplete.xml",
+      "set_popupOpen@chrome://global/content/bindings/autocomplete.xml",*/
     ],
   });
 }
 EXPECTED_REFLOWS_FIRST_OPEN.push(
   {
     stack: [
       "_handleOverflow@chrome://global/content/bindings/autocomplete.xml",
       "handleOverUnderflow@chrome://global/content/bindings/autocomplete.xml",
--- a/browser/base/content/test/performance/browser_urlbar_search.js
+++ b/browser/base/content/test/performance/browser_urlbar_search.js
@@ -11,32 +11,34 @@ requestLongerTimeout(5);
  * be modifying your code to avoid the reflow.
  *
  * See https://developer.mozilla.org/en-US/Firefox/Performance_best_practices_for_Firefox_fe_engineers
  * for tips on how to do that.
  */
 
 /* These reflows happen only the first time the awesomebar panel opens. */
 const EXPECTED_REFLOWS_FIRST_OPEN = [];
-if (AppConstants.DEBUG ||
-    AppConstants.platform == "linux" ||
-    AppConstants.platform == "macosx" ||
-    AppConstants.isPlatformAndVersionAtLeast("win", "10")) {
+if (AppConstants.platform != "macosx" &&
+    (AppConstants.DEBUG ||
+     AppConstants.platform == "linux" ||
+     AppConstants.isPlatformAndVersionAtLeast("win", "10"))) {
   EXPECTED_REFLOWS_FIRST_OPEN.push({
     stack: [
       "_rebuild@chrome://browser/content/search/search-one-offs.js",
-      "set popup@chrome://browser/content/search/search-one-offs.js",
+      /* This is limited to a one-line stack, because the next item is an async
+         function and as such not supported on all trees, according to bug 1501761.
+      "async*set popup@chrome://browser/content/search/search-one-offs.js",
       "_syncOneOffSearchesEnabled@chrome://browser/content/urlbarBindings.xml",
       "toggleOneOffSearches@chrome://browser/content/urlbarBindings.xml",
       "_enableOrDisableOneOffSearches@chrome://browser/content/urlbarBindings.xml",
       "@chrome://browser/content/urlbarBindings.xml",
       "_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
       "openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
       "openPopup@chrome://global/content/bindings/autocomplete.xml",
-      "set_popupOpen@chrome://global/content/bindings/autocomplete.xml",
+      "set_popupOpen@chrome://global/content/bindings/autocomplete.xml",*/
     ],
   });
 }
 EXPECTED_REFLOWS_FIRST_OPEN.push(
   {
     stack: [
       "_handleOverflow@chrome://global/content/bindings/autocomplete.xml",
       "handleOverUnderflow@chrome://global/content/bindings/autocomplete.xml",
--- a/browser/base/content/test/urlbar/browser_action_searchengine.js
+++ b/browser/base/content/test/urlbar/browser_action_searchengine.js
@@ -1,23 +1,23 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 add_task(async function() {
-  Services.search.addEngineWithDetails("MozSearch", "", "", "", "GET",
-                                       "http://example.com/?q={searchTerms}");
+  await Services.search.addEngineWithDetails("MozSearch", "", "", "", "GET",
+    "http://example.com/?q={searchTerms}");
   let engine = Services.search.getEngineByName("MozSearch");
-  let originalEngine = Services.search.defaultEngine;
-  Services.search.defaultEngine = engine;
+  let originalEngine = await Services.search.getDefault();
+  await Services.search.setDefault(engine);
 
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:mozilla");
 
   registerCleanupFunction(async function() {
-    Services.search.defaultEngine = originalEngine;
-    Services.search.removeEngine(engine);
+    await Services.search.setDefault(originalEngine);
+    await Services.search.removeEngine(engine);
     try {
       BrowserTestUtils.removeTab(tab);
     } catch (ex) { /* tab may have already been closed in case of failure */ }
     await PlacesUtils.history.clear();
   });
 
   await promiseAutocompleteResultPopup("open a search");
   let result = await waitForAutocompleteResultAt(0);
--- a/browser/base/content/test/urlbar/browser_action_searchengine_alias.js
+++ b/browser/base/content/test/urlbar/browser_action_searchengine_alias.js
@@ -1,24 +1,30 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 add_task(async function() {
-  let iconURI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC";
-  Services.search.addEngineWithDetails("MozSearch", iconURI, "moz", "", "GET",
-                                       "http://example.com/?q={searchTerms}");
+  let iconURI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQk" +
+    "Wg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i" +
+    "5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e" +
+    "2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh" +
+    "074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI" +
+    "1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWB" +
+    "foWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC";
+  await Services.search.addEngineWithDetails("MozSearch", iconURI, "moz", "", "GET",
+    "http://example.com/?q={searchTerms}");
   let engine = Services.search.getEngineByName("MozSearch");
-  let originalEngine = Services.search.defaultEngine;
-  Services.search.defaultEngine = engine;
+  let originalEngine = await Services.search.getDefault();
+  await Services.search.setDefault(engine);
 
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:mozilla");
 
   registerCleanupFunction(async function() {
-    Services.search.defaultEngine = originalEngine;
-    Services.search.removeEngine(engine);
+    await Services.search.setDefault(originalEngine);
+    await Services.search.removeEngine(engine);
     try {
       BrowserTestUtils.removeTab(tab);
     } catch (ex) { /* tab may have already been closed in case of failure */ }
     await PlacesUtils.history.clear();
   });
 
   await promiseAutocompleteResultPopup("moz open a search");
   let result = await waitForAutocompleteResultAt(0);
--- a/browser/base/content/test/urlbar/browser_autocomplete_a11y_label.js
+++ b/browser/base/content/test/urlbar/browser_autocomplete_a11y_label.js
@@ -16,23 +16,23 @@ add_task(async function switchToTab() {
   gURLBar.popup.hidePopup();
   await promisePopupHidden(gURLBar.popup);
   gBrowser.removeTab(tab);
 });
 
 add_task(async function searchSuggestions() {
   let engine = await SearchTestUtils.promiseNewSearchEngine(
     getRootDirectory(gTestPath) + TEST_ENGINE_BASENAME);
-  let oldDefaultEngine = Services.search.defaultEngine;
-  Services.search.defaultEngine = engine;
+  let oldDefaultEngine = await Services.search.getDefault();
+  await Services.search.setDefault(engine);
   Services.prefs.setBoolPref(SUGGEST_ALL_PREF, true);
   let suggestionsEnabled = Services.prefs.getBoolPref(SUGGEST_URLBAR_PREF);
   Services.prefs.setBoolPref(SUGGEST_URLBAR_PREF, true);
-  registerCleanupFunction(function() {
-    Services.search.defaultEngine = oldDefaultEngine;
+  registerCleanupFunction(async function() {
+    await Services.search.setDefault(oldDefaultEngine);
     Services.prefs.clearUserPref(SUGGEST_ALL_PREF);
     Services.prefs.setBoolPref(SUGGEST_URLBAR_PREF, suggestionsEnabled);
   });
 
   await promiseAutocompleteResultPopup("foo");
   await waitForAutocompleteResultAt(2);
   // Don't assume that the search doesn't match history or bookmarks left around
   // by earlier tests.
--- a/browser/base/content/test/urlbar/browser_autocomplete_enter_race.js
+++ b/browser/base/content/test/urlbar/browser_autocomplete_enter_race.js
@@ -58,31 +58,31 @@ add_task(taskWithNewTab(async function t
   // Disable autocomplete.
   let suggestHistory = Preferences.get("browser.urlbar.suggest.history");
   Preferences.set("browser.urlbar.suggest.history", false);
   let suggestBookmarks = Preferences.get("browser.urlbar.suggest.bookmark");
   Preferences.set("browser.urlbar.suggest.bookmark", false);
   let suggestOpenPages = Preferences.get("browser.urlbar.suggest.openpage");
   Preferences.set("browser.urlbar.suggest.openpage", false);
 
-  Services.search.addEngineWithDetails("MozSearch", "", "", "", "GET",
-                                       "http://example.com/?q={searchTerms}");
+  await Services.search.addEngineWithDetails("MozSearch", "", "", "", "GET",
+    "http://example.com/?q={searchTerms}");
   let engine = Services.search.getEngineByName("MozSearch");
-  let originalEngine = Services.search.defaultEngine;
-  Services.search.defaultEngine = engine;
+  let originalEngine = await Services.search.getDefault();
+  await Services.search.setDefault(engine);
 
-  function cleanup() {
+  async function cleanup() {
     Preferences.set("browser.urlbar.suggest.history", suggestHistory);
     Preferences.set("browser.urlbar.suggest.bookmark", suggestBookmarks);
     Preferences.set("browser.urlbar.suggest.openpage", suggestOpenPages);
 
-    Services.search.defaultEngine = originalEngine;
+    await Services.search.setDefault(originalEngine);
     let mozSearchEngine = Services.search.getEngineByName("MozSearch");
     if (mozSearchEngine) {
-      Services.search.removeEngine(mozSearchEngine);
+      await Services.search.removeEngine(mozSearchEngine);
     }
   }
   registerCleanupFunction(cleanup);
 
   gURLBar.focus();
   gURLBar.value = "e";
   EventUtils.sendString("x");
   EventUtils.synthesizeKey("KEY_Enter");
--- a/browser/base/content/test/urlbar/browser_canonizeURL.js
+++ b/browser/base/content/test/urlbar/browser_canonizeURL.js
@@ -16,17 +16,18 @@ add_task(async function checkCtrlWorks()
     ["example.net", "http://example.net/", { ctrlKey: true }],
     ["http://example", "http://example/", { ctrlKey: true }],
     ["example:8080", "http://example:8080/", { ctrlKey: true }],
     ["ex-ample.foo", "http://ex-ample.foo/", { ctrlKey: true }],
     ["example.foo/bar ", "http://example.foo/bar", { ctrlKey: true }],
     ["1.1.1.1", "http://1.1.1.1/", { ctrlKey: true }],
     ["ftp://example", "ftp://example/", { ctrlKey: true }],
     ["ftp.example.bar", "http://ftp.example.bar/", { ctrlKey: true }],
-    ["ex ample", Services.search.defaultEngine.getSubmission("ex ample", null, "keyword").uri.spec, { ctrlKey: true }],
+    ["ex ample", (await Services.search.getDefault()).getSubmission("ex ample", null, "keyword").uri.spec,
+      { ctrlKey: true }],
   ];
 
   // Disable autoFill for this test, since it could mess up the results.
   await SpecialPowers.pushPrefEnv({set: [
     ["browser.urlbar.autoFill", false],
     ["browser.urlbar.ctrlCanonizesURLs", true],
   ]});
 
@@ -39,19 +40,19 @@ add_task(async function checkCtrlWorks()
     await promiseLoad;
   }
 });
 
 add_task(async function checkPrefTurnsOffCanonize() {
   // Add a dummy search engine to avoid hitting the network.
   let engine = await SearchTestUtils.promiseNewSearchEngine(
     getRootDirectory(gTestPath) + TEST_ENGINE_BASENAME);
-  let oldDefaultEngine = Services.search.defaultEngine;
-  Services.search.defaultEngine = engine;
-  registerCleanupFunction(() => { Services.search.defaultEngine = oldDefaultEngine; });
+  let oldDefaultEngine = await Services.search.getDefault();
+  await Services.search.setDefault(engine);
+  registerCleanupFunction(async () => Services.search.setDefault(oldDefaultEngine));
 
   let tabsToClose = [];
   // Ensure we don't end up loading something in the current tab becuase it's empty:
   if (gBrowser.selectedTab.isEmpty) {
     tabsToClose.push(await BrowserTestUtils.openNewForegroundTab({gBrowser, opening: "about:mozilla"}));
   }
   let initialTabURL = gBrowser.selectedBrowser.currentURI.spec;
   let initialTab = gBrowser.selectedTab;
--- a/browser/base/content/test/urlbar/browser_dragdropURL.js
+++ b/browser/base/content/test/urlbar/browser_dragdropURL.js
@@ -7,29 +7,29 @@ const DRAG_TEXT = "Firefox is awesome";
 const DRAG_TEXT_URL = "http://example.com/?q=Firefox+is+awesome";
 const DRAG_WORD = "Firefox";
 const DRAG_WORD_URL = "http://example.com/?q=Firefox";
 
 registerCleanupFunction(async function cleanup() {
   while (gBrowser.tabs.length > 1) {
     BrowserTestUtils.removeTab(gBrowser.tabs[gBrowser.tabs.length - 1]);
   }
-  Services.search.defaultEngine = originalEngine;
+  await Services.search.setDefault(originalEngine);
   let engine = Services.search.getEngineByName("MozSearch");
-  Services.search.removeEngine(engine);
+  await Services.search.removeEngine(engine);
 });
 
 let originalEngine;
 add_task(async function test_setup() {
   // Stop search-engine loads from hitting the network
-  Services.search.addEngineWithDetails("MozSearch", "", "", "", "GET",
-                                       "http://example.com/?q={searchTerms}");
+  await Services.search.addEngineWithDetails("MozSearch", "", "", "", "GET",
+    "http://example.com/?q={searchTerms}");
   let engine = Services.search.getEngineByName("MozSearch");
-  originalEngine = Services.search.defaultEngine;
-  Services.search.defaultEngine = engine;
+  originalEngine = await Services.search.getDefault();
+  await Services.search.setDefault(engine);
 });
 
 add_task(async function checkDragURL() {
   await BrowserTestUtils.withNewTab(TEST_URL, function(browser) {
     // Have to use something other than the URL bar as a source, so picking the
     // home button somewhat arbitrarily:
     EventUtils.synthesizeDrop(document.getElementById("home-button"), gURLBar,
                               [[{type: "text/plain", data: DRAG_URL}]], "copy", window);
--- a/browser/base/content/test/urlbar/browser_page_action_menu_add_search_engine.js
+++ b/browser/base/content/test/urlbar/browser_page_action_menu_add_search_engine.js
@@ -61,17 +61,17 @@ add_task(async function one() {
     action = actions.find(a => a.id == "addSearchEngine");
     Assert.ok(!action, "Action should not be present in panel");
     button = BrowserPageActions.panelButtonNodeForActionID("addSearchEngine");
     Assert.ok(!button, "Action button should not be in panel");
 
     // Remove the engine.
     enginePromise =
       promiseEngine("engine-removed", "page_action_menu_add_search_engine_0");
-    Services.search.removeEngine(engine);
+    await Services.search.removeEngine(engine);
     await enginePromise;
 
     // Open the panel again.
     await promisePageActionPanelOpen();
     EventUtils.synthesizeMouseAtCenter(BrowserPageActions.mainButtonNode, {});
     await promisePageActionPanelHidden();
 
     // The action should be present again.
@@ -202,17 +202,17 @@ add_task(async function many() {
     action = actions.find(a => a.id == "addSearchEngine");
     Assert.ok(!action, "Action should be gone");
     button = BrowserPageActions.panelButtonNodeForActionID("addSearchEngine");
     Assert.ok(!button, "Button should not be in panel");
 
     // Remove the first engine.
     enginePromise =
       promiseEngine("engine-removed", "page_action_menu_add_search_engine_0");
-    Services.search.removeEngine(engines.shift());
+    await Services.search.removeEngine(engines.shift());
     await enginePromise;
 
     // Open the panel again.  The action should be present and showing the first
     // engine.
     await promisePageActionPanelOpen();
     EventUtils.synthesizeMouseAtCenter(BrowserPageActions.mainButtonNode, {});
     await promisePageActionPanelHidden();
     actions = PageActions.actionsInPanel(window);
@@ -224,17 +224,17 @@ add_task(async function many() {
     Assert.ok(button, "Button should be present in panel");
     Assert.equal(button.label, expectedTitle, "Button label");
     Assert.equal(button.classList.contains("subviewbutton-nav"), false,
                  "Button should not expand into a subview");
 
     // Remove the second engine.
     enginePromise =
       promiseEngine("engine-removed", "page_action_menu_add_search_engine_1");
-    Services.search.removeEngine(engines.shift());
+    await Services.search.removeEngine(engines.shift());
     await enginePromise;
 
     // Open the panel again and check the subview.  The subview should be
     // present now that there are two offered engines again.
     await promisePageActionPanelOpen();
     actions = PageActions.actionsInPanel(window);
     action = actions.find(a => a.id == "addSearchEngine");
     Assert.ok(action, "Action should be present in panel");
@@ -258,17 +258,17 @@ add_task(async function many() {
       "Subview children"
     );
     EventUtils.synthesizeMouseAtCenter(BrowserPageActions.mainButtonNode, {});
     await promisePageActionPanelHidden();
 
     // Remove the third engine.
     enginePromise =
       promiseEngine("engine-removed", "page_action_menu_add_search_engine_2");
-    Services.search.removeEngine(engines.shift());
+    await Services.search.removeEngine(engines.shift());
     await enginePromise;
 
     // Open the panel again and check the subview.
     await promisePageActionPanelOpen();
     viewPromise = promisePageActionViewShown();
     EventUtils.synthesizeMouseAtCenter(button, {});
     await viewPromise;
     Assert.deepEqual(
@@ -318,17 +318,17 @@ add_task(async function urlbarOne() {
     Assert.ok(!action, "Action should not be present in urlbar");
     button = BrowserPageActions.urlbarButtonNodeForActionID("addSearchEngine");
     Assert.ok(!button, "Action button should not be in urlbar");
 
     // Remove the engine.
     enginePromise =
       promiseEngine("engine-removed", "page_action_menu_add_search_engine_0");
     placedPromise = promisePlacedInUrlbar();
-    Services.search.removeEngine(engine);
+    await Services.search.removeEngine(engine);
     await enginePromise;
 
     // The action should be present again.
     button = await placedPromise;
     actions = PageActions.actionsInUrlbar(window);
     action = actions.find(a => a.id == "addSearchEngine");
     Assert.ok(action, "Action should be present in urlbar");
     Assert.ok(button, "Action button should be in urlbar");
@@ -434,30 +434,30 @@ add_task(async function urlbarMany() {
     Assert.ok(!action, "Action should be gone");
     button = BrowserPageActions.urlbarButtonNodeForActionID("addSearchEngine");
     Assert.ok(!button, "Button should not be in urlbar");
 
     // Remove the first engine.
     enginePromise =
       promiseEngine("engine-removed", "page_action_menu_add_search_engine_0");
     placedPromise = promisePlacedInUrlbar();
-    Services.search.removeEngine(engines.shift());
+    await Services.search.removeEngine(engines.shift());
     await enginePromise;
 
     // The action should be placed again.
     button = await placedPromise;
     actions = PageActions.actionsInUrlbar(window);
     action = actions.find(a => a.id == "addSearchEngine");
     Assert.ok(action, "Action should be present in urlbar");
     Assert.ok(button, "Button should be in urlbar");
 
     // Remove the second engine.
     enginePromise =
       promiseEngine("engine-removed", "page_action_menu_add_search_engine_1");
-    Services.search.removeEngine(engines.shift());
+    await Services.search.removeEngine(engines.shift());
     await enginePromise;
 
     // Open the panel again and check the subview.  The subview should be
     // present now that there are two offered engines again.
     EventUtils.synthesizeMouseAtCenter(button, {});
     view = await waitForActivatedActionPanel();
     body = view.firstElementChild;
     Assert.deepEqual(
@@ -473,17 +473,17 @@ add_task(async function urlbarMany() {
     hiddenPromise =
       promisePanelHidden(BrowserPageActions.activatedActionPanelNode);
     EventUtils.synthesizeMouseAtCenter(button, {});
     await hiddenPromise;
 
     // Remove the third engine.
     enginePromise =
       promiseEngine("engine-removed", "page_action_menu_add_search_engine_2");
-    Services.search.removeEngine(engines.shift());
+    await Services.search.removeEngine(engines.shift());
     await enginePromise;
 
     // Open the panel again and check the subview.
     EventUtils.synthesizeMouseAtCenter(button, {});
     view = await waitForActivatedActionPanel();
     body = view.firstElementChild;
     Assert.deepEqual(
       Array.map(body.children, n => n.label),
--- a/browser/base/content/test/urlbar/browser_search_favicon.js
+++ b/browser/base/content/test/urlbar/browser_search_favicon.js
@@ -1,35 +1,34 @@
 var gOriginalEngine;
 var gEngine;
 var gRestyleSearchesPref = "browser.urlbar.restyleSearches";
 
-registerCleanupFunction(() => {
+registerCleanupFunction(async () => {
   Services.prefs.clearUserPref(gRestyleSearchesPref);
-  Services.search.defaultEngine = gOriginalEngine;
-  Services.search.removeEngine(gEngine);
+  await Services.search.setDefault(gOriginalEngine);
+  await Services.search.removeEngine(gEngine);
   return PlacesUtils.history.clear();
 });
 
 add_task(async function() {
   Services.prefs.setBoolPref(gRestyleSearchesPref, true);
 
   // This test is sensitive to the mouse position hovering awesome
   // bar elements, so make sure it doesnt
   await EventUtils.synthesizeNativeMouseMove(document.documentElement, 0, 0);
 });
 
 add_task(async function() {
-
-  Services.search.addEngineWithDetails("SearchEngine", "", "", "",
-                                       "GET", "http://s.example.com/search");
+  await Services.search.addEngineWithDetails("SearchEngine", "", "", "",
+    "GET", "http://s.example.com/search");
   gEngine = Services.search.getEngineByName("SearchEngine");
   gEngine.addParam("q", "{searchTerms}", null);
-  gOriginalEngine = Services.search.defaultEngine;
-  Services.search.defaultEngine = gEngine;
+  gOriginalEngine = await Services.search.getDefault();
+  await Services.search.setDefault(gEngine);
 
   let uri = NetUtil.newURI("http://s.example.com/search?q=foobar&client=1");
   await PlacesTestUtils.addVisits({ uri, title: "Foo - SearchEngine Search" });
 
   await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:mozilla");
 
   // The first autocomplete result has the action searchengine, while
   // the second result is the "search favicon" element.
--- a/browser/base/content/test/urlbar/browser_urlbarAddonIframe.js
+++ b/browser/base/content/test/urlbar/browser_urlbarAddonIframe.js
@@ -100,17 +100,17 @@ add_task(async function() {
     promiseEvent("input")[1],
     promiseEvent("reset")[1],
     promiseEvent("result")[1],
     promiseAutocompleteResultPopup(value, window, true),
   ]);
 
   // Check the heuristic result.
   let result = promiseValues[2];
-  let engineName = Services.search.defaultEngine.name;
+  let engineName = (await Services.search.getDefault()).name;
   Assert.deepEqual(
     PlacesUtils.parseActionUrl(result.url),
     {
       type: "searchengine",
       params: {
         engineName,
         input: "test",
         searchQuery: "test",
--- a/browser/base/content/test/urlbar/browser_urlbarOneOffs.js
+++ b/browser/base/content/test/urlbar/browser_urlbarOneOffs.js
@@ -5,17 +5,17 @@ let gMaxResults;
 add_task(async function init() {
   Services.prefs.setBoolPref("browser.urlbar.oneOffSearches", true);
   gMaxResults = Services.prefs.getIntPref("browser.urlbar.maxRichResults");
 
   // Add a search suggestion engine and move it to the front so that it appears
   // as the first one-off.
   let engine = await SearchTestUtils.promiseNewSearchEngine(
     getRootDirectory(gTestPath) + TEST_ENGINE_BASENAME);
-  Services.search.moveEngine(engine, 0);
+  await Services.search.moveEngine(engine, 0);
 
   registerCleanupFunction(async function() {
     await hidePopup();
     await PlacesUtils.history.clear();
   });
 
   await PlacesUtils.history.clear();
 
@@ -162,26 +162,26 @@ add_task(async function() {
 add_task(async function searchWith() {
   let typedValue = "foo";
   await promiseAutocompleteResultPopup(typedValue);
   await waitForAutocompleteResultAt(0);
   assertState(0, -1, typedValue);
 
   let item = gURLBar.popup.richlistbox.firstElementChild;
   Assert.equal(item._actionText.textContent,
-               "Search with " + Services.search.defaultEngine.name,
+               "Search with " + (await Services.search.getDefault()).name,
                "Sanity check: first result's action text");
 
   // Alt+Down to the first one-off.  Now the first result and the first one-off
   // should both be selected.
   EventUtils.synthesizeKey("KEY_ArrowDown", { altKey: true });
   assertState(0, 0, typedValue);
 
   let engineName = gURLBar.popup.oneOffSearchButtons.selectedButton.engine.name;
-  Assert.notEqual(engineName, Services.search.defaultEngine.name,
+  Assert.notEqual(engineName, (await Services.search.getDefault()).name,
                   "Sanity check: First one-off engine should not be " +
                   "the current engine");
   Assert.equal(item._actionText.textContent,
                "Search with " + engineName,
                "First result's action text should be updated");
 
   await hidePopup();
 });
@@ -229,18 +229,18 @@ add_task(async function oneOffReturn() {
   await resultsPromise;
 
   gBrowser.removeTab(gBrowser.selectedTab);
 });
 
 add_task(async function collapsedOneOffs() {
   // Disable all the engines but the current one, check the oneoffs are
   // collapsed and that moving up selects the last match.
-  let engines = Services.search.getVisibleEngines()
-                               .filter(e => e.name != Services.search.defaultEngine.name);
+  let defaultEngine = await Services.search.getDefault();
+  let engines = (await Services.search.getVisibleEngines()).filter(e => e.name != defaultEngine.name);
   await SpecialPowers.pushPrefEnv({"set": [
     [ "browser.search.hiddenOneOffs", engines.map(e => e.name).join(",") ],
   ]});
 
   let typedValue = "foo";
   await promiseAutocompleteResultPopup(typedValue, window, true);
   await waitForAutocompleteResultAt(0);
   assertState(0, -1);
--- a/browser/base/content/test/urlbar/browser_urlbarOneOffs_searchSuggestions.js
+++ b/browser/base/content/test/urlbar/browser_urlbarOneOffs_searchSuggestions.js
@@ -3,21 +3,21 @@ const TEST_ENGINE_BASENAME = "searchSugg
 add_task(async function init() {
   await PlacesUtils.history.clear();
   await SpecialPowers.pushPrefEnv({
     set: [["browser.urlbar.oneOffSearches", true],
           ["browser.urlbar.suggest.searches", true]],
   });
   let engine = await SearchTestUtils.promiseNewSearchEngine(
     getRootDirectory(gTestPath) + TEST_ENGINE_BASENAME);
-  let oldDefaultEngine = Services.search.defaultEngine;
-  Services.search.moveEngine(engine, 0);
-  Services.search.defaultEngine = engine;
+  let oldDefaultEngine = await Services.search.getDefault();
+  await Services.search.moveEngine(engine, 0);
+  await Services.search.setDefault(engine);
   registerCleanupFunction(async function() {
-    Services.search.defaultEngine = oldDefaultEngine;
+    await Services.search.setDefault(oldDefaultEngine);
 
     await PlacesUtils.history.clear();
     // Make sure the popup is closed for the next test.
     gURLBar.blur();
     Assert.ok(!gURLBar.popup.popupOpen, "popup should be closed");
   });
 });
 
--- a/browser/base/content/test/urlbar/browser_urlbarOneOffs_settings.js
+++ b/browser/base/content/test/urlbar/browser_urlbarOneOffs_settings.js
@@ -8,17 +8,17 @@ let gMaxResults;
 add_task(async function init() {
   Services.prefs.setBoolPref("browser.urlbar.oneOffSearches", true);
   gMaxResults = Services.prefs.getIntPref("browser.urlbar.maxRichResults");
 
   // Add a search suggestion engine and move it to the front so that it appears
   // as the first one-off.
   let engine = await SearchTestUtils.promiseNewSearchEngine(
     getRootDirectory(gTestPath) + TEST_ENGINE_BASENAME);
-  Services.search.moveEngine(engine, 0);
+  await Services.search.moveEngine(engine, 0);
 
   registerCleanupFunction(async function() {
     await hidePopup();
     await PlacesUtils.history.clear();
   });
 
   await PlacesUtils.history.clear();
 
--- a/browser/base/content/test/urlbar/browser_urlbarPlaceholder.js
+++ b/browser/base/content/test/urlbar/browser_urlbarPlaceholder.js
@@ -5,90 +5,94 @@
  * This test ensures the placeholder is set correctly for different search
  * engines.
  */
 
 "use strict";
 
 const TEST_ENGINE_BASENAME = "searchSuggestionEngine.xml";
 
-const originalEngine = Services.search.defaultEngine;
-const expectedString = gBrowserBundle.formatStringFromName("urlbar.placeholder",
-  [originalEngine.name], 1);
-var extraEngine;
+var originalEngine, extraEngine, expectedString;
 var tabs = [];
 
 add_task(async function setup() {
+  originalEngine = await Services.search.getDefault();
+  expectedString = gBrowserBundle.formatStringFromName("urlbar.placeholder", [originalEngine.name], 1);
+
   let rootDir = getRootDirectory(gTestPath);
   extraEngine = await SearchTestUtils.promiseNewSearchEngine(rootDir + TEST_ENGINE_BASENAME);
 
   // Force display of a tab with a URL bar, to clear out any possible placeholder
   // initialization listeners that happen on startup.
   let urlTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:mozilla");
   BrowserTestUtils.removeTab(urlTab);
 
-  registerCleanupFunction(() => {
-    Services.search.defaultEngine = originalEngine;
+  registerCleanupFunction(async () => {
+    await Services.search.setDefault(originalEngine);
     for (let tab of tabs) {
       BrowserTestUtils.removeTab(tab);
     }
   });
 });
 
 add_task(async function test_change_default_engine_updates_placeholder() {
   tabs.push(await BrowserTestUtils.openNewForegroundTab(gBrowser));
 
-  Services.search.defaultEngine = extraEngine;
+  await Services.search.setDefault(extraEngine);
 
   await TestUtils.waitForCondition(
     () => gURLBar.getAttribute("placeholder") == gURLBar.getAttribute("defaultPlaceholder"),
     "The placeholder should match the default placeholder for non-built-in engines.");
+  Assert.equal(gURLBar.getAttribute("placeholder"), gURLBar.getAttribute("defaultPlaceholder"));
 
-  Services.search.defaultEngine = originalEngine;
+  await Services.search.setDefault(originalEngine);
 
   await TestUtils.waitForCondition(
     () => gURLBar.getAttribute("placeholder") == expectedString,
     "The placeholder should include the engine name for built-in engines.");
+  Assert.equal(gURLBar.getAttribute("placeholder"), expectedString);
 });
 
 add_task(async function test_delayed_update_placeholder() {
   // Since we can't easily test for startup changes, we'll at least test the delay
   // of update for the placeholder works.
   let urlTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:mozilla");
   tabs.push(urlTab);
 
   // Open a tab with a blank URL bar.
   let blankTab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
   tabs.push(blankTab);
 
   // Pretend we've "initialized".
-  BrowserSearch._updateURLBarPlaceholder(extraEngine, true);
+  BrowserSearch._updateURLBarPlaceholder(extraEngine.name, true);
 
   Assert.equal(gURLBar.getAttribute("placeholder"), expectedString,
     "Placeholder should be unchanged.");
 
   // Now switch to a tab with something in the URL Bar.
   await BrowserTestUtils.switchTab(gBrowser, urlTab);
 
   await TestUtils.waitForCondition(
     () => gURLBar.getAttribute("placeholder") == gURLBar.getAttribute("defaultPlaceholder"),
     "The placeholder should have updated in the background.");
 
   // Do it the other way to check both named engine and fallback code paths.
   await BrowserTestUtils.switchTab(gBrowser, blankTab);
 
-  BrowserSearch._updateURLBarPlaceholder(originalEngine, true);
+  BrowserSearch._updateURLBarPlaceholder(originalEngine.name, true);
+  await TestUtils.waitForTick();
 
   Assert.equal(gURLBar.getAttribute("placeholder"), gURLBar.getAttribute("defaultPlaceholder"),
     "Placeholder should be unchanged.");
 
   await BrowserTestUtils.switchTab(gBrowser, urlTab);
 
   await TestUtils.waitForCondition(
     () => gURLBar.getAttribute("placeholder") == expectedString,
     "The placeholder should include the engine name for built-in engines.");
 
   // Now check when we have a URL displayed, the placeholder is updated straight away.
-  BrowserSearch._updateURLBarPlaceholder(extraEngine);
+  BrowserSearch._updateURLBarPlaceholder(extraEngine.name);
+  await TestUtils.waitForTick();
 
   Assert.equal(gURLBar.getAttribute("placeholder"), gURLBar.getAttribute("defaultPlaceholder"),
     "Placeholder should be the default.");
 });
--- a/browser/base/content/test/urlbar/browser_urlbarSearchSingleWordNotification.js
+++ b/browser/base/content/test/urlbar/browser_urlbarSearchSingleWordNotification.js
@@ -27,20 +27,17 @@ function promiseNotification(aBrowser, v
 }
 
 async function runURLBarSearchTest({valueToOpen, expectSearch, expectNotification, aWindow = window}) {
   aWindow.gURLBar.value = valueToOpen;
   let expectedURI;
   if (!expectSearch) {
     expectedURI = "http://" + valueToOpen + "/";
   } else {
-    await new Promise(resolve => {
-      Services.search.init(resolve);
-    });
-    expectedURI = Services.search.defaultEngine.getSubmission(valueToOpen, null, "keyword").uri.spec;
+    expectedURI = (await Services.search.getDefault()).getSubmission(valueToOpen, null, "keyword").uri.spec;
   }
   aWindow.gURLBar.focus();
   let docLoadPromise = waitForDocLoadAndStopIt(expectedURI, aWindow.gBrowser.selectedBrowser);
   EventUtils.synthesizeKey("VK_RETURN", {}, aWindow);
 
   await Promise.all([
     docLoadPromise,
     promiseNotification(aWindow.gBrowser, "keyword-uri-fixup", expectNotification, valueToOpen),
--- a/browser/base/content/test/urlbar/browser_urlbarSearchSuggestions.js
+++ b/browser/base/content/test/urlbar/browser_urlbarSearchSuggestions.js
@@ -2,21 +2,21 @@ const SUGGEST_URLBAR_PREF = "browser.url
 const TEST_ENGINE_BASENAME = "searchSuggestionEngine.xml";
 
 // Must run first.
 add_task(async function prepare() {
   let suggestionsEnabled = Services.prefs.getBoolPref(SUGGEST_URLBAR_PREF);
   Services.prefs.setBoolPref(SUGGEST_URLBAR_PREF, true);
   let engine = await SearchTestUtils.promiseNewSearchEngine(
     getRootDirectory(gTestPath) + TEST_ENGINE_BASENAME);
-  let oldDefaultEngine = Services.search.defaultEngine;
-  Services.search.defaultEngine = engine;
+  let oldDefaultEngine = await Services.search.getDefault();
+  await Services.search.setDefault(engine);
   registerCleanupFunction(async function() {
     Services.prefs.setBoolPref(SUGGEST_URLBAR_PREF, suggestionsEnabled);
-    Services.search.defaultEngine = oldDefaultEngine;
+    await Services.search.setDefault(oldDefaultEngine);
 
     // Clicking suggestions causes visits to search results pages, so clear that
     // history now.
     await PlacesUtils.history.clear();
 
     // Make sure the popup is closed for the next test.
     gURLBar.blur();
     Assert.ok(!gURLBar.popup.popupOpen, "popup should be closed");
@@ -28,17 +28,17 @@ add_task(async function clickSuggestion(
   gURLBar.focus();
   await promiseAutocompleteResultPopup("foo");
   let [idx, suggestion, engineName] = await promiseFirstSuggestion();
   Assert.equal(engineName,
                "browser_searchSuggestionEngine%20searchSuggestionEngine.xml",
                "Expected suggestion engine");
   let item = gURLBar.popup.richlistbox.getItemAtIndex(idx);
 
-  let uri = Services.search.defaultEngine.getSubmission(suggestion).uri;
+  let uri = (await Services.search.getDefault()).getSubmission(suggestion).uri;
   let loadPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser,
                                                    false, uri.spec);
   item.click();
   await loadPromise;
   BrowserTestUtils.removeTab(tab);
 });
 
 async function testPressEnterOnSuggestion(expectedUrl = null, keyModifiers = {}) {
@@ -46,17 +46,17 @@ async function testPressEnterOnSuggestio
   gURLBar.focus();
   await promiseAutocompleteResultPopup("foo");
   let [idx, suggestion, engineName] = await promiseFirstSuggestion();
   Assert.equal(engineName,
                "browser_searchSuggestionEngine%20searchSuggestionEngine.xml",
                "Expected suggestion engine");
 
   if (!expectedUrl) {
-    expectedUrl = Services.search.defaultEngine.getSubmission(suggestion).uri.spec;
+    expectedUrl = (await Services.search.getDefault()).getSubmission(suggestion).uri.spec;
   }
 
   let promiseLoad = waitForDocLoadAndStopIt(expectedUrl);
 
   for (let i = 0; i < idx; ++i) {
     EventUtils.synthesizeKey("KEY_ArrowDown");
   }
   EventUtils.synthesizeKey("KEY_Enter", keyModifiers);
--- a/browser/base/content/test/urlbar/browser_urlbarSearchSuggestions_opt-out.js
+++ b/browser/base/content/test/urlbar/browser_urlbarSearchSuggestions_opt-out.js
@@ -9,29 +9,29 @@ const CHOICE_PREF = "browser.urlbar.user
 const TIMES_PREF = "browser.urlbar.timesBeforeHidingSuggestionsHint";
 const TEST_ENGINE_BASENAME = "searchSuggestionEngine.xml";
 const ONEOFF_PREF = "browser.urlbar.oneOffSearches";
 const NO_RESULTS_TIMEOUT_MS = 500;
 
 add_task(async function prepare() {
   let engine = await SearchTestUtils.promiseNewSearchEngine(
     getRootDirectory(gTestPath) + TEST_ENGINE_BASENAME);
-  let oldDefaultEngine = Services.search.defaultEngine;
-  Services.search.defaultEngine = engine;
+  let oldDefaultEngine = await Services.search.getDefault();
+  await Services.search.setDefault(engine);
   let suggestionsEnabled = Services.prefs.getBoolPref(SUGGEST_URLBAR_PREF);
   let defaults = Services.prefs.getDefaultBranch("browser.urlbar.");
   let searchSuggestionsDefault = defaults.getBoolPref("suggest.searches");
   defaults.setBoolPref("suggest.searches", true);
   let suggestionsChoice = Services.prefs.getBoolPref(CHOICE_PREF);
   Services.prefs.setBoolPref(CHOICE_PREF, false);
   let oneOffs = Services.prefs.getBoolPref(ONEOFF_PREF);
   Services.prefs.setBoolPref(ONEOFF_PREF, true);
   registerCleanupFunction(async function() {
     defaults.setBoolPref("suggest.searches", searchSuggestionsDefault);
-    Services.search.defaultEngine = oldDefaultEngine;
+    await Services.search.setDefault(oldDefaultEngine);
     Services.prefs.clearUserPref(SUGGEST_ALL_PREF);
     Services.prefs.setBoolPref(SUGGEST_URLBAR_PREF, suggestionsEnabled);
     Services.prefs.setBoolPref(CHOICE_PREF, suggestionsChoice);
     Services.prefs.setBoolPref(ONEOFF_PREF, oneOffs);
     // Make sure the popup is closed for the next test.
     gURLBar.blur();
     Assert.ok(!gURLBar.popup.popupOpen, "popup should be closed");
   });
--- a/browser/base/content/test/urlbar/browser_urlbarSearchTelemetry.js
+++ b/browser/base/content/test/urlbar/browser_urlbarSearchTelemetry.js
@@ -4,22 +4,22 @@ const SUGGEST_URLBAR_PREF = "browser.url
 const TEST_ENGINE_BASENAME = "searchSuggestionEngine.xml";
 
 // Must run first.
 add_task(async function prepare() {
   let suggestionsEnabled = Services.prefs.getBoolPref(SUGGEST_URLBAR_PREF);
   Services.prefs.setBoolPref(SUGGEST_URLBAR_PREF, true);
   let engine = await SearchTestUtils.promiseNewSearchEngine(
     getRootDirectory(gTestPath) + TEST_ENGINE_BASENAME);
-  let oldDefaultEngine = Services.search.defaultEngine;
-  Services.search.defaultEngine = engine;
+  let oldDefaultEngine = await Services.search.getDefault();
+  await Services.search.setDefault(engine);
 
   registerCleanupFunction(async function() {
     Services.prefs.setBoolPref(SUGGEST_URLBAR_PREF, suggestionsEnabled);
-    Services.search.defaultEngine = oldDefaultEngine;
+    await Services.search.setDefault(oldDefaultEngine);
 
     // Clicking urlbar results causes visits to their associated pages, so clear
     // that history now.
     await PlacesUtils.history.clear();
 
     // Make sure the popup is closed for the next test.
     gURLBar.blur();
     Assert.ok(!gURLBar.popup.popupOpen, "popup should be closed");
@@ -103,17 +103,17 @@ add_task(async function searchSuggestion
  *        result.
  */
 async function compareCounts(clickCallback) {
   // Search events triggered by clicks (not the Return key in the urlbar) are
   // recorded in three places:
   // * Telemetry histogram named "SEARCH_COUNTS"
   // * FHR
 
-  let engine = Services.search.defaultEngine;
+  let engine = await Services.search.getDefault();
   let engineID = "org.mozilla.testsearchsuggestions";
 
   // First, get the current counts.
 
   // telemetry histogram SEARCH_COUNTS
   let histogramCount = 0;
   let histogramKey = engineID + ".urlbar";
   let histogram;
--- a/browser/base/content/test/urlbar/browser_urlbarStopSearchOnSelection.js
+++ b/browser/base/content/test/urlbar/browser_urlbarStopSearchOnSelection.js
@@ -16,21 +16,21 @@ const TEST_ENGINE_NUM_EXPECTED_RESULTS =
 add_task(async function init() {
   await PlacesUtils.history.clear();
   await SpecialPowers.pushPrefEnv({
     set: [["browser.urlbar.suggest.searches", true]],
   });
   // Add a test search engine that returns suggestions on a delay.
   let engine = await SearchTestUtils.promiseNewSearchEngine(
     getRootDirectory(gTestPath) + TEST_ENGINE_BASENAME);
-  let oldDefaultEngine = Services.search.defaultEngine;
-  Services.search.moveEngine(engine, 0);
-  Services.search.defaultEngine = engine;
+  let oldDefaultEngine = await Services.search.getDefault();
+  await Services.search.moveEngine(engine, 0);
+  await Services.search.setDefault(engine);
   registerCleanupFunction(async () => {
-    Services.search.defaultEngine = oldDefaultEngine;
+    await Services.search.setDefault(oldDefaultEngine);
     await PlacesUtils.history.clear();
     // Make sure the popup is closed for the next test.
     gURLBar.blur();
     Assert.ok(!gURLBar.popup.popupOpen, "popup should be closed");
   });
 });
 
 add_task(async function mainTest() {
--- a/browser/base/content/test/urlbar/browser_urlbarTokenAlias.js
+++ b/browser/base/content/test/urlbar/browser_urlbarTokenAlias.js
@@ -3,23 +3,23 @@
 
 // This test checks "@" search engine aliases ("token aliases") in the urlbar.
 
 "use strict";
 
 const ALIAS = "@test";
 
 add_task(async function init() {
-  Services.search.addEngineWithDetails("Test", {
+  await Services.search.addEngineWithDetails("Test", {
     alias: ALIAS,
     template: "http://example.com/?search={searchTerms}",
   });
   registerCleanupFunction(async function() {
     let engine = Services.search.getEngineByName("Test");
-    Services.search.removeEngine(engine);
+    await Services.search.removeEngine(engine);
     // Make sure the popup is closed for the next test.
     gURLBar.handleRevert();
     gURLBar.blur();
     Assert.ok(!gURLBar.popup.popupOpen, "popup should be closed");
   });
 });
 
 
@@ -145,17 +145,17 @@ add_task(async function inputDoesntMatch
 
 
 // Selecting a non-heuristic (non-first) search engine result with an alias and
 // empty query should put the alias in the urlbar and highlight it.
 add_task(async function nonHeuristicAliases() {
   // Get the list of token alias engines (those with aliases that start with
   // "@").
   let tokenEngines = [];
-  for (let engine of Services.search.getEngines()) {
+  for (let engine of await Services.search.getEngines()) {
     let aliases = [];
     if (engine.alias) {
       aliases.push(engine.alias);
     }
     aliases.push(...engine.wrappedJSObject._internalAliases);
     let tokenAliases = aliases.filter(a => a.startsWith("@"));
     if (tokenAliases.length) {
       tokenEngines.push({ engine, tokenAliases });
--- a/browser/base/content/test/urlbar/browser_urlbar_search_speculative_connect_engine.js
+++ b/browser/base/content/test/urlbar/browser_urlbar_search_speculative_connect_engine.js
@@ -26,22 +26,22 @@ add_task(async function setup() {
           ["network.http.speculative-parallel-limit", 6],
           // The http server is using IPv4, so it's better to disable IPv6 to avoid weird
           // networking problem.
           ["network.dns.disableIPv6", true]],
   });
 
   let engine = await SearchTestUtils.promiseNewSearchEngine(
     getRootDirectory(gTestPath) + TEST_ENGINE_BASENAME);
-  let oldDefaultEngine = Services.search.defaultEngine;
-  Services.search.defaultEngine = engine;
+  let oldDefaultEngine = await Services.search.getDefault();
+  await Services.search.setDefault(engine);
 
   registerCleanupFunction(async function() {
     await PlacesUtils.history.clear();
-    Services.search.defaultEngine = oldDefaultEngine;
+    await Services.search.setDefault(oldDefaultEngine);
     gHttpServer.identity.remove(gScheme, gHost, gPort);
     gHttpServer.stop(() => {
       gHttpServer = null;
     });
   });
 });
 
 add_task(async function connect_search_engine_tests() {
--- a/browser/components/enterprisepolicies/tests/browser/browser_policy_search_engine.js
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_search_engine.js
@@ -46,17 +46,17 @@ async function test_opensearch(shouldWor
        "Search bar should not have addengines attribute");
   }
   await BrowserTestUtils.removeTab(tab);
 }
 
 add_task(async function test_install_and_set_default() {
   // Make sure we are starting in an expected state to avoid false positive
   // test results.
-  isnot(Services.search.defaultEngine.name, "MozSearch",
+  isnot((await Services.search.getDefault()).name, "MozSearch",
         "Default search engine should not be MozSearch when test starts");
   is(Services.search.getEngineByName("Foo"), null,
      "Engine \"Foo\" should not be present when test starts");
 
   await setupPolicyEngineWithJson({
     "policies": {
       "SearchEngines": {
         "Add": [
@@ -64,31 +64,33 @@ add_task(async function test_install_and
             "Name": "MozSearch",
             "URLTemplate": "http://example.com/?q={searchTerms}",
           },
         ],
         "Default": "MozSearch",
       },
     },
   });
+  // Get in line, because the Search policy callbacks are async.
+  await TestUtils.waitForTick();
 
   // If this passes, it means that the new search engine was properly installed
   // *and* was properly set as the default.
-  is(Services.search.defaultEngine.name, "MozSearch",
+  is((await Services.search.getDefault()).name, "MozSearch",
      "Specified search engine should be the default");
 
   // Clean up
-  Services.search.removeEngine(Services.search.defaultEngine);
+  await Services.search.removeEngine(await Services.search.getDefault());
   EnterprisePolicyTesting.resetRunOnceState();
 });
 
 // Same as the last test, but with "PreventInstalls" set to true to make sure
 // it does not prevent search engines from being installed properly
 add_task(async function test_install_and_set_default_prevent_installs() {
-  isnot(Services.search.defaultEngine.name, "MozSearch",
+  isnot((await Services.search.getDefault()).name, "MozSearch",
         "Default search engine should not be MozSearch when test starts");
   is(Services.search.getEngineByName("Foo"), null,
      "Engine \"Foo\" should not be present when test starts");
 
   await setupPolicyEngineWithJson({
     "policies": {
       "SearchEngines": {
         "Add": [
@@ -97,22 +99,24 @@ add_task(async function test_install_and
             "URLTemplate": "http://example.com/?q={searchTerms}",
           },
         ],
         "Default": "MozSearch",
         "PreventInstalls": true,
       },
     },
   });
+  // Get in line, because the Search policy callbacks are async.
+  await TestUtils.waitForTick();
 
-  is(Services.search.defaultEngine.name, "MozSearch",
+  is((await Services.search.getDefault()).name, "MozSearch",
      "Specified search engine should be the default");
 
   // Clean up
-  Services.search.removeEngine(Services.search.defaultEngine);
+  await Services.search.removeEngine(await Services.search.getDefault());
   EnterprisePolicyTesting.resetRunOnceState();
 });
 
 add_task(async function test_opensearch_works() {
   // Clear out policies so we can test with no policies applied
   await setupPolicyEngineWithJson({
     "policies": {
     },
@@ -208,16 +212,18 @@ add_task(async function test_install_and
             "Name": "Foo",
             "URLTemplate": "http://example.com/?q={searchTerms}",
             "IconURL": iconURL,
           },
         ],
       },
     },
   });
+  // Get in line, because the Search policy callbacks are async.
+  await TestUtils.waitForTick();
 
   // If this passes, it means that the new search engine was properly installed
 
   let engine = Services.search.getEngineByName("Foo");
   isnot(engine, null,
      "Specified search engine should be installed");
 
   is(engine.wrappedJSObject.iconURI.spec, iconURL,
@@ -225,15 +231,17 @@ add_task(async function test_install_and
 
   await setupPolicyEngineWithJson({
   "policies": {
       "SearchEngines": {
         "Remove": ["Foo"],
       },
     },
   });
+  // Get in line, because the Search policy callbacks are async.
+  await TestUtils.waitForTick();
 
   // If this passes, it means that the specified engine was properly removed
   is(Services.search.getEngineByName("Foo"), null,
      "Specified search engine should not be installed");
 
   EnterprisePolicyTesting.resetRunOnceState();
 });
--- a/browser/components/enterprisepolicies/tests/browser/head.js
+++ b/browser/components/enterprisepolicies/tests/browser/head.js
@@ -3,16 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const {
   EnterprisePolicyTesting,
   PoliciesPrefTracker,
 } = ChromeUtils.import("resource://testing-common/EnterprisePolicyTesting.jsm", {});
+const {TestUtils} = ChromeUtils.import("resource://testing-common/TestUtils.jsm", {});
 
 PoliciesPrefTracker.start();
 
 async function setupPolicyEngineWithJson(json, customSchema) {
   PoliciesPrefTracker.restoreDefaultValues();
   if (typeof(json) != "object") {
     let filePath = getTestFilePath(json ? json : "non-existing-file.json");
     return EnterprisePolicyTesting.setupPolicyEngineWithJson(filePath, customSchema);
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ b/browser/components/extensions/test/browser/browser-common.ini
@@ -64,16 +64,17 @@ skip-if = (os == 'mac' || os == 'win' ||
 [browser_ext_browserAction_simple.js]
 [browser_ext_browserAction_telemetry.js]
 [browser_ext_browserAction_theme_icons.js]
 [browser_ext_browsingData_formData.js]
 [browser_ext_browsingData_history.js]
 [browser_ext_browsingData_indexedDB.js]
 [browser_ext_browsingData_localStorage.js]
 [browser_ext_browsingData_pluginData.js]
+skip-if = (os == 'mac' && debug) # Plugin test causes Mac window to lose active state and times out other tests.
 [browser_ext_browsingData_serviceWorkers.js]
 [browser_ext_chrome_settings_overrides_home.js]
 [browser_ext_commands_execute_browser_action.js]
 [browser_ext_commands_execute_page_action.js]
 skip-if = (verify && (os == 'linux' || os == 'mac'))
 [browser_ext_commands_execute_sidebar_action.js]
 [browser_ext_commands_getAll.js]
 [browser_ext_commands_onCommand.js]
--- a/browser/components/extensions/test/browser/browser_ext_browserAction_contextMenu.js
+++ b/browser/components/extensions/test/browser/browser_ext_browserAction_contextMenu.js
@@ -100,31 +100,34 @@ add_task(async function browseraction_po
   ok(!item.hidden);
   ok(item.disabled);
 
   await closeContextMenu(contentAreaContextMenu);
 
   await extension.unload();
 });
 
-function openContextMenu(menuId, targetId) {
-  return openChromeContextMenu(menuId, "#" + CSS.escape(targetId));
+function openContextMenu(menuId, targetId, win = window) {
+  return openChromeContextMenu(menuId, "#" + CSS.escape(targetId), win);
 }
 
 function waitForElementShown(element) {
   let win = element.ownerGlobal;
   let dwu = win.windowUtils;
   return BrowserTestUtils.waitForCondition(() => {
     info("Waiting for overflow button to have non-0 size");
     let bounds = dwu.getBoundsWithoutFlushing(element);
     return bounds.width > 0 && bounds.height > 0;
   });
 }
 
 add_task(async function browseraction_contextmenu_manage_extension() {
+  // Do the customize mode shuffle in a separate window, because it interferes
+  // with other tests.
+  let win = await BrowserTestUtils.openNewBrowserWindow();
   let id = "addon_id@example.com";
   let buttonId = `${makeWidgetId(id)}-browser-action`;
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "applications": {
         "gecko": {id},
       },
       "browser_action": {},
@@ -148,115 +151,120 @@ add_task(async function browseraction_co
     let expected = visible ? "visible" : "hidden";
     is(removeExtension.hidden, !visible, `Remove Extension should be ${expected}`);
     is(manageExtension.hidden, !visible, `Manage Extension should be ${expected}`);
     is(separator.hidden, !visible, `Separator after Manage Extension should be ${expected}`);
   }
 
   async function testContextMenu(menuId, customizing) {
     info(`Open browserAction context menu in ${menuId}`);
-    let menu = await openContextMenu(menuId, buttonId);
+    let menu = await openContextMenu(menuId, buttonId, win);
     await checkVisibility(menu, true);
 
     info(`Choosing 'Manage Extension' in ${menuId} should load options`);
     let optionsLoaded = extension.awaitMessage("options-loaded");
     let manageExtension = menu.querySelector(".customize-context-manageExtension");
-    await closeChromeContextMenu(menuId, manageExtension);
+    await closeChromeContextMenu(menuId, manageExtension, win);
     await optionsLoaded;
 
     info(`Remove the opened tab, and await customize mode to be restored if necessary`);
-    let tab = gBrowser.selectedTab;
+    let tab = win.gBrowser.selectedTab;
     is(tab.linkedBrowser.currentURI.spec, "about:addons");
     if (customizing) {
-      let customizationReady = BrowserTestUtils.waitForEvent(gNavToolbox, "customizationready");
-      gBrowser.removeTab(tab);
+      let customizationReady = BrowserTestUtils.waitForEvent(win.gNavToolbox, "customizationready");
+      win.gBrowser.removeTab(tab);
       await customizationReady;
     } else {
-      gBrowser.removeTab(tab);
+      win.gBrowser.removeTab(tab);
     }
 
     return menu;
   }
 
   async function main(customizing) {
     if (customizing) {
       info("Enter customize mode");
-      let customizationReady = BrowserTestUtils.waitForEvent(gNavToolbox, "customizationready");
-      gCustomizeMode.enter();
+      let customizationReady = BrowserTestUtils.waitForEvent(win.gNavToolbox, "customizationready");
+      win.gCustomizeMode.enter();
       await customizationReady;
     }
 
     info("Test toolbar context menu in browserAction");
     let toolbarCtxMenu = await testContextMenu("toolbar-context-menu", customizing);
 
     info("Check toolbar context menu in another button");
     let otherButtonId = "home-button";
-    await openContextMenu(toolbarCtxMenu.id, otherButtonId);
+    await openContextMenu(toolbarCtxMenu.id, otherButtonId, win);
     checkVisibility(toolbarCtxMenu, false);
     toolbarCtxMenu.hidePopup();
 
     info("Check toolbar context menu without triggerNode");
     toolbarCtxMenu.openPopup();
     checkVisibility(toolbarCtxMenu, false);
     toolbarCtxMenu.hidePopup();
 
     info("Pin the browserAction and another button to the overflow menu");
     CustomizableUI.addWidgetToArea(buttonId, CustomizableUI.AREA_FIXED_OVERFLOW_PANEL);
     CustomizableUI.addWidgetToArea(otherButtonId, CustomizableUI.AREA_FIXED_OVERFLOW_PANEL);
 
     info("Wait until the overflow menu is ready");
-    let overflowButton = document.getElementById("nav-bar-overflow-button");
-    let icon = document.getAnonymousElementByAttribute(overflowButton, "class", "toolbarbutton-icon");
+    let overflowButton = win.document.getElementById("nav-bar-overflow-button");
+    let icon = win.document.getAnonymousElementByAttribute(overflowButton, "class", "toolbarbutton-icon");
     await waitForElementShown(icon);
 
     if (!customizing) {
       info("Open overflow menu");
-      let menu = document.getElementById("widget-overflow");
+      let menu = win.document.getElementById("widget-overflow");
       let shown = BrowserTestUtils.waitForEvent(menu, "popupshown");
       overflowButton.click();
       await shown;
     }
 
     info("Check overflow menu context menu in another button");
-    let overflowMenuCtxMenu = await openContextMenu("customizationPanelItemContextMenu", otherButtonId);
+    let overflowMenuCtxMenu = await openContextMenu("customizationPanelItemContextMenu", otherButtonId, win);
     checkVisibility(overflowMenuCtxMenu, false);
     overflowMenuCtxMenu.hidePopup();
 
     info("Test overflow menu context menu in browserAction");
     await testContextMenu(overflowMenuCtxMenu.id, customizing);
 
     info("Restore initial state");
     CustomizableUI.addWidgetToArea(buttonId, CustomizableUI.AREA_NAVBAR);
     CustomizableUI.addWidgetToArea(otherButtonId, CustomizableUI.AREA_NAVBAR);
 
     if (customizing) {
       info("Exit customize mode");
-      let afterCustomization = BrowserTestUtils.waitForEvent(gNavToolbox, "aftercustomization");
-      gCustomizeMode.exit();
+      let afterCustomization = BrowserTestUtils.waitForEvent(win.gNavToolbox, "aftercustomization");
+      win.gCustomizeMode.exit();
       await afterCustomization;
     }
   }
 
   await extension.startup();
 
   info("Add a dummy tab to prevent about:addons from being loaded in the initial about:blank tab");
-  let dummyTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.com", true, true);
+  let dummyTab = await BrowserTestUtils.openNewForegroundTab(win.gBrowser, "http://example.com", true, true);
 
   info("Run tests in normal mode");
   await main(false);
 
   info("Run tests in customize mode");
   await main(true);
 
   info("Close the dummy tab and finish");
-  gBrowser.removeTab(dummyTab);
+  win.gBrowser.removeTab(dummyTab);
   await extension.unload();
+
+  await BrowserTestUtils.closeWindow(win);
 });
 
 add_task(async function browseraction_contextmenu_remove_extension() {
+  // Do the customize mode shuffle in a separate window, because it interferes
+  // with other tests.
+  let win = await BrowserTestUtils.openNewBrowserWindow();
   let id = "addon_id@example.com";
   let name = "Awesome Add-on";
   let buttonId = `${makeWidgetId(id)}-browser-action`;
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       name,
       "applications": {
         "gecko": {id},
@@ -278,64 +286,64 @@ add_task(async function browseraction_co
   };
   Services.prompt = promptService;
   registerCleanupFunction(() => {
     Services.prompt = prompt;
   });
 
   async function testContextMenu(menuId, customizing) {
     info(`Open browserAction context menu in ${menuId}`);
-    let menu = await openContextMenu(menuId, buttonId);
+    let menu = await openContextMenu(menuId, buttonId, win);
 
     info(`Choosing 'Remove Extension' in ${menuId} should show confirm dialog`);
     let removeExtension = menu.querySelector(".customize-context-removeExtension");
-    await closeChromeContextMenu(menuId, removeExtension);
+    await closeChromeContextMenu(menuId, removeExtension, win);
     is(promptService._confirmExArgs[1], `Remove ${name}`);
     is(promptService._confirmExArgs[2], `Remove ${name} from ${brand}?`);
     is(promptService._confirmExArgs[4], "Remove");
     return menu;
   }
 
   async function main(customizing) {
     if (customizing) {
       info("Enter customize mode");
-      let customizationReady = BrowserTestUtils.waitForEvent(gNavToolbox, "customizationready");
-      gCustomizeMode.enter();
+      let customizationReady = BrowserTestUtils.waitForEvent(win.gNavToolbox, "customizationready");
+      win.gCustomizeMode.enter();
       await customizationReady;
     }
 
     info("Test toolbar context menu in browserAction");
     await testContextMenu("toolbar-context-menu", customizing);
 
     info("Pin the browserAction and another button to the overflow menu");
     CustomizableUI.addWidgetToArea(buttonId, CustomizableUI.AREA_FIXED_OVERFLOW_PANEL);
 
     info("Wait until the overflow menu is ready");
-    let overflowButton = document.getElementById("nav-bar-overflow-button");
-    let icon = document.getAnonymousElementByAttribute(overflowButton, "class", "toolbarbutton-icon");
+    let overflowButton = win.document.getElementById("nav-bar-overflow-button");
+    let icon = win.document.getAnonymousElementByAttribute(overflowButton, "class", "toolbarbutton-icon");
     await waitForElementShown(icon);
 
     if (!customizing) {
       info("Open overflow menu");
-      let menu = document.getElementById("widget-overflow");
+      let menu = win.document.getElementById("widget-overflow");
       let shown = BrowserTestUtils.waitForEvent(menu, "popupshown");
       overflowButton.click();
       await shown;
     }
 
     info("Test overflow menu context menu in browserAction");
     await testContextMenu("customizationPanelItemContextMenu", customizing);
 
     info("Restore initial state");
     CustomizableUI.addWidgetToArea(buttonId, CustomizableUI.AREA_NAVBAR);
 
     if (customizing) {
       info("Exit customize mode");
-      let afterCustomization = BrowserTestUtils.waitForEvent(gNavToolbox, "aftercustomization");
-      gCustomizeMode.exit();
+      let afterCustomization = BrowserTestUtils.waitForEvent(win.gNavToolbox, "aftercustomization");
+      win.gCustomizeMode.exit();
       await afterCustomization;
     }
   }
 
   await extension.startup();
 
   info("Run tests in normal mode");
   await main(false);
@@ -358,9 +366,11 @@ add_task(async function browseraction_co
   });
   await testContextMenu("toolbar-context-menu", false);
   await uninstalled;
 
   addon = await AddonManager.getAddonByID(id);
   ok(!addon, "Addon has been uninstalled");
 
   await extension.unload();
+
+  await BrowserTestUtils.closeWindow(win);
 });
--- a/browser/components/extensions/test/browser/browser_ext_omnibox.js
+++ b/browser/components/extensions/test/browser/browser_ext_omnibox.js
@@ -295,16 +295,20 @@ add_task(async function() {
     test: "test-multiple-suggest-calls",
     suggestions,
   });
   await testSuggestions({
     test: "test-suggestions-after-delay",
     suggestions,
   });
 
+  // When we're the first task to be added, `waitForExplicitFinish()` may not have
+  // been called yet. Let's just do that, otherwise the `monitorConsole` will make
+  // the test fail with a failing assertion.
+  SimpleTest.waitForExplicitFinish();
   // Start monitoring the console.
   let waitForConsole = new Promise(resolve => {
     SimpleTest.monitorConsole(resolve, [{
       message: new RegExp(`The keyword provided is already registered: "${keyword}"`),
     }]);
   });
 
   // Try registering another extension with the same keyword
--- a/browser/components/extensions/test/browser/browser_ext_search.js
+++ b/browser/components/extensions/test/browser/browser_ext_search.js
@@ -54,21 +54,21 @@ add_task(async function test_search() {
       },
     },
     background: `(${background})("${SEARCH_TERM}")`,
     useAddonManager: "temporary",
   });
   await extension.startup();
 
   let addonEngines = await extension.awaitMessage("engines");
-  let engines = Services.search.getEngines().filter(engine => !engine.hidden);
+  let engines = (await Services.search.getEngines()).filter(engine => !engine.hidden);
   is(addonEngines.length, engines.length, "Engine lengths are the same.");
   let defaultEngine = addonEngines.filter(engine => engine.isDefault === true);
   is(defaultEngine.length, 1, "One default engine");
-  is(defaultEngine[0].name, Services.search.defaultEngine.name, "Default engine is correct");
+  is(defaultEngine[0].name, (await Services.search.getDefault()).name, "Default engine is correct");
 
   let url = await extension.awaitMessage("searchLoaded");
   is(url, SEARCH_URL.replace("{searchTerms}", SEARCH_TERM + "1"), "Loaded page matches search");
 
   url = await extension.awaitMessage("searchLoaded");
   is(url, SEARCH_URL.replace("{searchTerms}", SEARCH_TERM + "2"), "Loaded page matches search");
 
   await extension.unload();
--- a/browser/components/extensions/test/browser/browser_ext_settings_overrides_default_search.js
+++ b/browser/components/extensions/test/browser/browser_ext_settings_overrides_default_search.js
@@ -4,23 +4,27 @@
 "use strict";
 
 ChromeUtils.defineModuleGetter(this, "AddonManager",
                                "resource://gre/modules/AddonManager.jsm");
 
 const EXTENSION1_ID = "extension1@mozilla.com";
 const EXTENSION2_ID = "extension2@mozilla.com";
 
-let defaultEngineName = Services.search.defaultEngine.name;
+var defaultEngineName;
 
-function restoreDefaultEngine() {
+async function restoreDefaultEngine() {
   let engine = Services.search.getEngineByName(defaultEngineName);
-  Services.search.defaultEngine = engine;
+  await Services.search.setDefault(engine);
 }
-registerCleanupFunction(restoreDefaultEngine);
+
+add_task(async function setup() {
+  defaultEngineName = (await Services.search.getDefault()).name;
+  registerCleanupFunction(restoreDefaultEngine);
+});
 
 /* This tests setting a default engine. */
 add_task(async function test_extension_setting_default_engine() {
   let ext1 = ExtensionTestUtils.loadExtension({
     manifest: {
       "chrome_settings_overrides": {
         "search_provider": {
           "name": "DuckDuckGo",
@@ -29,21 +33,21 @@ add_task(async function test_extension_s
         },
       },
     },
     useAddonManager: "temporary",
   });
 
   await ext1.startup();
 
-  is(Services.search.defaultEngine.name, "DuckDuckGo", "Default engine is DuckDuckGo");
+  is((await Services.search.getDefault()).name, "DuckDuckGo", "Default engine is DuckDuckGo");
 
   await ext1.unload();
 
-  is(Services.search.defaultEngine.name, defaultEngineName, `Default engine is ${defaultEngineName}`);
+  is((await Services.search.getDefault()).name, defaultEngineName, `Default engine is ${defaultEngineName}`);
 });
 
 /* This tests that uninstalling add-ons maintains the proper
  * search default. */
 add_task(async function test_extension_setting_multiple_default_engine() {
   let ext1 = ExtensionTestUtils.loadExtension({
     manifest: {
       "chrome_settings_overrides": {
@@ -67,29 +71,29 @@ add_task(async function test_extension_s
         },
       },
     },
     useAddonManager: "temporary",
   });
 
   await ext1.startup();
 
-  is(Services.search.defaultEngine.name, "DuckDuckGo", "Default engine is DuckDuckGo");
+  is((await Services.search.getDefault()).name, "DuckDuckGo", "Default engine is DuckDuckGo");
 
   await ext2.startup();
 
-  is(Services.search.defaultEngine.name, "Twitter", "Default engine is Twitter");
+  is((await Services.search.getDefault()).name, "Twitter", "Default engine is Twitter");
 
   await ext2.unload();
 
-  is(Services.search.defaultEngine.name, "DuckDuckGo", "Default engine is DuckDuckGo");
+  is((await Services.search.getDefault()).name, "DuckDuckGo", "Default engine is DuckDuckGo");
 
   await ext1.unload();
 
-  is(Services.search.defaultEngine.name, defaultEngineName, `Default engine is ${defaultEngineName}`);
+  is((await Services.search.getDefault()).name, defaultEngineName, `Default engine is ${defaultEngineName}`);
 });
 
 /* This tests that uninstalling add-ons in reverse order maintains the proper
  * search default. */
 add_task(async function test_extension_setting_multiple_default_engine_reversed() {
   let ext1 = ExtensionTestUtils.loadExtension({
     manifest: {
       "chrome_settings_overrides": {
@@ -113,29 +117,29 @@ add_task(async function test_extension_s
         },
       },
     },
     useAddonManager: "temporary",
   });
 
   await ext1.startup();
 
-  is(Services.search.defaultEngine.name, "DuckDuckGo", "Default engine is DuckDuckGo");
+  is((await Services.search.getDefault()).name, "DuckDuckGo", "Default engine is DuckDuckGo");
 
   await ext2.startup();
 
-  is(Services.search.defaultEngine.name, "Twitter", "Default engine is Twitter");
+  is((await Services.search.getDefault()).name, "Twitter", "Default engine is Twitter");
 
   await ext1.unload();
 
-  is(Services.search.defaultEngine.name, "Twitter", "Default engine is Twitter");
+  is((await Services.search.getDefault()).name, "Twitter", "Default engine is Twitter");
 
   await ext2.unload();
 
-  is(Services.search.defaultEngine.name, defaultEngineName, `Default engine is ${defaultEngineName}`);
+  is((await Services.search.getDefault()).name, defaultEngineName, `Default engine is ${defaultEngineName}`);
 });
 
 /* This tests that when the user changes the search engine and the add-on
  * is unistalled, search stays with the user's choice. */
 add_task(async function test_user_changing_default_engine() {
   let ext1 = ExtensionTestUtils.loadExtension({
     manifest: {
       "chrome_settings_overrides": {
@@ -146,24 +150,24 @@ add_task(async function test_user_changi
         },
       },
     },
     useAddonManager: "temporary",
   });
 
   await ext1.startup();
 
-  is(Services.search.defaultEngine.name, "DuckDuckGo", "Default engine is DuckDuckGo");
+  is((await Services.search.getDefault()).name, "DuckDuckGo", "Default engine is DuckDuckGo");
 
   let engine = Services.search.getEngineByName("Twitter");
-  Services.search.defaultEngine = engine;
+  await Services.search.setDefault(engine);
 
   await ext1.unload();
 
-  is(Services.search.defaultEngine.name, "Twitter", "Default engine is Twitter");
+  is((await Services.search.getDefault()).name, "Twitter", "Default engine is Twitter");
   restoreDefaultEngine();
 });
 
 /* This tests that when the user changes the search engine while it is
  * disabled, user choice is maintained when the add-on is reenabled. */
 add_task(async function test_user_change_with_disabling() {
   let ext1 = ExtensionTestUtils.loadExtension({
     manifest: {
@@ -180,37 +184,37 @@ add_task(async function test_user_change
         },
       },
     },
     useAddonManager: "temporary",
   });
 
   await ext1.startup();
 
-  is(Services.search.defaultEngine.name, "DuckDuckGo", "Default engine is DuckDuckGo");
+  is((await Services.search.getDefault()).name, "DuckDuckGo", "Default engine is DuckDuckGo");
 
   let engine = Services.search.getEngineByName("Twitter");
-  Services.search.defaultEngine = engine;
+  await Services.search.setDefault(engine);
 
-  is(Services.search.defaultEngine.name, "Twitter", "Default engine is Twitter");
+  is((await Services.search.getDefault()).name, "Twitter", "Default engine is Twitter");
 
   let disabledPromise = awaitEvent("shutdown", EXTENSION1_ID);
   let addon = await AddonManager.getAddonByID(EXTENSION1_ID);
   await addon.disable();
   await disabledPromise;
 
-  is(Services.search.defaultEngine.name, "Twitter", "Default engine is Twitter");
+  is((await Services.search.getDefault()).name, "Twitter", "Default engine is Twitter");
 
   let enabledPromise = awaitEvent("ready", EXTENSION1_ID);
   await addon.enable();
   await enabledPromise;
 
-  is(Services.search.defaultEngine.name, "Twitter", "Default engine is Twitter");
+  is((await Services.search.getDefault()).name, "Twitter", "Default engine is Twitter");
   await ext1.unload();
-  restoreDefaultEngine();
+  await restoreDefaultEngine();
 });
 
 /* This tests that when two add-ons are installed that change default
  * search and the first one is disabled, before the second one is installed,
  * when the first one is reenabled, the second add-on keeps the search. */
 add_task(async function test_two_addons_with_first_disabled_before_second() {
   let ext1 = ExtensionTestUtils.loadExtension({
     manifest: {
@@ -245,40 +249,40 @@ add_task(async function test_two_addons_
         },
       },
     },
     useAddonManager: "temporary",
   });
 
   await ext1.startup();
 
-  is(Services.search.defaultEngine.name, "DuckDuckGo", "Default engine is DuckDuckGo");
+  is((await Services.search.getDefault()).name, "DuckDuckGo", "Default engine is DuckDuckGo");
 
   let disabledPromise = awaitEvent("shutdown", EXTENSION1_ID);
   let addon1 = await AddonManager.getAddonByID(EXTENSION1_ID);
   await addon1.disable();
   await disabledPromise;
 
-  is(Services.search.defaultEngine.name, defaultEngineName, `Default engine is ${defaultEngineName}`);
+  is((await Services.search.getDefault()).name, defaultEngineName, `Default engine is ${defaultEngineName}`);
 
   await ext2.startup();
 
-  is(Services.search.defaultEngine.name, "Twitter", "Default engine is Twitter");
+  is((await Services.search.getDefault()).name, "Twitter", "Default engine is Twitter");
 
   let enabledPromise = awaitEvent("ready", EXTENSION1_ID);
   await addon1.enable();
   await enabledPromise;
 
-  is(Services.search.defaultEngine.name, "Twitter", "Default engine is Twitter");
+  is((await Services.search.getDefault()).name, "Twitter", "Default engine is Twitter");
   await ext2.unload();
 
-  is(Services.search.defaultEngine.name, "DuckDuckGo", "Default engine is DuckDuckGo");
+  is((await Services.search.getDefault()).name, "DuckDuckGo", "Default engine is DuckDuckGo");
   await ext1.unload();
 
-  is(Services.search.defaultEngine.name, defaultEngineName, `Default engine is ${defaultEngineName}`);
+  is((await Services.search.getDefault()).name, defaultEngineName, `Default engine is ${defaultEngineName}`);
 });
 
 /* This tests that when two add-ons are installed that change default
  * search and the first one is disabled, the second one maintains
  * the search. */
 add_task(async function test_two_addons_with_first_disabled() {
   let ext1 = ExtensionTestUtils.loadExtension({
     manifest: {
@@ -313,40 +317,40 @@ add_task(async function test_two_addons_
         },
       },
     },
     useAddonManager: "temporary",
   });
 
   await ext1.startup();
 
-  is(Services.search.defaultEngine.name, "DuckDuckGo", "Default engine is DuckDuckGo");
+  is((await Services.search.getDefault()).name, "DuckDuckGo", "Default engine is DuckDuckGo");
 
   await ext2.startup();
 
-  is(Services.search.defaultEngine.name, "Twitter", "Default engine is Twitter");
+  is((await Services.search.getDefault()).name, "Twitter", "Default engine is Twitter");
 
   let disabledPromise = awaitEvent("shutdown", EXTENSION1_ID);
   let addon1 = await AddonManager.getAddonByID(EXTENSION1_ID);
   await addon1.disable();
   await disabledPromise;
 
-  is(Services.search.defaultEngine.name, "Twitter", "Default engine is Twitter");
+  is((await Services.search.getDefault()).name, "Twitter", "Default engine is Twitter");
 
   let enabledPromise = awaitEvent("ready", EXTENSION1_ID);
   await addon1.enable();
   await enabledPromise;
 
-  is(Services.search.defaultEngine.name, "Twitter", "Default engine is Twitter");
+  is((await Services.search.getDefault()).name, "Twitter", "Default engine is Twitter");
   await ext2.unload();
 
-  is(Services.search.defaultEngine.name, "DuckDuckGo", "Default engine is DuckDuckGo");
+  is((await Services.search.getDefault()).name, "DuckDuckGo", "Default engine is DuckDuckGo");
   await ext1.unload();
 
-  is(Services.search.defaultEngine.name, defaultEngineName, `Default engine is ${defaultEngineName}`);
+  is((await Services.search.getDefault()).name, defaultEngineName, `Default engine is ${defaultEngineName}`);
 });
 
 /* This tests that when two add-ons are installed that change default
  * search and the second one is disabled, the first one properly
  * gets the search. */
 add_task(async function test_two_addons_with_second_disabled() {
   let ext1 = ExtensionTestUtils.loadExtension({
     manifest: {
@@ -381,33 +385,33 @@ add_task(async function test_two_addons_
         },
       },
     },
     useAddonManager: "temporary",
   });
 
   await ext1.startup();
 
-  is(Services.search.defaultEngine.name, "DuckDuckGo", "Default engine is DuckDuckGo");
+  is((await Services.search.getDefault()).name, "DuckDuckGo", "Default engine is DuckDuckGo");
 
   await ext2.startup();
 
-  is(Services.search.defaultEngine.name, "Twitter", "Default engine is Twitter");
+  is((await Services.search.getDefault()).name, "Twitter", "Default engine is Twitter");
 
   let disabledPromise = awaitEvent("shutdown", EXTENSION2_ID);
   let addon2 = await AddonManager.getAddonByID(EXTENSION2_ID);
   await addon2.disable();
   await disabledPromise;
 
-  is(Services.search.defaultEngine.name, "DuckDuckGo", "Default engine is DuckDuckGo");
+  is((await Services.search.getDefault()).name, "DuckDuckGo", "Default engine is DuckDuckGo");
 
   let enabledPromise = awaitEvent("ready", EXTENSION2_ID);
   await addon2.enable();
   await enabledPromise;
 
-  is(Services.search.defaultEngine.name, "Twitter", "Default engine is Twitter");
+  is((await Services.search.getDefault()).name, "Twitter", "Default engine is Twitter");
   await ext2.unload();
 
-  is(Services.search.defaultEngine.name, "DuckDuckGo", "Default engine is DuckDuckGo");
+  is((await Services.search.getDefault()).name, "DuckDuckGo", "Default engine is DuckDuckGo");
   await ext1.unload();
 
-  is(Services.search.defaultEngine.name, defaultEngineName, `Default engine is ${defaultEngineName}`);
+  is((await Services.search.getDefault()).name, defaultEngineName, `Default engine is ${defaultEngineName}`);
 });
--- a/browser/components/extensions/test/browser/browser_ext_webNavigation_urlbar_transitions.js
+++ b/browser/components/extensions/test/browser/browser_ext_webNavigation_urlbar_transitions.js
@@ -33,44 +33,36 @@ async function addBookmark(bookmark) {
     title: bookmark.title,
   });
 
   registerCleanupFunction(async function() {
     await PlacesUtils.bookmarks.eraseEverything();
   });
 }
 
-function addSearchEngine(basename) {
-  return new Promise((resolve, reject) => {
-    info("Waiting for engine to be added: " + basename);
-    let url = getRootDirectory(gTestPath) + basename;
-    Services.search.addEngine(url, "", false, {
-      onSuccess: (engine) => {
-        info(`Search engine added: ${basename}`);
-        registerCleanupFunction(() => Services.search.removeEngine(engine));
-        resolve(engine);
-      },
-      onError: (errCode) => {
-        ok(false, `addEngine failed with error code ${errCode}`);
-        reject();
-      },
-    });
-  });
+async function addSearchEngine(basename) {
+  info("Waiting for engine to be added: " + basename);
+  let url = getRootDirectory(gTestPath) + basename;
+  let engine = await Services.search.addEngine(url, "", false);
+
+  info(`Search engine added: ${basename}`);
+  registerCleanupFunction(async () => Services.search.removeEngine(engine));
+  return engine;
 }
 
 async function prepareSearchEngine() {
-  let oldDefaultEngine = Services.search.defaultEngine;
+  let oldDefaultEngine = await Services.search.getDefault();
   let suggestionsEnabled = Services.prefs.getBoolPref(SUGGEST_URLBAR_PREF);
   Services.prefs.setBoolPref(SUGGEST_URLBAR_PREF, true);
   let engine = await addSearchEngine(TEST_ENGINE_BASENAME);
-  Services.search.defaultEngine = engine;
+  await Services.search.setDefault(engine);
 
   registerCleanupFunction(async function() {
     Services.prefs.setBoolPref(SUGGEST_URLBAR_PREF, suggestionsEnabled);
-    Services.search.defaultEngine = oldDefaultEngine;
+    await Services.search.setDefault(oldDefaultEngine);
 
     // Make sure the popup is closed for the next test.
     gURLBar.blur();
     gURLBar.popup.selectedIndex = -1;
     gURLBar.popup.hidePopup();
     ok(!gURLBar.popup.popupOpen, "popup should be closed");
 
     // Clicking suggestions causes visits to search results pages, so clear that
--- a/browser/components/extensions/test/xpcshell/test_ext_chrome_settings_overrides_update.js
+++ b/browser/components/extensions/test/xpcshell/test_ext_chrome_settings_overrides_update.js
@@ -56,26 +56,26 @@ add_task(async function test_overrides_u
           "is_default": true,
         },
       },
     },
   };
   let extension = ExtensionTestUtils.loadExtension(extensionInfo);
 
   let defaultHomepageURL = HomePage.get();
-  let defaultEngineName = Services.search.defaultEngine.name;
+  let defaultEngineName = (await Services.search.getDefault()).name;
 
   let prefPromise = promisePrefChanged(HOMEPAGE_URI);
   await extension.startup();
   await prefPromise;
 
   equal(extension.version, "1.0", "The installed addon has the expected version.");
   ok(HomePage.get().endsWith(HOMEPAGE_URI),
      "Home page url is overridden by the extension.");
-  equal(Services.search.defaultEngine.name,
+  equal((await Services.search.getDefault()).name,
         "DuckDuckGo",
         "Default engine is overridden by the extension");
 
   extensionInfo.manifest = {
     "version": "2.0",
     "applications": {
       "gecko": {
         "id": EXTENSION_ID,
@@ -86,16 +86,16 @@ add_task(async function test_overrides_u
   prefPromise = promisePrefChanged(defaultHomepageURL);
   await extension.upgrade(extensionInfo);
   await prefPromise;
 
   equal(extension.version, "2.0", "The updated addon has the expected version.");
   equal(HomePage.get(),
         defaultHomepageURL,
         "Home page url reverted to the default after update.");
-  equal(Services.search.defaultEngine.name,
+  equal((await Services.search.getDefault()).name,
         defaultEngineName,
         "Default engine reverted to the default after update.");
 
   await extension.unload();
 
   await promiseShutdownManager();
 });
--- a/browser/components/extensions/test/xpcshell/test_ext_settings_overrides_search.js
+++ b/browser/components/extensions/test/xpcshell/test_ext_settings_overrides_search.js
@@ -14,17 +14,17 @@ const kSearchTerm = "foo";
 const kSearchTermIntl = "日";
 const URLTYPE_SUGGEST_JSON = "application/x-suggestions+json";
 
 AddonTestUtils.init(this);
 AddonTestUtils.createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "42", "42");
 
 add_task(async function setup() {
   await AddonTestUtils.promiseStartupManager();
-  Services.search.init();
+  await Services.search.init();
 });
 
 add_task(async function test_extension_adding_engine() {
   let ext1 = ExtensionTestUtils.loadExtension({
     manifest: {
       "icons": {
         "16": "foo.ico",
         "32": "foo32.ico",
@@ -113,18 +113,18 @@ add_task(async function test_upgrade_def
       "version": "0.1",
     },
     useAddonManager: "temporary",
   });
 
   await ext1.startup();
 
   let engine = Services.search.getEngineByName("MozSearch");
-  Services.search.defaultEngine = engine;
-  Services.search.moveEngine(engine, 1);
+  await Services.search.setDefault(engine);
+  await Services.search.moveEngine(engine, 1);
 
   await ext1.upgrade({
     manifest: {
       "chrome_settings_overrides": {
         "search_provider": {
           "name": "MozSearch",
           "keyword": "MozSearch",
           "search_url": "https://example.com/?q={searchTerms}",
@@ -137,17 +137,18 @@ add_task(async function test_upgrade_def
       },
       "version": "0.2",
     },
     useAddonManager: "temporary",
   });
 
   engine = Services.search.getEngineByName("MozSearch");
   equal(Services.search.defaultEngine, engine, "Default engine should still be MozSearch");
-  equal(Services.search.getEngines().indexOf(engine), 1, "Engine is in position 1");
+  equal((await Services.search.getEngines()).map(e => e.name).indexOf(engine.name),
+        1, "Engine is in position 1");
 
   await ext1.unload();
   await delay();
 
   engine = Services.search.getEngineByName("MozSearch");
   ok(!engine, "Engine should not exist");
 });
 
--- a/browser/components/extensions/test/xpcshell/test_ext_settings_overrides_search_mozParam.js
+++ b/browser/components/extensions/test/xpcshell/test_ext_settings_overrides_search_mozParam.js
@@ -11,17 +11,17 @@ AddonTestUtils.createAppInfo("xpcshell@t
 
 let {
   promiseShutdownManager,
   promiseStartupManager,
 } = AddonTestUtils;
 
 add_task(async function setup() {
   await promiseStartupManager();
-  Services.search.init();
+  await Services.search.init();
   registerCleanupFunction(async () => {
     await promiseShutdownManager();
   });
 });
 
 /* This tests setting moz params. */
 add_task(async function test_extension_setting_moz_params() {
   let defaultBranch = Services.prefs.getDefaultBranch("browser.search.");
--- a/browser/components/newtab/test/browser/browser_asrouter_targeting.js
+++ b/browser/components/newtab/test/browser/browser_asrouter_targeting.js
@@ -183,34 +183,34 @@ add_task(async function check_needsUpdat
   QueryCache.queries.CheckBrowserNeedsUpdate.setUp(false);
 
   is(await ASRouterTargeting.findMatchingMessage({messages: [message]}), null,
     "Should not select message because update count == 0");
 });
 
 add_task(async function checksearchEngines() {
   const result = await ASRouterTargeting.Environment.searchEngines;
-  const expectedInstalled = Services.search.getVisibleEngines()
+  const expectedInstalled = (await Services.search.getVisibleEngines())
     .map(engine => engine.identifier)
     .sort()
     .join(",");
   ok(result.installed.length,
     "searchEngines.installed should be a non-empty array");
   is(result.installed.sort().join(","), expectedInstalled,
     "searchEngines.installed should be an array of visible search engines");
   ok(result.current && typeof result.current === "string",
     "searchEngines.current should be a truthy string");
-  is(result.current, Services.search.defaultEngine.identifier,
+  is(result.current, (await Services.search.getDefault()).identifier,
     "searchEngines.current should be the current engine name");
 
-  const message = {id: "foo", targeting: `searchEngines[.current == ${Services.search.defaultEngine.identifier}]`};
+  const message = {id: "foo", targeting: `searchEngines[.current == ${(await Services.search.getDefault()).identifier}]`};
   is(await ASRouterTargeting.findMatchingMessage({messages: [message]}), message,
     "should select correct item by searchEngines.current");
 
-  const message2 = {id: "foo", targeting: `searchEngines[${Services.search.getVisibleEngines()[0].identifier} in .installed]`};
+  const message2 = {id: "foo", targeting: `searchEngines[${(await Services.search.getVisibleEngines())[0].identifier} in .installed]`};
   is(await ASRouterTargeting.findMatchingMessage({messages: [message2]}), message2,
     "should select correct item by searchEngines.installed");
 });
 
 add_task(async function checkisDefaultBrowser() {
   const expected = ShellService.isDefaultBrowser();
   const result = ASRouterTargeting.Environment.isDefaultBrowser;
   is(typeof result, "boolean",
--- a/browser/components/newtab/test/unit/lib/TopSitesFeed.test.js
+++ b/browser/components/newtab/test/unit/lib/TopSitesFeed.test.js
@@ -1119,17 +1119,17 @@ describe("Top Sites Feed", () => {
       assert.equal(feed.store.dispatch.firstCall.args[0].data.links[0].url, url);
       assert.equal(feed.store.dispatch.secondCall.args[0].data.links[0].url, FAKE_LINKS[0].url);
     });
   });
 
   describe("improvesearch.noDefaultSearchTile experiment", () => {
     const NO_DEFAULT_SEARCH_TILE_PREF = "improvesearch.noDefaultSearchTile";
     beforeEach(() => {
-      sandbox.stub(global.Services.search, "defaultEngine").value({identifier: "google", searchForm: "google.com"});
+      global.Services.search.getDefault = async () => {identifier: "google", searchForm: "google.com"};
       feed.store.state.Prefs.values[NO_DEFAULT_SEARCH_TILE_PREF] = true;
     });
     it("should filter out alexa top 5 search from the default sites", async () => {
       const TOP_5_TEST = [
         "google.com",
         "search.yahoo.com",
         "yahoo.com",
         "bing.com",
@@ -1157,17 +1157,17 @@ describe("Top Sites Feed", () => {
     it("should not filter out current default search from pinned sites even if it matches the current default search", async () => {
       links = [{url: "foo.com"}];
       fakeNewTabUtils.pinnedLinks.links = [{url: "google.com"}];
       const urlsReturned = (await feed.getLinksWithDefaults()).map(link => link.url);
       assert.include(urlsReturned, "google.com");
     });
     it("should call refresh and set ._currentSearchHostname to the new engine hostname when the the default search engine has been set", () => {
       sinon.stub(feed, "refresh");
-      sandbox.stub(global.Services.search, "defaultEngine").value({identifier: "ddg", searchForm: "duckduckgo.com"});
+      global.Services.search.getDefault = async () => {identifier: "ddg", searchForm: "duckduckgo.com"};
       feed.observe(null, "browser-search-engine-modified", "engine-current");
       assert.equal(feed._currentSearchHostname, "duckduckgo");
       assert.calledOnce(feed.refresh);
     });
     it("should call refresh when the experiment pref has changed", () => {
       sinon.stub(feed, "refresh");
 
       feed.onAction({type: at.PREF_CHANGED, data: {name: NO_DEFAULT_SEARCH_TILE_PREF, value: true}});
@@ -1182,17 +1182,17 @@ describe("Top Sites Feed", () => {
     beforeEach(() => {
       feed.store.state.Prefs.values[SEARCH_SHORTCUTS_EXPERIMENT_PREF] = true;
       feed.store.state.Prefs.values[SEARCH_SHORTCUTS_SEARCH_ENGINES_PREF] = "google,amazon";
       feed.store.state.Prefs.values[SEARCH_SHORTCUTS_HAVE_PINNED_PREF] = "";
       const searchEngines = [
         {wrappedJSObject: {_internalAliases: ["@google"]}},
         {wrappedJSObject: {_internalAliases: ["@amazon"]}},
       ];
-      global.Services.search.getDefaultEngines = () => searchEngines;
+      global.Services.search.getDefaultEngines = async () => searchEngines;
       fakeNewTabUtils.pinnedLinks.pin = sinon.stub().callsFake((site, index) => {
         fakeNewTabUtils.pinnedLinks.links[index] = site;
       });
     });
 
     it("should properly disable search improvements if the pref is off", async () => {
       sandbox.stub(global.Services.prefs, "clearUserPref");
       sandbox.spy(feed.pinnedCache, "expire");
@@ -1356,17 +1356,17 @@ describe("Top Sites Feed", () => {
         fakeNewTabUtils.pinnedLinks.links[6] = {url: ""};
         await feed._maybeInsertSearchShortcuts(fakeNewTabUtils.pinnedLinks.links);
         assert.notOk(fakeNewTabUtils.pinnedLinks.links.find(s => s && s.url === "https://google.com"));
         assert.notOk(fakeNewTabUtils.pinnedLinks.links.find(s => s && s.url === "https://amazon.com"));
       });
 
       it("should not pin a shortcut if the corresponding search engine is not available", async () => {
         // Make Amazon search engine unavailable
-        global.Services.search.getDefaultEngines = () => [{wrappedJSObject: {_internalAliases: ["@google"]}}];
+        global.Services.search.getDefaultEngines = async () => [{wrappedJSObject: {_internalAliases: ["@google"]}}];
         fakeNewTabUtils.pinnedLinks.links.fill(null);
         await feed._maybeInsertSearchShortcuts(fakeNewTabUtils.pinnedLinks.links);
         assert.notOk(fakeNewTabUtils.pinnedLinks.links.find(s => s && s.url === "https://amazon.com"));
       });
 
       it("should not pin a search shortcut if it's been pinned before", async () => {
         fakeNewTabUtils.pinnedLinks.links.fill(null);
         feed.store.state.Prefs.values[SEARCH_SHORTCUTS_HAVE_PINNED_PREF] = "google,amazon";
--- a/browser/components/preferences/in-content/tests/browser_engines.js
+++ b/browser/components/preferences/in-content/tests/browser_engines.js
@@ -3,17 +3,17 @@ add_task(async function() {
   let prefs = await openPreferencesViaOpenPreferencesAPI("search", {leaveOpen: true});
   is(prefs.selectedPane, "paneSearch", "Search pane is selected by default");
   let doc = gBrowser.contentDocument;
 
   let tree = doc.querySelector("#engineList");
   ok(!tree.hidden, "The search engine list should be visible when Search is requested");
 
   // Check for default search engines to be displayed in the engineList
-  let defaultEngines = Services.search.getDefaultEngines();
+  let defaultEngines = await Services.search.getDefaultEngines();
   for (let i = 0; i < defaultEngines.length; i++) {
       let engine = defaultEngines[i];
       let cellName = tree.view.getCellText(i, tree.columns.getNamedColumn("engineName"));
       is(cellName, engine.name, "Default search engine " + engine.name + " displayed correctly");
   }
 
   // Avoid duplicated keywords
   tree.view.setCellText(0, tree.columns.getNamedColumn("engineKeyword"), "keyword");
--- a/browser/components/preferences/in-content/tests/browser_extension_controlled.js
+++ b/browser/components/preferences/in-content/tests/browser_extension_controlled.js
@@ -437,16 +437,20 @@ add_task(async function testExtensionCon
       search_provider: {
         name: "DuckDuckGo",
         search_url: "https://duckduckgo.com/?q={searchTerms}",
         is_default: true,
       },
     },
   };
 
+  // This test is comparing nsISearchEngines by reference, so we need to initialize
+  // the SearchService here.
+  await Services.search.init();
+
   function setEngine(engine) {
     doc.querySelector(`#defaultEngine menuitem[label="${engine.name}"]`)
        .doCommand();
   }
 
   is(gBrowser.currentURI.spec, "about:preferences#search",
      "#search should be in the URI for about:preferences");
 
@@ -486,16 +490,18 @@ add_task(async function testExtensionCon
   await waitForMessageHidden(controlledContent.id);
 
   is(initialEngine, Services.search.defaultEngine,
      "default search engine is set back to default");
   is(controlledContent.hidden, true, "The extension controlled row is hidden");
 
   // Setting the engine back to the extension's engine does not show the message.
   setEngine(extensionEngine);
+  // Wait a tick for the Search Service's promises to resolve.
+  await new Promise(resolve => executeSoon(resolve));
 
   is(extensionEngine, Services.search.defaultEngine,
      "default search engine is set back to extension");
   is(controlledContent.hidden, true, "The extension controlled row is still hidden");
 
   // Set the engine to the initial one and verify an upgrade doesn't change it.
   setEngine(initialEngine);
   await waitForMessageHidden(controlledContent.id);
--- a/browser/components/search/test/browser/SearchTestUtils.jsm
+++ b/browser/components/search/test/browser/SearchTestUtils.jsm
@@ -21,23 +21,14 @@ var SearchTestUtils = Object.freeze({
    * at the end of the test.
    *
    * @param {string}   url                     The URL of the engine to add.
    * @param {Function} registerCleanupFunction Pass the registerCleanupFunction
    *                                           from the test's scope.
    * @returns {Promise} Returns a promise that is resolved with the new engine
    *                    or rejected if it fails.
    */
-  promiseNewSearchEngine(url) {
-    return new Promise((resolve, reject) => {
-      Services.search.addEngine(url, "", false, {
-        onSuccess(engine) {
-          gTestGlobals.registerCleanupFunction(() => Services.search.removeEngine(engine));
-          resolve(engine);
-        },
-        onError(errCode) {
-          gTestGlobals.Assert.ok(false, `addEngine failed with error code ${errCode}`);
-          reject();
-        },
-      });
-    });
+  async promiseNewSearchEngine(url) {
+    let engine = await Services.search.addEngine(url, "", false);
+    gTestGlobals.registerCleanupFunction(async () => Services.search.removeEngine(engine));
+    return engine;
   },
 });
--- a/browser/components/search/test/browser/browser_426329.js
+++ b/browser/components/search/test/browser/browser_426329.js
@@ -102,16 +102,18 @@ function promiseRemoveEngine() {
     ss.removeEngine(engine);
   });
 }
 
 
 var preSelectedBrowser;
 var preTabNo;
 async function prepareTest() {
+  await Services.search.init();
+
   preSelectedBrowser = gBrowser.selectedBrowser;
   preTabNo = gBrowser.tabs.length;
   searchBar = BrowserSearch.searchBar;
 
   await SimpleTest.promiseFocus();
 
   if (document.activeElement == searchBar)
     return;
--- a/browser/components/search/test/browser/browser_addEngine.js
+++ b/browser/components/search/test/browser/browser_addEngine.js
@@ -96,10 +96,10 @@ function nextTest() {
     info("Running " + gCurrentTest.name);
     gCurrentTest.run();
   } else
     executeSoon(finish);
 }
 
 function test() {
   waitForExplicitFinish();
-  nextTest();
+  gSS.init().then(nextTest);
 }
--- a/browser/components/search/test/browser/browser_amazon.js
+++ b/browser/components/search/test/browser/browser_amazon.js
@@ -4,17 +4,19 @@
 /*
  * Test Amazon search plugin URLs
  */
 
 "use strict";
 
 const BROWSER_SEARCH_PREF = "browser.search.";
 
-function test() {
+add_task(async function test() {
+  await Services.search.init();
+
   let engine = Services.search.getEngineByName("Amazon.com");
   ok(engine, "Amazon.com");
 
   let base = "https://www.amazon.com/exec/obidos/external-search/?field-keywords=foo&ie=UTF-8&mode=blended&tag=mozilla-20&sourceid=Mozilla-search";
   let url;
 
   // Test search URLs (including purposes).
   url = engine.getSubmission("foo").uri.spec;
@@ -74,9 +76,9 @@ function test() {
           ],
           mozparams: {},
         },
       ],
     },
   };
 
   isSubObjectOf(EXPECTED_ENGINE, engine, "Amazon");
-}
+});
--- a/browser/components/search/test/browser/browser_bing.js
+++ b/browser/components/search/test/browser/browser_bing.js
@@ -4,17 +4,19 @@
 /*
  * Test Bing search plugin URLs
  */
 
 "use strict";
 
 const BROWSER_SEARCH_PREF = "browser.search.";
 
-function test() {
+add_task(async function test() {
+  await Services.search.init();
+
   let engine = Services.search.getEngineByName("Bing");
   ok(engine, "Bing");
 
   let base = "https://www.bing.com/search?q=foo&pc=MOZI";
   let url;
 
   // Test search URLs (including purposes).
   url = engine.getSubmission("foo").uri.spec;
@@ -110,9 +112,9 @@ function test() {
           ],
           mozparams: {},
         },
       ],
     },
   };
 
   isSubObjectOf(EXPECTED_ENGINE, engine, "Bing");
-}
+});
--- a/browser/components/search/test/browser/browser_contextmenu.js
+++ b/browser/components/search/test/browser/browser_contextmenu.js
@@ -1,16 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
  *  * http://creativecommons.org/publicdomain/zero/1.0/ */
 /*
  * Test searching for the selected text using the context menu
  */
 
 add_task(async function() {
   const ss = Services.search;
+  await ss.init();
   const ENGINE_NAME = "Foo";
   let contextMenu;
 
   // We want select events to be fired.
   await SpecialPowers.pushPrefEnv({set: [["dom.select_events.enabled", true]]});
 
   let envService = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
   let originalValue = envService.get("XPCSHELL_TEST_PROFILE_DIR");
--- a/browser/components/search/test/browser/browser_ddg.js
+++ b/browser/components/search/test/browser/browser_ddg.js
@@ -4,17 +4,19 @@
 /*
  * Test DuckDuckGo search plugin URLs
  */
 
 "use strict";
 
 const BROWSER_SEARCH_PREF = "browser.search.";
 
-function test() {
+add_task(async function test() {
+  await Services.search.init();
+
   let engine = Services.search.getEngineByName("DuckDuckGo");
   ok(engine, "DuckDuckGo");
 
   let base = "https://duckduckgo.com/?q=foo";
   let url;
 
   // Test search URLs (including purposes).
   url = engine.getSubmission("foo").uri.spec;
@@ -100,9 +102,9 @@ function test() {
             },
           ],
         },
       ],
     },
   };
 
   isSubObjectOf(EXPECTED_ENGINE, engine, "DuckDuckGo");
-}
+});
--- a/browser/components/search/test/browser/browser_eBay.js
+++ b/browser/components/search/test/browser/browser_eBay.js
@@ -4,17 +4,19 @@
 /*
  * Test eBay search plugin URLs
  */
 
 "use strict";
 
 const BROWSER_SEARCH_PREF = "browser.search.";
 
-function test() {
+add_task(async function test() {
+  await Services.search.init();
+
   let engine = Services.search.getEngineByName("eBay");
   ok(engine, "eBay");
 
   let base = "https://rover.ebay.com/rover/1/711-53200-19255-0/1?ff3=4&toolid=20004&campid=5338192028&customid=&mpre=https://www.ebay.com/sch/foo";
   let url;
 
   // Test search URLs (including purposes).
   url = engine.getSubmission("foo").uri.spec;
@@ -63,9 +65,9 @@ function test() {
           ],
           mozparams: {},
         },
       ],
     },
   };
 
   isSubObjectOf(EXPECTED_ENGINE, engine, "eBay");
-}
+});
--- a/browser/components/search/test/browser/browser_google.js
+++ b/browser/components/search/test/browser/browser_google.js
@@ -36,17 +36,19 @@ let expectedEngine = {
         ],
         mozparams: {
         },
       },
     ],
   },
 };
 
-function test() {
+add_task(async function test() {
+  await Services.search.init();
+
   let engine = Services.search.getEngineByName("Google");
   ok(engine, "Found Google search engine");
 
   let region = Services.prefs.getCharPref("browser.search.region");
   let code = "";
   switch (region) {
     case "US":
       code = "firefox-b-1-d";
@@ -90,9 +92,9 @@ function test() {
   is(Services.search.parseSubmissionURL(base).terms, "foo",
      "Check result parsing");
   let alternateBase = base.replace("www.google.com", "www.google.fr");
   is(Services.search.parseSubmissionURL(alternateBase).terms, "foo",
      "Check alternate domain");
 
   // Check all other engine properties.
   isSubObjectOf(expectedEngine, engine, "Google");
-}
+});
--- a/browser/components/search/test/browser/browser_google_behavior.js
+++ b/browser/components/search/test/browser/browser_google_behavior.js
@@ -54,16 +54,20 @@ function promiseContentSearchReady(brows
           content.removeEventListener("ContentSearchService", listener);
           resolve();
         }
       });
     });
   });
 }
 
+add_task(async function setup() {
+  await Services.search.init();
+});
+
 for (let engine of searchEngineDetails) {
   add_task(async function() {
     let previouslySelectedEngine = Services.search.defaultEngine;
 
     registerCleanupFunction(function() {
       Services.search.defaultEngine = previouslySelectedEngine;
     });
 
--- a/browser/components/search/test/browser/browser_hiddenOneOffs_cleanup.js
+++ b/browser/components/search/test/browser/browser_hiddenOneOffs_cleanup.js
@@ -1,54 +1,41 @@
 /* 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/. */
 const testPref = "Foo,FooDupe";
 
-function promiseNewEngine(basename) {
-  return new Promise((resolve, reject) => {
-    info("Waiting for engine to be added: " + basename);
-    Services.search.init({
-      onInitComplete() {
-        let url = getRootDirectory(gTestPath) + basename;
-        Services.search.addEngine(url, "", false, {
-          onSuccess(engine) {
-            info("Search engine added: " + basename);
-            resolve(engine);
-          },
-          onError(errCode) {
-            ok(false, "addEngine failed with error code " + errCode);
-            reject();
-          },
-        });
-      },
-    });
-  });
+async function promiseNewEngine(basename) {
+  info("Waiting for engine to be added: " + basename);
+  let url = getRootDirectory(gTestPath) + basename;
+  let engine = await Services.search.addEngine(url, "", false);
+  info("Search engine added: " + basename);
+  return engine;
 }
 
 add_task(async function test_remove() {
   await promiseNewEngine("testEngine_dupe.xml");
   await promiseNewEngine("testEngine.xml");
   Services.prefs.setCharPref("browser.search.hiddenOneOffs", testPref);
 
   info("Removing testEngine_dupe.xml");
-  Services.search.removeEngine(Services.search.getEngineByName("FooDupe"));
+  await Services.search.removeEngine(Services.search.getEngineByName("FooDupe"));
 
   let hiddenOneOffs =
     Services.prefs.getCharPref("browser.search.hiddenOneOffs").split(",");
 
   is(hiddenOneOffs.length, 1,
      "hiddenOneOffs has the correct engine count post removal.");
   is(hiddenOneOffs.some(x => x == "FooDupe"), false,
      "Removed Engine is not in hiddenOneOffs after removal");
   is(hiddenOneOffs.some(x => x == "Foo"), true,
      "Current hidden engine is not affected by removal.");
 
   info("Removing testEngine.xml");
-  Services.search.removeEngine(Services.search.getEngineByName("Foo"));
+  await Services.search.removeEngine(Services.search.getEngineByName("Foo"));
 
   is(Services.prefs.getCharPref("browser.search.hiddenOneOffs"), "",
      "hiddenOneOffs is empty after removing all hidden engines.");
 });
 
 add_task(async function test_add() {
   await promiseNewEngine("testEngine.xml");
   info("setting prefs to " + testPref);
@@ -77,23 +64,23 @@ add_task(async function test_diacritics(
   let hiddenOneOffs =
     Preferences.get("browser.search.hiddenOneOffs").split(",");
   is(hiddenOneOffs.some(x => x == diacritic_engine), false,
      "Observer cleans up added hidden engines that include a diacritic.");
 
   Preferences.set("browser.search.hiddenOneOffs", diacritic_engine);
 
   info("Removing testEngine_diacritics.xml");
-  Services.search.removeEngine(Services.search.getEngineByName(diacritic_engine));
+  await Services.search.removeEngine(Services.search.getEngineByName(diacritic_engine));
 
   hiddenOneOffs =
     Preferences.get("browser.search.hiddenOneOffs").split(",");
   is(hiddenOneOffs.some(x => x == diacritic_engine), false,
      "Observer cleans up removed hidden engines that include a diacritic.");
 });
 
-registerCleanupFunction(() => {
+registerCleanupFunction(async () => {
   info("Removing testEngine.xml");
-  Services.search.removeEngine(Services.search.getEngineByName("Foo"));
+  await Services.search.removeEngine(Services.search.getEngineByName("Foo"));
   info("Removing testEngine_dupe.xml");
-  Services.search.removeEngine(Services.search.getEngineByName("FooDupe"));
+  await Services.search.removeEngine(Services.search.getEngineByName("FooDupe"));
   Services.prefs.clearUserPref("browser.search.hiddenOneOffs");
 });
--- a/browser/components/search/test/browser/browser_hiddenOneOffs_diacritics.js
+++ b/browser/components/search/test/browser/browser_hiddenOneOffs_diacritics.js
@@ -14,20 +14,20 @@ let searchIcon;
 
 add_task(async function init() {
   let searchbar = await gCUITestUtils.addSearchBar();
   registerCleanupFunction(() => {
     gCUITestUtils.removeSearchBar();
   });
   searchIcon = searchbar.querySelector(".searchbar-search-button");
 
-  let defaultEngine = Services.search.defaultEngine;
+  let defaultEngine = await Services.search.getDefault();
   await promiseNewEngine("testEngine_diacritics.xml", {setAsCurrent: false});
-  registerCleanupFunction(() => {
-    Services.search.defaultEngine = defaultEngine;
+  registerCleanupFunction(async () => {
+    await Services.search.setDefault(defaultEngine);
     Services.prefs.clearUserPref("browser.search.hiddenOneOffs");
   });
 });
 
 add_task(async function test_hidden() {
   Preferences.set("browser.search.hiddenOneOffs", diacritic_engine);
 
   let promise = promiseEvent(searchPopup, "popupshown");
--- a/browser/components/search/test/browser/browser_oneOffContextMenu_setDefault.js
+++ b/browser/components/search/test/browser/browser_oneOffContextMenu_setDefault.js
@@ -7,27 +7,28 @@ const URLBAR_BASE_ID = "urlbar-engine-on
 const ONEOFF_URLBAR_PREF = "browser.urlbar.oneOffSearches";
 
 const urlbar = document.getElementById("urlbar");
 const searchPopup = document.getElementById("PopupSearchAutoComplete");
 const urlbarPopup = document.getElementById("PopupAutoCompleteRichResult");
 const searchOneOff = searchPopup.oneOffButtons;
 const urlBarOneOff = urlbarPopup.oneOffSearchButtons;
 
-let originalEngine = Services.search.defaultEngine;
+var originalEngine;
 
-function resetEngine() {
-  Services.search.defaultEngine = originalEngine;
+async function resetEngine() {
+  await Services.search.setDefault(originalEngine);
 }
 
 registerCleanupFunction(resetEngine);
 
 let searchIcon;
 
 add_task(async function init() {
+  originalEngine = await Services.search.getDefault();
   let searchbar = await gCUITestUtils.addSearchBar();
   registerCleanupFunction(() => {
     gCUITestUtils.removeSearchBar();
   });
   searchIcon = searchbar.querySelector(".searchbar-search-button");
 
   await promiseNewEngine(TEST_ENGINE_BASENAME, {
     setAsCurrent: false,
@@ -79,17 +80,17 @@ add_task(async function test_urlBarChang
 
   // Click the set default engine menu item.
   let promise = promisedefaultEngineChanged();
   EventUtils.synthesizeMouseAtCenter(setDefaultEngineMenuItem, {});
 
   // This also checks the engine correctly changed.
   await promise;
 
-  let defaultEngine = Services.search.defaultEngine;
+  let defaultEngine = await Services.search.getDefault();
 
   // For the urlbar, we should keep the new engine's icon.
   Assert.equal(oneOffButton.id, URLBAR_BASE_ID + defaultEngine.name,
                "Should now have the original engine's id for the button");
   Assert.equal(oneOffButton.getAttribute("tooltiptext"), defaultEngine.name,
                "Should now have the original engine's name for the tooltip");
   Assert.equal(oneOffButton.image, defaultEngine.iconURI.spec,
                "Should now have the original engine's uri for the image");
--- a/browser/components/search/test/browser/browser_oneOffHeader.js
+++ b/browser/components/search/test/browser/browser_oneOffHeader.js
@@ -126,18 +126,17 @@ add_task(async function test_text() {
     document.getAnonymousElementByAttribute(searchPopup, "anonid",
                                             "searchbar-engine");
 
   await synthesizeNativeMouseMove(searchbarEngine);
   SimpleTest.executeSoon(() => {
     EventUtils.synthesizeMouseAtCenter(searchbarEngine, {});
   });
 
-  let url = Services.search.defaultEngine
-                           .getSubmission(searchbar.textbox.value).uri.spec;
+  let url = (await Services.search.getDefault()).getSubmission(searchbar.textbox.value).uri.spec;
   await promiseTabLoadEvent(gBrowser.selectedTab, url);
 
   // Move the cursor out of the panel area to avoid messing with other tests.
   await synthesizeNativeMouseMove(searchbar);
 });
 
 add_task(async function cleanup() {
   searchbar.textbox.value = "";
--- a/browser/components/search/test/browser/browser_searchEngine_behaviors.js
+++ b/browser/components/search/test/browser/browser_searchEngine_behaviors.js
@@ -76,31 +76,31 @@ add_task(async function test_setup() {
   await gCUITestUtils.addSearchBar();
   registerCleanupFunction(() => {
     gCUITestUtils.removeSearchBar();
   });
 });
 
 for (let engine of SEARCH_ENGINE_DETAILS) {
   add_task(async function() {
-    let previouslySelectedEngine = Services.search.defaultEngine;
+    let previouslySelectedEngine = await Services.search.getDefault();
 
-    registerCleanupFunction(function() {
-      Services.search.defaultEngine = previouslySelectedEngine;
+    registerCleanupFunction(async function() {
+      await Services.search.setDefault(previouslySelectedEngine);
     });
 
     await testSearchEngine(engine);
   });
 }
 
 async function testSearchEngine(engineDetails) {
   let engine = Services.search.getEngineByName(engineDetails.name);
   Assert.ok(engine, `${engineDetails.name} is installed`);
 
-  Services.search.defaultEngine = engine;
+  await Services.search.setDefault(engine);
   engine.alias = engineDetails.alias;
 
   let base = engineDetails.baseURL;
 
   // Test search URLs (including purposes).
   let url = engine.getSubmission("foo").uri.spec;
   Assert.equal(url, base + engineDetails.codes.submission, "Check search URL for 'foo'");
   let sb = BrowserSearch.searchBar;
--- a/browser/components/search/test/browser/head.js
+++ b/browser/components/search/test/browser/head.js
@@ -53,49 +53,35 @@ function promiseEvent(aTarget, aEventNam
  *   - {String} [iconURL]       The icon to use for the search engine.
  *   - {Boolean} [setAsCurrent] Whether to set the new engine to be the
  *                              current engine or not.
  *   - {String} [testPath]      Used to override the current test path if this
  *                              file is used from a different directory.
  * @returns {Promise} The promise is resolved once the engine is added, or
  *                    rejected if the addition failed.
  */
-function promiseNewEngine(basename, options = {}) {
-  return new Promise((resolve, reject) => {
-    // Default the setAsCurrent option to true.
-    let setAsCurrent =
-      options.setAsCurrent == undefined ? true : options.setAsCurrent;
-    info("Waiting for engine to be added: " + basename);
-    Services.search.init({
-      onInitComplete() {
-        let url = getRootDirectory(options.testPath || gTestPath) + basename;
-        let current = Services.search.defaultEngine;
-        Services.search.addEngine(url, options.iconURL || "", false, {
-          onSuccess(engine) {
-            info("Search engine added: " + basename);
-            if (setAsCurrent) {
-              Services.search.defaultEngine = engine;
-            }
-            registerCleanupFunction(() => {
-              if (setAsCurrent) {
-                Services.search.defaultEngine = current;
-              }
-              Services.search.removeEngine(engine);
-              info("Search engine removed: " + basename);
-            });
-            resolve(engine);
-          },
-          onError(errCode) {
-            ok(false, "addEngine failed with error code " + errCode);
-            reject();
-          },
-        });
-      },
-    });
+async function promiseNewEngine(basename, options = {}) {
+  // Default the setAsCurrent option to true.
+  let setAsCurrent = options.setAsCurrent == undefined ? true : options.setAsCurrent;
+  info("Waiting for engine to be added: " + basename);
+  let url = getRootDirectory(options.testPath || gTestPath) + basename;
+  let current = await Services.search.getDefault();
+  let engine = await Services.search.addEngine(url, options.iconURL || "", false);
+  info("Search engine added: " + basename);
+  if (setAsCurrent) {
+    await Services.search.setDefault(engine);
+  }
+  registerCleanupFunction(async () => {
+    if (setAsCurrent) {
+      await Services.search.setDefault(current);
+    }
+    await Services.search.removeEngine(engine);
+    info("Search engine removed: " + basename);
   });
+  return engine;
 }
 
 let promiseStateChangeFrameScript = "data:," + encodeURIComponent(`(${
   () => {
     ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
     /* globals docShell, sendAsyncMessage */
 
--- a/browser/components/tests/unit/test_distribution.js
+++ b/browser/components/tests/unit/test_distribution.js
@@ -141,17 +141,12 @@ add_task(async function() {
   Assert.equal(defaultBranch.getComplexValue("distribution.test.locale.set", Ci.nsIPrefLocalizedString).data, "Locale Set");
   // This value was overridden by a language specific setting
   Assert.equal(defaultBranch.getComplexValue("distribution.test.language.set", Ci.nsIPrefLocalizedString).data, "Language Set");
   // Language should not override locale
   Assert.notEqual(defaultBranch.getComplexValue("distribution.test.locale.set", Ci.nsIPrefLocalizedString).data, "Language Set");
 
   Services.prefs.setCharPref("distribution.searchplugins.defaultLocale", "de-DE");
 
-  await new Promise(resolve => {
-    Services.search.init(function() {
-      Assert.equal(Services.search.isInitialized, true);
-      var engine = Services.search.getEngineByName("Google");
-      Assert.equal(engine.description, "override-de-DE");
-      resolve();
-    });
-  });
+  await Services.search.init();
+  var engine = Services.search.getEngineByName("Google");
+  Assert.equal(engine.description, "override-de-DE");
 });
--- a/browser/components/uitour/test/browser_UITour.js
+++ b/browser/components/uitour/test/browser_UITour.js
@@ -352,58 +352,52 @@ var tests = [
 
           // Cleanup
           CustomizableUI.removeWidgetFromArea("panic-button");
           done();
         });
       });
     });
   },
-  function test_search(done) {
-    Services.search.init(rv => {
-      if (!Components.isSuccessCode(rv)) {
-        ok(false, "search service init failed: " + rv);
-        done();
-        return;
-      }
-      let defaultEngine = Services.search.defaultEngine;
-      gContentAPI.getConfiguration("search", data => {
-        let visibleEngines = Services.search.getVisibleEngines();
-        let expectedEngines = visibleEngines.filter((engine) => engine.identifier)
-                                            .map((engine) => "searchEngine-" + engine.identifier);
+  taskify(async function test_search() {
+    let defaultEngine = await Services.search.getDefault();
+    let visibleEngines = await Services.search.getVisibleEngines();
+    let expectedEngines = visibleEngines.filter((engine) => engine.identifier)
+                                        .map((engine) => "searchEngine-" + engine.identifier);
 
-        let engines = data.engines;
-        ok(Array.isArray(engines), "data.engines should be an array");
-        is(engines.sort().toString(), expectedEngines.sort().toString(),
-           "Engines should be as expected");
+    let data = await new Promise(resolve => gContentAPI.getConfiguration("search", resolve));
+    let engines = data.engines;
+    ok(Array.isArray(engines), "data.engines should be an array");
+    is(engines.sort().toString(), expectedEngines.sort().toString(),
+       "Engines should be as expected");
 
-        is(data.searchEngineIdentifier, defaultEngine.identifier,
-           "the searchEngineIdentifier property should contain the defaultEngine's identifier");
+    is(data.searchEngineIdentifier, defaultEngine.identifier,
+       "the searchEngineIdentifier property should contain the defaultEngine's identifier");
+
+    let someOtherEngineID = data.engines.filter(t => t != "searchEngine-" + defaultEngine.identifier)[0];
+    someOtherEngineID = someOtherEngineID.replace(/^searchEngine-/, "");
 
-        let someOtherEngineID = data.engines.filter(t => t != "searchEngine-" + defaultEngine.identifier)[0];
-        someOtherEngineID = someOtherEngineID.replace(/^searchEngine-/, "");
+    await new Promise(resolve => {
+      let observe = function(subject, topic, verb) {
+        info("browser-search-engine-modified: " + verb);
+        if (verb == "engine-current") {
+          is(Services.search.defaultEngine.identifier, someOtherEngineID, "correct engine was switched to");
+          done();
+        }
+      };
+      Services.obs.addObserver(observe, "browser-search-engine-modified");
+      registerCleanupFunction(async () => {
+        // Clean up
+        Services.obs.removeObserver(observe, "browser-search-engine-modified");
+        await Services.search.setDefault(defaultEngine);
+      });
 
-        let observe = function(subject, topic, verb) {
-          info("browser-search-engine-modified: " + verb);
-          if (verb == "engine-current") {
-            is(Services.search.defaultEngine.identifier, someOtherEngineID, "correct engine was switched to");
-            done();
-          }
-        };
-        Services.obs.addObserver(observe, "browser-search-engine-modified");
-        registerCleanupFunction(() => {
-          // Clean up
-          Services.obs.removeObserver(observe, "browser-search-engine-modified");
-          Services.search.defaultEngine = defaultEngine;
-        });
-
-        gContentAPI.setDefaultSearchEngine(someOtherEngineID);
-      });
+      gContentAPI.setDefaultSearchEngine(someOtherEngineID);
     });
-  },
+  }),
   taskify(async function test_treatment_tag() {
     let ac = new TelemetryArchiveTesting.Checker();
     await ac.promiseInit();
     await gContentAPI.setTreatmentTag("foobar", "baz");
     // Wait until the treatment telemetry is sent before looking in the archive.
     await BrowserTestUtils.waitForContentEvent(gTestTab.linkedBrowser, "mozUITourNotification", false,
                                                event => event.detail.event === "TreatmentTag:TelemetrySent");
     await new Promise((resolve) => {
--- a/browser/components/uitour/test/browser_UITour3.js
+++ b/browser/components/uitour/test/browser_UITour3.js
@@ -148,25 +148,19 @@ add_UITour_task(async function test_info
 
   // Cleanup.
   await hideInfoPromise();
 
   popup.removeAttribute("animate");
 });
 
 add_UITour_task(async function test_getConfiguration_selectedSearchEngine() {
-  await new Promise((resolve) => {
-    Services.search.init(async function(rv) {
-      ok(Components.isSuccessCode(rv), "Search service initialized");
-      let engine = Services.search.defaultEngine;
-      let data = await getConfigurationPromise("selectedSearchEngine");
-      is(data.searchEngineIdentifier, engine.identifier, "Correct engine identifier");
-      resolve();
-    });
-  });
+  let engine = await Services.search.getDefault();
+  let data = await getConfigurationPromise("selectedSearchEngine");
+  is(data.searchEngineIdentifier, engine.identifier, "Correct engine identifier");
 });
 
 add_UITour_task(async function test_setSearchTerm() {
   // Place the search bar in the navigation toolbar temporarily.
   await SpecialPowers.pushPrefEnv({ set: [
     ["browser.search.widget.inNavBar", true],
   ]});
 
--- a/browser/components/urlbar/tests/unit/test_UrlbarUtils_getShortcutOrURIAndPostData.js
+++ b/browser/components/urlbar/tests/unit/test_UrlbarUtils_getShortcutOrURIAndPostData.js
@@ -133,23 +133,25 @@ async function setupKeywords() {
   for (let item of testData) {
     let data = item[0];
     if (data instanceof bmKeywordData) {
       await PlacesUtils.bookmarks.insert({ url: data.uri, parentGuid: folder.guid });
       await PlacesUtils.keywords.insert({ keyword: data.keyword, url: data.uri.spec, postData: data.postData });
     }
 
     if (data instanceof searchKeywordData) {
-      Services.search.addEngineWithDetails(data.keyword, "", data.keyword, "", data.method, data.uri.spec);
+      await Services.search.addEngineWithDetails(data.keyword, "", data.keyword, "", data.method, data.uri.spec);
       let addedEngine = Services.search.getEngineByName(data.keyword);
       if (data.postData) {
         let [paramName, paramValue] = data.postData.split("=");
         addedEngine.addParam(paramName, paramValue, null);
       }
       gAddedEngines.push(addedEngine);
     }
   }
 }
 
 async function cleanupKeywords() {
   await PlacesUtils.bookmarks.remove(folder);
-  gAddedEngines.map(Services.search.removeEngine);
+  for (let engine of gAddedEngines)
+    await Services.search.removeEngine(engine);
+  gAddedEngines = [];
 }
--- a/browser/modules/test/browser/browser_ContentSearch.js
+++ b/browser/modules/test/browser/browser_ContentSearch.js
@@ -6,30 +6,32 @@ const TEST_MSG = "ContentSearchTest";
 const CONTENT_SEARCH_MSG = "ContentSearch";
 const TEST_CONTENT_SCRIPT_BASENAME = "contentSearch.js";
 
 /* import-globals-from ../../../components/search/test/browser/head.js */
 Services.scriptloader.loadSubScript(
   "chrome://mochitests/content/browser/browser/components/search/test/browser/head.js",
   this);
 
-let originalEngine = Services.search.defaultEngine;
+var originalEngine;
 
 add_task(async function setup() {
+  originalEngine = await Services.search.getDefault();
+
   await SpecialPowers.pushPrefEnv({
     set: [["browser.newtab.preload", false]],
   });
 
   await promiseNewEngine("testEngine.xml", {
     setAsCurrent: true,
     testPath: "chrome://mochitests/content/browser/browser/components/search/test/browser/",
   });
 
-  registerCleanupFunction(() => {
-    Services.search.defaultEngine = originalEngine;
+  registerCleanupFunction(async () => {
+    await Services.search.setDefault(originalEngine);
   });
 });
 
 add_task(async function GetState() {
   let { mm } = await addTab();
   mm.sendAsyncMessage(TEST_MSG, {
     type: "GetState",
   });
@@ -38,18 +40,18 @@ add_task(async function GetState() {
     type: "State",
     data: await currentStateObj(),
   });
 });
 
 add_task(async function SetDefaultEngine() {
   let { mm } = await addTab();
   let newDefaultEngine = null;
-  let oldDefaultEngine = Services.search.defaultEngine;
-  let engines = Services.search.getVisibleEngines();
+  let oldDefaultEngine = await Services.search.getDefault();
+  let engines = await Services.search.getVisibleEngines();
   for (let engine of engines) {
     if (engine != oldDefaultEngine) {
       newDefaultEngine = engine;
       break;
     }
   }
   if (!newDefaultEngine) {
     info("Couldn't find a non-selected search engine, " +
@@ -73,27 +75,27 @@ add_task(async function SetDefaultEngine
   info("Waiting for test to observe engine-current...");
   await deferred.promise;
   let msg = await searchPromise;
   checkMsg(msg, {
     type: "CurrentEngine",
     data: await defaultEngineObj(newDefaultEngine),
   });
 
-  Services.search.defaultEngine = oldDefaultEngine;
+  await Services.search.setDefault(oldDefaultEngine);
   msg = await waitForTestMsg(mm, "CurrentEngine");
   checkMsg(msg, {
     type: "CurrentEngine",
     data: await defaultEngineObj(oldDefaultEngine),
   });
 });
 
 add_task(async function modifyEngine() {
   let { mm } = await addTab();
-  let engine = Services.search.defaultEngine;
+  let engine = await Services.search.getDefault();
   let oldAlias = engine.alias;
   engine.alias = "ContentSearchTest";
   let msg = await waitForTestMsg(mm, "CurrentState");
   checkMsg(msg, {
     type: "CurrentState",
     data: await currentStateObj(),
   });
   engine.alias = oldAlias;
@@ -101,17 +103,17 @@ add_task(async function modifyEngine() {
   checkMsg(msg, {
     type: "CurrentState",
     data: await currentStateObj(),
   });
 });
 
 add_task(async function search() {
   let { browser } = await addTab();
-  let engine = Services.search.defaultEngine;
+  let engine = await Services.search.getDefault();
   let data = {
     engineName: engine.name,
     searchString: "ContentSearchTest",
     healthReportKey: "ContentSearchTest",
     searchPurpose: "ContentSearchTest",
   };
   let submissionURL =
     engine.getSubmission(data.searchString, "", data.whence).uri.spec;
@@ -120,17 +122,17 @@ add_task(async function search() {
 });
 
 add_task(async function searchInBackgroundTab() {
   // This test is like search(), but it opens a new tab after starting a search
   // in another.  In other words, it performs a search in a background tab.  The
   // search page should be loaded in the same tab that performed the search, in
   // the background tab.
   let { browser } = await addTab();
-  let engine = Services.search.defaultEngine;
+  let engine = await Services.search.getDefault();
   let data = {
     engineName: engine.name,
     searchString: "ContentSearchTest",
     healthReportKey: "ContentSearchTest",
     searchPurpose: "ContentSearchTest",
   };
   let submissionURL =
     engine.getSubmission(data.searchString, "", data.whence).uri.spec;
@@ -159,17 +161,17 @@ add_task(async function badImage() {
      "Sanity check: icon array buffer of engine in expected state " +
      "should be null: " + expectedEngine.iconBuffer);
   checkMsg(finalCurrentStateMsg, {
     type: "CurrentState",
     data: expectedCurrentState,
   });
   // Removing the engine triggers a final CurrentState message.  Wait for it so
   // it doesn't trip up subsequent tests.
-  Services.search.removeEngine(engine);
+  await Services.search.removeEngine(engine);
   await waitForTestMsg(mm, "CurrentState");
 });
 
 add_task(async function GetSuggestions_AddFormHistoryEntry_RemoveFormHistoryEntry() {
   let { mm } = await addTab();
 
   // Add the test engine that provides suggestions.
   let vals = await waitForNewEngine(mm, "contentSearchSuggestions.xml", 0);
@@ -244,17 +246,17 @@ add_task(async function GetSuggestions_A
       engineName: engine.name,
       searchString: searchStr,
       formHistory: [],
       remote: [searchStr + "foo", searchStr + "bar"],
     },
   });
 
   // Finally, clean up by removing the test engine.
-  Services.search.removeEngine(engine);
+  await Services.search.removeEngine(engine);
   await waitForTestMsg(mm, "CurrentState");
 });
 
 async function performSearch(browser, data, expectedURL) {
   let mm = browser.messageManager;
   let stoppedPromise = BrowserTestUtils.browserStopped(browser, expectedURL);
   mm.sendAsyncMessage(TEST_MSG, {
     type: "Search",
@@ -328,30 +330,18 @@ function waitForNewEngine(mm, basename, 
   let expectedSearchEvents = ["CurrentState", "CurrentState"];
   // engine-changed for each of the images
   for (let i = 0; i < numImages; i++) {
     expectedSearchEvents.push("CurrentState");
   }
   let eventPromises = expectedSearchEvents.map(e => waitForTestMsg(mm, e));
 
   // Wait for addEngine().
-  let addDeferred = PromiseUtils.defer();
   let url = getRootDirectory(gTestPath) + basename;
-  Services.search.addEngine(url, "", false, {
-    onSuccess(engine) {
-      info("Search engine added: " + basename);
-      addDeferred.resolve(engine);
-    },
-    onError(errCode) {
-      ok(false, "addEngine failed with error code " + errCode);
-      addDeferred.reject();
-    },
-  });
-
-  return Promise.all([addDeferred.promise].concat(eventPromises));
+  return Promise.all([Services.search.addEngine(url, "", false)].concat(eventPromises));
 }
 
 async function addTab() {
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:newtab");
   registerCleanupFunction(() => gBrowser.removeTab(tab));
 
   let url = getRootDirectory(gTestPath) + TEST_CONTENT_SCRIPT_BASENAME;
   let mm = tab.linkedBrowser.messageManager;
@@ -359,30 +349,30 @@ async function addTab() {
   return { browser: tab.linkedBrowser, mm };
 }
 
 var currentStateObj = async function() {
   let state = {
     engines: [],
     currentEngine: await defaultEngineObj(),
   };
-  for (let engine of Services.search.getVisibleEngines()) {
+  for (let engine of await Services.search.getVisibleEngines()) {
     let uri = engine.getIconURLBySize(16, 16);
     state.engines.push({
       name: engine.name,
       iconBuffer: await arrayBufferFromDataURI(uri),
       hidden: false,
       identifier: engine.identifier,
     });
   }
   return state;
 };
 
 var defaultEngineObj = async function() {
-  let engine = Services.search.defaultEngine;
+  let engine = await Services.search.getDefault();
   let uriFavicon = engine.getIconURLBySize(16, 16);
   let bundle = Services.strings.createBundle("chrome://global/locale/autocomplete.properties");
   return {
     name: engine.name,
     placeholder: bundle.formatStringFromName("searchWithEngine", [engine.name], 1),
     iconBuffer: await arrayBufferFromDataURI(uriFavicon),
   };
 };
--- a/browser/modules/test/browser/browser_UsageTelemetry_content.js
+++ b/browser/modules/test/browser/browser_UsageTelemetry_content.js
@@ -3,47 +3,47 @@
 const BASE_PROBE_NAME = "browser.engagement.navigation.";
 const SCALAR_CONTEXT_MENU = BASE_PROBE_NAME + "contextmenu";
 const SCALAR_ABOUT_NEWTAB = BASE_PROBE_NAME + "about_newtab";
 
 add_task(async function setup() {
   // Create two new search engines. Mark one as the default engine, so
   // the test don't crash. We need to engines for this test as the searchbar
   // in content doesn't display the default search engine among the one-off engines.
-  Services.search.addEngineWithDetails("MozSearch", "", "mozalias", "", "GET",
-                                       "http://example.com/?q={searchTerms}");
+  await Services.search.addEngineWithDetails("MozSearch", "", "mozalias", "", "GET",
+                                             "http://example.com/?q={searchTerms}");
 
-  Services.search.addEngineWithDetails("MozSearch2", "", "mozalias2", "", "GET",
-                                       "http://example.com/?q={searchTerms}");
+  await Services.search.addEngineWithDetails("MozSearch2", "", "mozalias2", "", "GET",
+                                             "http://example.com/?q={searchTerms}");
 
   // Make the first engine the default search engine.
   let engineDefault = Services.search.getEngineByName("MozSearch");
-  let originalEngine = Services.search.defaultEngine;
-  Services.search.defaultEngine = engineDefault;
+  let originalEngine = await Services.search.getDefault();
+  await Services.search.setDefault(engineDefault);
 
   // Move the second engine at the beginning of the one-off list.
   let engineOneOff = Services.search.getEngineByName("MozSearch2");
-  Services.search.moveEngine(engineOneOff, 0);
+  await Services.search.moveEngine(engineOneOff, 0);
 
   await SpecialPowers.pushPrefEnv({"set": [
     ["dom.select_events.enabled", true], // We want select events to be fired.
   ]});
 
   // Enable local telemetry recording for the duration of the tests.
   let oldCanRecord = Services.telemetry.canRecordExtended;
   Services.telemetry.canRecordExtended = true;
 
   // Enable event recording for the events tested here.
   Services.telemetry.setEventRecordingEnabled("navigation", true);
 
   // Make sure to restore the engine once we're done.
   registerCleanupFunction(async function() {
-    Services.search.defaultEngine = originalEngine;
-    Services.search.removeEngine(engineDefault);
-    Services.search.removeEngine(engineOneOff);
+    await Services.search.setDefault(originalEngine);
+    await Services.search.removeEngine(engineDefault);
+    await Services.search.removeEngine(engineOneOff);
     await PlacesUtils.history.clear();
     Services.telemetry.setEventRecordingEnabled("navigation", false);
     Services.telemetry.canRecordExtended = oldCanRecord;
   });
 });
 
 add_task(async function test_context_menu() {
   // Let's reset the Telemetry data.
--- a/browser/modules/test/browser/browser_UsageTelemetry_content_aboutHome.js
+++ b/browser/modules/test/browser/browser_UsageTelemetry_content_aboutHome.js
@@ -7,43 +7,43 @@ add_task(async function setup() {
   // allow it enougth time to save. So it throws. This disables all the uncaught
   // exception in this file and that's the reason why we split about:home tests
   // out of the other UsageTelemetry files.
   ignoreAllUncaughtExceptions();
 
   // Create two new search engines. Mark one as the default engine, so
   // the test don't crash. We need to engines for this test as the searchbar
   // in content doesn't display the default search engine among the one-off engines.
-  Services.search.addEngineWithDetails("MozSearch", "", "mozalias", "", "GET",
-                                       "http://example.com/?q={searchTerms}");
+  await Services.search.addEngineWithDetails("MozSearch", "", "mozalias", "", "GET",
+                                             "http://example.com/?q={searchTerms}");
 
-  Services.search.addEngineWithDetails("MozSearch2", "", "mozalias2", "", "GET",
-                                       "http://example.com/?q={searchTerms}");
+  await Services.search.addEngineWithDetails("MozSearch2", "", "mozalias2", "", "GET",
+                                             "http://example.com/?q={searchTerms}");
 
   // Make the first engine the default search engine.
   let engineDefault = Services.search.getEngineByName("MozSearch");
-  let originalEngine = Services.search.defaultEngine;
-  Services.search.defaultEngine = engineDefault;
+  let originalEngine = await Services.search.getDefault();
+  await Services.search.setDefault(engineDefault);
 
   // Move the second engine at the beginning of the one-off list.
   let engineOneOff = Services.search.getEngineByName("MozSearch2");
-  Services.search.moveEngine(engineOneOff, 0);
+  await Services.search.moveEngine(engineOneOff, 0);
 
   // Enable local telemetry recording for the duration of the tests.
   let oldCanRecord = Services.telemetry.canRecordExtended;
   Services.telemetry.canRecordExtended = true;
 
   // Enable event recording for the events tested here.
   Services.telemetry.setEventRecordingEnabled("navigation", true);
 
   // Make sure to restore the engine once we're done.
   registerCleanupFunction(async function() {
-    Services.search.defaultEngine = originalEngine;
-    Services.search.removeEngine(engineDefault);
-    Services.search.removeEngine(engineOneOff);
+    await Services.search.setDefault(originalEngine);
+    await Services.search.removeEngine(engineDefault);
+    await Services.search.removeEngine(engineOneOff);
     await PlacesUtils.history.clear();
     Services.telemetry.setEventRecordingEnabled("navigation", false);
     Services.telemetry.canRecordExtended = oldCanRecord;
   });
 });
 
 add_task(async function test_abouthome_activitystream_simpleQuery() {
   // Let's reset the counts.
--- a/browser/modules/test/browser/browser_UsageTelemetry_searchbar.js
+++ b/browser/modules/test/browser/browser_UsageTelemetry_searchbar.js
@@ -56,44 +56,44 @@ add_task(async function setup() {
   await gCUITestUtils.addSearchBar();
   registerCleanupFunction(() => {
     gCUITestUtils.removeSearchBar();
   });
 
   // Create two new search engines. Mark one as the default engine, so
   // the test don't crash. We need to engines for this test as the searchbar
   // doesn't display the default search engine among the one-off engines.
-  Services.search.addEngineWithDetails("MozSearch", "", "mozalias", "", "GET",
-                                       "http://example.com/?q={searchTerms}");
+  await Services.search.addEngineWithDetails("MozSearch", "", "mozalias", "", "GET",
+                                             "http://example.com/?q={searchTerms}");
 
-  Services.search.addEngineWithDetails("MozSearch2", "", "mozalias2", "", "GET",
-                                       "http://example.com/?q={searchTerms}");
+  await Services.search.addEngineWithDetails("MozSearch2", "", "mozalias2", "", "GET",
+                                             "http://example.com/?q={searchTerms}");
 
   // Make the first engine the default search engine.
   let engineDefault = Services.search.getEngineByName("MozSearch");
-  let originalEngine = Services.search.defaultEngine;
-  Services.search.defaultEngine = engineDefault;
+  let originalEngine = await Services.search.getDefault();
+  await Services.search.setDefault(engineDefault);
 
   // Move the second engine at the beginning of the one-off list.
   let engineOneOff = Services.search.getEngineByName("MozSearch2");
-  Services.search.moveEngine(engineOneOff, 0);
+  await Services.search.moveEngine(engineOneOff, 0);
 
   // Enable local telemetry recording for the duration of the tests.
   let oldCanRecord = Services.telemetry.canRecordExtended;
   Services.telemetry.canRecordExtended = true;
 
   // Enable event recording for the events tested here.
   Services.telemetry.setEventRecordingEnabled("navigation", true);
 
   // Make sure to restore the engine once we're done.
-  registerCleanupFunction(function() {
+  registerCleanupFunction(async function() {
     Services.telemetry.canRecordExtended = oldCanRecord;
-    Services.search.defaultEngine = originalEngine;
-    Services.search.removeEngine(engineDefault);
-    Services.search.removeEngine(engineOneOff);
+    await Services.search.setDefault(originalEngine);
+    await Services.search.removeEngine(engineDefault);
+    await Services.search.removeEngine(engineOneOff);
     Services.telemetry.setEventRecordingEnabled("navigation", false);
   });
 });
 
 add_task(async function test_plainQuery() {
   // Let's reset the counts.
   Services.telemetry.clearScalars();
   Services.telemetry.clearEvents();
@@ -180,25 +180,19 @@ add_task(async function test_oneOff_ente
 add_task(async function test_oneOff_enterSelection() {
   // Let's reset the counts.
   Services.telemetry.clearScalars();
   let resultMethodHist = getAndClearHistogram("FX_SEARCHBAR_SELECTED_RESULT_METHOD");
 
   // Create an engine to generate search suggestions and add it as default
   // for this test.
   const url = getRootDirectory(gTestPath) + "usageTelemetrySearchSuggestions.xml";
-  let suggestionEngine = await new Promise((resolve, reject) => {
-    Services.search.addEngine(url, "", false, {
-      onSuccess(engine) { resolve(engine); },
-      onError() { reject(); },
-    });
-  });
-
-  let previousEngine = Services.search.defaultEngine;
-  Services.search.defaultEngine = suggestionEngine;
+  let suggestionEngine = await Services.search.addEngine(url, "", false);
+  let previousEngine = await Services.search.getDefault();
+  await Services.search.setDefault(suggestionEngine);
 
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
 
   info("Type a query. Suggestions should be generated by the test engine.");
   let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
   await searchInSearchbar("query");
 
   info("Select the second result, press Alt+Down to take us to the first one-off engine.");
@@ -207,18 +201,18 @@ add_task(async function test_oneOff_ente
   EventUtils.synthesizeKey("KEY_Enter");
   await p;
 
   let resultMethods = resultMethodHist.snapshot();
   checkHistogramResults(resultMethods,
     URLBAR_SELECTED_RESULT_METHODS.enterSelection,
     "FX_SEARCHBAR_SELECTED_RESULT_METHOD");
 
-  Services.search.defaultEngine = previousEngine;
-  Services.search.removeEngine(suggestionEngine);
+  await Services.search.setDefault(previousEngine);
+  await Services.search.removeEngine(suggestionEngine);
   BrowserTestUtils.removeTab(tab);
 });
 
 // Performs a search using a click on a one-off button.  This only tests the
 // FX_SEARCHBAR_SELECTED_RESULT_METHOD histogram since test_oneOff_enter covers
 // everything else.
 add_task(async function test_oneOff_click() {
   // Let's reset the counts.
@@ -248,25 +242,19 @@ add_task(async function test_suggestion_
   Services.telemetry.clearScalars();
   Services.telemetry.clearEvents();
   let resultMethodHist = getAndClearHistogram("FX_SEARCHBAR_SELECTED_RESULT_METHOD");
   let search_hist = getAndClearKeyedHistogram("SEARCH_COUNTS");
 
   // Create an engine to generate search suggestions and add it as default
   // for this test.
   const url = getRootDirectory(gTestPath) + "usageTelemetrySearchSuggestions.xml";
-  let suggestionEngine = await new Promise((resolve, reject) => {
-    Services.search.addEngine(url, "", false, {
-      onSuccess(engine) { resolve(engine); },
-      onError() { reject(); },
-    });
-  });
-
-  let previousEngine = Services.search.defaultEngine;
-  Services.search.defaultEngine = suggestionEngine;
+  let suggestionEngine = await Services.search.addEngine(url, "", false);
+  let previousEngine = await Services.search.getDefault();
+  await Services.search.setDefault(suggestionEngine);
 
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
 
   info("Perform a one-off search using the first engine.");
   let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
   await searchInSearchbar("query");
   info("Clicking the searchbar suggestion.");
   clickSearchbarSuggestion("queryfoo");
@@ -288,54 +276,48 @@ add_task(async function test_suggestion_
   checkEvents(events, [["navigation", "search", "searchbar", "suggestion", {engine: searchEngineId}]]);
 
   // Check the histograms as well.
   let resultMethods = resultMethodHist.snapshot();
   checkHistogramResults(resultMethods,
     URLBAR_SELECTED_RESULT_METHODS.click,
     "FX_SEARCHBAR_SELECTED_RESULT_METHOD");
 
-  Services.search.defaultEngine = previousEngine;
-  Services.search.removeEngine(suggestionEngine);
+  await Services.search.setDefault(previousEngine);
+  await Services.search.removeEngine(suggestionEngine);
   BrowserTestUtils.removeTab(tab);
 });
 
 // Selects and presses the Return (Enter) key on the first suggestion offered by
 // the test search engine.  This only tests the
 // FX_SEARCHBAR_SELECTED_RESULT_METHOD histogram since test_suggestion_click
 // covers everything else.
 add_task(async function test_suggestion_enterSelection() {
   // Let's reset the counts.
   Services.telemetry.clearScalars();
   let resultMethodHist = getAndClearHistogram("FX_SEARCHBAR_SELECTED_RESULT_METHOD");
 
   // Create an engine to generate search suggestions and add it as default
   // for this test.
   const url = getRootDirectory(gTestPath) + "usageTelemetrySearchSuggestions.xml";
-  let suggestionEngine = await new Promise((resolve, reject) => {
-    Services.search.addEngine(url, "", false, {
-      onSuccess(engine) { resolve(engine); },
-      onError() { reject(); },
-    });
-  });
-
-  let previousEngine = Services.search.defaultEngine;
-  Services.search.defaultEngine = suggestionEngine;
+  let suggestionEngine = await Services.search.addEngine(url, "", false);
+  let previousEngine = await Services.search.getDefault();
+  await Services.search.setDefault(suggestionEngine);
 
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
 
   info("Type a query. Suggestions should be generated by the test engine.");
   let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
   await searchInSearchbar("query");
   info("Select the second result and press Return.");
   EventUtils.synthesizeKey("KEY_ArrowDown");
   EventUtils.synthesizeKey("KEY_Enter");
   await p;
 
   let resultMethods = resultMethodHist.snapshot();
   checkHistogramResults(resultMethods,
     URLBAR_SELECTED_RESULT_METHODS.enterSelection,
     "FX_SEARCHBAR_SELECTED_RESULT_METHOD");
 
-  Services.search.defaultEngine = previousEngine;
-  Services.search.removeEngine(suggestionEngine);
+  await Services.search.setDefault(previousEngine);
+  await Services.search.removeEngine(suggestionEngine);
   BrowserTestUtils.removeTab(tab);
 });
--- a/browser/modules/test/browser/browser_UsageTelemetry_urlbar.js
+++ b/browser/modules/test/browser/browser_UsageTelemetry_urlbar.js
@@ -79,49 +79,43 @@ function clickURLBarSuggestion(entryName
 }
 
 /**
  * Create an engine to generate search suggestions and add it as default
  * for this test.
  */
 async function withNewSearchEngine(taskFn) {
   const url = getRootDirectory(gTestPath) + "usageTelemetrySearchSuggestions.xml";
-  let suggestionEngine = await new Promise((resolve, reject) => {
-    Services.search.addEngine(url, "", false, {
-      onSuccess(engine) { resolve(engine); },
-      onError() { reject(); },
-    });
-  });
-
-  let previousEngine = Services.search.defaultEngine;
-  Services.search.defaultEngine = suggestionEngine;
+  let suggestionEngine = await Services.search.addEngine(url, "", false);
+  let previousEngine = await Services.search.getDefault();
+  await Services.search.setDefault(suggestionEngine);
 
   try {
     await taskFn(suggestionEngine);
   } finally {
-    Services.search.defaultEngine = previousEngine;
-    Services.search.removeEngine(suggestionEngine);
+    await Services.search.setDefault(previousEngine);
+    await Services.search.removeEngine(suggestionEngine);
   }
 }
 
 add_task(async function setup() {
   // Create a new search engine.
-  Services.search.addEngineWithDetails("MozSearch", "", "mozalias", "", "GET",
-                                       "http://example.com/?q={searchTerms}");
+  await Services.search.addEngineWithDetails("MozSearch", "", "mozalias", "", "GET",
+                                             "http://example.com/?q={searchTerms}");
 
   // Make it the default search engine.
   let engine = Services.search.getEngineByName("MozSearch");
-  let originalEngine = Services.search.defaultEngine;
-  Services.search.defaultEngine = engine;
+  let originalEngine = await Services.search.getDefault();
+  await Services.search.setDefault(engine);
 
   // Give it some mock internal aliases.
   engine.wrappedJSObject.__internalAliases = ["@mozaliasfoo", "@mozaliasbar"];
 
   // And the first one-off engine.
-  Services.search.moveEngine(engine, 0);
+  await Services.search.moveEngine(engine, 0);
 
   // Enable search suggestions in the urlbar.
   let suggestionsEnabled = Services.prefs.getBoolPref(SUGGEST_URLBAR_PREF);
   Services.prefs.setBoolPref(SUGGEST_URLBAR_PREF, true);
 
   // Enable the urlbar one-off buttons.
   Services.prefs.setBoolPref(ONEOFF_URLBAR_PREF, true);
 
@@ -141,18 +135,18 @@ add_task(async function setup() {
   await SpecialPowers.pushPrefEnv({"set": [["browser.urlbar.maxHistoricalSearchSuggestions", 0]]});
 
   // Use the default matching bucket configuration.
   await SpecialPowers.pushPrefEnv({"set": [["browser.urlbar.matchBuckets", "general:5,suggestion:4"]]});
 
   // Make sure to restore the engine once we're done.
   registerCleanupFunction(async function() {
     Services.telemetry.canRecordExtended = oldCanRecord;
-    Services.search.defaultEngine = originalEngine;
-    Services.search.removeEngine(engine);
+    await Services.search.setDefault(originalEngine);
+    await Services.search.removeEngine(engine);
     Services.prefs.setBoolPref(SUGGEST_URLBAR_PREF, suggestionsEnabled);
     Services.prefs.clearUserPref(ONEOFF_URLBAR_PREF);
     await PlacesUtils.history.clear();
     Services.telemetry.setEventRecordingEnabled("navigation", false);
   });
 });
 
 add_task(async function test_simpleQuery() {
--- a/docshell/test/browser/browser_search_notification.js
+++ b/docshell/test/browser/browser_search_notification.js
@@ -1,30 +1,29 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 add_task(async function () {
   const kSearchEngineID = "test_urifixup_search_engine";
   const kSearchEngineURL = "http://localhost/?search={searchTerms}";
-  Services.search.addEngineWithDetails(kSearchEngineID, "", "", "", "get",
-                                       kSearchEngineURL);
+  await Services.search.addEngineWithDetails(kSearchEngineID, "", "", "", "get", kSearchEngineURL);
 
-  let oldDefaultEngine = Services.search.defaultEngine;
-  Services.search.defaultEngine = Services.search.getEngineByName(kSearchEngineID);
+  let oldDefaultEngine = await Services.search.getDefault();
+  await Services.search.setDefault(Services.search.getEngineByName(kSearchEngineID));
 
-  let selectedName = Services.search.defaultEngine.name;
+  let selectedName = (await Services.search.getDefault()).name;
   Assert.equal(selectedName, kSearchEngineID, "Check fake search engine is selected");
 
-  registerCleanupFunction(function() {
+  registerCleanupFunction(async function() {
     if (oldDefaultEngine) {
-      Services.search.defaultEngine = oldDefaultEngine;
+      await Services.search.setDefault(oldDefaultEngine);
     }
     let engine = Services.search.getEngineByName(kSearchEngineID);
     if (engine) {
-      Services.search.removeEngine(engine);
+      await Services.search.removeEngine(engine);
     }
   });
 
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
   gBrowser.selectedTab = tab;
 
   gURLBar.value = "firefox health report";
   gURLBar.handleCommand();
--- a/docshell/test/browser/browser_uriFixupIntegration.js
+++ b/docshell/test/browser/browser_uriFixupIntegration.js
@@ -3,31 +3,30 @@
 
 "use strict";
 
 const kSearchEngineID = "browser_urifixup_search_engine";
 const kSearchEngineURL = "http://example.com/?search={searchTerms}";
 
 add_task(async function setup() {
   // Add a new fake search engine.
-  Services.search.addEngineWithDetails(kSearchEngineID, "", "", "", "get",
-                                       kSearchEngineURL);
+  await Services.search.addEngineWithDetails(kSearchEngineID, "", "", "", "get", kSearchEngineURL);
 
-  let oldDefaultEngine = Services.search.defaultEngine;
-  Services.search.defaultEngine = Services.search.getEngineByName(kSearchEngineID);
+  let oldDefaultEngine = await Services.search.getDefault();
+  await Services.search.setDefault(Services.search.getEngineByName(kSearchEngineID));
 
   // Remove the fake engine when done.
-  registerCleanupFunction(() => {
+  registerCleanupFunction(async () => {
     if (oldDefaultEngine) {
-      Services.search.defaultEngine = oldDefaultEngine;
+      await Services.search.setDefault(oldDefaultEngine);
     }
 
     let engine = Services.search.getEngineByName(kSearchEngineID);
     if (engine) {
-      Services.search.removeEngine(engine);
+      await Services.search.removeEngine(engine);
     }
   });
 });
 
 add_task(async function test() {
   for (let searchParams of ["foo bar", "brokenprotocol:somethingelse"]) {
     // Add a new blank tab.
     gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, "about:blank");
--- a/docshell/test/unit/test_nsDefaultURIFixup_info.js
+++ b/docshell/test/unit/test_nsDefaultURIFixup_info.js
@@ -1,45 +1,13 @@
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
-var prefList = ["browser.fixup.typo.scheme", "keyword.enabled",
-                "browser.fixup.domainwhitelist.whitelisted"];
-for (let pref of prefList) {
-  Services.prefs.setBoolPref(pref, true);
-}
-
 const kSearchEngineID = "test_urifixup_search_engine";
 const kSearchEngineURL = "http://www.example.org/?search={searchTerms}";
-Services.search.addEngineWithDetails(kSearchEngineID, "", "", "", "get",
-                                     kSearchEngineURL);
-
-Services.io.getProtocolHandler("resource")
-        .QueryInterface(Ci.nsIResProtocolHandler)
-        .setSubstitution("search-plugins",
-                         Services.io.newURI("chrome://mozapps/locale/searchplugins/"));
-
-var oldDefaultEngine = Services.search.defaultEngine;
-Services.search.defaultEngine = Services.search.getEngineByName(kSearchEngineID);
-
-var selectedName = Services.search.defaultEngine.name;
-Assert.equal(selectedName, kSearchEngineID);
-
 const kForceHostLookup = "browser.fixup.dns_first_for_single_words";
-registerCleanupFunction(function() {
-  if (oldDefaultEngine) {
-    Services.search.defaultEngine = oldDefaultEngine;
-  }
-  let engine = Services.search.getEngineByName(kSearchEngineID);
-  if (engine) {
-    Services.search.removeEngine(engine);
-  }
-  Services.prefs.clearUserPref("keyword.enabled");
-  Services.prefs.clearUserPref("browser.fixup.typo.scheme");
-  Services.prefs.clearUserPref(kForceHostLookup);
-});
 
 var flagInputs = [
   Services.uriFixup.FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP,
   Services.uriFixup.FIXUP_FLAGS_MAKE_ALTERNATE_URI,
   Services.uriFixup.FIXUP_FLAG_FIX_SCHEME_TYPOS,
 ];
 
 flagInputs.concat([
@@ -526,32 +494,65 @@ if (Services.appinfo.OS.toLowerCase().st
     protocolChange: true,
   });
 }
 
 function sanitize(input) {
   return input.replace(/\r|\n/g, "").trim();
 }
 
+add_task(async function setup() {
+  var prefList = ["browser.fixup.typo.scheme", "keyword.enabled",
+                  "browser.fixup.domainwhitelist.whitelisted"];
+  for (let pref of prefList) {
+    Services.prefs.setBoolPref(pref, true);
+  }
+
+  Services.io.getProtocolHandler("resource")
+          .QueryInterface(Ci.nsIResProtocolHandler)
+          .setSubstitution("search-plugins",
+                           Services.io.newURI("chrome://mozapps/locale/searchplugins/"));
+
+  await Services.search.addEngineWithDetails(kSearchEngineID, "", "", "", "get", kSearchEngineURL);
+
+  var oldCurrentEngine = await Services.search.getDefault();
+  await Services.search.setDefault(Services.search.getEngineByName(kSearchEngineID));
+
+  var selectedName = (await Services.search.getDefault()).name;
+  Assert.equal(selectedName, kSearchEngineID);
+
+  registerCleanupFunction(async function() {
+    if (oldCurrentEngine) {
+      await Services.search.setDefault(oldCurrentEngine);
+    }
+    let engine = Services.search.getEngineByName(kSearchEngineID);
+    if (engine) {
+      await Services.search.removeEngine(engine);
+    }
+    Services.prefs.clearUserPref("keyword.enabled");
+    Services.prefs.clearUserPref("browser.fixup.typo.scheme");
+    Services.prefs.clearUserPref(kForceHostLookup);
+  });
+});
 
 var gSingleWordHostLookup = false;
-function run_test() {
+add_task(async function run_test() {
   // Only keywordlookup things should be affected by requiring a DNS lookup for single-word hosts:
   info("Check only keyword lookup testcases should be affected by requiring DNS for single hosts");
   let affectedTests = testcases.filter(t => !t.keywordLookup && t.affectedByDNSForSingleHosts);
   if (affectedTests.length) {
     for (let testcase of affectedTests) {
       info("Affected: " + testcase.input);
     }
   }
   Assert.equal(affectedTests.length, 0);
   do_single_test_run();
   gSingleWordHostLookup = true;
   do_single_test_run();
-}
+});
 
 function do_single_test_run() {
   Services.prefs.setBoolPref(kForceHostLookup, gSingleWordHostLookup);
 
   let relevantTests = gSingleWordHostLookup ? testcases.filter(t => t.keywordLookup) :
                                               testcases;
 
   for (let { input: testInput,
--- a/docshell/test/unit/test_nsDefaultURIFixup_search.js
+++ b/docshell/test/unit/test_nsDefaultURIFixup_search.js
@@ -1,39 +1,13 @@
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
 
-Services.prefs.setBoolPref("keyword.enabled", true);
-
 const kSearchEngineID = "test_urifixup_search_engine";
 const kSearchEngineURL = "http://www.example.org/?search={searchTerms}";
-Services.search.addEngineWithDetails(kSearchEngineID, "", "", "", "get",
-                                     kSearchEngineURL);
-
-Services.io.getProtocolHandler("resource")
-        .QueryInterface(Ci.nsIResProtocolHandler)
-        .setSubstitution("search-plugins",
-                         Services.io.newURI("chrome://mozapps/locale/searchplugins/"));
-
-var oldDefaultEngine = Services.search.defaultEngine;
-Services.search.defaultEngine = Services.search.getEngineByName(kSearchEngineID);
-
-var selectedName = Services.search.defaultEngine.name;
-Assert.equal(selectedName, kSearchEngineID);
-
-registerCleanupFunction(function() {
-  if (oldDefaultEngine) {
-    Services.search.defaultEngine = oldDefaultEngine;
-  }
-  let engine = Services.search.getEngineByName(kSearchEngineID);
-  if (engine) {
-    Services.search.removeEngine(engine);
-  }
-  Services.prefs.clearUserPref("keyword.enabled");
-});
 
 var isWin = AppConstants.platform == "win";
 
 var data = [
   {
     // Valid should not be changed.
     wrong: "https://example.com/this/is/a/test.html",
     fixed: "https://example.com/this/is/a/test.html",
@@ -99,16 +73,44 @@ var extProtocolSvc = Cc["@mozilla.org/ur
 if (extProtocolSvc && extProtocolSvc.externalProtocolHandlerExists("mailto")) {
   data.push({
     wrong: "mailto:foo@bar.com",
     fixed: "mailto:foo@bar.com",
   });
 }
 
 var len = data.length;
+
+add_task(async function setup() {
+  Services.prefs.setBoolPref("keyword.enabled", true);
+  Services.io.getProtocolHandler("resource")
+          .QueryInterface(Ci.nsIResProtocolHandler)
+          .setSubstitution("search-plugins",
+                           Services.io.newURI("chrome://mozapps/locale/searchplugins/"));
+
+  await Services.search.addEngineWithDetails(kSearchEngineID, "", "", "", "get", kSearchEngineURL);
+
+  var oldCurrentEngine = await Services.search.getDefault();
+  await Services.search.setDefault(Services.search.getEngineByName(kSearchEngineID));
+
+  var selectedName = (await Services.search.getDefault()).name;
+  Assert.equal(selectedName, kSearchEngineID);
+
+  registerCleanupFunction(async function() {
+    if (oldCurrentEngine) {
+      await Services.search.setDefault(oldCurrentEngine);
+    }
+    let engine = Services.search.getEngineByName(kSearchEngineID);
+    if (engine) {
+      await Services.search.removeEngine(engine);
+    }
+    Services.prefs.clearUserPref("keyword.enabled");
+  });
+});
+
 // Make sure we fix what needs fixing
 add_task(function test_fix_unknown_schemes() {
   for (let i = 0; i < len; ++i) {
     let item = data[i];
     let result =
       Services.uriFixup.createFixupURI(item.wrong,
                               Services.uriFixup.FIXUP_FLAG_FIX_SCHEME_TYPOS).spec;
     Assert.equal(result, item.fixed);
--- a/toolkit/components/places/tests/unifiedcomplete/head_autocomplete.js
+++ b/toolkit/components/places/tests/unifiedcomplete/head_autocomplete.js
@@ -515,28 +515,24 @@ add_task(async function ensure_search_en
 
   // Initialize the search service, but first set this geo IP pref to a dummy
   // string.  When the search service is initialized, it contacts the URI named
   // in this pref, which breaks the test since outside connections aren't
   // allowed.
   let geoPref = "browser.search.geoip.url";
   Services.prefs.setCharPref(geoPref, "");
   registerCleanupFunction(() => Services.prefs.clearUserPref(geoPref));
-  await new Promise(resolve => {
-    Services.search.init(resolve);
-  });
-
   // Remove any existing engines before adding ours.
-  for (let engine of Services.search.getEngines()) {
-    Services.search.removeEngine(engine);
+  for (let engine of await Services.search.getEngines()) {
+    await Services.search.removeEngine(engine);
   }
-  Services.search.addEngineWithDetails("MozSearch", "", "", "", "GET",
-                                       "http://s.example.com/search");
+  await Services.search.addEngineWithDetails("MozSearch", "", "", "", "GET",
+                                             "http://s.example.com/search");
   let engine = Services.search.getEngineByName("MozSearch");
-  Services.search.defaultEngine = engine;
+  await Services.search.setDefault(engine);
 });
 
 /**
  * Add a adaptive result for a given (url, string) tuple.
  * @param {string} aUrl
  *        The url to add an adaptive result for.
  * @param {string} aSearch
  *        The string to add an adaptive result for.
--- a/toolkit/components/places/tests/unifiedcomplete/test_PlacesSearchAutocompleteProvider.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_PlacesSearchAutocompleteProvider.js
@@ -2,62 +2,62 @@
  * 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/. */
 
 ChromeUtils.import("resource://gre/modules/PlacesSearchAutocompleteProvider.jsm");
 ChromeUtils.import("resource://testing-common/AppInfo.jsm");
 updateAppInfo();
 
 add_task(async function() {
+  await Services.search.init();
     // Tell the search service we are running in the US.  This also has the
     // desired side-effect of preventing our geoip lookup.
    Services.prefs.setCharPref("browser.search.region", "US");
    Services.prefs.setBoolPref("browser.search.geoSpecificDefaults", false);
 
    Services.search.restoreDefaultEngines();
    Services.search.resetToOriginalDefaultEngine();
 });
 
 add_task(async function search_engine_match() {
-  let engine = await promiseDefaultSearchEngine();
+  let engine = await Services.search.getDefault();
   let domain = engine.getResultDomain();
   let token = domain.substr(0, 1);
   let matchedEngine =
     await PlacesSearchAutocompleteProvider.engineForDomainPrefix(token);
   Assert.equal(matchedEngine, engine);
 });
 
 add_task(async function no_match() {
   Assert.equal(
     null,
     await PlacesSearchAutocompleteProvider.engineForDomainPrefix("test")
   );
 });
 
 add_task(async function hide_search_engine_nomatch() {
-  let engine = await promiseDefaultSearchEngine();
+  let engine = await Services.search.getDefault();
   let domain = engine.getResultDomain();
   let token = domain.substr(0, 1);
   let promiseTopic = promiseSearchTopic("engine-changed");
-  Services.search.removeEngine(engine);
-  await promiseTopic;
+  await Promise.all([Services.search.removeEngine(engine), promiseTopic]);
   Assert.ok(engine.hidden);
   let matchedEngine =
     await PlacesSearchAutocompleteProvider.engineForDomainPrefix(token);
   Assert.ok(!matchedEngine || matchedEngine.getResultDomain() != domain);
 });
 
 add_task(async function add_search_engine_match() {
   let promiseTopic = promiseSearchTopic("engine-added");
   Assert.equal(
     null,
     await PlacesSearchAutocompleteProvider.engineForDomainPrefix("bacon")
   );
-  Services.search.addEngineWithDetails("bacon", "", "pork", "Search Bacon",
-                                       "GET", "http://www.bacon.moz/?search={searchTerms}");
+  await Promise.all([Services.search.addEngineWithDetails("bacon", "", "pork", "Search Bacon",
+    "GET", "http://www.bacon.moz/?search={searchTerms}"), promiseTopic]);
   await promiseTopic;
   let matchedEngine =
     await PlacesSearchAutocompleteProvider.engineForDomainPrefix("bacon");
   Assert.ok(matchedEngine);
   Assert.equal(matchedEngine.searchForm, "http://www.bacon.moz");
   Assert.equal(matchedEngine.name, "bacon");
   Assert.equal(matchedEngine.iconURI, null);
 });
@@ -89,19 +89,18 @@ add_task(async function test_aliased_sea
 });
 
 add_task(async function test_aliased_search_engine_match_upper_case_alias() {
   let promiseTopic = promiseSearchTopic("engine-added");
   Assert.equal(
     null,
     await PlacesSearchAutocompleteProvider.engineForDomainPrefix("patch")
   );
-  Services.search.addEngineWithDetails("patch", "", "PR", "Search Patch",
-                                       "GET", "http://www.patch.moz/?search={searchTerms}");
-  await promiseTopic;
+  await Promise.all([Services.search.addEngineWithDetails("patch", "", "PR", "Search Patch",
+    "GET", "http://www.patch.moz/?search={searchTerms}"), promiseTopic]);
   // lower case
   let matchedEngine =
     await PlacesSearchAutocompleteProvider.engineForAlias("pr");
   Assert.ok(matchedEngine);
   Assert.equal(matchedEngine.name, "patch");
   Assert.equal(matchedEngine.alias, "PR");
   Assert.equal(matchedEngine.iconURI, null);
   // Upper case
@@ -116,28 +115,27 @@ add_task(async function test_aliased_sea
   Assert.equal(matchedEngine.name, "patch");
   Assert.equal(matchedEngine.alias, "PR");
   Assert.equal(matchedEngine.iconURI, null);
 });
 
 add_task(async function remove_search_engine_nomatch() {
   let engine = Services.search.getEngineByName("bacon");
   let promiseTopic = promiseSearchTopic("engine-removed");
-  Services.search.removeEngine(engine);
-  await promiseTopic;
+  await Promise.all([Services.search.removeEngine(engine), promiseTopic]);
   Assert.equal(
     null,
     await PlacesSearchAutocompleteProvider.engineForDomainPrefix("bacon")
   );
 });
 
 add_task(async function test_parseSubmissionURL_basic() {
   // Most of the logic of parseSubmissionURL is tested in the search service
   // itself, thus we only do a sanity check of the wrapper here.
-  let engine = await promiseDefaultSearchEngine();
+  let engine = await Services.search.getDefault();
   let submissionURL = engine.getSubmission("terms").uri.spec;
 
   let result = PlacesSearchAutocompleteProvider.parseSubmissionURL(submissionURL);
   Assert.equal(result.engineName, engine.name);
   Assert.equal(result.terms, "terms");
 
   result = PlacesSearchAutocompleteProvider.parseSubmissionURL("http://example.org/");
   Assert.equal(result, null);
@@ -145,24 +143,16 @@ add_task(async function test_parseSubmis
 
 add_task(async function test_builtin_aliased_search_engine_match() {
   let matchedEngine =
     await PlacesSearchAutocompleteProvider.engineForAlias("@google");
   Assert.ok(matchedEngine);
   Assert.equal(matchedEngine.name, "Google");
 });
 
-function promiseDefaultSearchEngine() {
-  return new Promise(resolve => {
-    Services.search.init( () => {
-      resolve(Services.search.defaultEngine);
-    });
-  });
-}
-
 function promiseSearchTopic(expectedVerb) {
   return new Promise(resolve => {
     Services.obs.addObserver( function observe(subject, topic, verb) {
       info("browser-search-engine-modified: " + verb);
       if (verb == expectedVerb) {
         Services.obs.removeObserver(observe, "browser-search-engine-modified");
         resolve();
       }
--- a/toolkit/components/places/tests/unifiedcomplete/test_autofill_search_engine_aliases.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_autofill_search_engine_aliases.js
@@ -6,24 +6,24 @@
 
 "use strict";
 
 const TEST_ENGINE_NAME = "test autofill aliases";
 const TEST_ENGINE_ALIAS = "@autofilltest";
 
 add_task(async function init() {
   // Add an engine with an "@" alias.
-  Services.search.addEngineWithDetails(TEST_ENGINE_NAME, {
+  await Services.search.addEngineWithDetails(TEST_ENGINE_NAME, {
     alias: TEST_ENGINE_ALIAS,
     template: "http://example.com/?search={searchTerms}",
   });
-  registerCleanupFunction(() => {
+  registerCleanupFunction(async () => {
     let engine = Services.search.getEngineByName(TEST_ENGINE_NAME);
     Assert.ok(engine);
-    Services.search.removeEngine(engine);
+    await Services.search.removeEngine(engine);
   });
 });
 
 // Searching for @autofi should autofill to @autofilltest.
 add_task(async function basic() {
   // Add a history visit that should normally match but for the fact that the
   // search uses an @ alias.  When an @ alias is autofilled, there should be no
   // other matches except the autofill heuristic match.
--- a/toolkit/components/places/tests/unifiedcomplete/test_autofill_search_engines.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_autofill_search_engines.js
@@ -10,18 +10,18 @@
 "use strict";
 
 add_task(async function searchEngines() {
   Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true);
 
   let schemes = ["http", "https"];
   for (let i = 0; i < schemes.length; i++) {
     let scheme = schemes[i];
-    Services.search.addEngineWithDetails("TestEngine", "", "", "", "GET",
-                                         scheme + "://www.example.com/");
+    await Services.search.addEngineWithDetails("TestEngine", "", "", "", "GET",
+                                               scheme + "://www.example.com/");
     let engine = Services.search.getEngineByName("TestEngine");
     engine.addParam("q", "{searchTerms}", null);
 
     await check_autocomplete({
       search: "ex",
       autofilled: "example.com/",
       completed: scheme + "://www.example.com/",
       matches: [{
@@ -164,13 +164,13 @@ add_task(async function searchEngines() 
 
     await check_autocomplete({
       search: "example/",
       autofilled: "example/",
       completed: "example/",
       matches: [],
     });
 
-    Services.search.removeEngine(engine);
+    await Services.search.removeEngine(engine);
   }
 
   await cleanup();
 });
--- a/toolkit/components/places/tests/unifiedcomplete/test_avoid_middle_complete.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_avoid_middle_complete.js
@@ -31,111 +31,111 @@ add_task(async function test_trailing_sp
     completed: "mo ",
   });
 
   await cleanup();
 });
 
 add_task(async function test_searchEngine_autofill() {
   Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true);
-  Services.search.addEngineWithDetails("CakeSearch", "", "", "",
-                                       "GET", "http://cake.search/");
+  await Services.search.addEngineWithDetails("CakeSearch", "", "", "",
+                                             "GET", "http://cake.search/");
   let engine = Services.search.getEngineByName("CakeSearch");
   engine.addParam("q", "{searchTerms}", null);
-  registerCleanupFunction(() => Services.search.removeEngine(engine));
+  registerCleanupFunction(async () => Services.search.removeEngine(engine));
 
   info("Should autoFill search engine if search string does not contains a space");
   await check_autocomplete({
     search: "ca",
     autofilled: "cake.search/",
     completed: "http://cake.search/",
   });
 
   await cleanup();
 });
 
 add_task(async function test_searchEngine_prefix_space_noautofill() {
   Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true);
-  Services.search.addEngineWithDetails("CupcakeSearch", "", "", "",
-                                       "GET", "http://cupcake.search/");
+  await Services.search.addEngineWithDetails("CupcakeSearch", "", "", "",
+                                             "GET", "http://cupcake.search/");
   let engine = Services.search.getEngineByName("CupcakeSearch");
   engine.addParam("q", "{searchTerms}", null);
-  registerCleanupFunction(() => Services.search.removeEngine(engine));
+  registerCleanupFunction(async () => Services.search.removeEngine(engine));
 
   info("Should not try to autoFill search engine if search string contains a space");
   await check_autocomplete({
     search: " cu",
     autofilled: " cu",
     completed: " cu",
   });
 
   await cleanup();
 });
 
 add_task(async function test_searchEngine_trailing_space_noautofill() {
   Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true);
-  Services.search.addEngineWithDetails("BaconSearch", "", "", "",
-                                       "GET", "http://bacon.search/");
+  await Services.search.addEngineWithDetails("BaconSearch", "", "", "",
+                                             "GET", "http://bacon.search/");
   let engine = Services.search.getEngineByName("BaconSearch");
   engine.addParam("q", "{searchTerms}", null);
-  registerCleanupFunction(() => Services.search.removeEngine(engine));
+  registerCleanupFunction(async () => Services.search.removeEngine(engine));
 
   info("Should not try to autoFill search engine if search string contains a space");
   await check_autocomplete({
     search: "ba ",
     autofilled: "ba ",
     completed: "ba ",
   });
 
   await cleanup();
 });
 
 add_task(async function test_searchEngine_www_noautofill() {
   Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true);
-  Services.search.addEngineWithDetails("HamSearch", "", "", "",
-                                       "GET", "http://ham.search/");
+  await Services.search.addEngineWithDetails("HamSearch", "", "", "",
+                                             "GET", "http://ham.search/");
   let engine = Services.search.getEngineByName("HamSearch");
   engine.addParam("q", "{searchTerms}", null);
-  registerCleanupFunction(() => Services.search.removeEngine(engine));
+  registerCleanupFunction(async () => Services.search.removeEngine(engine));
 
   info("Should not autoFill search engine if search string contains www. but engine doesn't");
   await check_autocomplete({
     search: "www.ham",
     autofilled: "www.ham",
     completed: "www.ham",
   });
 
   await cleanup();
 });
 
 add_task(async function test_searchEngine_different_scheme_noautofill() {
   Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true);
-  Services.search.addEngineWithDetails("PieSearch", "", "", "",
-                                       "GET", "https://pie.search/");
+  await Services.search.addEngineWithDetails("PieSearch", "", "", "",
+                                             "GET", "https://pie.search/");
   let engine = Services.search.getEngineByName("PieSearch");
   engine.addParam("q", "{searchTerms}", null);
-  registerCleanupFunction(() => Services.search.removeEngine(engine));
+  registerCleanupFunction(async () => Services.search.removeEngine(engine));
 
   info("Should not autoFill search engine if search string has a different scheme.");
   await check_autocomplete({
     search: "http://pie",
     autofilled: "http://pie",
     completed: "http://pie",
   });
 
   await cleanup();
 });
 
 add_task(async function test_searchEngine_matching_prefix_autofill() {
   Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true);
-  Services.search.addEngineWithDetails("BeanSearch", "", "", "",
-                                       "GET", "http://www.bean.search/");
+  await Services.search.addEngineWithDetails("BeanSearch", "", "", "",
+                                             "GET", "http://www.bean.search/");
   let engine = Services.search.getEngineByName("BeanSearch");
   engine.addParam("q", "{searchTerms}", null);
-  registerCleanupFunction(() => Services.search.removeEngine(engine));
+  registerCleanupFunction(async () => Services.search.removeEngine(engine));
 
 
   info("Should autoFill search engine if search string has matching prefix.");
   await check_autocomplete({
     search: "http://www.be",
     autofilled: "http://www.bean.search/",
     completed: "http://www.bean.search/",
   });
--- a/toolkit/components/places/tests/unifiedcomplete/test_search_engine_alias.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_search_engine_alias.js
@@ -3,20 +3,20 @@
 
 const SUGGESTIONS_ENGINE_NAME = "engine-suggestions.xml";
 
 // Basic test that uses two engines, a GET engine and a POST engine, neither
 // providing search suggestions.
 add_task(async function basicGetAndPost() {
   // Note that head_autocomplete.js has already added a MozSearch engine.
   // Here we add another engine with a search alias.
-  Services.search.addEngineWithDetails("AliasedGETMozSearch", "", "get", "",
-                                       "GET", "http://s.example.com/search");
-  Services.search.addEngineWithDetails("AliasedPOSTMozSearch", "", "post", "",
-                                       "POST", "http://s.example.com/search");
+  await Services.search.addEngineWithDetails("AliasedGETMozSearch", "", "get", "",
+                                             "GET", "http://s.example.com/search");
+  await Services.search.addEngineWithDetails("AliasedPOSTMozSearch", "", "post", "",
+                                             "POST", "http://s.example.com/search");
 
   await PlacesTestUtils.addVisits("http://s.example.com/search?q=firefox");
   let historyMatch = {
     value: "http://s.example.com/search?q=firefox",
     comment: "test visit for http://s.example.com/search?q=firefox",
   };
 
   for (let alias of ["get", "post"]) {
@@ -205,17 +205,17 @@ add_task(async function engineWithSugges
   await cleanup();
 });
 
 
 // When the search is simply "@", the results should be a list of all the "@"
 // alias engines.
 add_task(async function tokenAliasEngines() {
   let tokenEngines = [];
-  for (let engine of Services.search.getEngines()) {
+  for (let engine of await Services.search.getEngines()) {
     let aliases = [];
     if (engine.alias) {
       aliases.push(engine.alias);
     }
     aliases.push(...engine.wrappedJSObject._internalAliases);
     let tokenAliases = aliases.filter(a => a.startsWith("@"));
     if (tokenAliases.length) {
       tokenEngines.push({ engine, tokenAliases });
--- a/toolkit/components/places/tests/unifiedcomplete/test_search_engine_current.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_search_engine_current.js
@@ -1,17 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 
 add_task(async function() {
   // Note that head_autocomplete.js has already added a MozSearch engine.
   // Here we add another engine with a search alias.
-  Services.search.addEngineWithDetails("AliasedMozSearch", "", "doit", "",
-                                       "GET", "http://s.example.com/search");
+  await Services.search.addEngineWithDetails("AliasedMozSearch", "", "doit", "",
+                                             "GET", "http://s.example.com/search");
 
   info("search engine");
   await check_autocomplete({
     search: "mozilla",
     searchParam: "enable-actions",
     matches: [ makeSearchMatch("mozilla", { heuristic: true }) ],
   });
 
@@ -25,21 +25,21 @@ add_task(async function() {
   info("search engine, multiple words");
   await check_autocomplete({
     search: "mozzarella cheese",
     searchParam: "enable-actions",
     matches: [ makeSearchMatch("mozzarella cheese", { heuristic: true }) ],
   });
 
   info("search engine, after current engine has changed");
-  Services.search.addEngineWithDetails("MozSearch2", "", "", "", "GET",
-                                       "http://s.example.com/search2");
+  await Services.search.addEngineWithDetails("MozSearch2", "", "", "", "GET",
+                                             "http://s.example.com/search2");
   let engine = Services.search.getEngineByName("MozSearch2");
   notEqual(Services.search.defaultEngine, engine, "New engine shouldn't be the current engine yet");
-  Services.search.defaultEngine = engine;
+  await Services.search.setDefault(engine);
   await check_autocomplete({
     search: "mozilla",
     searchParam: "enable-actions",
     matches: [ makeSearchMatch("mozilla", { engineName: "MozSearch2", heuristic: true }) ],
   });
 
   await cleanup();
 });
--- a/toolkit/components/places/tests/unifiedcomplete/test_search_engine_host.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_search_engine_host.js
@@ -1,17 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 add_task(async function test_searchEngine_autoFill() {
   Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true);
-  Services.search.addEngineWithDetails("MySearchEngine", "", "", "",
-                                       "GET", "http://my.search.com/");
+  await Services.search.addEngineWithDetails("MySearchEngine", "", "", "",
+                                             "GET", "http://my.search.com/");
   let engine = Services.search.getEngineByName("MySearchEngine");
-  registerCleanupFunction(() => Services.search.removeEngine(engine));
+  registerCleanupFunction(async () => Services.search.removeEngine(engine));
 
   // Add an uri that matches the search string with high frecency.
   let uri = NetUtil.newURI("http://www.example.com/my/");
   let visits = [];
   for (let i = 0; i < 100; ++i) {
     visits.push({ uri, title: "Terms - SearchEngine Search" });
   }
   await PlacesTestUtils.addVisits(visits);
--- a/toolkit/components/places/tests/unifiedcomplete/test_search_engine_restyle.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_search_engine_restyle.js
@@ -1,18 +1,18 @@
 /* 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/. */
 
 add_task(async function test_searchEngine() {
-  Services.search.addEngineWithDetails("SearchEngine", "", "", "",
-                                       "GET", "http://s.example.com/search");
+  await Services.search.addEngineWithDetails("SearchEngine", "", "", "",
+                                             "GET", "http://s.example.com/search");
   let engine = Services.search.getEngineByName("SearchEngine");
   engine.addParam("q", "{searchTerms}", null);
-  registerCleanupFunction(() => Services.search.removeEngine(engine));
+  registerCleanupFunction(async () => Services.search.removeEngine(engine));
 
   let uri1 = NetUtil.newURI("http://s.example.com/search?q=Terms&client=1");
   let uri2 = NetUtil.newURI("http://s.example.com/search?q=Terms&client=2");
   await PlacesTestUtils.addVisits({ uri: uri1, title: "Terms - SearchEngine Search" });
   await addBookmark({ uri: uri2, title: "Terms - SearchEngine Search" });
 
   info("Past search terms should be styled, unless bookmarked");
   Services.prefs.setBoolPref("browser.urlbar.restyleSearches", true);
--- a/toolkit/components/places/tests/unifiedcomplete/test_search_suggestions.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_search_suggestions.js
@@ -30,19 +30,19 @@ add_task(async function setup() {
     return suggestionsFn(searchStr);
   });
   setSuggestionsFn(searchStr => {
     let suffixes = ["foo", "bar"];
     return [searchStr].concat(suffixes.map(s => searchStr + " " + s));
   });
 
   // Install the test engine.
-  let oldDefaultEngine = Services.search.defaultEngine;
-  registerCleanupFunction(() => Services.search.defaultEngine = oldDefaultEngine);
-  Services.search.defaultEngine = engine;
+  let oldDefaultEngine = await Services.search.getDefault();
+  registerCleanupFunction(async () => Services.search.setDefault(oldDefaultEngine));
+  Services.search.setDefault(engine);
 
   // We must make sure the FormHistoryStartup component is initialized.
   Cc["@mozilla.org/satchel/form-history-startup;1"]
     .getService(Ci.nsIObserver)
     .observe(null, "profile-after-change", null);
   await updateSearchHistory("bump", "hello Fred!");
   await updateSearchHistory("bump", "hello Barney!");
 });
--- a/toolkit/components/search/tests/xpcshell/head_search.js
+++ b/toolkit/components/search/tests/xpcshell/head_search.js
@@ -133,64 +133,54 @@ function installDistributionEngine() {
       aPersistent.value = true;
       if (aProp == XRE_APP_DISTRIBUTION_DIR)
         return distDir.clone();
       return null;
     },
   });
 }
 
-function promiseCacheData() {
-  return new Promise(resolve => (async function() {
-    let path = OS.Path.join(OS.Constants.Path.profileDir, CACHE_FILENAME);
-    let bytes = await OS.File.read(path, {compression: "lz4"});
-    resolve(JSON.parse(new TextDecoder().decode(bytes)));
-  })());
+async function promiseCacheData() {
+  let path = OS.Path.join(OS.Constants.Path.profileDir, CACHE_FILENAME);
+  let bytes = await OS.File.read(path, {compression: "lz4"});
+  return JSON.parse(new TextDecoder().decode(bytes));
 }
 
 function promiseSaveCacheData(data) {
   return OS.File.writeAtomic(OS.Path.join(OS.Constants.Path.profileDir, CACHE_FILENAME),
                              new TextEncoder().encode(JSON.stringify(data)),
                              {compression: "lz4"});
 }
 
-function promiseEngineMetadata() {
-  return new Promise(resolve => (async function() {
-    let cache = await promiseCacheData();
-    let data = {};
-    for (let engine of cache.engines) {
-      data[engine._shortName] = engine._metaData;
-    }
-    resolve(data);
-  })());
+async function promiseEngineMetadata() {
+  let cache = await promiseCacheData();
+  let data = {};
+  for (let engine of cache.engines) {
+    data[engine._shortName] = engine._metaData;
+  }
+  return data;
 }
 
-function promiseGlobalMetadata() {
-  return new Promise(resolve => (async function() {
-    let cache = await promiseCacheData();
-    resolve(cache.metaData);
-  })());
+async function promiseGlobalMetadata() {
+  return (await promiseCacheData()).metaData;
 }
 
-function promiseSaveGlobalMetadata(globalData) {
-  return new Promise(resolve => (async function() {
-    let data = await promiseCacheData();
-    data.metaData = globalData;
-    await promiseSaveCacheData(data);
-    resolve();
-  })());
+async function promiseSaveGlobalMetadata(globalData) {
+  let data = await promiseCacheData();
+  data.metaData = globalData;
+  await promiseSaveCacheData(data);
 }
 
-var forceExpiration = async function() {
+async function forceExpiration() {
   let metadata = await promiseGlobalMetadata();
 
   // Make the current geodefaults expire 1s ago.
   metadata.searchDefaultExpir = Date.now() - 1000;
   await promiseSaveGlobalMetadata(metadata);
-};
+}
 
 /**
  * Clean the profile of any cache file left from a previous run.
  * Returns a boolean indicating if the cache file existed.
  */
 function removeCacheFile() {
   let file = gProfD.clone();
   file.append(CACHE_FILENAME);
deleted file mode 100644
--- a/toolkit/components/search/tests/xpcshell/test_645970.js
+++ /dev/null
@@ -1,20 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et: */
-/* 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/. */
-
-/**
- * Test nsSearchService with nested jar: uris, without async initialization
- */
-function run_test() {
-  do_load_manifest("data/chrome.manifest");
-
-  configureToLoadJarEngines();
-
-  // The search service needs to be started after the jarURIs pref has been
-  // set in order to initiate it correctly
-  let engine = Services.search.getEngineByName("bug645970");
-  Assert.notEqual(engine, null);
-  Services.obs.notifyObservers(null, "quit-application");
-}
--- a/toolkit/components/search/tests/xpcshell/test_addEngineWithDetails.js
+++ b/toolkit/components/search/tests/xpcshell/test_addEngineWithDetails.js
@@ -8,27 +8,23 @@ const kSearchEngineURL = "http://example
 const kSearchTerm = "foo";
 
 add_task(async function test_addEngineWithDetails() {
   Assert.ok(!Services.search.isInitialized);
 
   Services.prefs.getDefaultBranch(BROWSER_SEARCH_PREF)
           .setBoolPref("reset.enabled", true);
 
-  await asyncInit();
-
-  Services.search.addEngineWithDetails(kSearchEngineID, "", "", "", "get",
-                                       kSearchEngineURL);
+  await Services.search.addEngineWithDetails(kSearchEngineID, "", "", "", "get", kSearchEngineURL);
 
   // An engine added with addEngineWithDetails should have a load path, even
   // though we can't point to a specific file.
   let engine = Services.search.getEngineByName(kSearchEngineID);
   Assert.equal(engine.wrappedJSObject._loadPath, "[other]addEngineWithDetails");
 
   // Set the engine as default; this should set a loadPath verification hash,
   // which should ensure we don't show the search reset prompt.
-  Services.search.defaultEngine = engine;
+  await Services.search.setDefault(engine);
 
   let expectedURL = kSearchEngineURL.replace("{searchTerms}", kSearchTerm);
-  let submission =
-    Services.search.defaultEngine.getSubmission(kSearchTerm, null, "searchbar");
+  let submission = (await Services.search.getDefault()).getSubmission(kSearchTerm, null, "searchbar");
   Assert.equal(submission.uri.spec, expectedURL);
 });
--- a/toolkit/components/search/tests/xpcshell/test_addEngineWithDetailsObject.js
+++ b/toolkit/components/search/tests/xpcshell/test_addEngineWithDetailsObject.js
@@ -17,19 +17,17 @@ const kSearchEnginePOSTURL = "http://exa
 const kSearchEnginePOSTData = "search={searchTerms}&extra=more";
 
 add_task(async function test_addEngineWithDetails() {
   Assert.ok(!Services.search.isInitialized);
 
   Services.prefs.getDefaultBranch(BROWSER_SEARCH_PREF)
           .setBoolPref("reset.enabled", true);
 
-  await asyncInit();
-
-  Services.search.addEngineWithDetails(kSearchEngineID, {
+  await Services.search.addEngineWithDetails(kSearchEngineID, {
     template: kSearchEngineURL,
     description: kDescription,
     iconURL: kIconURL,
     suggestURL: kSearchSuggestURL,
     alias: "alias_foo",
     extensionID: kExtensionID,
   });
 
@@ -38,32 +36,30 @@ add_task(async function test_addEngineWi
   let engine = Services.search.getEngineByName(kSearchEngineID);
   Assert.equal(engine.wrappedJSObject._loadPath, "[other]addEngineWithDetails:" + kExtensionID);
   Assert.equal(engine.description, kDescription);
   Assert.equal(engine.iconURI.spec, kIconURL);
   Assert.equal(engine.alias, kAlias);
 
   // Set the engine as default; this should set a loadPath verification hash,
   // which should ensure we don't show the search reset prompt.
-  Services.search.defaultEngine = engine;
+  await Services.search.setDefault(engine);
 
   let expectedURL = kSearchEngineURL.replace("{searchTerms}", kSearchTerm);
-  let submission =
-    Services.search.defaultEngine.getSubmission(kSearchTerm, null, "searchbar");
+  let submission = (await Services.search.getDefault()).getSubmission(kSearchTerm, null, "searchbar");
   Assert.equal(submission.uri.spec, expectedURL);
   let expectedSuggestURL = kSearchSuggestURL.replace("{searchTerms}", kSearchTerm);
-  let submissionSuggest =
-    Services.search.defaultEngine.getSubmission(kSearchTerm, URLTYPE_SUGGEST_JSON);
+  let submissionSuggest = (await Services.search.getDefault()).getSubmission(kSearchTerm, URLTYPE_SUGGEST_JSON);
   Assert.equal(submissionSuggest.uri.spec, expectedSuggestURL);
 });
 
 add_task(async function test_addEngineWithDetailsPOST() {
   Assert.ok(Services.search.isInitialized);
 
-  Services.search.addEngineWithDetails(kSearchEnginePOSTID, {
+  await Services.search.addEngineWithDetails(kSearchEnginePOSTID, {
     template: kSearchEnginePOSTURL,
     method: "POST",
     postData: kSearchEnginePOSTData,
   });
 
   let engine = Services.search.getEngineByName(kSearchEnginePOSTID);
 
   let expectedPOSTData = kSearchEnginePOSTData.replace("{searchTerms}", kSearchTerm);
--- a/toolkit/components/search/tests/xpcshell/test_addEngineWithExtensionID.js
+++ b/toolkit/components/search/tests/xpcshell/test_addEngineWithExtensionID.js
@@ -8,43 +8,33 @@ const kSearchEngineURL = "http://example
 const kSearchTerm = "foo";
 const kExtensionID1 = "extension1@mozilla.com";
 const kExtensionID2 = "extension2@mozilla.com";
 const kExtension2LoadPath = "[http]localhost/test-search-engine.xml:extension2@mozilla.com";
 
 add_task(async function test_addEngineWithDetailsWithExtensionID() {
   Assert.ok(!Services.search.isInitialized);
 
-  await asyncInit();
-
-  Services.search.addEngineWithDetails(kSearchEngineID, "", "", "", "get",
-                                       kSearchEngineURL, kExtensionID1);
+  await Services.search.addEngineWithDetails(kSearchEngineID, "", "", "", "get",
+                                             kSearchEngineURL, kExtensionID1);
 
   let engine = Services.search.getEngineByName(kSearchEngineID);
   Assert.notEqual(engine, null);
 
-  let engines = Services.search.getEnginesByExtensionID(kExtensionID1);
+  let engines = await Services.search.getEnginesByExtensionID(kExtensionID1);
   Assert.equal(engines.length, 1);
-  Assert.equal(engines[0], engine);
+  Assert.equal(engines[0].name, engine.name);
 });
 
-add_test(function test_addEngineWithExtensionID() {
-  let searchCallback = {
-    onSuccess(engine) {
-      let engines = Services.search.getEnginesByExtensionID(kExtensionID2);
-      Assert.equal(engines.length, 1);
-      Assert.equal(engines[0], engine);
-      Assert.equal(engine.wrappedJSObject._loadPath, kExtension2LoadPath);
-      run_next_test();
-    },
-    onError(errorCode) {
-      do_throw("search callback returned error: " + errorCode);
-    },
-  };
-  Services.search.addEngine(gDataUrl + "engine.xml", null,
-                            false, searchCallback, kExtensionID2);
+add_task(async function test_addEngineWithExtensionID() {
+  let engine = await Services.search.addEngine(gDataUrl + "engine.xml", null,
+                                               false, kExtensionID2);
+  let engines = await Services.search.getEnginesByExtensionID(kExtensionID2);
+  Assert.equal(engines.length, 1);
+  Assert.deepEqual(engines[0].name, engine.name);
+  Assert.equal(engine.wrappedJSObject._loadPath, kExtension2LoadPath);
 });
 
 function run_test() {
   useHttpServer();
 
   run_next_test();
 }
--- a/toolkit/components/search/tests/xpcshell/test_addEngine_callback.js
+++ b/toolkit/components/search/tests/xpcshell/test_addEngine_callback.js
@@ -21,74 +21,50 @@ var prompt = {
 // Override the prompt service and nsIPrompt, since the search service currently
 // prompts in response to certain installation failures we test here
 // XXX this should disappear once bug 863474 is fixed
 MockRegistrar.register("@mozilla.org/embedcomp/prompt-service;1", promptService);
 MockRegistrar.register("@mozilla.org/prompter;1", prompt);
 
 
 // First test inits the search service
-add_test(function init_search_service() {
-  Services.search.init(function(status) {
-    if (!Components.isSuccessCode(status))
-      do_throw("Failed to initialize search service");
-
-    run_next_test();
-  });
+add_task(async function init_search_service() {
+  useHttpServer();
 });
 
 // Simple test of the search callback
-add_test(function simple_callback_test() {
-  let searchCallback = {
-    onSuccess(engine) {
-      Assert.ok(!!engine);
-      Assert.notEqual(engine.name, Services.search.defaultEngine.name);
-      Assert.equal(engine.wrappedJSObject._loadPath,
-                   "[http]localhost/test-search-engine.xml");
-      run_next_test();
-    },
-    onError(errorCode) {
-      do_throw("search callback returned error: " + errorCode);
-    },
-  };
-  Services.search.addEngine(gDataUrl + "engine.xml", null,
-                            false, searchCallback);
+add_task(async function simple_callback_test() {
+  let engine = await Services.search.addEngine(gDataUrl + "engine.xml", null, false);
+  Assert.ok(!!engine);
+  Assert.notEqual(engine.name, (await Services.search.getDefault()).name);
+  Assert.equal(engine.wrappedJSObject._loadPath,
+               "[http]localhost/test-search-engine.xml");
 });
 
 // Test of the search callback on duplicate engine failures
-add_test(function duplicate_failure_test() {
-  let searchCallback = {
-    onSuccess(engine) {
-      do_throw("this addition should not have succeeded");
-    },
-    onError(errorCode) {
-      Assert.ok(!!errorCode);
-      Assert.equal(errorCode, Ci.nsISearchInstallCallback.ERROR_DUPLICATE_ENGINE);
-      run_next_test();
-    },
-  };
+add_task(async function duplicate_failure_test() {
   // Re-add the same engine added in the previous test
-  Services.search.addEngine(gDataUrl + "engine.xml", null,
-                            false, searchCallback);
+  let engine;
+  try {
+    engine = await Services.search.addEngine(gDataUrl + "engine.xml", null, false);
+  } catch (ex) {
+    let errorCode = ex.result;
+    Assert.ok(!!errorCode);
+    Assert.equal(errorCode, Ci.nsISearchInstallCallback.ERROR_DUPLICATE_ENGINE);
+  } finally {
+    Assert.ok(!engine);
+  }
 });
 
 // Test of the search callback on failure to load the engine failures
-add_test(function load_failure_test() {
-  let searchCallback = {
-    onSuccess(engine) {
-      do_throw("this addition should not have succeeded");
-    },
-    onError(errorCode) {
-      Assert.ok(!!errorCode);
-      Assert.equal(errorCode, Ci.nsISearchInstallCallback.ERROR_UNKNOWN_FAILURE);
-      run_next_test();
-    },
-  };
-  // Try adding an engine that doesn't exist
-  Services.search.addEngine("http://invalid/data/engine.xml", null,
-                            false, searchCallback);
+add_task(async function load_failure_test() {
+  // Try adding an engine that doesn't exist.
+  let engine;
+  try {
+    engine = await Services.search.addEngine("http://invalid/data/engine.xml", null, false);
+  } catch (ex) {
+    let errorCode = ex.result;
+    Assert.ok(!!errorCode);
+    Assert.equal(errorCode, Ci.nsISearchInstallCallback.ERROR_UNKNOWN_FAILURE);
+  } finally {
+    Assert.ok(!engine);
+  }
 });
-
-function run_test() {
-  useHttpServer();
-
-  run_next_test();
-}
--- a/toolkit/components/search/tests/xpcshell/test_async.js
+++ b/toolkit/components/search/tests/xpcshell/test_async.js
@@ -5,27 +5,28 @@ function run_test() {
   do_test_pending();
 
   do_load_manifest("data/chrome.manifest");
 
   configureToLoadJarEngines();
 
   Assert.ok(!Services.search.isInitialized);
 
-  Services.search.init(function search_initialized(aStatus) {
+  Services.search.init().then(function search_initialized(aStatus) {
     Assert.ok(Components.isSuccessCode(aStatus));
     Assert.ok(Services.search.isInitialized);
 
     // test engines from dir are not loaded.
-    let engines = Services.search.getEngines();
-    Assert.equal(engines.length, 1);
+    Services.search.getEngines().then(engines => {
+      Assert.equal(engines.length, 1);
+
+      // test jar engine is loaded ok.
+      let engine = Services.search.getEngineByName("bug645970");
+      Assert.notEqual(engine, null);
 
-    // test jar engine is loaded ok.
-    let engine = Services.search.getEngineByName("bug645970");
-    Assert.notEqual(engine, null);
+      // Check the hidden engine is not loaded.
+      engine = Services.search.getEngineByName("hidden");
+      Assert.equal(engine, null);
 
-    // Check the hidden engine is not loaded.
-    engine = Services.search.getEngineByName("hidden");
-    Assert.equal(engine, null);
-
-    do_test_finished();
+      do_test_finished();
+    });
   });
 }
--- a/toolkit/components/search/tests/xpcshell/test_async_addon.js
+++ b/toolkit/components/search/tests/xpcshell/test_async_addon.js
@@ -6,20 +6,21 @@ function run_test() {
 
   do_load_manifest("data/chrome.manifest");
 
   configureToLoadJarEngines();
   installAddonEngine();
 
   Assert.ok(!Services.search.isInitialized);
 
-  Services.search.init(function search_initialized(aStatus) {
+  Services.search.init().then(function search_initialized(aStatus) {
     Assert.ok(Components.isSuccessCode(aStatus));
     Assert.ok(Services.search.isInitialized);
 
     // test the legacy add-on engine is _not_ loaded
-    let engines = Services.search.getEngines();
-    Assert.equal(engines.length, 1);
-    Assert.equal(Services.search.getEngineByName("addon"), null);
+    Services.search.getEngines().then(engines => {
+      Assert.equal(engines.length, 1);
+      Assert.equal(Services.search.getEngineByName("addon"), null);
 
-    do_test_finished();
+      do_test_finished();
+    });
   });
 }
--- a/toolkit/components/search/tests/xpcshell/test_async_addon_no_override.js
+++ b/toolkit/components/search/tests/xpcshell/test_async_addon_no_override.js
@@ -6,25 +6,26 @@ function run_test() {
 
   do_load_manifest("data/chrome.manifest");
 
   configureToLoadJarEngines();
   installAddonEngine("engine-override");
 
   Assert.ok(!Services.search.isInitialized);
 
-  Services.search.init(function search_initialized(aStatus) {
+  Services.search.init().then(function search_initialized(aStatus) {
     Assert.ok(Components.isSuccessCode(aStatus));
     Assert.ok(Services.search.isInitialized);
 
     // test the add-on engine isn't overriding our jar engine
-    let engines = Services.search.getEngines();
-    Assert.equal(engines.length, 1);
+    Services.search.getEngines().then(engines => {
+      Assert.equal(engines.length, 1);
 
-    // test jar engine is loaded ok.
-    let engine = Services.search.getEngineByName("bug645970");
-    Assert.notEqual(engine, null);
+      // test jar engine is loaded ok.
+      let engine = Services.search.getEngineByName("bug645970");
+      Assert.notEqual(engine, null);
 
-    Assert.equal(engine.description, "bug645970");
+      Assert.equal(engine.description, "bug645970");
 
-    do_test_finished();
+      do_test_finished();
+    });
   });
 }
--- a/toolkit/components/search/tests/xpcshell/test_async_disthidden.js
+++ b/toolkit/components/search/tests/xpcshell/test_async_disthidden.js
@@ -22,17 +22,17 @@ function run_test() {
   run_next_test();
 }
 
 add_task(async function test_disthidden() {
   await asyncInit();
 
   Assert.ok(Services.search.isInitialized);
 
-  let engines = Services.search.getEngines();
+  let engines = await Services.search.getEngines();
   // From data/list.json - only 6 out of 7
   // since one is hidden
   Assert.equal(engines.length, 6);
 
   // Verify that the Test search engine is not available
   let engine = Services.search.getEngineByName("Test search engine");
   Assert.equal(engine, null);
 });
--- a/toolkit/components/search/tests/xpcshell/test_async_distribution.js
+++ b/toolkit/components/search/tests/xpcshell/test_async_distribution.js
@@ -6,25 +6,26 @@ function run_test() {
 
   do_load_manifest("data/chrome.manifest");
 
   configureToLoadJarEngines();
   installDistributionEngine();
 
   Assert.ok(!Services.search.isInitialized);
 
-  Services.search.init(function search_initialized(aStatus) {
+  Services.search.init().then(function search_initialized(aStatus) {
     Assert.ok(Components.isSuccessCode(aStatus));
     Assert.ok(Services.search.isInitialized);
 
     // test that the engine from the distribution overrides our jar engine
-    let engines = Services.search.getEngines();
-    Assert.equal(engines.length, 1);
+    Services.search.getEngines().then(engines => {
+      Assert.equal(engines.length, 1);
+
+      let engine = Services.search.getEngineByName("bug645970");
+      Assert.notEqual(engine, null);
 
-    let engine = Services.search.getEngineByName("bug645970");
-    Assert.notEqual(engine, null);
+      // check the engine we have is actually the one from the distribution
+      Assert.equal(engine.description, "override");
 
-    // check the engine we have is actually the one from the distribution
-    Assert.equal(engine.description, "override");
-
-    do_test_finished();
+      do_test_finished();
+    });
   });
 }
--- a/toolkit/components/search/tests/xpcshell/test_async_profile_engine.js
+++ b/toolkit/components/search/tests/xpcshell/test_async_profile_engine.js
@@ -14,25 +14,26 @@ function run_test() {
   let dir = gProfD.clone();
   dir.append("searchplugins");
   if (!dir.exists())
     dir.create(dir.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
   do_get_file("data/engine-override.xml").copyTo(dir, "bug645970.xml");
 
   Assert.ok(!Services.search.isInitialized);
 
-  Services.search.init(function search_initialized(aStatus) {
+  Services.search.init().then(function search_initialized(aStatus) {
     Assert.ok(Components.isSuccessCode(aStatus));
     Assert.ok(Services.search.isInitialized);
 
     // test engines from dir are not loaded.
-    let engines = Services.search.getEngines();
-    Assert.equal(engines.length, 1);
+    Services.search.getEngines().then(engines => {
+      Assert.equal(engines.length, 1);
 
-    // test jar engine is loaded ok.
-    let engine = Services.search.getEngineByName("bug645970");
-    Assert.notEqual(engine, null);
+      // test jar engine is loaded ok.
+      let engine = Services.search.getEngineByName("bug645970");
+      Assert.notEqual(engine, null);
 
-    Assert.equal(engine.description, "bug645970");
+      Assert.equal(engine.description, "bug645970");
 
-    do_test_finished();
+      do_test_finished();
+    });
   });
 }
--- a/toolkit/components/search/tests/xpcshell/test_big_icon.js
+++ b/toolkit/components/search/tests/xpcshell/test_big_icon.js
@@ -16,11 +16,12 @@ add_task(async function test_big_icon() 
     { name: "BigIcon",
       details: [iconUrl, "", "Big icon", "GET",
                 "http://test_big_icon/search?q={searchTerms}"] },
   ]);
 
   await promiseAfterCache();
 
   let [engine] = await promiseChanged;
+  engine.QueryInterface(Ci.nsISearchEngine);
   Assert.ok(engine.iconURI.spec.startsWith("data:image/png"),
             "The icon is saved as a PNG data url");
 });
--- a/toolkit/components/search/tests/xpcshell/test_currentEngine_fallback.js
+++ b/toolkit/components/search/tests/xpcshell/test_currentEngine_fallback.js
@@ -1,25 +1,27 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
-function run_test() {
-  Assert.ok(Services.search.getVisibleEngines().length > 1);
+add_task(async function test_fallbacks() {
+  Assert.ok((await Services.search.getVisibleEngines()).length > 1);
   Assert.ok(Services.search.isInitialized);
 
   // Remove the current engine...
-  let defaultEngine = Services.search.defaultEngine;
-  Services.search.removeEngine(defaultEngine);
+  let defaultEngine = await Services.search.getDefault();
+  await Services.search.removeEngine(defaultEngine);
 
   // ... and verify a new current engine has been set.
-  Assert.notEqual(Services.search.defaultEngine.name, defaultEngine.name);
+  Assert.notEqual((await Services.search.getDefault()).name, defaultEngine.name);
   Assert.ok(defaultEngine.hidden);
 
   // Remove all the other engines.
-  Services.search.getVisibleEngines().forEach(Services.search.removeEngine);
-  Assert.equal(Services.search.getVisibleEngines().length, 0);
+  for (let engine of await Services.search.getVisibleEngines()) {
+    await Services.search.removeEngine(engine);
+  }
+  Assert.strictEqual((await Services.search.getVisibleEngines()).length, 0);
 
   // Verify the original default engine is used as a fallback and no
   // longer hidden.
-  Assert.equal(Services.search.defaultEngine.name, defaultEngine.name);
+  Assert.equal((await Services.search.getDefault()).name, defaultEngine.name);
   Assert.ok(!defaultEngine.hidden);
-  Assert.equal(Services.search.getVisibleEngines().length, 1);
-}
+  Assert.equal((await Services.search.getVisibleEngines()).length, 1);
+});
--- a/toolkit/components/search/tests/xpcshell/test_defaultEngine.js
+++ b/toolkit/components/search/tests/xpcshell/test_defaultEngine.js
@@ -11,16 +11,17 @@
 function run_test() {
   useHttpServer();
 
   run_next_test();
 }
 
 add_task(async function test_defaultEngine() {
   let search = Services.search;
+  await search.init();
 
   let originalDefault = search.defaultEngine;
 
   let [engine1, engine2] = await addTestEngines([
     { name: "Test search engine", xmlFileName: "engine.xml" },
     { name: "A second test engine", xmlFileName: "engine2.xml" },
   ]);
 
@@ -33,17 +34,17 @@ add_task(async function test_defaultEngi
 
   // Test that hiding the currently-default engine affects the defaultEngine getter
   // We fallback first to the original default...
   engine1.hidden = true;
   Assert.equal(search.defaultEngine, originalDefault);
 
   // ... and then to the first visible engine in the list, so move our second
   // engine to that position.
-  search.moveEngine(engine2, 0);
+  await search.moveEngine(engine2, 0);
   originalDefault.hidden = true;
   Assert.equal(search.defaultEngine, engine2);
 
   // Test that setting defaultEngine to an already-hidden engine works, but
   // doesn't change the return value of the getter
   search.defaultEngine = engine1;
   Assert.equal(search.defaultEngine, engine2);
 });
--- a/toolkit/components/search/tests/xpcshell/test_engineUpdate.js
+++ b/toolkit/components/search/tests/xpcshell/test_engineUpdate.js
@@ -19,17 +19,17 @@ add_task(async function test_engineUpdat
 
   await asyncInit();
 
   let [engine] = await addTestEngines([
     { name: "Test search engine", xmlFileName: FILENAME },
   ]);
 
   engine.alias = KEYWORD;
-  Services.search.moveEngine(engine, 0);
+  await Services.search.moveEngine(engine, 0);
   // can't have an accurate updateURL in the file since we can't know the test
   // server origin, so manually set it
   engine.wrappedJSObject._updateURL = gDataUrl + FILENAME;
 
   await new Promise(resolve => {
     Services.obs.addObserver(function obs(subject, topic, data) {
       if (data == "engine-loaded") {
         let loadedEngine = subject.QueryInterface(Ci.nsISearchEngine);
--- a/toolkit/components/search/tests/xpcshell/test_engine_set_alias.js
+++ b/toolkit/components/search/tests/xpcshell/test_engine_set_alias.js
@@ -13,68 +13,68 @@ add_task(async function test_engine_set_
     {
       name: "bacon",
       details: ["", "b", "Search Bacon", "GET", "http://www.bacon.test/find"],
     },
   ]);
   Assert.equal(engine1.alias, "b");
   engine1.alias = "a";
   Assert.equal(engine1.alias, "a");
-  Services.search.removeEngine(engine1);
+  await Services.search.removeEngine(engine1);
 });
 
 add_task(async function test_engine_set_alias_with_left_space() {
   info("Set engine alias with left space");
   let [engine2] = await addTestEngines([
     {
       name: "bacon",
       details: ["", "   a", "Search Bacon", "GET", "http://www.bacon.test/find"],
     },
   ]);
   Assert.equal(engine2.alias, "a");
   engine2.alias = "    c";
   Assert.equal(engine2.alias, "c");
-  Services.search.removeEngine(engine2);
+  await Services.search.removeEngine(engine2);
 });
 
 add_task(async function test_engine_set_alias_with_right_space() {
   info("Set engine alias with right space");
   let [engine3] = await addTestEngines([
     {
       name: "bacon",
       details: ["", "c   ", "Search Bacon", "GET", "http://www.bacon.test/find"],
     },
   ]);
   Assert.equal(engine3.alias, "c");
   engine3.alias = "o    ";
   Assert.equal(engine3.alias, "o");
-  Services.search.removeEngine(engine3);
+  await Services.search.removeEngine(engine3);
 });
 
 add_task(async function test_engine_set_alias_with_right_left_space() {
   info("Set engine alias with left and right space");
   let [engine4] = await addTestEngines([
     {
       name: "bacon",
       details: ["", " o  ", "Search Bacon", "GET", "http://www.bacon.test/find"],
     },
   ]);
   Assert.equal(engine4.alias, "o");
   engine4.alias = "  n ";
   Assert.equal(engine4.alias, "n");
-  Services.search.removeEngine(engine4);
+  await Services.search.removeEngine(engine4);
 });
 
 add_task(async function test_engine_set_alias_with_space() {
   info("Set engine alias with space");
   let [engine5] = await addTestEngines([
     {
       name: "bacon",
       details: ["", " ", "Search Bacon", "GET", "http://www.bacon.test/find"],
     },
   ]);
   Assert.equal(engine5.alias, null);
   engine5.alias = "b";
   Assert.equal(engine5.alias, "b");
   engine5.alias = "  ";
   Assert.equal(engine5.alias, null);
-  Services.search.removeEngine(engine5);
+  await Services.search.removeEngine(engine5);
 });
--- a/toolkit/components/search/tests/xpcshell/test_hasEngineWithURL.js
+++ b/toolkit/components/search/tests/xpcshell/test_hasEngineWithURL.js
@@ -1,49 +1,45 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Tests the hasEngineWithURL() method of the nsIBrowserSearchService.
  */
-function run_test() {
-  info("Setting up test");
-
-  useHttpServer();
-
-  info("Test starting");
-  run_next_test();
-}
-
 
 // Return a discreet, cloned copy of an (engine) object.
 function getEngineClone(engine) {
   return JSON.parse(JSON.stringify(engine));
 }
 
 // Check whether and engine does or doesn't exist.
 function checkEngineState(exists, engine) {
   Assert.equal(exists, Services.search.hasEngineWithURL(engine.method,
                                                         engine.formURL,
                                                         engine.queryParams));
 }
 
 // Add a search engine for testing.
-function addEngineWithParams(engine) {
-  Services.search.addEngineWithDetails(engine.name, null, null, null,
-                                       engine.method, engine.formURL);
+async function addEngineWithParams(engine) {
+  await Services.search.addEngineWithDetails(engine.name, null, null, null,
+                                             engine.method, engine.formURL);
 
   let addedEngine = Services.search.getEngineByName(engine.name);
   for (let param of engine.queryParams) {
     addedEngine.addParam(param.name, param.value, null);
   }
 }
 
 // Main test.
 add_task(async function test_hasEngineWithURL() {
+  info("Setting up test");
+
+  useHttpServer();
+
+  info("Test starting");
   // Avoid deprecated synchronous initialization.
   await asyncInit();
 
   // Setup various Engine definitions for method tests.
   let UNSORTED_ENGINE = {
     name: "mySearch Engine",
     method: "GET",
     formURL: "https://totallyNotRealSearchEngine.com/",
@@ -106,17 +102,17 @@ add_task(async function test_hasEngineWi
   info("There are no modified versions of the sorted test engine.");
 
   // Note that this method doesn't check name variations.
   checkEngineState(false, SORTED_ENGINE_NAME_CHANGE);
   info("There is no NAME modified version of the sorted test engine.");
 
 
   // Add the unsorted engine and it's queryParams.
-  addEngineWithParams(UNSORTED_ENGINE);
+  await addEngineWithParams(UNSORTED_ENGINE);
   info("The unsorted engine has been added.");
 
 
   // Then, ensure we find a match for the unsorted engine, and for the
   // same engine with a pre-sorted list of query parms.
   checkEngineState(true, UNSORTED_ENGINE);
   info("The unsorted version of the test engine now exists.");
   checkEngineState(true, SORTED_ENGINE);
--- a/toolkit/components/search/tests/xpcshell/test_hidden.js
+++ b/toolkit/components/search/tests/xpcshell/test_hidden.js
@@ -8,81 +8,69 @@ function run_test() {
 
   configureToLoadJarEngines();
 
   // Geo specific defaults won't be fetched if there's no country code.
   Services.prefs.setCharPref("browser.search.geoip.url",
                              'data:application/json,{"country_code": "US"}');
 
   // Make 'hidden' the only visible engine.
- let url = "data:application/json,{\"interval\": 31536000, \"settings\": {\"searchDefault\": \"hidden\", \"visibleDefaultEngines\": [\"hidden\"]}}";
+  let url = "data:application/json," + JSON.stringify({
+    "interval": 31536000,
+    "settings": {
+      "searchDefault": "hidden",
+      "visibleDefaultEngines": ["hidden"],
+    },
+  });
   Services.prefs.getDefaultBranch(BROWSER_SEARCH_PREF).setCharPref(kUrlPref, url);
 
   Assert.ok(!Services.search.isInitialized);
 
   run_next_test();
 }
 
 add_task(async function async_init() {
   let commitPromise = promiseAfterCache();
   await asyncInit();
 
-  let engines = Services.search.getEngines();
+  let engines = await Services.search.getEngines();
   Assert.equal(engines.length, 1);
 
   // The default test jar engine has been hidden.
   let engine = Services.search.getEngineByName("bug645970");
   Assert.equal(engine, null);
 
   // The hidden engine is visible.
   engine = Services.search.getEngineByName("hidden");
   Assert.notEqual(engine, null);
 
   // The next test does a sync init, which won't do the geoSpecificDefaults XHR,
   // so it depends on the metadata having been written to disk.
   await commitPromise;
 });
 
-add_task(async function sync_init() {
-  let unInitPromise = waitForSearchNotification("uninit-complete");
-  let reInitPromise = asyncReInit();
-  await unInitPromise;
-  Assert.ok(!Services.search.isInitialized);
-
-  // Synchronously check the current default engine, to force a sync init.
-  Assert.equal(Services.search.defaultEngine.name, "hidden");
-  Assert.ok(Services.search.isInitialized);
-
-  let engines = Services.search.getEngines();
-  Assert.equal(engines.length, 1);
-
-  // The default test jar engine has been hidden.
-  let engine = Services.search.getEngineByName("bug645970");
-  Assert.equal(engine, null);
-
-  // The hidden engine is visible.
-  engine = Services.search.getEngineByName("hidden");
-  Assert.notEqual(engine, null);
-
-  await reInitPromise;
-});
-
 add_task(async function invalid_engine() {
   // Trigger a new request.
   await forceExpiration();
 
   // Set the visibleDefaultEngines list to something that contains a non-existent engine.
   // This should cause the search service to ignore the list altogether and fallback to
   // local defaults.
-  let url = "data:application/json,{\"interval\": 31536000, \"settings\": {\"searchDefault\": \"hidden\", \"visibleDefaultEngines\": [\"hidden\", \"bogus\"]}}";
+  let url = "data:application/json," + JSON.stringify({
+    "interval": 31536000,
+    "settings": {
+      "searchDefault": "hidden",
+      "visibleDefaultEngines": ["hidden", "bogus"],
+    },
+  });
   Services.prefs.getDefaultBranch(BROWSER_SEARCH_PREF).setCharPref(kUrlPref, url);
 
   await asyncReInit();
 
-  let engines = Services.search.getEngines();
+  let engines = await Services.search.getEngines();
   Assert.equal(engines.length, 1);
 
   // The default test jar engine is visible.
   let engine = Services.search.getEngineByName("bug645970");
   Assert.notEqual(engine, null);
 
   // The hidden engine is... hidden.
   engine = Services.search.getEngineByName("hidden");
--- a/toolkit/components/search/tests/xpcshell/test_identifiers.js
+++ b/toolkit/components/search/tests/xpcshell/test_identifiers.js
@@ -13,17 +13,17 @@ function run_test() {
   do_load_manifest("data/chrome.manifest");
 
   configureToLoadJarEngines();
 
   run_next_test();
 }
 
 add_test(function test_identifier() {
-  Services.search.init(async function initComplete(aResult) {
+  Services.search.init().then(async function initComplete(aResult) {
     info("init'd search service");
     Assert.ok(Components.isSuccessCode(aResult));
 
     await installTestEngine();
     let profileEngine = Services.search.getEngineByName(kTestEngineName);
     let jarEngine = Services.search.getEngineByName("bug645970");
 
     Assert.ok(profileEngine instanceof Ci.nsISearchEngine);
--- a/toolkit/components/search/tests/xpcshell/test_ignorelist.js
+++ b/toolkit/components/search/tests/xpcshell/test_ignorelist.js
@@ -9,31 +9,27 @@ const kSearchEngineID3 = "ignorelist_tes
 const kSearchEngineURL1 = "http://example.com/?search={searchTerms}&ignore=true";
 const kSearchEngineURL2 = "http://example.com/?search={searchTerms}&IGNORE=TRUE";
 const kSearchEngineURL3 = "http://example.com/?search={searchTerms}";
 const kExtensionID = "searchignore@mozilla.com";
 
 add_task(async function test_ignorelistEngineLowerCase() {
   Assert.ok(!Services.search.isInitialized);
 
-  await asyncInit();
-
-  Services.search.addEngineWithDetails(kSearchEngineID1, "", "", "", "get",
-                                       kSearchEngineURL1);
+  await Services.search.addEngineWithDetails(kSearchEngineID1, "", "", "", "get", kSearchEngineURL1);
 
   // An ignored engine shouldn't be available at all
   let engine = Services.search.getEngineByName(kSearchEngineID1);
   Assert.equal(engine, null, "Engine should not exist");
 
-  Services.search.addEngineWithDetails(kSearchEngineID2, "", "", "", "get",
-                                       kSearchEngineURL2);
+  await Services.search.addEngineWithDetails(kSearchEngineID2, "", "", "", "get", kSearchEngineURL2);
 
   // An ignored engine shouldn't be available at all
   engine = Services.search.getEngineByName(kSearchEngineID2);
   Assert.equal(engine, null, "Engine should not exist");
 
-  Services.search.addEngineWithDetails(kSearchEngineID3, "", "", "", "get",
-                                       kSearchEngineURL3, kExtensionID);
+  await Services.search.addEngineWithDetails(kSearchEngineID3, "", "", "", "get",
+                                             kSearchEngineURL3, kExtensionID);
 
   // An ignored engine shouldn't be available at all
   engine = Services.search.getEngineByName(kSearchEngineID3);
   Assert.equal(engine, null, "Engine should not exist");
 });
--- a/toolkit/components/search/tests/xpcshell/test_init_async_multiple.js
+++ b/toolkit/components/search/tests/xpcshell/test_init_async_multiple.js
@@ -20,35 +20,36 @@ function run_test() {
   let numberOfInitializers = 4;
   let pending = [];
   let numberPending = numberOfInitializers;
 
   // Start asynchronous initializations
   for (let i = 0; i < numberOfInitializers; ++i) {
     let me = i;
     pending[me] = true;
-    Services.search.init(function search_initialized_0(aStatus) {
+    Services.search.init().then(function search_initialized_0(aStatus) {
       Assert.ok(Components.isSuccessCode(aStatus));
       init_complete(me);
     });
   }
 
   // Wait until all initializers have completed
   let init_complete = function init_complete(i) {
     Assert.ok(pending[i]);
     pending[i] = false;
     numberPending--;
     Assert.ok(numberPending >= 0);
     Assert.ok(Services.search.isInitialized);
     if (numberPending == 0) {
       // Just check that we can access a list of engines.
-      let engines = Services.search.getEngines();
-      Assert.notEqual(engines, null);
+      Services.search.getEngines().then(engines => {
+        Assert.notEqual(engines, null);
 
-      // Wait a little before quitting: if some initializer is
-      // triggered twice, we want to catch that error.
-      do_timeout(1000, function() {
-        do_test_finished();
+        // Wait a little before quitting: if some initializer is
+        // triggered twice, we want to catch that error.
+        do_timeout(1000, function() {
+          do_test_finished();
+        });
       });
     }
   };
 }
 
deleted file mode 100644
--- a/toolkit/components/search/tests/xpcshell/test_init_async_multiple_then_sync.js
+++ /dev/null
@@ -1,67 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et: */
-/* 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/. */
-
-/**
- * Test nsSearchService with with the following initialization scenario:
- * - launch asynchronous initialization several times;
- * - force fallback to synchronous initialization.
- * - all asynchronous initializations must complete;
- * - no asynchronous initialization must complete more than once.
- *
- * Test case comes from test_645970.js
- */
-function run_test() {
-  info("Setting up test");
-  do_test_pending();
-
-  info("Test starting");
-
-  let numberOfInitializers = 4;
-  let pending = [];
-  let numberPending = numberOfInitializers;
-
-  // Start asynchronous initializations
-  for (let i = 0; i < numberOfInitializers; ++i) {
-    let me = i;
-    pending[me] = true;
-    Services.search.init(function search_initialized(aStatus) {
-      Assert.ok(Components.isSuccessCode(aStatus));
-      init_complete(me);
-    });
-  }
-
-  // Ensure that all asynchronous initializers eventually complete
-  let init_complete = function init_complete(i) {
-    info("init complete " + i);
-    Assert.ok(pending[i]);
-    pending[i] = false;
-    numberPending--;
-    Assert.ok(numberPending >= 0);
-    Assert.ok(Services.search.isInitialized);
-    if (numberPending != 0) {
-      info("Still waiting for the following initializations: " + JSON.stringify(pending));
-      return;
-    }
-    info("All initializations have completed");
-    // Just check that we can access a list of engines.
-    let engines = Services.search.getEngines();
-    Assert.notEqual(engines, null);
-
-    info("Waiting a second before quitting");
-    // Wait a little before quitting: if some initializer is
-    // triggered twice, we want to catch that error.
-    do_timeout(1000, function() {
-      info("Test is complete");
-      do_test_finished();
-    });
-  };
-
-  // ... but don't wait for asynchronous initializations to complete
-  let engines = Services.search.getEngines();
-  Assert.notEqual(engines, null);
-  info("Synchronous part of the test complete");
-}
-
--- a/toolkit/components/search/tests/xpcshell/test_invalid_engine_from_dir.js
+++ b/toolkit/components/search/tests/xpcshell/test_invalid_engine_from_dir.js
@@ -14,17 +14,17 @@ function run_test() {
   engineFile.append("searchplugins");
   engineFile.append("test-search-engine.xml");
   engineFile.parent.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
 
   // Copy the invalid engine to the test profile.
   let engineTemplateFile = do_get_file("data/invalid-engine.xml");
   engineTemplateFile.copyTo(engineFile.parent, "test-search-engine.xml");
 
-  Services.search.init(function search_initialized(aStatus) {
+  Services.search.init().then(function search_initialized(aStatus) {
     // The invalid engine should have been skipped and should not
     // have caused an exception.
     Assert.ok(Components.isSuccessCode(aStatus));
     Assert.ok(Services.search.isInitialized);
 
     do_test_finished();
   });
 }
--- a/toolkit/components/search/tests/xpcshell/test_json_cache.js
+++ b/toolkit/components/search/tests/xpcshell/test_json_cache.js
@@ -40,32 +40,31 @@ add_test(function prepare_test_data() {
 });
 
 /**
  * Start the search service and confirm the engine properties match the expected values.
  */
 add_test(function test_cached_engine_properties() {
   info("init search service");
 
-  Services.search.init(function initComplete(aResult) {
+  Services.search.init().then(function initComplete(aResult) {
     info("init'd search service");
     Assert.ok(Components.isSuccessCode(aResult));
 
-    let engines = Services.search.getEngines({});
-    let engine = engines[0];
-
-    Assert.ok(engine instanceof Ci.nsISearchEngine);
-    isSubObjectOf(EXPECTED_ENGINE.engine, engine);
+    Services.search.getEngines().then(engines => {
+      let engine = engines[0].QueryInterface(Ci.nsISearchEngine);
+      isSubObjectOf(EXPECTED_ENGINE.engine, engine);
 
-    let engineFromSS = Services.search.getEngineByName(EXPECTED_ENGINE.engine.name);
-    Assert.ok(!!engineFromSS);
-    isSubObjectOf(EXPECTED_ENGINE.engine, engineFromSS);
+      let engineFromSS = Services.search.getEngineByName(EXPECTED_ENGINE.engine.name);
+      Assert.ok(!!engineFromSS);
+      isSubObjectOf(EXPECTED_ENGINE.engine, engineFromSS);
 
-    removeCacheFile();
-    run_next_test();
+      removeCacheFile();
+      run_next_test();
+    });
   });
 });
 
 /**
  * Test that the JSON cache written in the profile is correct.
  */
 add_test(function test_cache_write() {
   info("test cache writing");
@@ -108,17 +107,40 @@ add_test(function test_cache_write() {
 var EXPECTED_ENGINE = {
   engine: {
     name: "Test search engine",
     alias: null,
     description: "A test search engine (based on Google search)",
     searchForm: "http://www.google.com/",
     wrappedJSObject: {
       _extensionID: "test-addon-id@mozilla.org",
-      "_iconURL": "data:image/png;base64,AAABAAEAEBAAAAEAGABoAwAAFgAAACgAAAAQAAAAIAAAAAEAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADs9Pt8xetPtu9FsfFNtu%2BTzvb2%2B%2Fne4dFJeBw0egA%2FfAJAfAA8ewBBegAAAAD%2B%2FPtft98Mp%2BwWsfAVsvEbs%2FQeqvF8xO7%2F%2F%2F63yqkxdgM7gwE%2FggM%2BfQA%2BegBDeQDe7PIbotgQufcMufEPtfIPsvAbs%2FQvq%2Bfz%2Bf%2F%2B%2B%2FZKhR05hgBBhQI8hgBAgAI9ewD0%2B%2Fg3pswAtO8Cxf4Kw%2FsJvvYAqupKsNv%2B%2Fv7%2F%2FP5VkSU0iQA7jQA9hgBDgQU%2BfQH%2F%2Ff%2FQ6fM4sM4KsN8AteMCruIqqdbZ7PH8%2Fv%2Fg6Nc%2Fhg05kAA8jAM9iQI%2BhQA%2BgQDQu6b97uv%2F%2F%2F7V8Pqw3eiWz97q8%2Ff%2F%2F%2F%2F7%2FPptpkkqjQE4kwA7kAA5iwI8iAA8hQCOSSKdXjiyflbAkG7u2s%2F%2B%2F%2F39%2F%2F7r8utrqEYtjQE8lgA7kwA7kwA9jwA9igA9hACiWSekVRyeSgiYSBHx6N%2F%2B%2Fv7k7OFRmiYtlAA5lwI7lwI4lAA7kgI9jwE9iwI4iQCoVhWcTxCmb0K%2BooT8%2Fv%2F7%2F%2F%2FJ2r8fdwI1mwA3mQA3mgA8lAE8lAE4jwA9iwE%2BhwGfXifWvqz%2B%2Ff%2F58u%2Fev6Dt4tr%2B%2F%2F2ZuIUsggA7mgM6mAM3lgA5lgA6kQE%2FkwBChwHt4dv%2F%2F%2F728ei1bCi7VAC5XQ7kz7n%2F%2F%2F6bsZkgcB03lQA9lgM7kwA2iQktZToPK4r9%2F%2F%2F9%2F%2F%2FSqYK5UwDKZAS9WALIkFn%2B%2F%2F3%2F%2BP8oKccGGcIRJrERILYFEMwAAuEAAdX%2F%2Ff7%2F%2FP%2B%2BfDvGXQLIZgLEWgLOjlf7%2F%2F%2F%2F%2F%2F9QU90EAPQAAf8DAP0AAfMAAOUDAtr%2F%2F%2F%2F7%2B%2Fu2bCTIYwDPZgDBWQDSr4P%2F%2Fv%2F%2F%2FP5GRuABAPkAA%2FwBAfkDAPAAAesAAN%2F%2F%2B%2Fz%2F%2F%2F64g1C5VwDMYwK8Yg7y5tz8%2Fv%2FV1PYKDOcAAP0DAf4AAf0AAfYEAOwAAuAAAAD%2F%2FPvi28ymXyChTATRrIb8%2F%2F3v8fk6P8MAAdUCAvoAAP0CAP0AAfYAAO4AAACAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAA",
+      "_iconURL": "data:image/png;base64,AAABAAEAEBAAAAEAGABoAwAAFgAAACgAAAAQAAA" +
+                  "AIAAAAAEAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADs9Pt8xetPtu9F" +
+                  "sfFNtu%2BTzvb2%2B%2Fne4dFJeBw0egA%2FfAJAfAA8ewBBegAAAAD%2B%2F" +
+                  "Ptft98Mp%2BwWsfAVsvEbs%2FQeqvF8xO7%2F%2F%2F63yqkxdgM7gwE%2Fgg" +
+                  "M%2BfQA%2BegBDeQDe7PIbotgQufcMufEPtfIPsvAbs%2FQvq%2Bfz%2Bf%2F" +
+                  "%2B%2B%2FZKhR05hgBBhQI8hgBAgAI9ewD0%2B%2Fg3pswAtO8Cxf4Kw%2FsJ" +
+                  "vvYAqupKsNv%2B%2Fv7%2F%2FP5VkSU0iQA7jQA9hgBDgQU%2BfQH%2F%2Ff%" +
+                  "2FQ6fM4sM4KsN8AteMCruIqqdbZ7PH8%2Fv%2Fg6Nc%2Fhg05kAA8jAM9iQI%" +
+                  "2BhQA%2BgQDQu6b97uv%2F%2F%2F7V8Pqw3eiWz97q8%2Ff%2F%2F%2F%2F7%" +
+                  "2FPptpkkqjQE4kwA7kAA5iwI8iAA8hQCOSSKdXjiyflbAkG7u2s%2F%2B%2F%" +
+                  "2F39%2F%2F7r8utrqEYtjQE8lgA7kwA7kwA9jwA9igA9hACiWSekVRyeSgiYS" +
+                  "BHx6N%2F%2B%2Fv7k7OFRmiYtlAA5lwI7lwI4lAA7kgI9jwE9iwI4iQCoVhWc" +
+                  "TxCmb0K%2BooT8%2Fv%2F7%2F%2F%2FJ2r8fdwI1mwA3mQA3mgA8lAE8lAE4j" +
+                  "wA9iwE%2BhwGfXifWvqz%2B%2Ff%2F58u%2Fev6Dt4tr%2B%2F%2F2ZuIUsgg" +
+                  "A7mgM6mAM3lgA5lgA6kQE%2FkwBChwHt4dv%2F%2F%2F728ei1bCi7VAC5XQ7" +
+                  "kz7n%2F%2F%2F6bsZkgcB03lQA9lgM7kwA2iQktZToPK4r9%2F%2F%2F9%2F%" +
+                  "2F%2FSqYK5UwDKZAS9WALIkFn%2B%2F%2F3%2F%2BP8oKccGGcIRJrERILYFE" +
+                  "MwAAuEAAdX%2F%2Ff7%2F%2FP%2B%2BfDvGXQLIZgLEWgLOjlf7%2F%2F%2F%" +
+                  "2F%2F%2F9QU90EAPQAAf8DAP0AAfMAAOUDAtr%2F%2F%2F%2F7%2B%2Fu2bCT" +
+                  "IYwDPZgDBWQDSr4P%2F%2Fv%2F%2F%2FP5GRuABAPkAA%2FwBAfkDAPAAAesA" +
+                  "AN%2F%2F%2B%2Fz%2F%2F%2F64g1C5VwDMYwK8Yg7y5tz8%2Fv%2FV1PYKDOc" +
+                  "AAP0DAf4AAf0AAfYEAOwAAuAAAAD%2F%2FPvi28ymXyChTATRrIb8%2F%2F3v" +
+                  "8fk6P8MAAdUCAvoAAP0CAP0AAfYAAO4AAACAAQAAAAAAAAAAAAAAAAAAAAAAA" +
+                  "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAA",
       _urls: [
         {
           type: "application/x-suggestions+json",
           method: "GET",
           template: "http://suggestqueries.google.com/complete/search?output=firefox&client=firefox" +
                       "&hl={moz:locale}&q={searchTerms}",
           params: "",
         },
--- a/toolkit/components/search/tests/xpcshell/test_json_cache_ignorelist.js
+++ b/toolkit/components/search/tests/xpcshell/test_json_cache_ignorelist.js
@@ -37,23 +37,23 @@ add_test(function prepare_test_data() {
 });
 
 /**
  * Start the search service and confirm the cache was reset
  */
 add_test(function test_cache_rest() {
   info("init search service");
 
-  Services.search.init(function initComplete(aResult) {
+  Services.search.init().then(function initComplete(aResult) {
     info("init'd search service");
     Assert.ok(Components.isSuccessCode(aResult));
 
-    let engines = Services.search.getEngines({});
+    Services.search.getEngines().then(engines => {
+      // Engine list will have been reset to the default,
+      // Not the one engine in the cache.
+      // It should have more than one engine.
+      Assert.ok(engines.length > 1);
 
-    // Engine list will have been reset to the default,
-    // Not the one engine in the cache.
-    // It should have more than one engine.
-    Assert.ok(engines.length > 1);
-
-    removeCacheFile();
-    run_next_test();
+      removeCacheFile();
+      run_next_test();
+    });
   });
 });
--- a/toolkit/components/search/tests/xpcshell/test_list_json_locale.js
+++ b/toolkit/components/search/tests/xpcshell/test_list_json_locale.js
@@ -21,40 +21,41 @@ add_task(async function test_listJSONloc
 
   Services.locale.availableLocales = ["de"];
   Services.locale.requestedLocales = ["de"];
 
   await asyncInit();
 
   Assert.ok(Services.search.isInitialized, "search initialized");
 
-  let sortedEngines = Services.search.getEngines();
+  let sortedEngines = await Services.search.getEngines();
   Assert.equal(sortedEngines.length, 1, "Should have only one engine");
 });
 
 
 // Check that switching locale switches search engines
 add_task(async function test_listJSONlocaleSwitch() {
   let promise = waitForSearchNotification("reinit-complete");
 
   Services.locale.availableLocales = ["fr"];
   Services.locale.requestedLocales = ["fr"];
 
   await promise;
 
   Assert.ok(Services.search.isInitialized, "search initialized");
 
-  let sortedEngines = Services.search.getEngines();
+  let sortedEngines = await Services.search.getEngines();
   Assert.equal(sortedEngines.length, 2, "Should have two engines");
+  // Assert.equal(sortedEngines[0].identifier, "engine-pref");
 });
 
 // Check that region overrides apply
 add_task(async function test_listJSONRegionOverride() {
   Services.prefs.setCharPref("browser.search.region", "RU");
 
   await asyncReInit();
 
   Assert.ok(Services.search.isInitialized, "search initialized");
 
-  let sortedEngines = Services.search.getEngines();
+  let sortedEngines = await Services.search.getEngines();
   Assert.equal(sortedEngines.length, 2, "Should have two engines");
   Assert.equal(sortedEngines[0].identifier, "engine-chromeicon", "Engine should have been overridden by engine-chromeicon");
 });
--- a/toolkit/components/search/tests/xpcshell/test_list_json_searchdefault_distro.js
+++ b/toolkit/components/search/tests/xpcshell/test_list_json_searchdefault_distro.js
@@ -18,35 +18,34 @@ function run_test() {
 // Giving defaultenginename prefs a user value for partner build
 // shouldn't change the default engine assigned from list.json
 add_task(async function test_defaultEngineNamePref() {
   let defaultEngineName = getDefaultEngineName();
 
   // Set the browser.search.defaultenginename pref.
   Services.prefs.setCharPref(kDefaultenginenamePref, "Bing");
 
-  await asyncInit();
-  Assert.equal(Services.search.defaultEngine.name,
+  Assert.equal((await Services.search.getDefault()).name,
                defaultEngineName, "expected default search engine after pref set");
 
   Services.prefs.clearUserPref(kDefaultenginenamePref);
 });
 
 // Giving defaultenginename prefs a user value with region US
 // shouldn't change the default engine assigned from list.json
 add_task(async function test_defaultEngineNameUserPrefUS() {
   let defaultEngineName = getDefaultEngineName(true);
 
   Services.prefs.setCharPref("browser.search.region", "US");
 
   // Set the browser.search.defaultenginename pref.
   Services.prefs.setCharPref(kDefaultenginenamePref, "Bing");
 
   await asyncReInit();
-  Assert.equal(Services.search.defaultEngine.name,
+  Assert.equal((await Services.search.getDefault()).name,
                defaultEngineName, "expected US default search engine after pref set");
 
   Services.prefs.clearUserPref(kDefaultenginenamePref);
   Services.prefs.clearUserPref("browser.search.region");
 });
 
 // Giving defaultenginename prefs a default value with region US
 // should change the default engine assigned from list.json
@@ -56,13 +55,13 @@ add_task(async function test_defaultEngi
   Services.prefs.setCharPref("browser.search.region", "US");
 
   // Set the browser.search.defaultenginename pref.
   let defaultBranch = Services.prefs.getDefaultBranch(null);
   defaultBranch.setCharPref(kDefaultenginenamePref,
                             "data:text/plain,browser.search.defaultenginename=Bing");
 
   await asyncReInit();
-  Assert.equal(Services.search.defaultEngine.name,
+  Assert.equal((await Services.search.getDefault()).name,
                "Bing", "expected new default search engine after pref set");
 
   Services.prefs.clearUserPref("browser.search.region");
 });
--- a/toolkit/components/search/tests/xpcshell/test_list_json_searchorder.js
+++ b/toolkit/components/search/tests/xpcshell/test_list_json_searchorder.js
@@ -20,13 +20,13 @@ add_task(async function test_searchOrder
   resProt.setSubstitution("search-plugins", Services.io.newURI(url));
 
   await asyncReInit();
 
   Assert.ok(Services.search.isInitialized, "search initialized");
   Assert.equal(Services.search.defaultEngine.name,
                kTestEngineName, "expected test list JSON default search engine");
 
-  let sortedEngines = Services.search.getEngines();
+  let sortedEngines = await Services.search.getEngines();
   Assert.equal(sortedEngines[0].name, "Test search engine", "First engine should be default");
   Assert.equal(sortedEngines[1].name, "engine-resourceicon", "Second engine should be resource");
   Assert.equal(sortedEngines[2].name, "engine-chromeicon", "Third engine should be chrome");
 });
--- a/toolkit/components/search/tests/xpcshell/test_location.js
+++ b/toolkit/components/search/tests/xpcshell/test_location.js
@@ -1,14 +1,14 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 function run_test() {
   Services.prefs.setCharPref("browser.search.geoip.url", 'data:application/json,{"country_code": "AU"}');
-  Services.search.init(() => {
+  Services.search.init().then(() => {
     equal(Services.prefs.getCharPref("browser.search.region"), "AU", "got the correct region.");
     // check we have "success" recorded in telemetry
     checkCountryResultTelemetry(TELEMETRY_RESULT_ENUM.SUCCESS);
     // a false value for each of SEARCH_SERVICE_COUNTRY_TIMEOUT and SEARCH_SERVICE_COUNTRY_FETCH_CAUSED_SYNC_INIT
     for (let hid of ["SEARCH_SERVICE_COUNTRY_TIMEOUT",
                      "SEARCH_SERVICE_COUNTRY_FETCH_CAUSED_SYNC_INIT"]) {
       let histogram = Services.telemetry.getHistogramById(hid);
       let snapshot = histogram.snapshot();
--- a/toolkit/components/search/tests/xpcshell/test_location_error.js
+++ b/toolkit/components/search/tests/xpcshell/test_location_error.js
@@ -1,17 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 function run_test() {
   // We use an invalid port that parses but won't open
   let url = "http://localhost:0";
 
   Services.prefs.setCharPref("browser.search.geoip.url", url);
-  Services.search.init(() => {
+  Services.search.init().then(() => {
     try {
       Services.prefs.getCharPref("browser.search.region");
       ok(false, "not expecting region to be set");
     } catch (ex) {}
     // should have an error recorded.
     checkCountryResultTelemetry(TELEMETRY_RESULT_ENUM.ERROR);
     // but false values for timeout and forced-sync-init.
     for (let hid of ["SEARCH_SERVICE_COUNTRY_TIMEOUT",
--- a/toolkit/components/search/tests/xpcshell/test_location_malformed_json.js
+++ b/toolkit/components/search/tests/xpcshell/test_location_malformed_json.js
@@ -15,27 +15,28 @@ function promiseTimezoneMessage() {
     };
     Services.console.registerListener(listener);
   });
 }
 
 function run_test() {
   // Here we have malformed JSON
   Services.prefs.setCharPref("browser.search.geoip.url", 'data:application/json,{"country_code"');
-  Services.search.init(() => {
+  Services.search.init().then(() => {
     ok(!Services.prefs.prefHasUserValue("browser.search.region"), "should be no region pref");
     // fetch the engines - this should not persist any prefs.
-    Services.search.getEngines();
-    ok(!Services.prefs.prefHasUserValue("browser.search.region"), "should be no region pref");
-    // should have recorded SUCCESS_WITHOUT_DATA
-    checkCountryResultTelemetry(TELEMETRY_RESULT_ENUM.SUCCESS_WITHOUT_DATA);
-    // and false values for timeout and forced-sync-init.
-    for (let hid of ["SEARCH_SERVICE_COUNTRY_TIMEOUT",
-                     "SEARCH_SERVICE_COUNTRY_FETCH_CAUSED_SYNC_INIT"]) {
-      let histogram = Services.telemetry.getHistogramById(hid);
-      let snapshot = histogram.snapshot();
-      deepEqual(snapshot.values, {0: 1, 1: 0}); // boolean probe so 3 buckets, expect 1 result for |0|.
-    }
-    do_test_finished();
-    run_next_test();
+    Services.search.getEngines().then(() => {
+      ok(!Services.prefs.prefHasUserValue("browser.search.region"), "should be no region pref");
+      // should have recorded SUCCESS_WITHOUT_DATA
+      checkCountryResultTelemetry(TELEMETRY_RESULT_ENUM.SUCCESS_WITHOUT_DATA);
+      // and false values for timeout and forced-sync-init.
+      for (let hid of ["SEARCH_SERVICE_COUNTRY_TIMEOUT",
+                       "SEARCH_SERVICE_COUNTRY_FETCH_CAUSED_SYNC_INIT"]) {
+        let histogram = Services.telemetry.getHistogramById(hid);
+        let snapshot = histogram.snapshot();
+        deepEqual(snapshot.values, {0: 1, 1: 0}); // boolean probe so 3 buckets, expect 1 result for |0|.
+      }
+      do_test_finished();
+      run_next_test();
+    });
   });
   do_test_pending();
 }
deleted file mode 100644
--- a/toolkit/components/search/tests/xpcshell/test_location_sync.js
+++ /dev/null
@@ -1,60 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-function getRegionPref() {
-  try {
-    return Services.prefs.getCharPref("browser.search.region");
-  } catch (_) {
-    return undefined;
-  }
-}
-
-// Force a sync init and ensure the right thing happens (ie, that no xhr
-// request is made )
-add_task(async function test_simple() {
-  deepEqual(getRegionPref(), undefined, "no region pref");
-
-  // Still set a geoip pref so we can (indirectly) check it wasn't used.
-  Services.prefs.setCharPref("browser.search.geoip.url", 'data:application/json,{"country_code": "AU"}');
-
-  ok(!Services.search.isInitialized);
-
-  // fetching the engines forces a sync init
-  Services.search.getEngines();
-  ok(Services.search.isInitialized);
-
-  // a little wait to check we didn't do the xhr thang.
-  await new Promise(resolve => {
-    do_timeout(500, resolve);
-  });
-
-  deepEqual(getRegionPref(), undefined, "didn't do the geoip xhr");
-  // and no telemetry evidence of geoip.
-  for (let hid of [
-    "SEARCH_SERVICE_COUNTRY_FETCH_RESULT",
-    "SEARCH_SERVICE_COUNTRY_FETCH_TIME_MS",
-    "SEARCH_SERVICE_COUNTRY_TIMEOUT",
-    "SEARCH_SERVICE_US_COUNTRY_MISMATCHED_TIMEZONE",
-    "SEARCH_SERVICE_US_TIMEZONE_MISMATCHED_COUNTRY",
-    "SEARCH_SERVICE_COUNTRY_FETCH_CAUSED_SYNC_INIT",
-    ]) {
-      let histogram = Services.telemetry.getHistogramById(hid);
-      let snapshot = histogram.snapshot();
-      equal(snapshot.sum, 0, hid);
-      switch (snapshot.histogram_type) {
-        case Ci.nsITelemetry.HISTOGRAM_FLAG:
-          // flags are a special case in that they are initialized with a default
-          // of one |0|.
-          deepEqual(snapshot.values, {0: 1, 1: 0}, hid);
-          break;
-        case Ci.nsITelemetry.HISTOGRAM_BOOLEAN:
-        case Ci.nsITelemetry.HISTOGRAM_EXPONENTIAL:
-        case Ci.nsITelemetry.HISTOGRAM_LINEAR:
-          // booleans, exponential and linear aren't initialized at all, so should be empty.
-          deepEqual(snapshot.values, {}, hid);
-          break;
-        default:
-          ok(false, "unknown histogram type " + snapshot.histogram_type + " for " + hid);
-      }
-    }
-});
--- a/toolkit/components/search/tests/xpcshell/test_location_timeout.js
+++ b/toolkit/components/search/tests/xpcshell/test_location_timeout.js
@@ -32,17 +32,17 @@ function run_test() {
   let continuePromise = new Promise(resolve => {
     resolveContinuePromise = resolve;
   });
 
   let server = startServer(continuePromise);
   let url = "http://localhost:" + server.identity.primaryPort + "/lookup_country";
   Services.prefs.setCharPref("browser.search.geoip.url", url);
   Services.prefs.setIntPref("browser.search.geoip.timeout", 50);
-  Services.search.init(() => {
+  Services.search.init().then(() => {
     ok(!Services.prefs.prefHasUserValue("browser.search.region"), "should be no region pref");
     // should be no result recorded at all.
     checkCountryResultTelemetry(null);
 
     // should have set the flag indicating we saw a timeout.
     let histogram = Services.telemetry.getHistogramById("SEARCH_SERVICE_COUNTRY_TIMEOUT");
     let snapshot = histogram.snapshot();
     deepEqual(snapshot.values, {0: 0, 1: 1, 2: 0});
--- a/toolkit/components/search/tests/xpcshell/test_location_timeout_xhr.js
+++ b/toolkit/components/search/tests/xpcshell/test_location_timeout_xhr.js
@@ -36,17 +36,17 @@ function run_test() {
   });
 
   let server = startServer(continuePromise);
   let url = "http://localhost:" + server.identity.primaryPort + "/lookup_country";
   Services.prefs.setCharPref("browser.search.geoip.url", url);
   // The timeout for the timer.
   Services.prefs.setIntPref("browser.search.geoip.timeout", 10);
   let promiseXHRStarted = waitForSearchNotification("geoip-lookup-xhr-starting");
-  Services.search.init(() => {
+  Services.search.init().then(() => {
     ok(!Services.prefs.prefHasUserValue("browser.search.region"), "should be no region pref");
     // should be no result recorded at all.
     checkCountryResultTelemetry(null);
 
     // should have set the flag indicating we saw a timeout.
     let histogram = Services.telemetry.getHistogramById("SEARCH_SERVICE_COUNTRY_TIMEOUT");
     let snapshot = histogram.snapshot();
     deepEqual(snapshot.values, {0: 0, 1: 1, 2: 0});
--- a/toolkit/components/search/tests/xpcshell/test_migrateWebExtensionEngine.js
+++ b/toolkit/components/search/tests/xpcshell/test_migrateWebExtensionEngine.js
@@ -14,24 +14,22 @@ const kSearchEngineDetails = {
   alias: "alias_foo",
   extensionID: kExtensionID,
 };
 
 
 add_task(async function test_migrateLegacyEngine() {
   Assert.ok(!Services.search.isInitialized);
 
-  await asyncInit();
-
-  Services.search.addEngineWithDetails(kSearchEngineID, kSearchEngineDetails);
+  await 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);
+  await 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/test_multipleIcons.js
+++ b/toolkit/components/search/tests/xpcshell/test_multipleIcons.js
@@ -42,18 +42,15 @@ add_task(async function test_multipleIco
     Assert.equal(icon, "ico" + width);
 
     return true;
   }));
 });
 
 add_task(async function test_icon_not_in_file() {
   let engineUrl = gDataUrl + "engine-fr.xml";
-  let engine = await new Promise((resolve, reject) => {
-    Services.search.addEngine(engineUrl, "data:image/x-icon;base64,ico16",
-                              false, {onSuccess: resolve, onError: reject});
-  });
+  let engine = await Services.search.addEngine(engineUrl, "data:image/x-icon;base64,ico16", false);
 
   // Even though the icon wasn't specified inside the XML file, it should be
   // available both in the iconURI attribute and with getIconURLBySize.
   Assert.ok(engine.iconURI.spec.includes("ico16"));
   Assert.ok(engine.getIconURLBySize(16, 16).includes("ico16"));
 });
--- a/toolkit/components/search/tests/xpcshell/test_nocache.js
+++ b/toolkit/components/search/tests/xpcshell/test_nocache.js
@@ -17,19 +17,17 @@ function run_test() {
   run_next_test();
 }
 
 add_task(async function test_nocache() {
   let search = Services.search;
 
   let afterCachePromise = promiseAfterCache();
 
-  await new Promise((resolve, reject) => search.init(rv => {
-    Components.isSuccessCode(rv) ? resolve() : reject();
-  }));
+  await search.init();
 
   // Check that the cache is created at startup
   await afterCachePromise;
 
   // Check that search.json.mozlz4 has been created.
   let cacheFile = gProfD.clone();
   cacheFile.append(CACHE_FILENAME);
   Assert.ok(cacheFile.exists());
--- a/toolkit/components/search/tests/xpcshell/test_nodb_pluschanges.js
+++ b/toolkit/components/search/tests/xpcshell/test_nodb_pluschanges.js
@@ -28,18 +28,18 @@ add_task(async function test_nodb_plusch
   let [engine1, engine2] = await addTestEngines([
     { name: "Test search engine", xmlFileName: "engine.xml" },
     { name: "A second test engine", xmlFileName: "engine2.xml"},
   ]);
   await promiseAfterCache();
 
   let search = Services.search;
 
-  search.moveEngine(engine1, 0);
-  search.moveEngine(engine2, 1);
+  await search.moveEngine(engine1, 0);
+  await search.moveEngine(engine2, 1);
 
   // This is needed to avoid some reentrency issues in nsSearchService.
   info("Next step is forcing flush");
   await new Promise(resolve => executeSoon(resolve));
 
   info("Forcing flush");
   let promiseCommit = promiseAfterCache();
   search.QueryInterface(Ci.nsIObserver)
--- a/toolkit/components/search/tests/xpcshell/test_parseSubmissionURL.js
+++ b/toolkit/components/search/tests/xpcshell/test_parseSubmissionURL.js
@@ -10,18 +10,18 @@
 function run_test() {
   useHttpServer();
 
   run_next_test();
 }
 
 add_task(async function test_parseSubmissionURL() {
   // Hide the default engines to prevent them from being used in the search.
-  for (let engine of Services.search.getEngines()) {
-    Services.search.removeEngine(engine);
+  for (let engine of await Services.search.getEngines()) {
+    await Services.search.removeEngine(engine);
   }
 
   let [engine1, engine2, engine3, engine4] = await addTestEngines([
     { name: "Test search engine", xmlFileName: "engine.xml" },
     { name: "Test search engine (fr)", xmlFileName: "engine-fr.xml" },
     { name: "bacon_addParam", details: ["", "bacon_addParam", "Search Bacon",
                                         "GET", "http://www.bacon.test/find"] },
     { name: "idn_addParam", details: ["", "idn_addParam", "Search IDN",
--- a/toolkit/components/search/tests/xpcshell/test_purpose.js
+++ b/toolkit/components/search/tests/xpcshell/test_purpose.js
@@ -3,27 +3,27 @@
 
 /*
  * Test that a search purpose can be specified and that query parameters for
  * that purpose are included in the search URL.
  */
 
 "use strict";
 
-function run_test() {
+add_task(async function setup() {
   // The test engines used in this test need to be recognized as 'default'
   // engines, or their MozParams used to set the purpose will be ignored.
   let url = "resource://test/data/";
   let resProt = Services.io.getProtocolHandler("resource")
                         .QueryInterface(Ci.nsIResProtocolHandler);
   resProt.setSubstitution("search-plugins",
                           Services.io.newURI(url));
 
-  run_next_test();
-}
+  await Services.search.init();
+});
 
 add_task(async function test_purpose() {
   let engine = Services.search.getEngineByName("Test search engine");
 
   function check_submission(aValue, aSearchTerm, aType, aPurpose) {
     let submissionURL = engine.getSubmission(aSearchTerm, aType, aPurpose).uri.spec;
     let searchParams = new URLSearchParams(submissionURL.split("?")[1]);
     if (aValue) {
@@ -62,18 +62,16 @@ add_task(async function test_purpose() {
 
   // verify that the 'system' purpose falls back to the 'searchbar' purpose.
   check_submission("sb", "foo", "text/html", "system");
   check_submission("sb", "foo", "text/html", "searchbar");
   // Use an engine that actually defines the 'system' purpose...
   engine = Services.search.getEngineByName("engine-system-purpose");
   // ... and check that the system purpose is used correctly.
   check_submission("sys", "foo", "text/html", "system");
-
-  do_test_finished();
 });
 
 add_task(async function test_purpose() {
   let engine = Services.search.getEngineByName("Test search engine (Reordered)");
 
   function check_submission(aValue, aSearchTerm, aType, aPurpose) {
     let submissionURL = engine.getSubmission(aSearchTerm, aType, aPurpose).uri.spec;
     let searchParams = new URLSearchParams(submissionURL.split("?")[1]);
@@ -113,11 +111,9 @@ add_task(async function test_purpose() {
 
   // verify that the 'system' purpose falls back to the 'searchbar' purpose.
   check_submission("sb", "foo", "text/html", "system");
   check_submission("sb", "foo", "text/html", "searchbar");
   // Use an engine that actually defines the 'system' purpose...
   engine = Services.search.getEngineByName("engine-system-purpose");
   // ... and check that the system purpose is used correctly.
   check_submission("sys", "foo", "text/html", "system");
-
-  do_test_finished();
 });
--- a/toolkit/components/search/tests/xpcshell/test_remove_profile_engine.js
+++ b/toolkit/components/search/tests/xpcshell/test_remove_profile_engine.js
@@ -35,11 +35,11 @@ add_task(async function run_test() {
 
   await asyncReInit();
 
   // test the engine is loaded ok.
   let engine = Services.search.getEngineByName("bug645970");
   Assert.notEqual(engine, null);
 
   // remove the engine and verify the file has been removed too.
-  Services.search.removeEngine(engine);
+  await Services.search.removeEngine(engine);
   Assert.ok(!file.exists());
 });
--- a/toolkit/components/search/tests/xpcshell/test_require_engines_in_cache.js
+++ b/toolkit/components/search/tests/xpcshell/test_require_engines_in_cache.js
@@ -7,43 +7,41 @@ function run_test() {
   configureToLoadJarEngines();
   Assert.ok(!Services.search.isInitialized);
 
   run_next_test();
 }
 
 add_task(async function ignore_cache_files_without_engines() {
   let commitPromise = promiseAfterCache();
-  await asyncInit();
-
-  let engineCount = Services.search.getEngines().length;
+  let engineCount = (await Services.search.getEngines()).length;
   Assert.equal(engineCount, 1);
 
   // Wait for the file to be saved to disk, so that we can mess with it.
   await commitPromise;
 
   // Remove all engines from the cache file.
   let cache = await promiseCacheData();
   cache.engines = [];
   await promiseSaveCacheData(cache);
 
   // Check that after an async re-initialization, we still have the same engine count.
   commitPromise = promiseAfterCache();
   await asyncReInit();
-  Assert.equal(engineCount, Services.search.getEngines().length);
+  Assert.equal(engineCount, (await Services.search.getEngines()).length);
   await commitPromise;
 
   // Check that after a sync re-initialization, we still have the same engine count.
   await promiseSaveCacheData(cache);
   let unInitPromise = waitForSearchNotification("uninit-complete");
   let reInitPromise = asyncReInit();
   await unInitPromise;
   Assert.ok(!Services.search.isInitialized);
   // Synchronously check the engine count; will force a sync init.
-  Assert.equal(engineCount, Services.search.getEngines().length);
+  Assert.equal(engineCount, (await Services.search.getEngines()).length);
   Assert.ok(Services.search.isInitialized);
   await reInitPromise;
 });
 
 add_task(async function skip_writing_cache_without_engines() {
   let unInitPromise = waitForSearchNotification("uninit-complete");
   let reInitPromise = asyncReInit();
   await unInitPromise;
@@ -52,17 +50,17 @@ add_task(async function skip_writing_cac
   Assert.ok(removeCacheFile());
   let resProt = Services.io.getProtocolHandler("resource")
                         .QueryInterface(Ci.nsIResProtocolHandler);
   resProt.setSubstitution("search-plugins",
                           Services.io.newURI("about:blank"));
 
   // Let the async-reInit happen.
   await reInitPromise;
-  Assert.equal(0, Services.search.getEngines().length);
+  Assert.strictEqual(0, (await Services.search.getEngines()).length);
 
   // Trigger yet another re-init, to flush of any pending cache writing task.
   unInitPromise = waitForSearchNotification("uninit-complete");
   reInitPromise = asyncReInit();
   await unInitPromise;
 
   // Now check that a cache file doesn't exist.
   Assert.ok(!removeCacheFile());
--- a/toolkit/components/search/tests/xpcshell/test_save_sorted_engines.js
+++ b/toolkit/components/search/tests/xpcshell/test_save_sorted_engines.js
@@ -24,18 +24,18 @@ add_task(async function test_save_sorted
     { name: "Test search engine", xmlFileName: "engine.xml" },
     { name: "A second test engine", xmlFileName: "engine2.xml"},
   ]);
   await promiseAfterCache();
 
   let search = Services.search;
 
   // Test moving the engines
-  search.moveEngine(engine1, 0);
-  search.moveEngine(engine2, 1);
+  await search.moveEngine(engine1, 0);
+  await search.moveEngine(engine2, 1);
 
   // Changes should be commited immediately
   await promiseAfterCache();
   info("Commit complete after moveEngine");
 
   // Check that the entries are placed as specified correctly
   let metadata = await promiseEngineMetadata();
   Assert.equal(metadata["test-search-engine"].order, 1);
--- a/toolkit/components/search/tests/xpcshell/test_selectedEngine.js
+++ b/toolkit/components/search/tests/xpcshell/test_selectedEngine.js
@@ -30,18 +30,19 @@ add_task(async function test_selectedEng
   await asyncReInit();
   Assert.equal(Services.search.defaultEngine.name, defaultEngineName);
 
   Services.prefs.clearUserPref(kDefaultenginenamePref);
 });
 
 // Setting the search engine should be persisted across restarts.
 add_task(async function test_persistAcrossRestarts() {
+  await installTestEngine();
   // Set the engine through the API.
-  Services.search.defaultEngine = Services.search.getEngineByName(kTestEngineName);
+  await Services.search.setDefault(Services.search.getEngineByName(kTestEngineName));
   Assert.equal(Services.search.defaultEngine.name, kTestEngineName);
   await promiseAfterCache();
 
   // Check that the a hash was saved.
   let metadata = await promiseGlobalMetadata();
   Assert.equal(metadata.hash.length, 44);
 
   // Re-init and check the engine is still the same.
@@ -51,82 +52,80 @@ add_task(async function test_persistAcro
   // Cleanup (set the engine back to default).
   Services.search.resetToOriginalDefaultEngine();
   Assert.equal(Services.search.defaultEngine.name, getDefaultEngineName());
 });
 
 // An engine set without a valid hash should be ignored.
 add_task(async function test_ignoreInvalidHash() {
   // Set the engine through the API.
-  Services.search.defaultEngine = Services.search.getEngineByName(kTestEngineName);
+  await Services.search.setDefault(Services.search.getEngineByName(kTestEngineName));
   Assert.equal(Services.search.defaultEngine.name, kTestEngineName);
   await promiseAfterCache();
 
   // Then mess with the file (make the hash invalid).
   let metadata = await promiseGlobalMetadata();
   metadata.hash = "invalid";
   await promiseSaveGlobalMetadata(metadata);
 
   // Re-init the search service, and check that the json file is ignored.
   await asyncReInit();
   Assert.equal(Services.search.defaultEngine.name, getDefaultEngineName());
 });
 
 // Resetting the engine to the default should remove the saved value.
 add_task(async function test_settingToDefault() {
   // Set the engine through the API.
-  Services.search.defaultEngine = Services.search.getEngineByName(kTestEngineName);
+  await Services.search.setDefault(Services.search.getEngineByName(kTestEngineName));
   Assert.equal(Services.search.defaultEngine.name, kTestEngineName);
   await promiseAfterCache();
 
   // Check that the current engine was saved.
   let metadata = await promiseGlobalMetadata();
   Assert.equal(metadata.current, kTestEngineName);
 
   // Then set the engine back to the default through the API.
-  Services.search.defaultEngine =
-    Services.search.getEngineByName(getDefaultEngineName());
+  await Services.search.setDefault(Services.search.getEngineByName(getDefaultEngineName()));
   await promiseAfterCache();
 
   // Check that the current engine is no longer saved in the JSON file.
   metadata = await promiseGlobalMetadata();
   Assert.equal(metadata.current, "");
 });
 
 add_task(async function test_resetToOriginalDefaultEngine() {
   let defaultName = getDefaultEngineName();
   Assert.equal(Services.search.defaultEngine.name, defaultName);
 
-  Services.search.defaultEngine =
-    Services.search.getEngineByName(kTestEngineName);
+  await Services.search.setDefault(Services.search.getEngineByName(kTestEngineName));
   Assert.equal(Services.search.defaultEngine.name, kTestEngineName);
   await promiseAfterCache();
 
   Services.search.resetToOriginalDefaultEngine();
   Assert.equal(Services.search.defaultEngine.name, defaultName);
   await promiseAfterCache();
 });
 
 add_task(async function test_fallback_kept_after_restart() {
   // Set current engine to a default engine that isn't the original default.
-  let builtInEngines = Services.search.getDefaultEngines();
+  let builtInEngines = await Services.search.getDefaultEngines();
   let defaultName = getDefaultEngineName();
   let nonDefaultBuiltInEngine;
   for (let engine of builtInEngines) {
     if (engine.name != defaultName) {
       nonDefaultBuiltInEngine = engine;
       break;
     }
   }
-  Services.search.defaultEngine = nonDefaultBuiltInEngine;
+  await Services.search.setDefault(nonDefaultBuiltInEngine);
   Assert.equal(Services.search.defaultEngine.name, nonDefaultBuiltInEngine.name);
   await promiseAfterCache();
 
   // Remove that engine...
-  Services.search.removeEngine(nonDefaultBuiltInEngine);
+  await Services.search.removeEngine(nonDefaultBuiltInEngine);
   // The engine being a default (built-in) one, it should be hidden
   // rather than actually removed.
   Assert.ok(nonDefaultBuiltInEngine.hidden);
 
   // Using the defaultEngine getter should force a fallback to the
   // original default engine.
   Assert.equal(Services.search.defaultEngine.name, defaultName);
 
--- a/toolkit/components/search/tests/xpcshell/test_sendSubmissionURL.js
+++ b/toolkit/components/search/tests/xpcshell/test_sendSubmissionURL.js
@@ -22,37 +22,34 @@ const SUBMISSION_YES = new Map([
   ["Baidu Test", "https://www.baidu.com/s?wd={searchTerms}"],
 ]);
 
 const SUBMISSION_NO = new Map([
   ["Other1 Test", "https://example.com?q={searchTerms}"],
   ["Other2 Test", "https://googlebutnotgoogle.com?q={searchTerms}"],
 ]);
 
-function addAndMakeDefault(name, searchURL) {
-   Services.search.addEngineWithDetails(name, null, null, null, "GET", searchURL);
-   let engine = Services.search.getEngineByName(name);
-   Services.search.defaultEngine = engine;
-   return engine;
+async function addAndMakeDefault(name, searchURL) {
+  await Services.search.addEngineWithDetails(name, null, null, null, "GET", searchURL);
+  let engine = Services.search.getEngineByName(name);
+  await Services.search.setDefault(engine);
+  return engine;
 }
 
 add_task(async function test() {
   Assert.ok(!Services.search.isInitialized);
-
-  await asyncInit();
-
   let engineInfo;
   let engine;
 
   for (let [name, searchURL] of SUBMISSION_YES) {
-    engine = addAndMakeDefault(name, searchURL);
-    engineInfo = Services.search.getDefaultEngineInfo();
+    engine = await addAndMakeDefault(name, searchURL);
+    engineInfo = await Services.search.getDefaultEngineInfo();
     Assert.equal(engineInfo.submissionURL, searchURL.replace("{searchTerms}", ""));
-    Services.search.removeEngine(engine);
+    await Services.search.removeEngine(engine);
   }
 
  for (let [name, searchURL] of SUBMISSION_NO) {
-   engine = addAndMakeDefault(name, searchURL);
-   engineInfo = Services.search.getDefaultEngineInfo();
+   engine = await addAndMakeDefault(name, searchURL);
+   engineInfo = await Services.search.getDefaultEngineInfo();
    Assert.equal(engineInfo.submissionURL, null);
-   Services.search.removeEngine(engine);
+   await Services.search.removeEngine(engine);
  }
 });
deleted file mode 100644
--- a/toolkit/components/search/tests/xpcshell/test_sync.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-function run_test() {
-  do_load_manifest("data/chrome.manifest");
-
-  configureToLoadJarEngines();
-
-  Assert.ok(!Services.search.isInitialized);
-
-  // test engines from dir are not loaded.
-  let engines = Services.search.getEngines();
-  Assert.equal(engines.length, 1);
-
-  Assert.ok(Services.search.isInitialized);
-
-  // test jar engine is loaded ok.
-  let engine = Services.search.getEngineByName("bug645970");
-  Assert.notEqual(engine, null);
-
-  // Check the hidden engine is not loaded.
-  engine = Services.search.getEngineByName("hidden");
-  Assert.equal(engine, null);
-}
deleted file mode 100644
--- a/toolkit/components/search/tests/xpcshell/test_sync_addon.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-function run_test() {
-  do_load_manifest("data/chrome.manifest");
-
-  configureToLoadJarEngines();
-  installAddonEngine();
-
-  Assert.ok(!Services.search.isInitialized);
-
-  // test the legacy add-on engine is _not_ loaded
-  let engines = Services.search.getEngines();
-  Assert.ok(Services.search.isInitialized);
-  Assert.equal(engines.length, 1);
-  Assert.equal(Services.search.getEngineByName("addon"), null);
-}
deleted file mode 100644
--- a/toolkit/components/search/tests/xpcshell/test_sync_addon_no_override.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-function run_test() {
-  do_load_manifest("data/chrome.manifest");
-
-  configureToLoadJarEngines();
-  installAddonEngine("engine-override");
-
-  Assert.ok(!Services.search.isInitialized);
-
-  // test the add-on engine isn't overriding our jar engine
-  let engines = Services.search.getEngines();
-  Assert.equal(engines.length, 1);
-
-  Assert.ok(Services.search.isInitialized);
-
-  // test jar engine is loaded ok.
-  let engine = Services.search.getEngineByName("bug645970");
-  Assert.notEqual(engine, null);
-
-  Assert.equal(engine.description, "bug645970");
-}
deleted file mode 100644
--- a/toolkit/components/search/tests/xpcshell/test_sync_delay_fallback.js
+++ /dev/null
@@ -1,49 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-function run_test() {
-  do_test_pending();
-
-  do_load_manifest("data/chrome.manifest");
-
-  configureToLoadJarEngines();
-
-  Assert.ok(!Services.search.isInitialized);
-  let fallback = false;
-
-  Services.search.init(function search_initialized(aStatus) {
-    Assert.ok(fallback);
-    Assert.ok(Components.isSuccessCode(aStatus));
-    Assert.ok(Services.search.isInitialized);
-
-    // test engines from dir are not loaded.
-    let engines = Services.search.getEngines();
-    Assert.equal(engines.length, 1);
-
-    // test jar engine is loaded ok.
-    let engine = Services.search.getEngineByName("bug645970");
-    Assert.notEqual(engine, null);
-
-    do_test_finished();
-  });
-
-  // Execute test for the sync fallback while the async code is being executed.
-  Services.obs.addObserver(function searchServiceObserver(aResult, aTopic, aVerb) {
-    if (aVerb == "find-jar-engines") {
-      Services.obs.removeObserver(searchServiceObserver, aTopic);
-      fallback = true;
-
-      Assert.ok(!Services.search.isInitialized);
-
-      // test engines from dir are not loaded.
-      let engines = Services.search.getEngines();
-      Assert.equal(engines.length, 1);
-
-      // test jar engine is loaded ok.
-      let engine = Services.search.getEngineByName("bug645970");
-      Assert.notEqual(engine, null);
-
-      Assert.ok(Services.search.isInitialized);
-    }
-  }, "browser-search-service");
-}
deleted file mode 100644
--- a/toolkit/components/search/tests/xpcshell/test_sync_disthidden.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/* Test that the ignoredJAREngines pref hides search engines  */
-
-"use strict";
-
-function run_test() {
-  let defaultBranch = Services.prefs.getDefaultBranch(BROWSER_SEARCH_PREF);
-  defaultBranch.setCharPref("ignoredJAREngines", "engine");
-  Services.prefs.getDefaultBranch("").setCharPref("distribution.id", "partner-1");
-
-  // The test engines used in this test need to be recognized as 'default'
-  // engines or the resource URL won't be used
-  let url = "resource://test/data/";
-  let resProt = Services.io.getProtocolHandler("resource")
-                        .QueryInterface(Ci.nsIResProtocolHandler);
-  resProt.setSubstitution("search-plugins", Services.io.newURI(url));
-
-  Assert.ok(!Services.search.isInitialized);
-
-  let engines = Services.search.getEngines();
-  // From data/list.json - only 6 out of 7
-  // since one is hidden
-  Assert.equal(engines.length, 6);
-
-  Assert.ok(Services.search.isInitialized);
-
-  // Verify that the Test search engine is not available
-  let engine = Services.search.getEngineByName("Test search engine");
-  Assert.equal(engine, null);
-}
deleted file mode 100644
--- a/toolkit/components/search/tests/xpcshell/test_sync_distribution.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-function run_test() {
-  do_load_manifest("data/chrome.manifest");
-
-  configureToLoadJarEngines();
-  installDistributionEngine();
-
-  Assert.ok(!Services.search.isInitialized);
-
-  // test that the engine from the distribution overrides our jar engine
-  let engines = Services.search.getEngines();
-  Assert.equal(engines.length, 1);
-
-  Assert.ok(Services.search.isInitialized);
-
-  let engine = Services.search.getEngineByName("bug645970");
-  Assert.notEqual(engine, null);
-
-  // check the engine we have is actually the one from the distribution
-  Assert.equal(engine.description, "override");
-}
deleted file mode 100644
--- a/toolkit/components/search/tests/xpcshell/test_sync_fallback.js
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-function run_test() {
-  do_test_pending();
-
-  do_load_manifest("data/chrome.manifest");
-
-  configureToLoadJarEngines();
-
-  Assert.ok(!Services.search.isInitialized);
-
-  Services.search.init(function search_initialized(aStatus) {
-    Assert.ok(Components.isSuccessCode(aStatus));
-    Assert.ok(Services.search.isInitialized);
-
-    // test engines from dir are not loaded.
-    let engines = Services.search.getEngines();
-    Assert.equal(engines.length, 1);
-
-    // test jar engine is loaded ok.
-    let engine = Services.search.getEngineByName("bug645970");
-    Assert.notEqual(engine, null);
-
-    do_test_finished();
-  });
-
-  Assert.ok(!Services.search.isInitialized);
-
-  // test engines from dir are not loaded.
-  let engines = Services.search.getEngines();
-  Assert.equal(engines.length, 1);
-
-  Assert.ok(Services.search.isInitialized);
-
-  // test jar engine is loaded ok.
-  let engine = Services.search.getEngineByName("bug645970");
-  Assert.notEqual(engine, null);
-}
deleted file mode 100644
--- a/toolkit/components/search/tests/xpcshell/test_sync_profile_engine.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-function run_test() {
-  do_load_manifest("data/chrome.manifest");
-
-  configureToLoadJarEngines();
-
-  // Copy an engine in [profile]/searchplugins/ and ensure it's not
-  // overriding the same file from a jar.
-  // The description in the file we are copying is 'profile'.
-  let dir = gProfD.clone();
-  dir.append("searchplugins");
-  if (!dir.exists())
-    dir.create(dir.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
-  do_get_file("data/engine-override.xml").copyTo(dir, "bug645970.xml");
-
-  Assert.ok(!Services.search.isInitialized);
-
-  // test engines from dir are not loaded.
-  let engines = Services.search.getEngines();
-  Assert.equal(engines.length, 1);
-
-  Assert.ok(Services.search.isInitialized);
-
-  // test jar engine is loaded ok.
-  let engine = Services.search.getEngineByName("bug645970");
-  Assert.notEqual(engine, null);
-
-  Assert.equal(engine.description, "bug645970");
-}
--- a/toolkit/components/search/tests/xpcshell/xpcshell.ini
+++ b/toolkit/components/search/tests/xpcshell/xpcshell.ini
@@ -25,38 +25,35 @@ support-files =
   data/invalid-engine.xml
   data/install.rdf
   data/list.json
   data/search.json
   data/searchSuggestions.sjs
   data/searchTest.jar
 
 [test_nocache.js]
-[test_645970.js]
 [test_big_icon.js]
 [test_bug930456.js]
 [test_bug930456_child.js]
 [test_engine_set_alias.js]
 [test_hasEngineWithURL.js]
 [test_identifiers.js]
 [test_ignorelist.js]
 [test_invalid_engine_from_dir.js]
 [test_init_async_multiple.js]
-[test_init_async_multiple_then_sync.js]
 [test_json_cache.js]
 [test_json_cache_ignorelist.js]
 support-files = data/search_ignorelist.json
 [test_list_json_locale.js]
 [test_list_json_searchdefault.js]
 [test_list_json_searchdefault_distro.js]
 [test_list_json_searchorder.js]
 [test_location.js]
 [test_location_error.js]
 [test_location_malformed_json.js]
-[test_location_sync.js]
 [test_location_timeout.js]
 [test_location_timeout_xhr.js]
 [test_nodb_pluschanges.js]
 [test_save_sorted_engines.js]
 [test_pref.js]
 [test_purpose.js]
 [test_defaultEngine.js]
 [test_notifications.js]
@@ -70,26 +67,16 @@ support-files = data/search_ignorelist.j
 [test_async.js]
 [test_async_addon.js]
 tags = addons
 [test_async_addon_no_override.js]
 tags = addons
 [test_async_distribution.js]
 [test_async_disthidden.js]
 [test_async_profile_engine.js]
-[test_sync.js]
-[test_sync_addon.js]
-tags = addons
-[test_sync_addon_no_override.js]
-tags = addons
-[test_sync_distribution.js]
-[test_sync_disthidden.js]
-[test_sync_fallback.js]
-[test_sync_delay_fallback.js]
-[test_sync_profile_engine.js]
 [test_rel_searchform.js]
 [test_reloadEngines.js]
 [test_remove_profile_engine.js]
 [test_selectedEngine.js]
 [test_geodefaults.js]
 [test_hidden.js]
 [test_currentEngine_fallback.js]
 [test_require_engines_in_cache.js]
--- a/toolkit/components/telemetry/tests/unit/head.js
+++ b/toolkit/components/telemetry/tests/unit/head.js
@@ -333,20 +333,18 @@ function getHistogram(histogramId) {
 function getSnapshot(histogramId) {
   return Telemetry.getHistogramById(histogramId).snapshot();
 }
 
 // Helper for setting an empty list of Environment preferences to watch.
 function setEmptyPrefWatchlist() {
   let TelemetryEnvironment =
     ChromeUtils.import("resource://gre/modules/TelemetryEnvironment.jsm").TelemetryEnvironment;
-  return TelemetryEnvironment.onInitialized().then(() => {
-    TelemetryEnvironment.testWatchPreferences(new Map());
-
-  });
+  return TelemetryEnvironment.onInitialized().then(() =>
+    TelemetryEnvironment.testWatchPreferences(new Map()));
 }
 
 if (runningInParent) {
   // Set logging preferences for all the tests.
   Services.prefs.setCharPref("toolkit.telemetry.log.level", "Trace");
   // Telemetry archiving should be on.
   Services.prefs.setBoolPref(TelemetryUtils.Preferences.ArchiveEnabled, true);
   // Telemetry xpcshell tests cannot show the infobar.
--- a/toolkit/components/telemetry/tests/unit/test_SubsessionChaining.js
+++ b/toolkit/components/telemetry/tests/unit/test_SubsessionChaining.js
@@ -146,17 +146,17 @@ add_task(async function test_subsessions
   await schedulerTickCallback();
   expectedReasons.push(REASON_ABORTED_SESSION);
 
   // Start Telemetry and trigger an environment change through a pref modification. We expect
   // an environment-change ping with profileSubsessionCounter: 4, subsessionCounter: 1,
   // subsessionId: D and previousSubsessionId: C to be archived.
   moveClockForward(30);
   await TelemetryController.testReset();
-  TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
+  await TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
   moveClockForward(30);
   Preferences.set(PREF_TEST, 1);
   expectedReasons.push(REASON_ENVIRONMENT_CHANGE);
 
   // Shut down Telemetry. We expect a shutdown ping with profileSubsessionCounter: 5,
   // subsessionCounter: 2, subsessionId: E and previousSubsessionId: D to be archived.
   moveClockForward(30);
   await TelemetryController.testShutdown();
@@ -183,17 +183,17 @@ add_task(async function test_subsessions
 
   // Shut down Telemetry and trigger a shutdown ping.
   moveClockForward(30);
   await TelemetryController.testShutdown();
   expectedReasons.push(REASON_SHUTDOWN);
 
   // Start Telemetry and trigger an environment change.
   await TelemetryController.testReset();
-  TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
+  await TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
   moveClockForward(30);
   Preferences.set(PREF_TEST, 1);
   expectedReasons.push(REASON_ENVIRONMENT_CHANGE);
 
   // Don't shut down, instead trigger an aborted-session ping.
   moveClockForward(6);
   // Trigger the an aborted session ping save.
   await schedulerTickCallback();
--- a/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js
+++ b/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js
@@ -25,16 +25,20 @@ ChromeUtils.defineModuleGetter(this, "Li
 ChromeUtils.defineModuleGetter(this, "ExtensionTestUtils",
                                "resource://testing-common/ExtensionXPCShellUtils.jsm");
 
 async function installXPIFromURL(url) {
   let install = await AddonManager.getInstallForURL(url, "application/x-xpinstall");
   return install.install();
 }
 
+function promiseNextTick() {
+  return new Promise(resolve => executeSoon(resolve));
+}
+
 // The webserver hosting the addons.
 var gHttpServer = null;
 // The URL of the webserver root.
 var gHttpRoot = null;
 // The URL of the data directory, on the webserver.
 var gDataRoot = null;
 
 const PLATFORM_VERSION = "1.9.2";
@@ -940,17 +944,17 @@ add_task(async function test_prefWatchPo
     [PREF_TEST_4, {what: TelemetryEnvironment.RECORD_PREF_VALUE}],
     [PREF_TEST_5, {what: TelemetryEnvironment.RECORD_PREF_VALUE, requiresRestart: true}],
   ]);
 
   Preferences.set(PREF_TEST_4, expectedValue);
   Preferences.set(PREF_TEST_5, expectedValue);
 
   // Set the Environment preferences to watch.
-  TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
+  await TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
   let deferred = PromiseUtils.defer();
 
   // Check that the pref values are missing or present as expected
   Assert.strictEqual(TelemetryEnvironment.currentEnvironment.settings.userPrefs[PREF_TEST_1], undefined);
   Assert.strictEqual(TelemetryEnvironment.currentEnvironment.settings.userPrefs[PREF_TEST_4], expectedValue);
   Assert.strictEqual(TelemetryEnvironment.currentEnvironment.settings.userPrefs[PREF_TEST_5], expectedValue);
 
   TelemetryEnvironment.registerChangeListener("testWatchPrefs",
@@ -985,17 +989,17 @@ add_task(async function test_prefWatch_p
   const PREFS_TO_WATCH = new Map([
     [PREF_TEST, {what: TelemetryEnvironment.RECORD_PREF_STATE}],
   ]);
 
   // Set the preference to a non-default value.
   Preferences.set(PREF_TEST, false);
 
   // Set the Environment preferences to watch.
-  TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
+  await TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
   let deferred = PromiseUtils.defer();
   TelemetryEnvironment.registerChangeListener("testWatchPrefs_reset", deferred.resolve);
 
   Assert.strictEqual(TelemetryEnvironment.currentEnvironment.settings.userPrefs[PREF_TEST], "<user-set>");
 
   // Trigger a change in the watched preferences.
   Preferences.reset(PREF_TEST);
   await deferred.promise;
@@ -1014,30 +1018,30 @@ add_task(async function test_prefDefault
     [PREF_TEST, {what: TelemetryEnvironment.RECORD_DEFAULTPREF_VALUE}],
   ]);
 
   // Set the preference to a default value.
   Services.prefs.getDefaultBranch(null).setCharPref(PREF_TEST, expectedValue);
 
   // Set the Environment preferences to watch.
   // We're not watching, but this function does the setup we need.
-  TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
+  await TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
 
   Assert.strictEqual(TelemetryEnvironment.currentEnvironment.settings.userPrefs[PREF_TEST], expectedValue);
 });
 
 add_task(async function test_prefDefaultState() {
   const PREF_TEST = "toolkit.telemetry.test.defaultpref2";
   const expectedValue = "some-test-value";
 
   const PREFS_TO_WATCH = new Map([
     [PREF_TEST, {what: TelemetryEnvironment.RECORD_DEFAULTPREF_STATE}],
   ]);
 
-  TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
+  await TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
 
   Assert.equal(PREF_TEST in TelemetryEnvironment.currentEnvironment.settings.userPrefs, false);
 
   // Set the preference to a default value.
   Services.prefs.getDefaultBranch(null).setCharPref(PREF_TEST, expectedValue);
 
   Assert.strictEqual(TelemetryEnvironment.currentEnvironment.settings.userPrefs[PREF_TEST], "<set>");
 });
@@ -1046,17 +1050,17 @@ add_task(async function test_prefInvalid
   const PREF_TEST_1 = "toolkit.telemetry.test.invalid1";
   const PREF_TEST_2 = "toolkit.telemetry.test.invalid2";
 
   const PREFS_TO_WATCH = new Map([
     [PREF_TEST_1, {what: TelemetryEnvironment.RECORD_DEFAULTPREF_VALUE}],
     [PREF_TEST_2, {what: TelemetryEnvironment.RECORD_DEFAULTPREF_STATE}],
   ]);
 
-  TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
+  await TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
 
   Assert.strictEqual(TelemetryEnvironment.currentEnvironment.settings.userPrefs[PREF_TEST_1], undefined);
   Assert.strictEqual(TelemetryEnvironment.currentEnvironment.settings.userPrefs[PREF_TEST_2], undefined);
 
 });
 
 add_task(async function test_addonsWatch_InterestingChange() {
   const ADDON_INSTALL_URL = gDataRoot + "restartless.xpi";
@@ -1528,55 +1532,57 @@ add_task(async function test_defaultSear
   // the search provider reports an engine identifier.
   let url = "chrome://testsearchplugin/locale/searchplugins/";
   let resProt = Services.io.getProtocolHandler("resource")
                         .QueryInterface(Ci.nsIResProtocolHandler);
   resProt.setSubstitution("search-plugins",
                           Services.io.newURI(url));
 
   // Initialize the search service.
-  await new Promise(resolve => Services.search.init(resolve));
+  await Services.search.init();
+  await promiseNextTick();
 
   // Our default engine from the JAR file has an identifier. Check if it is correctly
   // reported.
   data = TelemetryEnvironment.currentEnvironment;
   checkEnvironmentData(data);
   Assert.equal(data.settings.defaultSearchEngine, "telemetrySearchIdentifier");
   let expectedSearchEngineData = {
     name: "telemetrySearchIdentifier",
     loadPath: "jar:[other]/searchTest.jar!testsearchplugin/telemetrySearchIdentifier.xml",
     origin: "default",
     submissionURL: "http://ar.wikipedia.org/wiki/%D8%AE%D8%A7%D8%B5:%D8%A8%D8%AD%D8%AB?search=&sourceid=Mozilla-search",
   };
   Assert.deepEqual(data.settings.defaultSearchEngineData, expectedSearchEngineData);
 
   // Remove all the search engines.
-  for (let engine of Services.search.getEngines()) {
-    Services.search.removeEngine(engine);
+  for (let engine of await Services.search.getEngines()) {
+    await Services.search.removeEngine(engine);
   }
   // The search service does not notify "engine-current" when removing a default engine.
   // Manually force the notification.
   // TODO: remove this when bug 1165341 is resolved.
   Services.obs.notifyObservers(null, "browser-search-engine-modified", "engine-current");
+  await promiseNextTick();
 
   // Then check that no default engine is reported if none is available.
   data = TelemetryEnvironment.currentEnvironment;
   checkEnvironmentData(data);
   Assert.equal(data.settings.defaultSearchEngine, "NONE");
   Assert.deepEqual(data.settings.defaultSearchEngineData, {name: "NONE"});
 
   // Add a new search engine (this will have no engine identifier).
   const SEARCH_ENGINE_ID = "telemetry_default";
   const SEARCH_ENGINE_URL = "http://www.example.org/?search={searchTerms}";
-  Services.search.addEngineWithDetails(SEARCH_ENGINE_ID, "", null, "", "get", SEARCH_ENGINE_URL);
+  await Services.search.addEngineWithDetails(SEARCH_ENGINE_ID, "", null, "", "get", SEARCH_ENGINE_URL);
 
   // Register a new change listener and then wait for the search engine change to be notified.
   let deferred = PromiseUtils.defer();
   TelemetryEnvironment.registerChangeListener("testWatch_SearchDefault", deferred.resolve);
-  Services.search.defaultEngine = Services.search.getEngineByName(SEARCH_ENGINE_ID);
+  await Services.search.setDefault(Services.search.getEngineByName(SEARCH_ENGINE_ID));
   await deferred.promise;
 
   data = TelemetryEnvironment.currentEnvironment;
   checkEnvironmentData(data);
 
   const EXPECTED_SEARCH_ENGINE = "other-" + SEARCH_ENGINE_ID;
   Assert.equal(data.settings.defaultSearchEngine, EXPECTED_SEARCH_ENGINE);
 
@@ -1603,20 +1609,19 @@ add_task(async function test_defaultSear
         }
 
         Services.obs.removeObserver(obs, "browser-search-engine-modified");
         resolve(searchEngine);
       } catch (ex) {
         reject(ex);
       }
     }, "browser-search-engine-modified");
-    Services.search.addEngine("file://" + do_get_cwd().path + "/engine.xml",
-                              null, false);
+    Services.search.addEngine("file://" + do_get_cwd().path + "/engine.xml", null, false);
   });
-  Services.search.defaultEngine = engine;
+  await Services.search.setDefault(engine);
   await promise;
   TelemetryEnvironment.unregisterChangeListener("testWatch_SearchDefault");
   data = TelemetryEnvironment.currentEnvironment;
   checkEnvironmentData(data);
   Assert.deepEqual(data.settings.defaultSearchEngineData,
                    {"name": "engine-telemetry", "loadPath": "[other]/engine.xml", "origin": "verified"});
 
   // Now break this engine's load path hash.
@@ -1624,27 +1629,27 @@ add_task(async function test_defaultSear
     TelemetryEnvironment.registerChangeListener("testWatch_SearchDefault", resolve);
   });
   engine.wrappedJSObject.setAttr("loadPathHash", "broken");
   Services.obs.notifyObservers(null, "browser-search-engine-modified", "engine-current");
   await promise;
   TelemetryEnvironment.unregisterChangeListener("testWatch_SearchDefault");
   data = TelemetryEnvironment.currentEnvironment;
   Assert.equal(data.settings.defaultSearchEngineData.origin, "invalid");
-  Services.search.removeEngine(engine);
+  await Services.search.removeEngine(engine);
 
   // Define and reset the test preference.
   const PREF_TEST = "toolkit.telemetry.test.pref1";
   const PREFS_TO_WATCH = new Map([
     [PREF_TEST, {what: TelemetryEnvironment.RECORD_PREF_STATE}],
   ]);
   Preferences.reset(PREF_TEST);
 
   // Watch the test preference.
-  TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
+  await TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
   deferred = PromiseUtils.defer();
   TelemetryEnvironment.registerChangeListener("testSearchEngine_pref", deferred.resolve);
   // Trigger an environment change.
   Preferences.set(PREF_TEST, 1);
   await deferred.promise;
   TelemetryEnvironment.unregisterChangeListener("testSearchEngine_pref");
 
   // Check that the search engine information is correctly retained when prefs change.
@@ -1704,17 +1709,17 @@ add_task({ skip_if: () => AppConstants.M
   // Make sure pref-flipping doesn't overwrite the browser default state.
   const PREF_TEST = "toolkit.telemetry.test.pref1";
   const PREFS_TO_WATCH = new Map([
     [PREF_TEST, {what: TelemetryEnvironment.RECORD_PREF_STATE}],
   ]);
   Preferences.reset(PREF_TEST);
 
   // Watch the test preference.
-  TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
+  await TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
   let deferred = PromiseUtils.defer();
   TelemetryEnvironment.registerChangeListener("testDefaultBrowser_pref", deferred.resolve);
   // Trigger an environment change.
   Preferences.set(PREF_TEST, 1);
   await deferred.promise;
   TelemetryEnvironment.unregisterChangeListener("testDefaultBrowser_pref");
 
   // Check that the data is still available.
@@ -1920,17 +1925,17 @@ add_task(async function test_environment
   // Define and reset the test preference.
   const PREF_TEST = "toolkit.telemetry.test.pref1";
   const PREFS_TO_WATCH = new Map([
     [PREF_TEST, {what: TelemetryEnvironment.RECORD_PREF_STATE}],
   ]);
   Preferences.reset(PREF_TEST);
 
   // Set up the preferences and listener, then the trigger shutdown
-  TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
+  await TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
   TelemetryEnvironment.registerChangeListener("test_environmentShutdownChange", () => {
   // Register a new change listener that asserts if change is propogated
     Assert.ok(false, "No change should be propagated after shutdown.");
   });
   TelemetryEnvironment.shutdown();
 
   // Flipping  the test preference after shutdown should not trigger the listener
   Preferences.set(PREF_TEST, 1);
--- a/toolkit/components/telemetry/tests/unit/test_TelemetrySession.js
+++ b/toolkit/components/telemetry/tests/unit/test_TelemetrySession.js
@@ -876,17 +876,17 @@ add_task(async function test_environment
 
   const PREFS_TO_WATCH = new Map([
     [PREF_TEST, {what: TelemetryEnvironment.RECORD_PREF_VALUE}],
   ]);
 
   // Setup.
   await TelemetryController.testReset();
   TelemetrySend.setServer("http://localhost:" + PingServer.port);
-  TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
+  await TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
 
   // Set histograms to expected state.
   const COUNT_ID = "TELEMETRY_TEST_COUNT";
   const KEYED_ID = "TELEMETRY_TEST_KEYED_COUNT";
   const count = Telemetry.getHistogramById(COUNT_ID);
   const keyed = Telemetry.getKeyedHistogramById(KEYED_ID);
 
   count.clear();
@@ -1343,17 +1343,17 @@ add_task(async function test_savedSessio
   Assert.equal(0, getSnapshot("TELEMETRY_SESSIONDATA_FAILED_LOAD").sum);
   Assert.equal(0, getSnapshot("TELEMETRY_SESSIONDATA_FAILED_PARSE").sum);
   Assert.equal(0, getSnapshot("TELEMETRY_SESSIONDATA_FAILED_VALIDATION").sum);
 
   // Watch a test preference, trigger and environment change and wait for it to propagate.
   // _watchPreferences triggers a subsession notification
   gMonotonicNow = fakeMonotonicNow(gMonotonicNow + 10 * MILLISECONDS_PER_MINUTE);
   fakeNow(new Date(2050, 1, 1, 12, 0, 0));
-  TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
+  await TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
   let changePromise = new Promise(resolve =>
     TelemetryEnvironment.registerChangeListener("test_fake_change", resolve));
   Preferences.set(PREF_TEST, 1);
   await changePromise;
   TelemetryEnvironment.unregisterChangeListener("test_fake_change");
 
   let payload = TelemetrySession.getPayload();
   Assert.equal(payload.info.profileSubsessionCounter, expectedSubsessions);
@@ -1693,17 +1693,17 @@ add_task(async function test_schedulerEn
   PingServer.clearRequests();
 
   // Set a fake current date and start Telemetry.
   let nowDate = fakeNow(2060, 10, 18, 0, 0, 0);
   gMonotonicNow = fakeMonotonicNow(gMonotonicNow + 10 * MILLISECONDS_PER_MINUTE);
   let schedulerTickCallback = null;
   fakeSchedulerTimer(callback => schedulerTickCallback = callback, () => {});
   await TelemetryController.testReset();
-  TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
+  await TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
 
   // Set the current time at midnight.
   fakeNow(futureDate(nowDate, MS_IN_ONE_DAY));
   gMonotonicNow = fakeMonotonicNow(gMonotonicNow + 10 * MILLISECONDS_PER_MINUTE);
 
   // Trigger the environment change.
   Preferences.set(PREF_TEST, 1);
 
@@ -1984,17 +1984,17 @@ add_task(async function test_changeThrot
   Preferences.reset(PREF_TEST);
 
   let now = fakeNow(2050, 1, 2, 0, 0, 0);
   gMonotonicNow = fakeMonotonicNow(gMonotonicNow + 10 * MILLISECONDS_PER_MINUTE);
   await TelemetryController.testReset();
   Assert.equal(getSubsessionCount(), 1);
 
   // Set the Environment preferences to watch.
-  TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
+  await TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH);
 
   // The first pref change should not trigger a notification.
   Preferences.set(PREF_TEST, 1);
   Assert.equal(getSubsessionCount(), 1);
 
   // We should get a change notification after the 5min throttling interval.
   fakeNow(futureDate(now, 5 * MILLISECONDS_PER_MINUTE + 1));
   gMonotonicNow = fakeMonotonicNow(gMonotonicNow + 5 * MILLISECONDS_PER_MINUTE + 1);