Bug 1380771 - Add support for suggest_url to addEngineWithDetails. r?florian
MozReview-Commit-ID: LoUlLwXqSOH
--- a/netwerk/base/nsIBrowserSearchService.idl
+++ b/netwerk/base/nsIBrowserSearchService.idl
@@ -325,41 +325,60 @@ interface nsIBrowserSearchService : nsIS
* without starting to use it right away.
*
* @param name
* The search engine's name. Must be unique. Must not be null.
*
* @param iconURL
* Optional: A URL string pointing to the icon to be used to represent
* the engine.
+ * This is a jsval so that an object can be passed to replace the
+ * parameters below.
*
* @param alias
* Optional: A unique shortcut that can be used to retrieve the
* search engine.
*
* @param description
* Optional: a description of the search engine.
*
* @param method
- * The HTTP request method used when submitting a search query.
- * Must be a case insensitive value of either "get" or "post".
+ * Optional: The HTTP request method used when submitting a search query.
+ * Case insensitive value of either "get" or "post".
+ * Defaults to "get".
*
* @param url
* The URL to which search queries should be sent.
* Must not be null.
*
* @param extensionID [optional]
* Optional: The correct extensionID if called by an add-on.
+ *
+ * Alternatively, all of these parameters except for name can be
+ * passed as an object in place of parameter two.
+ *
+ * Services.search.addEngineWithDetails("Example engine", {
+ * template: "http://example.com/?search={searchTerms}",
+ * description: "Example search engine description",
+ * suggestURL: http://example.com/?suggest={searchTerms},
+ * });
+ *
+ * Using this method, you can use a new parameter, suggestURL:
+ *
+ * @param suggestURL [optional]
+ * Optional: The URL to which search suggestion requests
+ * should be sent.
+ *
*/
void addEngineWithDetails(in AString name,
- in AString iconURL,
- in AString alias,
- in AString description,
- in AString method,
- in AString url,
+ in jsval iconURL,
+ [optional] in AString alias,
+ [optional] in AString description,
+ [optional] in AString method,
+ [optional] in AString url,
[optional] in AString extensionID);
/**
* Un-hides all engines installed in the directory corresponding to
* the directory service's NS_APP_SEARCH_DIR key. (i.e. the set of
* engines returned by getDefaultEngines)
*/
void restoreDefaultEngines();
--- a/toolkit/components/search/nsSearchService.js
+++ b/toolkit/components/search/nsSearchService.js
@@ -1800,30 +1800,32 @@ Engine.prototype = {
// No need to keep a ref to our data (which in some cases can be a document
// element) past this point
this._data = null;
},
/**
* Initialize this Engine object from a collection of metadata.
*/
- _initFromMetadata: function SRCH_ENG_initMetaData(aName, aIconURL, aAlias,
- aDescription, aMethod,
- aTemplate, aExtensionID) {
+ _initFromMetadata: function SRCH_ENG_initMetaData(aName, aParams) {
ENSURE_WARN(!this._readOnly,
"Can't call _initFromMetaData on a readonly engine!",
Cr.NS_ERROR_FAILURE);
- this._urls.push(new EngineURL(URLTYPE_SEARCH_HTML, aMethod, aTemplate));
+ let method = aParams.method || "GET";
+ this._urls.push(new EngineURL(URLTYPE_SEARCH_HTML, method, aParams.template));
+ if (aParams.suggestURL) {
+ this._urls.push(new EngineURL(URLTYPE_SUGGEST_JSON, "GET", aParams.suggestURL));
+ }
this._name = aName;
- this.alias = aAlias;
- this._description = aDescription;
- this._setIcon(aIconURL, true);
- this._extensionID = aExtensionID;
+ this.alias = aParams.alias;
+ this._description = aParams.description;
+ this._setIcon(aParams.iconURL, true);
+ this._extensionID = aParams.extensionID;
},
/**
* Extracts data from an OpenSearch URL element and creates an EngineURL
* object which is then added to the engine's list of URLs.
*
* @throws NS_ERROR_FAILURE if a URL object could not be created.
*
@@ -4003,35 +4005,47 @@ SearchService.prototype = {
for (var engineName in this._engines) {
var engine = this._engines[engineName];
if (engine && engine.alias == aAlias)
return engine;
}
return null;
},
- addEngineWithDetails: function SRCH_SVC_addEWD(aName, aIconURL, aAlias,
- aDescription, aMethod,
- aTemplate, aExtensionID) {
+ addEngineWithDetails: function SRCH_SVC_addEWD(aName, iconURL, alias,
+ description, method,
+ template, extensionID) {
+ var params;
+
+ if (iconURL && typeof iconURL == "object") {
+ params = iconURL;
+ } else {
+ params = {
+ iconURL,
+ alias,
+ description,
+ method,
+ template,
+ extensionID,
+ };
+ }
+
this._ensureInitialized();
if (!aName)
FAIL("Invalid name passed to addEngineWithDetails!");
- if (!aMethod)
- FAIL("Invalid method passed to addEngineWithDetails!");
- if (!aTemplate)
+ if (!params.template)
FAIL("Invalid template passed to addEngineWithDetails!");
if (this._engines[aName])
FAIL("An engine with that name already exists!", Cr.NS_ERROR_FILE_ALREADY_EXISTS);
var engine = new Engine(sanitizeName(aName), false);
- engine._initFromMetadata(aName, aIconURL, aAlias, aDescription,
- aMethod, aTemplate, aExtensionID);
+ engine._initFromMetadata(aName, params);
engine._loadPath = "[other]addEngineWithDetails";
- if (aExtensionID) {
- engine._loadPath += ":" + aExtensionID;
+ if (params.extensionID) {
+ engine._loadPath += ":" + params.extensionID;
}
this._addEngineToStore(engine);
},
addEngine: function SRCH_SVC_addEngine(aEngineURL, aDataType, aIconURL,
aConfirm, aCallback) {
LOG("addEngine: Adding \"" + aEngineURL + "\".");
this._ensureInitialized();
new file mode 100644
--- /dev/null
+++ b/toolkit/components/search/tests/xpcshell/test_addEngineWithDetailsObject.js
@@ -0,0 +1,53 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const kSearchEngineID = "addEngineWithDetails_test_engine";
+const kSearchEngineURL = "http://example.com/?search={searchTerms}";
+const kSearchSuggestURL = "http://example.com/?suggest={searchTerms}";
+const kIconURL = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==";
+const kDescription = "Test Description";
+const kAlias = "alias_foo"
+const kSearchTerm = "foo";
+const kExtensionID = "test@example.com";
+const URLTYPE_SUGGEST_JSON = "application/x-suggestions+json";
+
+add_task(async function test_addEngineWithDetails() {
+ do_check_false(Services.search.isInitialized);
+
+ Services.prefs.getDefaultBranch(BROWSER_SEARCH_PREF)
+ .setBoolPref("reset.enabled", true);
+
+ await asyncInit();
+
+ Services.search.addEngineWithDetails(kSearchEngineID, {
+ template: kSearchEngineURL,
+ description: kDescription,
+ iconURL: kIconURL,
+ suggestURL: kSearchSuggestURL,
+ alias: "alias_foo",
+ extensionID: kExtensionID,
+ });
+
+ // 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);
+ do_check_eq(engine.wrappedJSObject._loadPath, "[other]addEngineWithDetails:" + kExtensionID);
+ do_check_eq(engine.description, kDescription);
+ do_check_eq(engine.iconURI.spec, kIconURL);
+ do_check_eq(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.currentEngine = engine;
+
+ let expectedURL = kSearchEngineURL.replace("{searchTerms}", kSearchTerm);
+ let submission =
+ Services.search.currentEngine.getSubmission(kSearchTerm, null, "searchbar");
+ do_check_eq(submission.uri.spec, expectedURL);
+ let expectedSuggestURL = kSearchSuggestURL.replace("{searchTerms}", kSearchTerm);
+ let submissionSuggest =
+ Services.search.currentEngine.getSubmission(kSearchTerm, URLTYPE_SUGGEST_JSON);
+ do_check_eq(submissionSuggest.uri.spec, expectedSuggestURL);
+});
--- a/toolkit/components/search/tests/xpcshell/xpcshell.ini
+++ b/toolkit/components/search/tests/xpcshell/xpcshell.ini
@@ -91,13 +91,14 @@ tags = addons
[test_selectedEngine.js]
[test_geodefaults.js]
[test_hidden.js]
[test_currentEngine_fallback.js]
[test_require_engines_in_cache.js]
[test_svg_icon.js]
[test_searchReset.js]
[test_addEngineWithDetails.js]
+[test_addEngineWithDetailsObject.js]
[test_addEngineWithExtensionID.js]
[test_chromeresource_icon1.js]
[test_chromeresource_icon2.js]
[test_engineUpdate.js]
[test_paramSubstitution.js]