Skip to content
This repository has been archived by the owner on Aug 4, 2022. It is now read-only.

Commit

Permalink
Bug 1599840 - part 2 - Set restricting behavior based on QueryContext…
Browse files Browse the repository at this point in the history
… sources. r=adw

Differential Revision: https://phabricator.services.mozilla.com/D56354
  • Loading branch information
mak77 committed Dec 11, 2019
1 parent 4e32909 commit 2fbc75f
Show file tree
Hide file tree
Showing 12 changed files with 180 additions and 44 deletions.
8 changes: 4 additions & 4 deletions browser/components/urlbar/UrlbarProviderOpenTabs.jsm
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,13 @@ class ProviderOpenTabs extends UrlbarProvider {
* @param {string} url Address of the tab
* @param {integer} userContextId Containers user context id
*/
registerOpenTab(url, userContextId = 0) {
async registerOpenTab(url, userContextId = 0) {
if (!this.openTabs.has(userContextId)) {
this.openTabs.set(userContextId, []);
}
this.openTabs.get(userContextId).push(url);
if (this._db) {
addToMemoryTable(this._db, url, userContextId);
await addToMemoryTable(this._db, url, userContextId);
}
}

Expand All @@ -141,14 +141,14 @@ class ProviderOpenTabs extends UrlbarProvider {
* @param {string} url Address of the tab
* @param {integer} userContextId Containers user context id
*/
unregisterOpenTab(url, userContextId = 0) {
async unregisterOpenTab(url, userContextId = 0) {
let openTabs = this.openTabs.get(userContextId);
if (openTabs) {
let index = openTabs.indexOf(url);
if (index != -1) {
openTabs.splice(index, 1);
if (this._db) {
removeFromMemoryTable(this._db, url, userContextId);
await removeFromMemoryTable(this._db, url, userContextId);
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions browser/components/urlbar/UrlbarProvidersManager.jsm
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ class ProvidersManager {
// Apply tokenization.
UrlbarTokenizer.tokenize(queryContext);

// If there's a single source, we are in restriction mode.
if (queryContext.sources && queryContext.sources.length == 1) {
queryContext.restrictSource = queryContext.sources[0];
}
// Providers can use queryContext.sources to decide whether they want to be
// invoked or not.
updateSourcesIfEmpty(queryContext);
Expand Down
20 changes: 10 additions & 10 deletions browser/components/urlbar/UrlbarUtils.jsm
Original file line number Diff line number Diff line change
Expand Up @@ -559,18 +559,18 @@ class UrlbarQueryContext {
);
}

if (
options.providers &&
(!Array.isArray(options.providers) || !options.providers.length)
) {
throw new Error(`Invalid providers list`);
if (options.providers) {
if (!Array.isArray(options.providers) || !options.providers.length) {
throw new Error(`Invalid providers list`);
}
this.providers = options.providers;
}

if (
options.sources &&
(!Array.isArray(options.sources) || !options.sources.length)
) {
throw new Error(`Invalid sources list`);
if (options.sources) {
if (!Array.isArray(options.sources) || !options.sources.length) {
throw new Error(`Invalid sources list`);
}
this.sources = options.sources;
}

this.lastResultCount = 0;
Expand Down
18 changes: 11 additions & 7 deletions browser/components/urlbar/tests/unit/head.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,17 @@ const { sinon } = ChromeUtils.import("resource://testing-common/Sinon.jsm");
* required options.
*/
function createContext(searchString = "foo", properties = {}) {
let context = new UrlbarQueryContext({
allowAutofill: UrlbarPrefs.get("autoFill"),
isPrivate: true,
maxResults: UrlbarPrefs.get("maxRichResults"),
searchString,
});
return Object.assign(context, properties);
return new UrlbarQueryContext(
Object.assign(
{
allowAutofill: UrlbarPrefs.get("autoFill"),
isPrivate: true,
maxResults: UrlbarPrefs.get("maxRichResults"),
searchString,
},
properties
)
);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/* 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 for restrictions set through UrlbarQueryContext.sources.
*/

add_task(async function setup() {
Services.prefs.setBoolPref("browser.urlbar.geoSpecificDefaults", false);
let engine = await addTestSuggestionsEngine();
let oldDefaultEngine = await Services.search.getDefault();
Services.search.setDefault(engine);
registerCleanupFunction(async () =>
Services.search.setDefault(oldDefaultEngine)
);
});

XPCOMUtils.defineLazyServiceGetter(
this,
"unifiedComplete",
"@mozilla.org/autocomplete/search;1?name=unifiedcomplete",
"nsIAutoCompleteSearch"
);

add_task(async function test_restrictions() {
await PlacesTestUtils.addVisits([
{ uri: "http://history.com/", title: "match" },
]);
await PlacesUtils.bookmarks.insert({
url: "http://bookmark.com/",
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
title: "match",
});
await UrlbarProviderOpenTabs.registerOpenTab("http://openpagematch.com/");

info("Bookmark restrict");
let results = await get_results({
sources: [UrlbarUtils.RESULT_SOURCE.BOOKMARKS],
searchString: "match",
});
// Skip the heuristic result.
Assert.deepEqual(results.filter(r => !r.heuristic).map(r => r.payload.url), [
"http://bookmark.com/",
]);

info("History restrict");
results = await get_results({
sources: [UrlbarUtils.RESULT_SOURCE.HISTORY],
searchString: "match",
});
// Skip the heuristic result.
Assert.deepEqual(results.filter(r => !r.heuristic).map(r => r.payload.url), [
"http://history.com/",
]);

info("tabs restrict");
results = await get_results({
sources: [UrlbarUtils.RESULT_SOURCE.TABS],
searchString: "match",
});
// Skip the heuristic result.
Assert.deepEqual(results.filter(r => !r.heuristic).map(r => r.payload.url), [
"http://openpagematch.com/",
]);

info("search restrict");
results = await get_results({
sources: [UrlbarUtils.RESULT_SOURCE.SEARCH],
searchString: "match",
});
// Heuristic, private window, 2 suggestions.
Assert.deepEqual(
results.map(r => r.payload.engine),
new Array(4).fill("engine-suggestions.xml")
);
});

async function get_results(test) {
let controller = UrlbarTestUtils.newMockController();
let queryContext = createContext(test.searchString, {
allowAutofill: false,
isPrivate: false,
maxResults: 10,
sources: test.sources,
});
await controller.startQuery(queryContext);
info(JSON.stringify(queryContext.results));
return queryContext.results;
}
1 change: 1 addition & 0 deletions browser/components/urlbar/tests/unit/xpcshell.ini
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ support-files =
[test_UrlbarController_telemetry.js]
[test_UrlbarController_integration.js]
[test_UrlbarQueryContext.js]
[test_UrlbarQueryContext_restrictSource.js]
[test_UrlbarUtils_addToUrlbarHistory.js]
[test_UrlbarUtils_getShortcutOrURIAndPostData.js]
[test_UrlbarUtils_getTokenMatches.js]
46 changes: 37 additions & 9 deletions toolkit/components/places/UnifiedComplete.jsm
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,15 @@ XPCOMUtils.defineLazyGetter(this, "typeToBehaviorMap", () => {
]);
});

XPCOMUtils.defineLazyGetter(this, "sourceToBehaviorMap", () => {
return new Map([
[UrlbarUtils.RESULT_SOURCE.HISTORY, "history"],
[UrlbarUtils.RESULT_SOURCE.BOOKMARKS, "bookmark"],
[UrlbarUtils.RESULT_SOURCE.TABS, "openpage"],
[UrlbarUtils.RESULT_SOURCE.SEARCH, "search"],
]);
});

// Helper functions

/**
Expand Down Expand Up @@ -721,7 +730,28 @@ function Search(
}
}

this._searchTokens = this.filterTokens(tokens);
// The behavior can be set through:
// 1. a specific restrictSource in the QueryContext
// 2. typed restriction tokens
if (
queryContext &&
queryContext.restrictSource &&
sourceToBehaviorMap.has(queryContext.restrictSource)
) {
this._searchTokens = tokens;
this._behavior = 0;
this.setBehavior("restrict");
this.setBehavior(sourceToBehaviorMap.get(queryContext.restrictSource));
} else {
this._searchTokens = this.filterTokens(tokens);
}

// Set the right JavaScript behavior based on our preference. Note that the
// preference is whether or not we should filter JavaScript, and the
// behavior is if we should search it or not.
if (!UrlbarPrefs.get("filter.javascript")) {
this.setBehavior("javascript");
}

// The heuristic token is the first filtered search token, but only when it's
// actually the first thing in the search string. If a prefix or restriction
Expand Down Expand Up @@ -895,12 +925,6 @@ Search.prototype = {
}
}
}
// Set the right JavaScript behavior based on our preference. Note that the
// preference is whether or not we should filter JavaScript, and the
// behavior is if we should search it or not.
if (!UrlbarPrefs.get("filter.javascript")) {
this.setBehavior("javascript");
}
return filtered;
},

Expand Down Expand Up @@ -1157,7 +1181,7 @@ Search.prototype = {
}
queries.push(this._searchQuery);

// Finally run all the other queries.
// Finally run all the remaining queries.
for (let [query, params] of queries) {
await conn.executeCached(query, params, this._onResultRow.bind(this));
if (!this.pending) {
Expand Down Expand Up @@ -1194,7 +1218,11 @@ Search.prototype = {
this._counts[UrlbarUtils.RESULT_GROUP.HEURISTIC];
if (count < this._maxResults) {
this._matchBehavior = Ci.mozIPlacesAutoComplete.MATCH_ANYWHERE;
for (let [query, params] of [this._adaptiveQuery, this._searchQuery]) {
let queries = [this._adaptiveQuery, this._searchQuery];
if (this.hasBehavior("openpage")) {
queries.unshift(this._switchToTabQuery);
}
for (let [query, params] of queries) {
await conn.executeCached(query, params, this._onResultRow.bind(this));
if (!this.pending) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -408,15 +408,15 @@ var addBookmark = async function(aBookmarkObj) {
}
};

function addOpenPages(aUri, aCount = 1, aUserContextId = 0) {
async function addOpenPages(aUri, aCount = 1, aUserContextId = 0) {
for (let i = 0; i < aCount; i++) {
UrlbarProviderOpenTabs.registerOpenTab(aUri.spec, aUserContextId);
await UrlbarProviderOpenTabs.registerOpenTab(aUri.spec, aUserContextId);
}
}

function removeOpenPages(aUri, aCount = 1, aUserContextId = 0) {
async function removeOpenPages(aUri, aCount = 1, aUserContextId = 0) {
for (let i = 0; i < aCount; i++) {
UrlbarProviderOpenTabs.unregisterOpenTab(aUri.spec, aUserContextId);
await UrlbarProviderOpenTabs.unregisterOpenTab(aUri.spec, aUserContextId);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ add_task(async function test_javascript_match() {
await addBookmark({ uri: uri5, title: "title" });
await addBookmark({ uri: uri6, title: "title" });

addOpenPages(uri7, 1);
await addOpenPages(uri7, 1);

// Now remove page 6 from history, so it is an unvisited bookmark.
await PlacesUtils.history.remove(uri6);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ add_task(async function test_localtab_matches_override() {
// Setup Places to think the tab is open locally.
let uri = NetUtil.newURI("http://foo.com/");
await PlacesTestUtils.addVisits([{ uri, title: "An Example" }]);
addOpenPages(uri, 1);
await addOpenPages(uri, 1);

await check_autocomplete({
search: "ex",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ add_task(async function test_tab_matches() {
title: "foobar.org - much better than ABC, definitely better than XYZ",
},
]);
addOpenPages(uri1, 1);
await addOpenPages(uri1, 1);
// Pages that cannot be registered in history.
addOpenPages(uri3, 1);
addOpenPages(uri4, 1);
await addOpenPages(uri3, 1);
await addOpenPages(uri4, 1);

info("two results, normal result is a tab match");
await check_autocomplete({
Expand Down Expand Up @@ -57,7 +57,7 @@ add_task(async function test_tab_matches() {
});

info("three results, both normal results are tab matches");
addOpenPages(uri2, 1);
await addOpenPages(uri2, 1);
await check_autocomplete({
search: "abc",
searchParam: "enable-actions",
Expand All @@ -76,7 +76,7 @@ add_task(async function test_tab_matches() {
});

info("a container tab is not visible in 'switch to tab'");
addOpenPages(uri5, 1, /* userContextId: */ 3);
await addOpenPages(uri5, 1, /* userContextId: */ 3);
await check_autocomplete({
search: "abc",
searchParam: "enable-actions",
Expand Down Expand Up @@ -137,7 +137,7 @@ add_task(async function test_tab_matches() {
info(
"three results, both normal results are tab matches, one has multiple tabs"
);
addOpenPages(uri2, 5);
await addOpenPages(uri2, 5);
await check_autocomplete({
search: "abc",
searchParam: "enable-actions",
Expand Down Expand Up @@ -217,7 +217,7 @@ add_task(async function test_tab_matches() {
});

info("tab match search with restriction character");
addOpenPages(uri1, 1);
await addOpenPages(uri1, 1);
await check_autocomplete({
search: UrlbarTokenizer.RESTRICT.OPENPAGE + " abc",
searchParam: "enable-actions",
Expand All @@ -240,6 +240,16 @@ add_task(async function test_tab_matches() {
],
});

info("tab match with not-addable pages, no boundary search");
await check_autocomplete({
search: "ut:mo",
searchParam: "enable-actions",
matches: [
makeSearchMatch("ut:mo", { heuristic: true }),
makeSwitchToTabMatch("about:mozilla"),
],
});

info("tab match with not-addable pages and restriction character");
await check_autocomplete({
search: UrlbarTokenizer.RESTRICT.OPENPAGE + " mozilla",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ support-files =
[test_keywords.js]
[test_multi_word_search.js]
[test_PlacesSearchAutocompleteProvider.js]
skip-if = appname == "thunderbird"
[test_preloaded_sites.js]
[test_query_url.js]
[test_remote_tab_matches.js]
Expand Down

0 comments on commit 2fbc75f

Please sign in to comment.