Bug 959576 - Create a component to get the list of priority domains. r=gavin
authorMarco Bonardo <mbonardo@mozilla.com>
Sat, 22 Mar 2014 14:24:36 +0100
changeset 174846 473edac990f3a5037f162e25f8ff11d8aa335076
parent 174845 f1cbdea2e334bc66d0691ca3d025f017fbc7f40a
child 174847 0469cf95fbfe9f07f69374ae8ab25ddce36ba2c3
push id5850
push usermak77@bonardo.net
push dateSat, 22 Mar 2014 13:24:52 +0000
treeherderfx-team@473edac990f3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgavin
bugs959576
milestone31.0a1
Bug 959576 - Create a component to get the list of priority domains. r=gavin
browser/locales/en-US/searchplugins/creativecommons.xml
browser/locales/en-US/searchplugins/eBay.xml
browser/locales/en-US/searchplugins/wikipedia.xml
browser/locales/en-US/searchplugins/yahoo.xml
netwerk/base/public/nsIBrowserSearchService.idl
toolkit/components/places/PriorityUrlProvider.jsm
toolkit/components/places/moz.build
toolkit/components/places/tests/unit/test_priorityUrlProvider.js
toolkit/components/places/tests/unit/xpcshell.ini
toolkit/components/search/nsSearchService.js
toolkit/components/search/tests/xpcshell/data/engine.xml
toolkit/components/search/tests/xpcshell/data/search.json
toolkit/components/search/tests/xpcshell/head_search.js
toolkit/components/search/tests/xpcshell/test_json_cache.js
toolkit/components/search/tests/xpcshell/test_resultDomain.js
toolkit/components/search/tests/xpcshell/xpcshell.ini
--- a/browser/locales/en-US/searchplugins/creativecommons.xml
+++ b/browser/locales/en-US/searchplugins/creativecommons.xml
@@ -2,14 +2,14 @@
    - 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/. -->
 
 <SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
 <ShortName>Creative Commons</ShortName>
 <Description>Find photos, movies, music, and text to rip, sample, mash, and share.</Description>
 <InputEncoding>utf-8</InputEncoding>
 <Image width="16" height="16">data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAJUSURBVDiNjZO9S1thGMXPvTfJFbnkipNkLLS0ksFg0M0lf4CboNCEgIIg/RiKtEOn0qGWTtbVoBYcIji10I9J0ApWCjp0kRaXdhHjTW4+uGnur4NJ8GOwZ3nf4TnnfZ5z3scAdBGGYdyVdN+yrGHTNNOtVqsVhuG+pO+S3gE/LtV3BIxzPDJNc8FxHGN0dNRKpVIGoJ2dndr+/r5Vr9cl6bmkN0AoSQIEyHXdj5KYnZ3F932uolKpkM/nK5KQ9FmSCZwLOI7zQBLr6+vXiFdRLBaDtsiTTve3YrFYkM/nbyR3MDU1dSKpLumO+vr6Xruui+d5AFSrVVZWVtjY2KDRaABwdHTE4uIie3t7AJTLZaLRaFXSCyUSid1MJgOA53n09/eTTqdJJpPMzc2xurqKbduMj48Tj8fZ3d0FYHBw8FjSezmOU56fnwdgeXkZ27ap1WpUKhWazSZjY2Nks1kASqVSd4zp6eljSX/MtiHdRDpnEATyfb+bkiSVSqXu3TCM8xgHBga+dkY4OzvDdV2GhoZIJBLMzMxQKBSIRqNkMhlisRhbW1sAJJPJn5I+KB6Pv7poou/7rK2tsbm5SRAEXROXlpY4ODgAoFarYdu2J+llN8ZcLvffMeZyud+SGpLuCVBPT89jSRQKhRvJxWKxISmU9JTOT5Rk9Pb2fpHE5OQkJycn14inp6dMTEx4bdM/SbKAy8sk6WEkElmwLCuSSqUYGRmxgHB7e7t+eHgYazabgaRnkt7SeZnr63xbUtYwjGHTNNNhGP4F9iR9a6/zr4v1/wDE1D9XlC4rrAAAAABJRU5ErkJggg==</Image>
-<Url type="text/html" method="GET" template="http://search.creativecommons.org/">
+<Url type="text/html" method="GET" template="http://search.creativecommons.org/" resultdomain="creativecommons.org">
   <Param name="q" value="{searchTerms}"/>
   <Param name="sourceid" value="Mozilla-search"/>
 </Url>
 <SearchForm>http://search.creativecommons.org/</SearchForm>
 </SearchPlugin>
--- a/browser/locales/en-US/searchplugins/eBay.xml
+++ b/browser/locales/en-US/searchplugins/eBay.xml
@@ -6,14 +6,14 @@
 <ShortName>eBay</ShortName>
 <Description>eBay - Online auctions</Description>
 <InputEncoding>ISO-8859-1</InputEncoding>
 <Image width="16" height="16">data:image/x-icon;base64,AAABAAIAEBAAAAAAAAB6AQAAJgAAACAgAAAAAAAAQgMAAKABAACJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAFBSURBVDjLtZPdK0MBGIf3J5Babhx3rinFBWuipaUskX9DYvkopqgV90q5UJpyp0OKrUWM2VrRsS9D0zZKHGaOnW1nj4vtypVtPPe/533r9746QAAOAJXfo5Yzgg44pHrcugon/6Sgo0b+XuAOZ2iZiVQmyPoDpIwmUkYTzqM7GsdDdC7F6Lbf8pzOkfWOouzqeZem2b+2AqAV8zjD8yVBqqcf2b7C66yNiMGMfixIQSvi8Mp0LEbR5ADq1QSKWM+Gx0RC9nOZ2GLzwlIWdPWiuNzk4w/EpThNkyEAXKEP2ud8KGId2sspilhPMrmNwzfCuqePr/xbSfC5I/I0MMSj2YJ3z49gDdO2cEOrLUowJpE9G0QRG1ClKbR0EIdvmOPYcnUtnN+vsnZiQC1k/qnGagQ1n3LNzySUJZVskitnmr8BlQG7T2hvgxsAAAAASUVORK5CYIKJUE5HDQoaCgAAAA1JSERSAAAAIAAAACAIBgAAAHN6evQAAAMJSURBVFjD7ZddSFNhGMeHXXQTZFFCWfR1pRhUECQlBdWVToo+6KYu1KigtDASG5qUfZgFZvahEDosECPDktKZS1FL+1DRnEvdUptjug91X2dnZzv/3vO6OZbWnR4v9sADL+fs7P97/s/znu2VAJD4UkpSSdKG+QubTyPBr+sXz8XCR64fIAHihVTis0SsUAoAVhEBrBKIHCGAEMB/ARi3F5LkbpS2WMRzYEEBXC2tsD6T03R9agsCGLNyqPw6CXmrBT06JvhbPHZwmkdwtR0B138PPKOHgzXD5jLAy3tmibo4K9weZwDAazJj/FQKRnfugfHMeRiTz0K3Ixam1HQKcPC+Fisu9NK1P08Uj4DleHgMdXC+WQ7nu3UEOhFMfTQcVUvQ1H4IN2sj8H2k7K+2TqCc3GseyA8AmDOzMBq7D9bS8sAr6nEJdNt3UbHVF1XQGtmZew8bTPT6tWoD3KpsUvlR8NxUoEICMvl6KQo+xqCwcRs4T8Ax5c8bFExjbAgAjO7aS8VsLypgq3g5nWStjztAhWRVhqAqeB6IuKTClkw1eNYEbrCQQBwD8yGGOsAooogLYejQPKBi7UPF9DkH+ezd+o141ZkUPAOC+L9SAMivNc7q46YMNSLTe4n1kaQF4XD3ZIDTPgU3XEYciKcAHrsGJS1xKFBGgyVzouiT4VbdGhjt/cEA5isyKsaz7jl3we7bg7Rqf6j0LoSldON4wWcqJDgQNGTN++l13vELA+MK6kKd6iryFOvxtidt9i5gO7owdjKJQliflNAU1pas6xQgnAzg1ux+lJEdILixNr0Pq9JUUA8NwVG9DM73G0jlcnh+V4BpjIWzJmIGQIjnXw5TiDuKSEwxurm3ITc8DNO51BnrLbIcsrW0dNA6RxgUKU1UdGVqLy5X6qGzTLvlnewiBZyGs3Yz6X8UeaYI3olvZDhzwLumZ+eHvooCCC0Q5VUsb4unwycM4YIDqA01tPqmgbzQr2EIYPECiPm33LYoDiZSsY9moh9O/Znoa4d9HkXtPg2pX/cPKCoRQ+ocZa4AAAAASUVORK5CYII=</Image>
 <Url type="application/x-suggestions+json" method="GET" template="http://anywhere.ebay.com/services/suggest/">
   <Param name="s" value="0"/>
   <Param name="q" value="{searchTerms}"/>
 </Url>
-<Url type="text/html" method="GET" template="http://rover.ebay.com/rover/1/711-47294-18009-3/4">
+<Url type="text/html" method="GET" template="http://rover.ebay.com/rover/1/711-47294-18009-3/4" resultdomain="ebay.com">
   <Param name="mpre" value="http://shop.ebay.com/?_nkw={searchTerms}"/>
 </Url>
 <SearchForm>http://search.ebay.com/</SearchForm>
 </SearchPlugin>
 
--- a/browser/locales/en-US/searchplugins/wikipedia.xml
+++ b/browser/locales/en-US/searchplugins/wikipedia.xml
@@ -6,14 +6,14 @@
 <ShortName>Wikipedia (en)</ShortName>
 <Description>Wikipedia, the free encyclopedia</Description>
 <InputEncoding>UTF-8</InputEncoding>
 <Image width="16" height="16">data:image/x-icon;base64,AAABAAIAEBAAAAAAAAA4AQAAJgAAACAgAAAAAAAAJAMAAGQBAACJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAEFSURBVDjLxZPRDYJAEESJoQjpgBoM/9IBtoAl4KcUQQlSAjYgJWAH0gPmyNtkzEEuxkQTPzawc3Ozc3MQTc/JfVPR/wW6a+eKQ+Hyfe54B2wvrfXVqXLDfTCMd3j0VHksrTcH9bl2aZq+BCgEwCCPj9E4TdPYGj0C9CYAKdkmBrIIxiIYbvpbb2sSl8AiA+ywAbJE5YLpCImLU/WRDyIAWRgu4k1s4v50ODru4haYSCk4ntkuM0wcMAINXiPKTJQ9CfgB40phBr8DyFjGKkKEhYhCY4iCDgpAYAM2EZBlhJnsZxQUYBNkSkfBvjDd0ttPeR0mxREQ+OhfYOJ6EmL+l/qzn2kGli9cAF3BOfkAAAAASUVORK5CYIKJUE5HDQoaCgAAAA1JSERSAAAAIAAAACAIBgAAAHN6evQAAAIKSURBVFjD7ZdBSgNRDIYLguAB7FLwAkXwBl0JgiDYjQcY8ARduBJKu3I5C0EoWDxAT9AL9AK9QBeCIHQlCM/3DZOSmeZNZ2r1bQyEGV7yXv7kJZlJq6XIOXfs+crzwPPTnvnR863n05ZFufDD/T595Q4eauM37u/pWYwfeX53cegcABcuHg0AkEQE8AKAu4gAXv8BrAEMh0PXbrddt9t1vV4v406nk62laeqm02n2LjKYIuK5WCyyfeiLDF32yLn6TJ5mBFarlev3+9nBMMqsabkYhmezWcEd2ctTE/tYBwhgt14BhtmAV2VaLpdrAHioCW+VdwWy9IMAUBQjJcQFTwGqvcTD+Xy+oc8askZJyAYrnKEokCeWLpQkSSZvBIANYgSDVVEQQJaeyHQu1QIgiQNb6AmrTtaQ9+RFSLa1D4iXgfsrVITloeSFFZlaAEjAUMaXo2DJWQtVRe1OKF5aJUkf0NdglXO5VzQGoI2USwwD3LEl590CtdO3QBoT5WSFV+Q63Oha17ITgMlkslGSGBWPdeNiDR2SL1B6zQFINmOAkFOW5eTSURCdvX6OdUlapaWjsKX0dgOg26/VWHSUKhrPz35ISKwq76R9Wx+kKgC1f0o5mISsypUG3kPj2L/lDzKYvEUwzoh2JtPRdQQAo1jD6afne88H1oTMeH6ZK+x7PB/lQ/CJtvkNEgDh1dr/bVYAAAAASUVORK5CYII=</Image>
 <Url type="application/x-suggestions+json" method="GET" template="http://en.wikipedia.org/w/api.php">
   <Param name="action" value="opensearch"/>
   <Param name="search" value="{searchTerms}"/>
 </Url>
-<Url type="text/html" method="GET" template="http://en.wikipedia.org/wiki/Special:Search">
+<Url type="text/html" method="GET" template="http://en.wikipedia.org/wiki/Special:Search" resultdomain="wikipedia.org">
   <Param name="search" value="{searchTerms}"/>
   <Param name="sourceid" value="Mozilla-search"/>
 </Url>
 <SearchForm>http://en.wikipedia.org/wiki/Special:Search</SearchForm>
 </SearchPlugin>
--- a/browser/locales/en-US/searchplugins/yahoo.xml
+++ b/browser/locales/en-US/searchplugins/yahoo.xml
@@ -4,15 +4,15 @@
 
 <SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
 <ShortName>Yahoo</ShortName>
 <Description>Yahoo Search</Description>
 <InputEncoding>UTF-8</InputEncoding>
 <Image width="16" height="16">data:image/x-icon;base64,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</Image>
 <Url type="application/x-suggestions+json" method="GET"
      template="http://ff.search.yahoo.com/gossip?output=fxjson&amp;command={searchTerms}" />
-<Url type="text/html" method="GET" template="http://search.yahoo.com/search">
+<Url type="text/html" method="GET" template="http://search.yahoo.com/search" resultdomain="yahoo.com">
   <Param name="p" value="{searchTerms}"/>
   <Param name="ei" value="UTF-8"/>
   <MozParam name="fr" condition="pref" pref="yahoo-fr" />
 </Url>
 <SearchForm>http://search.yahoo.com/</SearchForm>
 </SearchPlugin>
--- a/netwerk/base/public/nsIBrowserSearchService.idl
+++ b/netwerk/base/public/nsIBrowserSearchService.idl
@@ -17,17 +17,17 @@ interface nsISearchSubmission : nsISuppo
   readonly attribute nsIInputStream postData;
 
   /**
    * The URI to submit a search to.
    */
   readonly attribute nsIURI uri;
 };
 
-[scriptable, uuid(7914c4b8-f05b-40c9-a982-38a058cd1769)]
+[scriptable, uuid(77de6680-57ec-4105-a183-cc7cf7e84b09)]
 interface nsISearchEngine : nsISupports
 {
   /**
    * Gets a nsISearchSubmission object that contains information about what to
    * send to the search engine, including the URI and postData, if applicable.
    *
    * @param  data
    *         Data to add to the submission object.
@@ -152,16 +152,28 @@ interface nsISearchEngine : nsISupports
   readonly attribute long type;
 
   /**
    * An optional unique identifier for this search engine within the context of
    * the distribution, as provided by the distributing entity.
    */
   readonly attribute AString identifier;
 
+  /**
+   * Gets a string representing the hostname from which search results for a
+   * given responseType are returned, minus the leading "www." (if present).
+   * This can be specified as an url attribute in the engine description file,
+   * but will default to host from the <Url>'s template otherwise.
+   *
+   * @param  responseType [optional]
+   *         The MIME type to get resultDomain for.  Defaults to "text/html".
+   *
+   * @return the resultDomain for the given responseType.
+   */
+  AString getResultDomain([optional] in AString responseType);
 };
 
 [scriptable, uuid(9fc39136-f08b-46d3-b232-96f4b7b0e235)]
 interface nsISearchInstallCallback : nsISupports
 {
   const unsigned long ERROR_UNKNOWN_FAILURE = 0x1;
   const unsigned long ERROR_DUPLICATE_ENGINE = 0x2;
 
new file mode 100644
--- /dev/null
+++ b/toolkit/components/places/PriorityUrlProvider.jsm
@@ -0,0 +1,142 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = [ "PriorityUrlProvider" ];
+
+const Ci = Components.interfaces;
+const Cc = Components.classes;
+const Cu = Components.utils;
+const Cr = Components.results;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/Promise.jsm");
+Cu.import("resource://gre/modules/Task.jsm");
+
+
+/**
+ * Provides search engines matches to the PriorityUrlProvider through the
+ * search engines definitions handled by the Search Service.
+ */
+const SEARCH_ENGINE_TOPIC = "browser-search-engine-modified";
+
+let SearchEnginesProvider = {
+  init: function () {
+    this._engines = new Map();
+    let deferred = Promise.defer();
+    Services.search.init(rv => {
+      if (Components.isSuccessCode(rv)) {
+        Services.search.getVisibleEngines().forEach(this._addEngine, this);
+        deferred.resolve();
+      } else {
+        deferred.reject(new Error("Unable to initialize search service."));
+      }
+    });
+    Services.obs.addObserver(this, SEARCH_ENGINE_TOPIC, true);
+    return deferred.promise;
+  },
+
+  observe: function (engine, topic, verb) {
+    let engine = engine.QueryInterface(Ci.nsISearchEngine);
+    switch (verb) {
+      case "engine-added":
+        this._addEngine(engine);
+        break;
+      case "engine-changed":
+        if (engine.hidden) {
+          this._removeEngine(engine);
+        } else {
+          this._addEngine(engine);
+        }
+        break;
+      case "engine-removed":
+        this._removeEngine(engine);
+        break;
+    }
+  },
+
+  _addEngine: function (engine) {
+    if (this._engines.has(engine.name)) {
+      return;
+    }
+    let token = engine.getResultDomain();
+    if (!token) {
+      return;
+    }
+    let match = { token: token,
+                  // TODO (bug 557665): searchForm should provide an usable
+                  // url with affiliate code, if available.
+                  url: engine.searchForm,
+                  title: engine.name,
+                  iconUrl: engine.iconURI ? engine.iconURI.spec : null,
+                  reason: "search" }
+    this._engines.set(engine.name, match);
+    PriorityUrlProvider.addMatch(match);
+  },
+
+  _removeEngine: function (engine) {
+    if (!this._engines.has(engine.name)) {
+      return;
+    }
+    this._engines.delete(engine.name);
+    PriorityUrlProvider.removeMatchByToken(engine.getResultDomain());
+  },
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
+                                         Ci.nsISupportsWeakReference])
+}
+
+/**
+ * The PriorityUrlProvider allows to match a given string to a list of
+ * urls that should have priority in url search components, like autocomplete.
+ * Each returned match is an object with the following properties:
+ *  - token: string used to match the search term to the url
+ *  - url: url string represented by the match
+ *  - title: title describing the match, or an empty string if not available
+ *  - iconUrl: url of the icon associated to the match, or null if not available
+ *  - reason: a string describing the origin of the match, for example if it
+ *            represents a search engine, it will be "search".
+ */
+let matches = new Map();
+
+let initialized = false;
+function promiseInitialized() {
+  if (initialized) {
+    return Promise.resolve();
+  }
+  return Task.spawn(function* () {
+    try {
+      yield SearchEnginesProvider.init();
+    } catch (ex) {
+      Cu.reportError(ex);
+    }
+    initialized = true;
+  });
+}
+
+this.PriorityUrlProvider = Object.freeze({
+  addMatch: function (match) {
+    matches.set(match.token, match);
+  },
+
+  removeMatchByToken: function (token) {
+    matches.delete(token);
+  },
+
+  getMatchingSpec: function (searchToken) {
+    return Task.spawn(function* () {
+      yield promiseInitialized();
+      for (let [token, match] of matches.entries()) {
+        // Match at the beginning for now.  In future an aOptions argument may
+        // allow  to control the matching behavior.
+        if (token.startsWith(searchToken)) {
+          return match;
+        }
+      }
+      return null;
+    }.bind(this));
+  }
+});
--- a/toolkit/components/places/moz.build
+++ b/toolkit/components/places/moz.build
@@ -63,16 +63,17 @@ if CONFIG['MOZ_PLACES']:
         'BookmarkHTMLUtils.jsm',
         'BookmarkJSONUtils.jsm',
         'ClusterLib.js',
         'ColorAnalyzer_worker.js',
         'ColorConversion.js',
         'PlacesBackups.jsm',
         'PlacesDBUtils.jsm',
         'PlacesTransactions.jsm',
+        'PriorityUrlProvider.jsm'
     ]
 
     EXTRA_PP_JS_MODULES += [
         'PlacesUtils.jsm',
     ]
 
     EXTRA_COMPONENTS += [
         'ColorAnalyzer.js',
new file mode 100644
--- /dev/null
+++ b/toolkit/components/places/tests/unit/test_priorityUrlProvider.js
@@ -0,0 +1,74 @@
+/* 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/. */
+
+Cu.import("resource://gre/modules/PriorityUrlProvider.jsm");
+
+function run_test() {
+  run_next_test();
+}
+
+add_task(function* search_engine_match() {
+  let engine = yield promiseDefaultSearchEngine();
+  let token = engine.getResultDomain();
+  let match = yield PriorityUrlProvider.getMatchingSpec(token.substr(0, 1));
+  do_check_eq(match.url, engine.searchForm);
+  do_check_eq(match.title, engine.name);
+  do_check_eq(match.iconUrl, engine.iconURI ? engine.iconURI.spec : null);
+  do_check_eq(match.reason, "search");
+});
+
+add_task(function* no_match() {
+  do_check_eq(null, yield PriorityUrlProvider.getMatchingSpec("test"));
+});
+
+add_task(function* hide_search_engine_nomatch() {
+  let engine = yield promiseDefaultSearchEngine();
+  let token = engine.getResultDomain();
+  let promiseTopic = promiseSearchTopic("engine-changed");
+  Services.search.removeEngine(engine);
+  yield promiseTopic;
+  do_check_true(engine.hidden);
+  do_check_eq(null, yield PriorityUrlProvider.getMatchingSpec(token.substr(0, 1)));
+});
+
+add_task(function* add_search_engine_match() {
+  let promiseTopic = promiseSearchTopic("engine-added");
+  do_check_eq(null, yield PriorityUrlProvider.getMatchingSpec("bacon"));
+  Services.search.addEngineWithDetails("bacon", "", "bacon", "Search Bacon",
+                                       "GET", "http://www.bacon.moz/?search={searchTerms}");
+  yield promiseSearchTopic;
+  let match = yield PriorityUrlProvider.getMatchingSpec("bacon");
+  do_check_eq(match.url, "http://www.bacon.moz");
+  do_check_eq(match.title, "bacon");
+  do_check_eq(match.iconUrl, null);
+  do_check_eq(match.reason, "search");
+});
+
+add_task(function* remove_search_engine_nomatch() {
+  let engine = Services.search.getEngineByName("bacon");
+  let promiseTopic = promiseSearchTopic("engine-removed");
+  Services.search.removeEngine(engine);
+  yield promiseTopic;
+  do_check_eq(null, yield PriorityUrlProvider.getMatchingSpec("bacon"));
+});
+
+function promiseDefaultSearchEngine() {
+  let deferred = Promise.defer();
+  Services.search.init( () => {
+    deferred.resolve(Services.search.defaultEngine);
+  });
+  return deferred.promise;
+}
+
+function promiseSearchTopic(expectedVerb) {
+  let deferred = Promise.defer();
+  Services.obs.addObserver( function observe(subject, topic, verb) {
+    do_log_info("browser-search-engine-modified: " + verb);
+    if (verb == expectedVerb) {
+      Services.obs.removeObserver(observe, "browser-search-engine-modified");
+      deferred.resolve();
+    }
+  }, "browser-search-engine-modified", false);
+  return deferred.promise;
+}
--- a/toolkit/components/places/tests/unit/xpcshell.ini
+++ b/toolkit/components/places/tests/unit/xpcshell.ini
@@ -59,16 +59,17 @@ skip-if = os == "android"
 skip-if = os == "android"
 [test_adaptive_bug527311.js]
 [test_analyze.js]
 [test_annotations.js]
 [test_asyncExecuteLegacyQueries.js]
 # Bug 676989: test hangs consistently on Android
 skip-if = os == "android"
 [test_async_history_api.js]
+[test_async_transactions.js]
 [test_autocomplete_stopSearch_no_throw.js]
 [test_bookmark_catobs.js]
 [test_bookmarks_json.js]
 [test_bookmarks_html.js]
 [test_bookmarks_html_corrupt.js]
 [test_bookmarks_html_singleframe.js]
 [test_bookmarks_restore_notification.js]
 [test_bookmarks_setNullTitle.js]
@@ -81,16 +82,17 @@ skip-if = os == "android"
 [test_download_history.js]
 # Bug 676989: test fails consistently on Android
 fail-if = os == "android"
 [test_frecency.js]
 [test_frecency_zero_updated.js]
 # Bug 676989: test hangs consistently on Android
 skip-if = os == "android"
 [test_getChildIndex.js]
+[test_getPlacesInfo.js]
 [test_history.js]
 [test_history_autocomplete_tags.js]
 [test_history_catobs.js]
 [test_history_notifications.js]
 [test_history_observer.js]
 [test_history_removeAllPages.js]
 # Bug 676989: test hangs consistently on Android
 skip-if = os == "android"
@@ -105,37 +107,36 @@ skip-if = os == "android"
 # Bug 676989: test fails consistently on Android
 fail-if = os == "android"
 [test_multi_word_tags.js]
 [test_nsINavHistoryViewer.js]
 # Bug 902248: intermittent timeouts on all platforms
 skip-if = true
 [test_null_interfaces.js]
 [test_onItemChanged_tags.js]
+[test_pageGuid_bookmarkGuid.js]
 [test_placeURIs.js]
+[test_PlacesUtils_asyncGetBookmarkIds.js]
+[test_PlacesUtils_lazyobservers.js]
+[test_placesTxn.js]
 [test_preventive_maintenance.js]
 # Bug 676989: test hangs consistently on Android
 skip-if = os == "android"
 [test_preventive_maintenance_checkAndFixDatabase.js]
 # Bug 676989: test hangs consistently on Android
 skip-if = os == "android"
 [test_preventive_maintenance_runTasks.js]
+[test_priorityUrlProvider.js]
 [test_removeVisitsByTimeframe.js]
 # Bug 676989: test hangs consistently on Android
 skip-if = os == "android"
 [test_resolveNullBookmarkTitles.js]
 [test_result_sort.js]
 [test_sql_guid_functions.js]
 [test_tag_autocomplete_search.js]
 [test_tagging.js]
+[test_telemetry.js]
 [test_update_frecency_after_delete.js]
 # Bug 676989: test hangs consistently on Android
 skip-if = os == "android"
 [test_utils_backups_create.js]
 [test_utils_getURLsForContainerNode.js]
 [test_utils_setAnnotationsFor.js]
-[test_PlacesUtils_asyncGetBookmarkIds.js]
-[test_PlacesUtils_lazyobservers.js]
-[test_placesTxn.js]
-[test_telemetry.js]
-[test_getPlacesInfo.js]
-[test_pageGuid_bookmarkGuid.js]
-[test_async_transactions.js]
--- a/toolkit/components/search/nsSearchService.js
+++ b/toolkit/components/search/nsSearchService.js
@@ -856,22 +856,24 @@ function ParamSubstitution(aParamValue, 
  *        returned by this URL.
  * @param aMethod
  *        The HTTP request method. Must be a case insensitive value of either
  *        "GET" or "POST".
  * @param aTemplate
  *        The URL to which search queries should be sent. For GET requests,
  *        must contain the string "{searchTerms}", to indicate where the user
  *        entered search terms should be inserted.
+ * @param aResultDomain
+ *        The root domain for this URL.  Defaults to the template's host.
  *
  * @see http://opensearch.a9.com/spec/1.1/querysyntax/#urltag
  *
  * @throws NS_ERROR_NOT_IMPLEMENTED if aType is unsupported.
  */
-function EngineURL(aType, aMethod, aTemplate) {
+function EngineURL(aType, aMethod, aTemplate, aResultDomain) {
   if (!aType || !aMethod || !aTemplate)
     FAIL("missing type, method or template for EngineURL!");
 
   var method = aMethod.toUpperCase();
   var type   = aType.toLowerCase();
 
   if (method != "GET" && method != "POST")
     FAIL("method passed to EngineURL must be \"GET\" or \"POST\"");
@@ -893,16 +895,24 @@ function EngineURL(aType, aMethod, aTemp
     // Disable these for now, see bug 295018
     // case "file":
     // case "resource":
       this.template = aTemplate;
       break;
     default:
       FAIL("new EngineURL: template uses invalid scheme!", Cr.NS_ERROR_FAILURE);
   }
+
+  // If no resultDomain was specified in the engine definition file, use the
+  // host from the template.
+  this.resultDomain = aResultDomain || templateURI.host;
+  // We never want to return a "www." prefix, so eventually strip it.
+  if (this.resultDomain.startsWith("www.")) {
+    this.resultDomain = this.resultDomain.substr(4);
+  }
 }
 EngineURL.prototype = {
 
   addParam: function SRCH_EURL_addParam(aName, aValue, aPurpose) {
     this.params.push(new QueryParameter(aName, aValue, aPurpose));
   },
 
   // Note: This method requires that aObj has a unique name or the previous MozParams entry with
@@ -1013,17 +1023,18 @@ EngineURL.prototype = {
 
   /**
    * Creates a JavaScript object that represents this URL.
    * @returns An object suitable for serialization as JSON.
    **/
   _serializeToJSON: function SRCH_EURL__serializeToJSON() {
     var json = {
       template: this.template,
-      rels: this.rels
+      rels: this.rels,
+      resultDomain: this.resultDomain
     };
 
     if (this.type != URLTYPE_SEARCH_HTML)
       json.type = this.type;
     if (this.method != "GET")
       json.method = this.method;
 
     function collapseMozParams(aParam)
@@ -1044,16 +1055,18 @@ EngineURL.prototype = {
    */
   _serializeToElement: function SRCH_EURL_serializeToEl(aDoc, aElement) {
     var url = aDoc.createElementNS(OPENSEARCH_NS_11, "Url");
     url.setAttribute("type", this.type);
     url.setAttribute("method", this.method);
     url.setAttribute("template", this.template);
     if (this.rels.length)
       url.setAttribute("rel", this.rels.join(" "));
+    if (this.resultDomain)
+      url.setAttribute("resultDomain", this.resultDomain);
 
     for (var i = 0; i < this.params.length; ++i) {
       var param = aDoc.createElementNS(OPENSEARCH_NS_11, "Param");
       param.setAttribute("name", this.params[i].name);
       param.setAttribute("value", this.params[i].value);
       url.appendChild(aDoc.createTextNode("\n  "));
       url.appendChild(param);
     }
@@ -1765,19 +1778,20 @@ Engine.prototype = {
    * @see EngineURL()
    */
   _parseURL: function SRCH_ENG_parseURL(aElement) {
     var type     = aElement.getAttribute("type");
     // According to the spec, method is optional, defaulting to "GET" if not
     // specified
     var method   = aElement.getAttribute("method") || "GET";
     var template = aElement.getAttribute("template");
+    var resultDomain = aElement.getAttribute("resultdomain");
 
     try {
-      var url = new EngineURL(type, method, template);
+      var url = new EngineURL(type, method, template, resultDomain);
     } catch (ex) {
       FAIL("_parseURL: failed to add " + template + " as a URL",
            Cr.NS_ERROR_FAILURE);
     }
 
     if (aElement.hasAttribute("rel"))
       url.rels = aElement.getAttribute("rel").toLowerCase().split(/\s+/);
 
@@ -2266,17 +2280,18 @@ Engine.prototype = {
       this._readOnly = true;
     else
       this._readOnly = false;
     this._iconURI = makeURI(aJson._iconURL);
     this._iconMapObj = aJson._iconMapObj;
     for (let i = 0; i < aJson._urls.length; ++i) {
       let url = aJson._urls[i];
       let engineURL = new EngineURL(url.type || URLTYPE_SEARCH_HTML,
-                                    url.method || "GET", url.template);
+                                    url.method || "GET", url.template,
+                                    url.resultDomain);
       engineURL._initWithJSON(url, this);
       this._urls.push(engineURL);
     }
   },
 
   /**
    * Creates a JavaScript object that represents this engine.
    * @param aFilter
@@ -2714,16 +2729,35 @@ Engine.prototype = {
     return url.getSubmission(data, this, aPurpose);
   },
 
   // from nsISearchEngine
   supportsResponseType: function SRCH_ENG_supportsResponseType(type) {
     return (this._getURLOfType(type) != null);
   },
 
+  // from nsISearchEngine
+  getResultDomain: function SRCH_ENG_getResultDomain(aResponseType) {
+#ifdef ANDROID
+    if (!aResponseType) {
+      aResponseType = this._defaultMobileResponseType;
+    }
+#endif
+    if (!aResponseType) {
+      aResponseType = URLTYPE_SEARCH_HTML;
+    }
+
+    LOG("getResultDomain: responseType: \"" + aResponseType + "\"");
+
+    let url = this._getURLOfType(aResponseType);
+    if (url)
+      return url.resultDomain;
+    return "";
+  },
+
   // nsISupports
   QueryInterface: function SRCH_ENG_QI(aIID) {
     if (aIID.equals(Ci.nsISearchEngine) ||
         aIID.equals(Ci.nsISupports))
       return this;
     throw Cr.NS_ERROR_NO_INTERFACE;
   },
 
--- a/toolkit/components/search/tests/xpcshell/data/engine.xml
+++ b/toolkit/components/search/tests/xpcshell/data/engine.xml
@@ -1,26 +1,26 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
 <ShortName>Test search engine</ShortName>
 <Description>A test search engine (based on Google search)</Description>
 <InputEncoding>UTF-8</InputEncoding>
 <Image width="16" height="16">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</Image>
 <Url type="application/x-suggestions+json" method="GET" template="http://suggestqueries.google.com/complete/search?output=firefox&amp;client=firefox&amp;hl={moz:locale}&amp;q={searchTerms}"/>
-<Url type="text/html" method="GET" template="http://www.google.com/search">
+<Url type="text/html" method="GET" template="http://www.google.com/search" resultdomain="google.com">
   <Param name="q" value="{searchTerms}"/>
   <Param name="ie" value="utf-8"/>
   <Param name="oe" value="utf-8"/>
   <Param name="aq" value="t"/>
   <!-- Dynamic parameters -->
   <MozParam name="client" condition="defaultEngine" trueValue="firefox-a" falseValue="firefox"/>
   <MozParam name="channel" condition="purpose" purpose="contextmenu" value="rcs"/>
   <MozParam name="channel" condition="purpose" purpose="keyword" value="fflb"/>
 </Url>
-<Url type="application/x-moz-default-purpose" method="GET" template="http://www.google.com/search">
+<Url type="application/x-moz-default-purpose" method="GET" template="http://www.google.com/search" resultdomain="purpose.google.com">
   <Param name="q" value="{searchTerms}"/>
   <MozParam name="client" condition="defaultEngine" trueValue="firefox-a" falseValue="firefox"/>
   <!-- MozParam with a default value if purpose is not specified -->
   <MozParam name="channel" condition="purpose" purpose="" value="none"/>
   <MozParam name="channel" condition="purpose" purpose="contextmenu" value="rcs"/>
   <MozParam name="channel" condition="purpose" purpose="keyword" value="fflb"/>
 </Url>
 <SearchForm>http://www.google.com/</SearchForm>
--- a/toolkit/components/search/tests/xpcshell/data/search.json
+++ b/toolkit/components/search/tests/xpcshell/data/search.json
@@ -19,16 +19,17 @@
               "rels": [
               ],
               "type": "application/x-suggestions+json",
               "params": [
               ]
             },
             {
               "template": "http://www.google.com/search",
+              "resultDomain": "google.com",
               "rels": [
               ],
               "params": [
                 {
                   "name": "q",
                   "value": "{searchTerms}"
                 },
                 {
@@ -59,16 +60,17 @@
                   "name": "channel",
                   "value": "rcs",
                   "purpose": "contextmenu"
                 }
               ]
             },
             {
               "template": "http://www.google.com/search",
+              "resultDomain": "purpose.google.com",
               "rels": [
               ],
               "type": "application/x-moz-default-purpose",
               "params": [
                 {
                   "name": "q",
                   "value": "{searchTerms}"
                 },
--- a/toolkit/components/search/tests/xpcshell/head_search.js
+++ b/toolkit/components/search/tests/xpcshell/head_search.js
@@ -1,16 +1,16 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et: */
 
 Components.utils.import("resource://gre/modules/Services.jsm");
 Components.utils.import("resource://gre/modules/NetUtil.jsm");
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 Components.utils.import("resource://gre/modules/FileUtils.jsm");
-
+Components.utils.import("resource://gre/modules/Promise.jsm");
 Components.utils.import("resource://testing-common/AppInfo.jsm");
 
 const BROWSER_SEARCH_PREF = "browser.search.";
 const NS_APP_SEARCH_DIR = "SrchPlugns";
 
 const MODE_RDONLY = FileUtils.MODE_RDONLY;
 const MODE_WRONLY = FileUtils.MODE_WRONLY;
 const MODE_CREATE = FileUtils.MODE_CREATE;
--- a/toolkit/components/search/tests/xpcshell/test_json_cache.js
+++ b/toolkit/components/search/tests/xpcshell/test_json_cache.js
@@ -194,16 +194,17 @@ let EXPECTED_ENGINE = {
           template: "http://suggestqueries.google.com/complete/search?output=firefox&client=firefox" +
                       "&hl={moz:locale}&q={searchTerms}",
           params: "",
         },
         {
           type: "text/html",
           method: "GET",
           template: "http://www.google.com/search",
+          resultDomain: "google.com",
           params: [
             {
               "name": "q",
               "value": "{searchTerms}",
               "purpose": undefined,
             },
             {
               "name": "ie",
@@ -245,16 +246,17 @@ let EXPECTED_ENGINE = {
               "mozparam": true,
             },
           },
         },
         {
           type: "application/x-moz-default-purpose",
           method: "GET",
           template: "http://www.google.com/search",
+          resultDomain: "purpose.google.com",
           params: [
             {
               "name": "q",
               "value": "{searchTerms}",
               "purpose": undefined,
             },
             {
               "name": "client",
new file mode 100644
--- /dev/null
+++ b/toolkit/components/search/tests/xpcshell/test_resultDomain.js
@@ -0,0 +1,79 @@
+/* Any copyright is dedicated to the Public Domain.
+ *    http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/*
+ * Tests getResultDomain API.
+ */
+
+"use strict";
+
+const Ci = Components.interfaces;
+
+Components.utils.import("resource://testing-common/httpd.js");
+
+let waitForEngines = new Set([ "Test search engine",
+                               "A second test engine",
+                               "bacon" ]);
+
+function promiseEnginesAdded() {
+  let deferred = Promise.defer();
+
+  let observe = function observe(aSubject, aTopic, aData) {
+    let engine = aSubject.QueryInterface(Ci.nsISearchEngine);
+    do_print("Observer: " + aData + " for " + engine.name);
+    if (aData != "engine-added") {
+      return;
+    }
+    waitForEngines.delete(engine.name);
+    if (waitForEngines.size > 0) {
+      return;
+    }
+
+    let engine1 = Services.search.getEngineByName("Test search engine");
+    do_check_eq(engine1.getResultDomain(), "google.com");
+    do_check_eq(engine1.getResultDomain("text/html"), "google.com");
+    do_check_eq(engine1.getResultDomain("application/x-moz-default-purpose"),
+                "purpose.google.com");
+    do_check_eq(engine1.getResultDomain("fake-response-type"), "");
+    let engine2 = Services.search.getEngineByName("A second test engine");
+    do_check_eq(engine2.getResultDomain(), "duckduckgo.com");
+    let engine3 = Services.search.getEngineByName("bacon");
+    do_check_eq(engine3.getResultDomain(), "bacon.moz");
+    deferred.resolve();
+  };
+
+  Services.obs.addObserver(observe, "browser-search-engine-modified", false);
+  do_register_cleanup(function cleanup() {
+    Services.obs.removeObserver(observe, "browser-search-engine-modified");
+  });
+
+  return deferred.promise;
+}
+
+function run_test() {
+  removeMetadata();
+  updateAppInfo();
+
+  run_next_test();
+}
+
+add_task(function* check_resultDomain() {
+  let httpServer = new HttpServer();
+  httpServer.start(-1);
+  httpServer.registerDirectory("/", do_get_cwd());
+  let baseUrl = "http://localhost:" + httpServer.identity.primaryPort;
+  do_register_cleanup(function cleanup() {
+    httpServer.stop(function() {});
+  });
+
+  let promise = promiseEnginesAdded();
+  Services.search.addEngine(baseUrl + "/data/engine.xml",
+                            Ci.nsISearchEngine.DATA_XML,
+                            null, false);
+  Services.search.addEngine(baseUrl + "/data/engine2.xml",
+                            Ci.nsISearchEngine.DATA_XML,
+                            null, false);
+  Services.search.addEngineWithDetails("bacon", "", "bacon", "Search Bacon",
+                                       "GET", "http://www.bacon.moz/?search={searchTerms}");
+  yield promise;
+});
--- a/toolkit/components/search/tests/xpcshell/xpcshell.ini
+++ b/toolkit/components/search/tests/xpcshell/xpcshell.ini
@@ -26,13 +26,14 @@ support-files =
 [test_nodb_pluschanges.js]
 [test_save_sorted_engines.js]
 [test_purpose.js]
 [test_defaultEngine.js]
 [test_prefSync.js]
 [test_notifications.js]
 [test_addEngine_callback.js]
 [test_multipleIcons.js]
+[test_resultDomain.js]
 [test_serialize_file.js]
 [test_async.js]
 [test_sync.js]
 [test_sync_fallback.js]
 [test_sync_delay_fallback.js]