Bug 1648468 - Part 3 - Allow UrlbarProviderTokenAliasEngines to provide its own heuristic result. r=adw

Differential Revision: https://phabricator.services.mozilla.com/D82236
This commit is contained in:
Harry Twyford 2020-07-11 22:53:11 +00:00
Родитель ec02dade55
Коммит b2ff98e2f8
3 изменённых файлов: 91 добавлений и 83 удалений

Просмотреть файл

@ -49,6 +49,7 @@ const heuristicOrder = [
"Omnibox",
"UnifiedComplete",
"Autofill",
"TokenAliasEngines",
"HeuristicFallback",
];
/**

Просмотреть файл

@ -14,6 +14,7 @@ const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
XPCOMUtils.defineLazyModuleGetters(this, {
UrlbarPrefs: "resource:///modules/UrlbarPrefs.jsm",
UrlbarProvider: "resource:///modules/UrlbarUtils.jsm",
UrlbarResult: "resource:///modules/UrlbarResult.jsm",
UrlbarSearchUtils: "resource:///modules/UrlbarSearchUtils.jsm",
@ -44,7 +45,7 @@ class ProviderTokenAliasEngines extends UrlbarProvider {
* @returns {integer} one of the types from UrlbarUtils.PROVIDER_TYPE.*
*/
get type() {
return UrlbarUtils.PROVIDER_TYPE.PROFILE;
return UrlbarUtils.PROVIDER_TYPE.HEURISTIC;
}
get PRIORITY() {
@ -60,12 +61,34 @@ class ProviderTokenAliasEngines extends UrlbarProvider {
* @returns {boolean} Whether this provider should be invoked for the search.
*/
async isActive(queryContext) {
this._engines = [];
if (queryContext.searchString.trim() == "@") {
this._engines = await UrlbarSearchUtils.tokenAliasEngines();
// Once the user starts typing a search string after the token, we hand off
// suggestions to UrlbarProviderSearchSuggestions.
if (
!queryContext.searchString.startsWith("@") ||
queryContext.tokens.length != 1
) {
return false;
}
return this._engines.length;
this._engines = await UrlbarSearchUtils.tokenAliasEngines();
if (!this._engines.length) {
return false;
}
if (queryContext.searchString.trim() == "@") {
return true;
}
// If there's no engine associated with the searchString, then we don't want
// to block other kinds of results.
if (UrlbarPrefs.get("autoFill") && queryContext.allowAutofill) {
this._autofillResult = this._getAutofillResult(queryContext);
if (this._autofillResult) {
return true;
}
}
return false;
}
/**
@ -89,19 +112,25 @@ class ProviderTokenAliasEngines extends UrlbarProvider {
return;
}
for (let { engine, tokenAliases } of this._engines) {
let result = new UrlbarResult(
UrlbarUtils.RESULT_TYPE.SEARCH,
UrlbarUtils.RESULT_SOURCE.SEARCH,
...UrlbarResult.payloadAndSimpleHighlights(queryContext.tokens, {
engine: [engine.name, UrlbarUtils.HIGHLIGHT.TYPED],
keyword: [tokenAliases[0], UrlbarUtils.HIGHLIGHT.TYPED],
query: ["", UrlbarUtils.HIGHLIGHT.TYPED],
icon: engine.iconURI ? engine.iconURI.spec : null,
keywordOffer: UrlbarUtils.KEYWORD_OFFER.SHOW,
})
);
addCallback(this, result);
if (queryContext.searchString.trim() == "@") {
for (let { engine, tokenAliases } of this._engines) {
let result = new UrlbarResult(
UrlbarUtils.RESULT_TYPE.SEARCH,
UrlbarUtils.RESULT_SOURCE.SEARCH,
...UrlbarResult.payloadAndSimpleHighlights(queryContext.tokens, {
engine: [engine.name, UrlbarUtils.HIGHLIGHT.TYPED],
keyword: [tokenAliases[0], UrlbarUtils.HIGHLIGHT.TYPED],
query: ["", UrlbarUtils.HIGHLIGHT.TYPED],
icon: engine.iconURI ? engine.iconURI.spec : "",
keywordOffer: UrlbarUtils.KEYWORD_OFFER.SHOW,
})
);
addCallback(this, result);
}
} else if (this._autofillResult) {
addCallback(this, this._autofillResult);
this.queries.delete(queryContext);
return;
}
this.queries.delete(queryContext);
@ -121,8 +150,49 @@ class ProviderTokenAliasEngines extends UrlbarProvider {
* @param {object} queryContext The query context object
*/
cancelQuery(queryContext) {
delete this._autofillResult;
this.queries.delete(queryContext);
}
_getAutofillResult(queryContext) {
let token = queryContext.tokens[0];
// The user is typing a specific engine. We should show a heuristic result.
for (let { engine, tokenAliases } of this._engines) {
for (let alias of tokenAliases) {
if (alias.startsWith(token.lowerCaseValue)) {
// We found a specific engine. We will add an autofill result.
let aliasPreservingUserCase =
token.value + alias.substr(token.value.length);
let value = aliasPreservingUserCase + " ";
let result = new UrlbarResult(
UrlbarUtils.RESULT_TYPE.SEARCH,
UrlbarUtils.RESULT_SOURCE.SEARCH,
...UrlbarResult.payloadAndSimpleHighlights(queryContext.tokens, {
engine: [engine.name, UrlbarUtils.HIGHLIGHT.TYPED],
keyword: [aliasPreservingUserCase, UrlbarUtils.HIGHLIGHT.TYPED],
query: ["", UrlbarUtils.HIGHLIGHT.TYPED],
icon: engine.iconURI ? engine.iconURI.spec : "",
keywordOffer: UrlbarUtils.KEYWORD_OFFER.HIDE,
// For test interoperabilty with UrlbarProviderSearchSuggestions.
suggestion: undefined,
tailPrefix: undefined,
tail: undefined,
tailOffsetIndex: -1,
isSearchHistory: false,
})
);
result.heuristic = true;
result.autofill = {
value,
selectionStart: queryContext.searchString.length,
selectionEnd: value.length,
};
return result;
}
}
}
return null;
}
}
var UrlbarProviderTokenAliasEngines = new ProviderTokenAliasEngines();

Просмотреть файл

@ -814,16 +814,14 @@ Search.prototype = {
// If the heuristic result is an engine from a token alias, the search
// restriction char, or we're in search-restriction mode, then we're done.
// UrlbarProviderSearchSuggestions will handle suggestions, if any.
let tokenAliasQuery =
this._searchEngineAliasMatch &&
this._searchEngineAliasMatch.isTokenAlias;
let emptySearchRestriction =
this._trimmedOriginalSearchString.length <= 3 &&
this._leadingRestrictionToken == UrlbarTokenizer.RESTRICT.SEARCH &&
/\s*\S?$/.test(this._trimmedOriginalSearchString);
if (
emptySearchRestriction ||
tokenAliasQuery ||
(tokenAliasEngines &&
this._trimmedOriginalSearchString.startsWith("@")) ||
(this.hasBehavior("search") && this.hasBehavior("restrict"))
) {
this._autocompleteSearch.finishSearch(true);
@ -1000,60 +998,6 @@ Search.prototype = {
return true;
},
async _matchSearchEngineTokenAliasForAutofill() {
// We need an "@engine" heuristic token.
let token = this._heuristicToken;
if (!token || token.length == 1 || !token.startsWith("@")) {
return false;
}
// See if any engine has a token alias that starts with the heuristic token.
let engines = await UrlbarSearchUtils.tokenAliasEngines();
for (let { engine, tokenAliases } of engines) {
for (let alias of tokenAliases) {
if (alias.startsWith(token.toLocaleLowerCase())) {
// We found one. The match we add here is a little special compared
// to others. It needs to be an autofill match and its `value` must
// be the string that will be autofilled so that the controller will
// autofill it. But it also must be a searchengine action so that the
// front end will style it as a search engine result. The front end
// uses `finalCompleteValue` as the URL for autofill results, so set
// that to the moz-action URL.
let aliasPreservingUserCase = token + alias.substr(token.length);
let value = aliasPreservingUserCase + " ";
this._result.setDefaultIndex(0);
this._addMatch({
value,
finalCompleteValue: makeActionUrl("searchengine", {
engineName: engine.name,
alias: aliasPreservingUserCase,
input: value,
searchQuery: "",
}),
comment: engine.name,
frecency: FRECENCY_DEFAULT,
style: "autofill action searchengine",
icon: engine.iconURI ? engine.iconURI.spec : null,
});
// Set _searchEngineAliasMatch with an empty query so that we don't
// attempt to add any more matches. When a token alias is autofilled,
// the only match should be the one we just added.
this._searchEngineAliasMatch = {
engine,
alias: aliasPreservingUserCase,
query: "",
isTokenAlias: true,
};
return true;
}
}
}
return false;
},
async _matchFirstHeuristicResult(conn) {
// We always try to make the first result a special "heuristic" result. The
// heuristics below determine what type of result it will be, if any.
@ -1083,13 +1027,6 @@ Search.prototype = {
}
}
if (this.pending && shouldAutofill) {
let matched = await this._matchSearchEngineTokenAliasForAutofill();
if (matched) {
return true;
}
}
// Fall back to UrlbarProviderHeuristicFallback.
return false;
},