зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1244340 - Part 3: pass userContextId to search suggestions r=mak
This commit is contained in:
Родитель
69ed1a79e4
Коммит
8c13a9fd49
|
@ -13,6 +13,7 @@
|
|||
#include "nsIServiceManager.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsITreeBoxObject.h"
|
||||
#include "nsITreeColumns.h"
|
||||
#include "nsIObserverService.h"
|
||||
|
@ -1201,6 +1202,14 @@ nsAutoCompleteController::StartSearch(uint16_t aSearchType)
|
|||
searchParam.AppendLiteral(" prohibit-autofill");
|
||||
}
|
||||
|
||||
uint32_t userContextId;
|
||||
rv = input->GetUserContextId(&userContextId);
|
||||
if (NS_SUCCEEDED(rv) &&
|
||||
userContextId != nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID) {
|
||||
searchParam.AppendLiteral(" user-context-id:");
|
||||
searchParam.AppendInt(userContextId, 10);
|
||||
}
|
||||
|
||||
rv = search->StartSearch(mSearchString, searchParam, result, static_cast<nsIAutoCompleteObserver *>(this));
|
||||
if (NS_FAILED(rv)) {
|
||||
++mSearchesFailed;
|
||||
|
|
|
@ -154,4 +154,9 @@ interface nsIAutoCompleteInput : nsISupports
|
|||
* Don't rollup the popup when the caret is moved.
|
||||
*/
|
||||
readonly attribute boolean noRollupOnCaretMove;
|
||||
|
||||
/**
|
||||
* The userContextId of the current browser.
|
||||
*/
|
||||
readonly attribute unsigned long userContextId;
|
||||
};
|
||||
|
|
|
@ -5,6 +5,7 @@ Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
|||
|
||||
var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
var Cu = Components.utils;
|
||||
|
||||
/**
|
||||
* Dummy nsIAutoCompleteInput source that returns
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
"use strict";
|
||||
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
|
||||
function AutoCompleteInput(aSearches, aUserContextId) {
|
||||
this.searches = aSearches;
|
||||
this.userContextId = aUserContextId;
|
||||
this.popup.selectedIndex = -1;
|
||||
}
|
||||
AutoCompleteInput.prototype = Object.create(AutoCompleteInputBase.prototype);
|
||||
|
||||
function AutoCompleteSearch(aName) {
|
||||
this.name = aName;
|
||||
}
|
||||
AutoCompleteSearch.prototype = Object.create(AutoCompleteSearchBase.prototype);
|
||||
|
||||
add_task(function *test_userContextId() {
|
||||
let searchParam = yield doSearch("test", 1);
|
||||
Assert.equal(searchParam, " user-context-id:1");
|
||||
});
|
||||
|
||||
function doSearch(aString, aUserContextId) {
|
||||
let deferred = Promise.defer();
|
||||
let search = new AutoCompleteSearch("test");
|
||||
|
||||
search.startSearch = function (aSearchString,
|
||||
aSearchParam,
|
||||
aPreviousResult,
|
||||
aListener) {
|
||||
unregisterAutoCompleteSearch(search);
|
||||
deferred.resolve(aSearchParam);
|
||||
};
|
||||
|
||||
registerAutoCompleteSearch(search);
|
||||
|
||||
let controller = Cc["@mozilla.org/autocomplete/controller;1"].
|
||||
getService(Ci.nsIAutoCompleteController);
|
||||
|
||||
let input = new AutoCompleteInput([ search.name ], aUserContextId);
|
||||
controller.input = input;
|
||||
controller.startSearch(aString);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ skip-if = toolkit == 'gonk'
|
|||
[test_463023.js]
|
||||
[test_660156.js]
|
||||
[test_autocomplete_multiple.js]
|
||||
[test_autocomplete_userContextId.js]
|
||||
[test_autofillSelectedPopupIndex.js]
|
||||
[test_badDefaultIndex.js]
|
||||
[test_completeDefaultIndex_casing.js]
|
||||
|
|
|
@ -113,13 +113,14 @@ const SearchAutocompleteProviderInternal = {
|
|||
}
|
||||
},
|
||||
|
||||
getSuggestionController(searchToken, inPrivateContext, maxResults) {
|
||||
getSuggestionController(searchToken, inPrivateContext, maxResults, userContextId) {
|
||||
let engine = Services.search.currentEngine;
|
||||
if (!engine) {
|
||||
return null;
|
||||
}
|
||||
return new SearchSuggestionControllerWrapper(engine, searchToken,
|
||||
inPrivateContext, maxResults);
|
||||
inPrivateContext, maxResults,
|
||||
userContextId);
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||
|
@ -127,11 +128,12 @@ const SearchAutocompleteProviderInternal = {
|
|||
}
|
||||
|
||||
function SearchSuggestionControllerWrapper(engine, searchToken,
|
||||
inPrivateContext, maxResults) {
|
||||
inPrivateContext, maxResults,
|
||||
userContextId) {
|
||||
this._controller = new SearchSuggestionController();
|
||||
this._controller.maxLocalResults = 0;
|
||||
this._controller.maxRemoteResults = maxResults;
|
||||
let promise = this._controller.fetch(searchToken, inPrivateContext, engine);
|
||||
let promise = this._controller.fetch(searchToken, inPrivateContext, engine, userContextId);
|
||||
this._suggestions = [];
|
||||
this._success = false;
|
||||
this._promise = promise.then(results => {
|
||||
|
@ -283,11 +285,11 @@ this.PlacesSearchAutocompleteProvider = Object.freeze({
|
|||
};
|
||||
},
|
||||
|
||||
getSuggestionController(searchToken, inPrivateContext, maxResults) {
|
||||
getSuggestionController(searchToken, inPrivateContext, maxResults, userContextId) {
|
||||
if (!SearchAutocompleteProviderInternal.initialized) {
|
||||
throw new Error("The component has not been initialized.");
|
||||
}
|
||||
return SearchAutocompleteProviderInternal.getSuggestionController(
|
||||
searchToken, inPrivateContext, maxResults);
|
||||
searchToken, inPrivateContext, maxResults, userContextId);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -75,6 +75,9 @@ const MINIMUM_LOCAL_MATCHES = 6;
|
|||
// don't need to be exhaustive here, so allow dashes anywhere.
|
||||
const REGEXP_SINGLEWORD_HOST = new RegExp("^[a-z0-9-]+$", "i");
|
||||
|
||||
// Regex used to match userContextId.
|
||||
const REGEXP_USER_CONTEXT_ID = /(?:^| )user-context-id:(\d+)/;
|
||||
|
||||
// Regex used to match one or more whitespace.
|
||||
const REGEXP_SPACES = /\s+/;
|
||||
|
||||
|
@ -641,6 +644,7 @@ function looksLikeUrl(str) {
|
|||
* * private-window: The search is taking place in a private window,
|
||||
* possibly in permanent private-browsing mode. The search
|
||||
* should exclude privacy-sensitive results as appropriate.
|
||||
* * user-context-id: The userContextId of the selected tab.
|
||||
* @param autocompleteListener
|
||||
* An nsIAutoCompleteObserver.
|
||||
* @param resultListener
|
||||
|
@ -668,6 +672,11 @@ function Search(searchString, searchParam, autocompleteListener,
|
|||
this._inPrivateWindow = params.has("private-window");
|
||||
this._prohibitAutoFill = params.has("prohibit-autofill");
|
||||
|
||||
let userContextId = searchParam.match(REGEXP_USER_CONTEXT_ID);
|
||||
this._userContextId = userContextId ?
|
||||
parseInt(userContextId[1], 10) :
|
||||
Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID;
|
||||
|
||||
this._searchTokens =
|
||||
this.filterTokens(getUnfilteredSearchTokens(this._searchString));
|
||||
// The protocol and the host are lowercased by nsIURI, so it's fine to
|
||||
|
@ -1010,7 +1019,8 @@ Search.prototype = {
|
|||
PlacesSearchAutocompleteProvider.getSuggestionController(
|
||||
searchString,
|
||||
this._inPrivateWindow,
|
||||
Prefs.maxRichResults
|
||||
Prefs.maxRichResults,
|
||||
this._userContextId
|
||||
);
|
||||
let promise = this._searchSuggestionController.fetchCompletePromise
|
||||
.then(() => {
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "nsContentUtils.h"
|
||||
#include "nsILoadContext.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
|
@ -625,6 +626,13 @@ nsFormFillController::GetNoRollupOnCaretMove(bool *aNoRollupOnCaretMove)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFormFillController::GetUserContextId(uint32_t* aUserContextId)
|
||||
{
|
||||
*aUserContextId = nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//// nsIAutoCompleteSearch
|
||||
|
||||
|
|
|
@ -106,10 +106,11 @@ this.SearchSuggestionController.prototype = {
|
|||
* @param {string} searchTerm - the term to provide suggestions for
|
||||
* @param {bool} privateMode - whether the request is being made in the context of private browsing
|
||||
* @param {nsISearchEngine} engine - search engine for the suggestions.
|
||||
* @param {int} userContextId - the userContextId of the selected tab.
|
||||
*
|
||||
* @return {Promise} resolving to an object containing results or null.
|
||||
*/
|
||||
fetch: function(searchTerm, privateMode, engine) {
|
||||
fetch: function(searchTerm, privateMode, engine, userContextId) {
|
||||
// There is no smart filtering from previous results here (as there is when looking through
|
||||
// history/form data) because the result set returned by the server is different for every typed
|
||||
// value - e.g. "ocean breathes" does not return a subset of the results returned for "ocean".
|
||||
|
@ -139,7 +140,7 @@ this.SearchSuggestionController.prototype = {
|
|||
// Remote results
|
||||
if (searchTerm && gRemoteSuggestionsEnabled && this.maxRemoteResults &&
|
||||
engine.supportsResponseType(SEARCH_RESPONSE_SUGGESTION_JSON)) {
|
||||
this._deferredRemoteResult = this._fetchRemote(searchTerm, engine, privateMode);
|
||||
this._deferredRemoteResult = this._fetchRemote(searchTerm, engine, privateMode, userContextId);
|
||||
promises.push(this._deferredRemoteResult.promise);
|
||||
}
|
||||
|
||||
|
@ -230,7 +231,7 @@ this.SearchSuggestionController.prototype = {
|
|||
/**
|
||||
* Fetch suggestions from the search engine over the network.
|
||||
*/
|
||||
_fetchRemote: function(searchTerm, engine, privateMode) {
|
||||
_fetchRemote: function(searchTerm, engine, privateMode, userContextId) {
|
||||
let deferredResponse = Promise.defer();
|
||||
this._request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
|
||||
createInstance(Ci.nsIXMLHttpRequest);
|
||||
|
@ -238,9 +239,10 @@ this.SearchSuggestionController.prototype = {
|
|||
SEARCH_RESPONSE_SUGGESTION_JSON);
|
||||
let method = (submission.postData ? "POST" : "GET");
|
||||
this._request.open(method, submission.uri.spec, true);
|
||||
if (this._request.channel instanceof Ci.nsIPrivateBrowsingChannel) {
|
||||
this._request.channel.setPrivate(privateMode);
|
||||
}
|
||||
|
||||
this._request.setOriginAttributes({userContextId,
|
||||
privateBrowsingId: privateMode ? 1 : 0});
|
||||
|
||||
this._request.mozBackgroundRequest = true; // suppress dialogs and fail silently
|
||||
|
||||
this._request.addEventListener("load", this._onRemoteLoaded.bind(this, deferredResponse));
|
||||
|
|
|
@ -539,6 +539,15 @@ add_task(function* minus_one_results_requested() {
|
|||
}, /result/i);
|
||||
});
|
||||
|
||||
add_task(function* test_userContextId() {
|
||||
let controller = new SearchSuggestionController();
|
||||
controller._fetchRemote = function(searchTerm, engine, privateMode, userContextId) {
|
||||
Assert.equal(userContextId, 1);
|
||||
return Promise.defer();
|
||||
};
|
||||
|
||||
controller.fetch("test", false, getEngine, 1);
|
||||
});
|
||||
|
||||
// Helpers
|
||||
|
||||
|
|
|
@ -621,8 +621,12 @@
|
|||
<handler event="compositionend" phase="capturing"
|
||||
action="if (this.mController.input == this) this.mController.handleEndComposition();"/>
|
||||
|
||||
<handler event="focus" phase="capturing"
|
||||
action="this.attachController();"/>
|
||||
<handler event="focus" phase="capturing"><![CDATA[
|
||||
this.attachController();
|
||||
if (window.gBrowser) {
|
||||
this.userContextId = window.gBrowser.selectedBrowser.contentPrincipal.originAttributes.userContextId;
|
||||
}
|
||||
]]></handler>
|
||||
|
||||
<handler event="blur" phase="capturing"><![CDATA[
|
||||
if (!this._dontBlur) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче