зеркало из https://github.com/mozilla/pjs.git
Adds support for the OpenSearch suggestions extension, and updates the
Google and Yahoo plugins to use it. bug=340857 r=gavin sr/branch=mconnor
This commit is contained in:
Родитель
bc1d4eb4d1
Коммит
fc207b6130
|
@ -3057,7 +3057,14 @@ const BrowserSearch = {
|
|||
else
|
||||
engine = ss.defaultEngine;
|
||||
|
||||
var submission = engine.getSubmission(searchText);
|
||||
var submission = engine.getSubmission(searchText, null); // HTML response
|
||||
|
||||
// getSubmission can return null if the engine doesn't have a URL
|
||||
// with a text/html response type. This is unlikely (since
|
||||
// SearchService._addEngineToStore() should fail for such an engine),
|
||||
// but let's be on the safe side.
|
||||
if (!submission)
|
||||
return;
|
||||
|
||||
if (useNewTab) {
|
||||
getBrowser().loadOneTab(submission.uri.spec, null, null,
|
||||
|
|
|
@ -430,20 +430,22 @@
|
|||
<parameter name="aData"/>
|
||||
<parameter name="aInNewTab"/>
|
||||
<body><![CDATA[
|
||||
var postData = { value: null };
|
||||
var submission = this.currentEngine.getSubmission(aData);
|
||||
var postData = null;
|
||||
|
||||
// null parameter below specifies HTML response for search
|
||||
var submission = this.currentEngine.getSubmission(aData, null);
|
||||
if (submission) {
|
||||
var url = submission.uri.spec;
|
||||
postData.value = submission.postData;
|
||||
postData = submission.postData;
|
||||
}
|
||||
|
||||
if (aInNewTab) {
|
||||
content.focus();
|
||||
getBrowser().loadOneTab(url, null, null, postData.value, false, false);
|
||||
getBrowser().loadOneTab(url, null, null, postData, false, false);
|
||||
if (gURLBar)
|
||||
gURLBar.value = url;
|
||||
} else
|
||||
loadURI(url, null, postData.value, false);
|
||||
loadURI(url, null, postData, false);
|
||||
content.focus();
|
||||
]]></body>
|
||||
</method>
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
* Contributor(s):
|
||||
* Ben Goodger <beng@google.com> (Original author)
|
||||
* Gavin Sharp <gavin@gavinsharp.com>
|
||||
* Joe Hughes <joe@retrovirus.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -56,7 +57,7 @@ interface nsISearchSubmission : nsISupports
|
|||
readonly attribute nsIURI uri;
|
||||
};
|
||||
|
||||
[scriptable, uuid(d8ceea19-d004-4206-a614-bef9849a2cc9)]
|
||||
[scriptable, uuid(803e510b-4b27-4ba2-a16d-bb5fa953c166)]
|
||||
interface nsISearchEngine : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -67,10 +68,15 @@ interface nsISearchEngine : nsISupports
|
|||
* Data to add to the submission object.
|
||||
* i.e. the search terms.
|
||||
*
|
||||
* @param responseType
|
||||
* The MIME type that we'd like to receive in response
|
||||
* to this submission. If null, will default to "text/html".
|
||||
*
|
||||
* @returns A nsISearchSubmission object that contains information about what
|
||||
* to send to the search engine.
|
||||
* to send to the search engine. If no submission can be
|
||||
* obtained for the given responseType, returns null.
|
||||
*/
|
||||
nsISearchSubmission getSubmission(in AString data);
|
||||
nsISearchSubmission getSubmission(in AString data, in AString responseType);
|
||||
|
||||
/**
|
||||
* Adds a parameter to the search engine's submission data. This should only
|
||||
|
@ -84,10 +90,26 @@ interface nsISearchEngine : nsISupports
|
|||
* substituted with the user-entered data when retrieving the
|
||||
* submission. Must not be null.
|
||||
*
|
||||
* @param responseType
|
||||
* Since an engine can have several different request URLs,
|
||||
* differentiated by response types, this parameter selects
|
||||
* a request to add parameters to. If null, will default
|
||||
* to "text/html"
|
||||
*
|
||||
* @throws NS_ERROR_FAILURE if the search engine is read-only.
|
||||
* @throws NS_ERROR_INVALID_ARG if name or value are null.
|
||||
*/
|
||||
void addParam(in AString name, in AString value);
|
||||
void addParam(in AString name, in AString value, in AString responseType);
|
||||
|
||||
/**
|
||||
* Determines whether the engine can return responses in the given
|
||||
* MIME type. Returns true if the engine spec has a URL with the
|
||||
* given responseType, false otherwise.
|
||||
*
|
||||
* @param responseType
|
||||
* The MIME type to check for
|
||||
*/
|
||||
boolean supportsResponseType(in AString responseType);
|
||||
|
||||
/**
|
||||
* Supported search engine types.
|
||||
|
@ -132,11 +154,6 @@ interface nsISearchEngine : nsISupports
|
|||
*/
|
||||
readonly attribute AString searchForm;
|
||||
|
||||
/**
|
||||
* A URI object for retrieving suggested searches.
|
||||
*/
|
||||
readonly attribute nsIURI suggestionURI;
|
||||
|
||||
/**
|
||||
* The search engine type.
|
||||
*/
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
# Contributor(s):
|
||||
# Ben Goodger <beng@google.com> (Original author)
|
||||
# Gavin Sharp <gavin@gavinsharp.com>
|
||||
# Joe Hughes <joe@retrovirus.com
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -106,6 +107,9 @@ const OPENSEARCH_LOCALNAME = "OpenSearchDescription";
|
|||
const MOZSEARCH_NS_10 = "http://www.mozilla.org/2006/browser/search/";
|
||||
const MOZSEARCH_LOCALNAME = "SearchPlugin";
|
||||
|
||||
const URLTYPE_SUGGEST_JSON = "application/x-suggestions+json";
|
||||
const URLTYPE_SEARCH_HTML = "text/html";
|
||||
|
||||
// Empty base document used to serialize engines to file.
|
||||
const EMPTY_DOC = "<?xml version=\"1.0\"?>\n" +
|
||||
"<" + MOZSEARCH_LOCALNAME +
|
||||
|
@ -697,9 +701,6 @@ function EngineURL(aType, aMethod, aTemplate) {
|
|||
ENSURE_ARG(method == "GET" || method == "POST",
|
||||
"method passed to EngineURL must be \"GET\" or \"POST\"");
|
||||
|
||||
ENSURE(type == "text/html", "EngineURLs must be of type text/html!",
|
||||
Cr.NS_ERROR_NOT_IMPLEMENTED);
|
||||
|
||||
this.type = type;
|
||||
this.method = method;
|
||||
this.template = aTemplate;
|
||||
|
@ -936,6 +937,24 @@ Engine.prototype = {
|
|||
chan.asyncOpen(listener, null);
|
||||
},
|
||||
|
||||
/**
|
||||
* Attempts to find an EngineURL object in the set of EngineURLs for
|
||||
* this Engine that has the given type string. (This corresponds to the
|
||||
* "type" attribute in the "Url" node in the OpenSearch spec.)
|
||||
* This method will return the first matching URL object found, or null
|
||||
* if no matching URL is found.
|
||||
*
|
||||
* @param aType string to match the EngineURL's type attribute
|
||||
*/
|
||||
_getURLOfType: function SRCH_ENG__getURLOfType(aType) {
|
||||
for (var i = 0; i < this._urls.length; ++i) {
|
||||
if (this._urls[i].type == aType)
|
||||
return this._urls[i];
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle the successful download of an engine. Initializes the engine and
|
||||
* triggers parsing of the data. The engine is then flushed to disk. Notifies
|
||||
|
@ -1238,9 +1257,6 @@ Engine.prototype = {
|
|||
case "Alias":
|
||||
this._alias = child.textContent;
|
||||
break;
|
||||
case "SuggestionUrl":
|
||||
this._createSuggestionURI(child.textContent);
|
||||
break;
|
||||
case "SearchForm":
|
||||
this._searchForm = child.textContent;
|
||||
break;
|
||||
|
@ -1637,13 +1653,6 @@ Engine.prototype = {
|
|||
closeSafeOutputStream(fos);
|
||||
},
|
||||
|
||||
_createSuggestionURI: function SRCH_ENG_createSuggestionURI (aURLString) {
|
||||
var suggestionURI = makeURI(aURLString, this._queryCharset);
|
||||
if (suggestionURI &&
|
||||
(suggestionURI.schemeIs("http") || suggestionURI.schemeIs("https")))
|
||||
this._suggestionURI = suggestionURI;
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove the engine's file from disk. The search service calls this once it
|
||||
* removes the engine from its internal store. This function will throw if
|
||||
|
@ -1692,10 +1701,6 @@ Engine.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
get suggestionURI() {
|
||||
return this._suggestionURI;
|
||||
},
|
||||
|
||||
get iconURI() {
|
||||
return this._iconURI;
|
||||
},
|
||||
|
@ -1731,7 +1736,9 @@ Engine.prototype = {
|
|||
if (!this._searchForm) {
|
||||
// No searchForm specified in the engine definition file, use the prePath
|
||||
// (e.g. https://foo.com for https://foo.com/search.php?q=bar).
|
||||
this._searchForm = makeURI(this._urls[0].template).prePath;
|
||||
var htmlUrl = this._getURLOfType(URLTYPE_SEARCH_HTML);
|
||||
ENSURE_WARN(htmlUrl, "Engine has no HTML URL!", Cr.NS_ERROR_UNEXPECTED);
|
||||
this._searchForm = makeURI(htmlUrl.template).prePath;
|
||||
}
|
||||
|
||||
return this._searchForm;
|
||||
|
@ -1743,19 +1750,33 @@ Engine.prototype = {
|
|||
return this._queryCharset = queryCharsetFromCode(/* get the default */);
|
||||
},
|
||||
|
||||
addParam: function SRCH_ENG_addParam(aName, aValue) {
|
||||
// from nsISearchEngine
|
||||
addParam: function SRCH_ENG_addParam(aName, aValue, aResponseType) {
|
||||
ENSURE_ARG(aName && (aValue != null),
|
||||
"missing name or value for nsISearchEngine::addParam!");
|
||||
ENSURE_WARN(!this._readOnly,
|
||||
"called nsISearchEngine::addParam on a read-only engine!",
|
||||
Cr.NS_ERROR_FAILURE);
|
||||
if (!aResponseType)
|
||||
aResponseType = URLTYPE_SEARCH_HTML;
|
||||
|
||||
this._urls[0].addParam(aName, aValue);
|
||||
var url = this._getURLOfType(aResponseType);
|
||||
|
||||
ENSURE(url, "Engine object has no URL for response type " + aResponseType,
|
||||
Cr.NS_ERROR_FAILURE);
|
||||
|
||||
url.addParam(aName, aValue);
|
||||
},
|
||||
|
||||
getSubmission: function SRCH_ENG_getSubmission(aData) {
|
||||
ENSURE_WARN(this._urls[0], "engine object has no URL!",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
// from nsISearchEngine
|
||||
getSubmission: function SRCH_ENG_getSubmission(aData, aResponseType) {
|
||||
if (!aResponseType)
|
||||
aResponseType = URLTYPE_SEARCH_HTML;
|
||||
|
||||
var url = this._getURLOfType(aResponseType);
|
||||
|
||||
if (!url)
|
||||
return null;
|
||||
|
||||
if (!aData) {
|
||||
// Return a dummy submission object with our searchForm attribute
|
||||
|
@ -1773,7 +1794,12 @@ Engine.prototype = {
|
|||
data = textToSubURI.ConvertAndEscape(DEFAULT_QUERY_CHARSET, aData);
|
||||
}
|
||||
LOG("getSubmission: Out data: \"" + data + "\"");
|
||||
return this._urls[0].getSubmission(data); //XXX only support one URL?
|
||||
return url.getSubmission(data);
|
||||
},
|
||||
|
||||
// from nsISearchEngine
|
||||
supportsResponseType: function SRCH_ENG_supportsResponseType(type) {
|
||||
return (this._getURLOfType(type) != null);
|
||||
},
|
||||
|
||||
// nsISupports
|
||||
|
@ -1850,6 +1876,12 @@ SearchService.prototype = {
|
|||
// might want to prompt the user in the case where the engine is being
|
||||
// added through a user action
|
||||
}
|
||||
|
||||
if (!aEngine.supportsResponseType(URLTYPE_SEARCH_HTML)) {
|
||||
LOG("_addEngineToStore: Won't add engines that have no HTML output!");
|
||||
return;
|
||||
}
|
||||
|
||||
this._engines[aEngine.name] = aEngine;
|
||||
this._sortedEngines.push(aEngine);
|
||||
notifyAction(aEngine, SEARCH_ENGINE_ADDED);
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const SEARCH_RESPONSE_SUGGESTION_JSON = "application/x-suggestions+json";
|
||||
|
||||
/**
|
||||
* Metadata describing the Web Search suggest mode
|
||||
*/
|
||||
|
@ -276,10 +278,10 @@ SuggestAutoComplete.prototype = {
|
|||
_nextRequestTime: 0,
|
||||
|
||||
/**
|
||||
* The last URI we requested against (so that we can tell if the
|
||||
* The last engine we requested against (so that we can tell if the
|
||||
* user switched engines).
|
||||
*/
|
||||
_serverErrorURI: null,
|
||||
_serverErrorEngine: null,
|
||||
|
||||
/**
|
||||
* The XMLHttpRequest object.
|
||||
|
@ -348,6 +350,11 @@ SuggestAutoComplete.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* This is the URI that the last suggest request was sent to.
|
||||
*/
|
||||
_suggestURI: null,
|
||||
|
||||
/**
|
||||
* Autocomplete results from the form history service get stored here.
|
||||
*/
|
||||
|
@ -421,19 +428,19 @@ SuggestAutoComplete.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* This checks to see if the new search suggestion URI is different
|
||||
* This checks to see if the new search engine is different
|
||||
* from the previous one, and if so clears any error state that might
|
||||
* have accumulated for the old engine/URI.
|
||||
* have accumulated for the old engine.
|
||||
*
|
||||
* @param uri The URI that the suggestion request would be sent to.
|
||||
* @param engine The engine that the suggestion request would be sent to.
|
||||
* @private
|
||||
*/
|
||||
_checkForEngineSwitch: function SAC__checkForEngineSwitch(uri) {
|
||||
if (uri == this._serverErrorURI)
|
||||
_checkForEngineSwitch: function SAC__checkForEngineSwitch(engine) {
|
||||
if (engine == this._serverErrorEngine)
|
||||
return;
|
||||
|
||||
// must've switched search providers, clear old errors
|
||||
this._serverErrorURI = uri;
|
||||
this._serverErrorEngine = engine;
|
||||
this._clearServerErrors();
|
||||
},
|
||||
|
||||
|
@ -479,10 +486,7 @@ SuggestAutoComplete.prototype = {
|
|||
this._clearServerErrors();
|
||||
|
||||
var searchString, results, queryURLs;
|
||||
var searchService = Cc["@mozilla.org/browser/search-service;1"].
|
||||
getService(Ci.nsIBrowserSearchService);
|
||||
var sandboxHost = searchService.currentEngine.suggestionURI.prePath;
|
||||
var sandbox = new Components.utils.Sandbox(sandboxHost);
|
||||
var sandbox = new Components.utils.Sandbox(this._suggestURI.prePath);
|
||||
var results2 = Components.utils.evalInSandbox(responseText, sandbox);
|
||||
|
||||
if (results2[0]) {
|
||||
|
@ -598,10 +602,13 @@ SuggestAutoComplete.prototype = {
|
|||
|
||||
this._listener = listener;
|
||||
|
||||
var suggestionURI = searchService.currentEngine.suggestionURI;
|
||||
this._checkForEngineSwitch(suggestionURI);
|
||||
var engine = searchService.currentEngine;
|
||||
|
||||
if (!searchString || !suggestionURI || !this._okToRequest()) {
|
||||
this._checkForEngineSwitch(engine);
|
||||
|
||||
if (!searchString ||
|
||||
!engine.supportsResponseType(SEARCH_RESPONSE_SUGGESTION_JSON) ||
|
||||
!this._okToRequest()) {
|
||||
// We have an empty search string (user pressed down arrow to see
|
||||
// history), or the current engine has no suggest functionality,
|
||||
// or we're in backoff mode; so just use local history.
|
||||
|
@ -610,18 +617,21 @@ SuggestAutoComplete.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
var suggestionURL = suggestionURI.spec;
|
||||
// Actually do the search
|
||||
this._request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
|
||||
createInstance(Ci.nsIXMLHttpRequest);
|
||||
this._request.open("GET", suggestionURL + encodeURIComponent(searchString), true);
|
||||
var submission = engine.getSubmission(searchString,
|
||||
SEARCH_RESPONSE_SUGGESTION_JSON);
|
||||
this._suggestURI = submission.uri;
|
||||
var method = (submission.postData ? "POST" : "GET");
|
||||
this._request.open(method, this._suggestURI.spec, true);
|
||||
|
||||
var self = this;
|
||||
function onReadyStateChange() {
|
||||
self.onReadyStateChange();
|
||||
}
|
||||
this._request.onreadystatechange = onReadyStateChange;
|
||||
this._request.send(null);
|
||||
this._request.send(submission.postData);
|
||||
|
||||
if (this._includeFormHistory) {
|
||||
this._sentSuggestRequest = true;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<Description>Google Search</Description>
|
||||
<InputEncoding>UTF-8</InputEncoding>
|
||||
<Image width="16" height="16">data:image/x-icon;base64,R0lGODlhEAAQAPfLAAATVikwdA8SnxUfgAsWpAAilholjxw4jBc7kwAlvQQ2sRMsoBUqqhMzuhY/vxw4tSgmiyM1mSUztiQ6sTE3sQ4qyxMxxRoyxiAuxR1CtBxJsBxasSJuuTFguBte0Rlf2xVc9h9W9xVjzxVr0gdj6BRh4R1o5yBcyiZbyydT1i9b2Ddb1iFY6CJg2Vpor1dzvEJu20Z0yi23QDy1REi2OUy0O1WzOVC4PU+tVUe5Sk2xQU2zRUO4UE21Ula2SmKEqWWF2HyPx2+a6X6e6Xqk1m+s78sUDs4UGdEQB9YfDdwaANEfHd0YEscjAM4mAM0qANIoD9IkGdslGswuItYgL4aP0ImP2YGZ36Opzaq2wq/S+rzX/7/e8MrS1MLO/sTb48rT8snX/83c89PZ+crq+cH1/9Dl/9Ln/93r/9fy/+Hf7P/42eDm/O7u/+T29uX2/eT2/+f4/+f5/+j/9u//8+3/9u7/9ur5/+j//+n//+v//u3//+7//e7//+////b66/T/6vX/6/f/7f/07fj/4fv/4Pj/5v/45v7/4/r+7/3/6fDw+Pfx//D/9/X/8fT/8/f/8ff/8/D///H///L8/fL///P///X7//b6/ff/+/T///b9//f///v19//w9v/09P/29v/x+f/y///z///1+v/1///2///3//j79P/58/z/8/z99/z/9v7/9P7/9vn7//v6//j9//n9//j///n///v//vv////4+v/5+//6+P/4///6/P/6/v/6///7///9+P/8+v/9+v7/+Pz////8/f/9/f79///8///9//7//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAMsALAAAAAAQABAAAAj/AEn4oIFjBw8bOnrMuJGjhowZM1T8UdYJUZ5ZcNRYWjSrVK5QU0DMmtUnzRAXEy4o6FCEy6NDTkQIq1MmRgM0eZTlCXMgQJtRSE4gmgUkwh1EiZTNUiamy6NUUExcuoJgDCdDjQg9KgVL2SNFT1hwEvKglLBWuixZ+jSrlSBdRlL04bBBkTBdpZTpIqWsFaBcTEr0QaEhl6dWlswKW6poDRUPlmAUQKWMkTJLc76QMQNGUZMWgIgkCFJnlq5WXigwkFClVZQQyuRgELAlk7JBymCZGYAF0ZEPrQixgUDAihxVdPpoAZAFUZIRfThxgvPCwAILDipk+OFG2ZIVoxApERtPfvwlvZ+kQFzPvv0MJQEBADs=</Image>
|
||||
<SuggestionUrl>http://www.google.com/complete/search?csv=t&qu=</SuggestionUrl>
|
||||
<Url type="application/x-suggestions+json" method="GET" template="http://www.google.com/complete/search?csv=t&qu={searchTerms}"/>
|
||||
<Url type="text/html" method="GET" template="http://www.google.com/search">
|
||||
<Param name="q" value="{searchTerms}"/>
|
||||
<Param name="start" value="0"/>
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
<ShortName>Yahoo</ShortName>
|
||||
<Description>Yahoo Search</Description>
|
||||
<InputEncoding>UTF-8</InputEncoding>
|
||||
<SuggestionUrl>http://ff.search.yahoo.com/gossip?output=fxjson&command=</SuggestionUrl>
|
||||
<Image width="16" height="16">data:image/x-icon;base64,R0lGODlhEAAQAJECAP8AAAAAAP///wAAACH5BAEAAAIALAAAAAAQABAAAAIplI+py+0NogQuyBDEnEd2kHkfFWUamEzmpZSfmaIHPHrRguUm/fT+UwAAOw==</Image>
|
||||
<Url type="application/x-suggestions+json" method="GET"
|
||||
template="http://ff.search.yahoo.com/gossip?output=fxjson&command={searchTerms}" />
|
||||
<Url type="text/html" method="GET" template="http://search.yahoo.com/search">
|
||||
<Param name="p" value="{searchTerms}"/>
|
||||
<Param name="ei" value="UTF-8"/>
|
||||
|
|
Загрузка…
Ссылка в новой задаче