зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1645521 - Part 2 - Allow for multiple heuristic providers and enable ProviderHeuristicFallback. r=adw
Differential Revision: https://phabricator.services.mozilla.com/D80293
This commit is contained in:
Родитель
382aaa0d5a
Коммит
7e31642215
|
@ -188,7 +188,7 @@ add_task(async function test_registerProvider() {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Adds a single active provider that returns many kinds of results. This also
|
// Adds a single active provider that returns many kinds of results. This also
|
||||||
// checks that the heuristic result from the built-in UnifiedComplete provider
|
// checks that the heuristic result from the built-in HeuristicFallback provider
|
||||||
// is included.
|
// is included.
|
||||||
add_task(async function test_onProviderResultsRequested() {
|
add_task(async function test_onProviderResultsRequested() {
|
||||||
let ext = ExtensionTestUtils.loadExtension({
|
let ext = ExtensionTestUtils.loadExtension({
|
||||||
|
@ -276,7 +276,7 @@ add_task(async function test_onProviderResultsRequested() {
|
||||||
|
|
||||||
// Check the results.
|
// Check the results.
|
||||||
let expectedResults = [
|
let expectedResults = [
|
||||||
// The first result should be a search result returned by UnifiedComplete.
|
// The first result should be a search result returned by HeuristicFallback.
|
||||||
{
|
{
|
||||||
type: UrlbarUtils.RESULT_TYPE.SEARCH,
|
type: UrlbarUtils.RESULT_TYPE.SEARCH,
|
||||||
source: UrlbarUtils.RESULT_SOURCE.SEARCH,
|
source: UrlbarUtils.RESULT_SOURCE.SEARCH,
|
||||||
|
|
|
@ -41,6 +41,15 @@ function groupFromResult(result) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Breaks ties among heuristic results. Providers higher up the list are higher
|
||||||
|
// priority.
|
||||||
|
const heuristicOrder = [
|
||||||
|
// Test providers are handled in sort(),
|
||||||
|
// Extension providers are handled in sort(),
|
||||||
|
"UrlbarProviderSearchTips",
|
||||||
|
"UnifiedComplete",
|
||||||
|
"HeuristicFallback",
|
||||||
|
];
|
||||||
/**
|
/**
|
||||||
* Class used to create a muxer.
|
* Class used to create a muxer.
|
||||||
* The muxer receives and sorts results in a UrlbarQueryContext.
|
* The muxer receives and sorts results in a UrlbarQueryContext.
|
||||||
|
@ -54,11 +63,19 @@ class MuxerUnifiedComplete extends UrlbarMuxer {
|
||||||
return "UnifiedComplete";
|
return "UnifiedComplete";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* eslint-disable complexity */
|
||||||
/**
|
/**
|
||||||
* Sorts results in the given UrlbarQueryContext.
|
* Sorts results in the given UrlbarQueryContext.
|
||||||
*
|
*
|
||||||
|
* sort() is not suitable to be broken up into smaller functions or to rely
|
||||||
|
* on more convenience functions. It exists to efficiently group many
|
||||||
|
* conditions into just three loops. As a result, we must disable complexity
|
||||||
|
* linting.
|
||||||
|
*
|
||||||
* @param {UrlbarQueryContext} context
|
* @param {UrlbarQueryContext} context
|
||||||
* The query context.
|
* The query context.
|
||||||
|
* @returns {boolean} If results were successfully sorted. This return value
|
||||||
|
* is a stopgap and can be removed when bug 1648468 lands.
|
||||||
*/
|
*/
|
||||||
sort(context) {
|
sort(context) {
|
||||||
// This method is called multiple times per keystroke, so it should be as
|
// This method is called multiple times per keystroke, so it should be as
|
||||||
|
@ -70,19 +87,42 @@ class MuxerUnifiedComplete extends UrlbarMuxer {
|
||||||
|
|
||||||
// Capture information about the heuristic result to dedupe results from the
|
// Capture information about the heuristic result to dedupe results from the
|
||||||
// heuristic more quickly.
|
// heuristic more quickly.
|
||||||
|
let topHeuristicRank = Infinity;
|
||||||
|
for (let result of context.allHeuristicResults) {
|
||||||
|
// Determine the highest-ranking heuristic result.
|
||||||
|
if (!result.heuristic) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// + 2 to reserve the highest-priority slots for test and extension
|
||||||
|
// providers.
|
||||||
|
let heuristicRank = heuristicOrder.indexOf(result.providerName) + 2;
|
||||||
|
// Extension and test provider names vary widely and aren't suitable
|
||||||
|
// for a static safelist like heuristicOrder.
|
||||||
|
if (result.providerType == UrlbarUtils.PROVIDER_TYPE.EXTENSION) {
|
||||||
|
heuristicRank = 1;
|
||||||
|
} else if (result.providerName.startsWith("TestProvider")) {
|
||||||
|
heuristicRank = 0;
|
||||||
|
} else if (heuristicRank - 2 == -1) {
|
||||||
|
throw new Error(
|
||||||
|
`Heuristic result returned by unexpected provider: ${result.providerName}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Replace in case of ties, which would occur if a provider sent two
|
||||||
|
// heuristic results.
|
||||||
|
if (heuristicRank <= topHeuristicRank) {
|
||||||
|
topHeuristicRank = heuristicRank;
|
||||||
|
context.heuristicResult = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let heuristicResultQuery;
|
let heuristicResultQuery;
|
||||||
let heuristicResultOmniboxContent;
|
|
||||||
if (context.heuristicResult) {
|
if (context.heuristicResult) {
|
||||||
if (
|
if (
|
||||||
context.heuristicResult.type == UrlbarUtils.RESULT_TYPE.SEARCH &&
|
context.heuristicResult.type == UrlbarUtils.RESULT_TYPE.SEARCH &&
|
||||||
context.heuristicResult.payload.query
|
context.heuristicResult.payload.query
|
||||||
) {
|
) {
|
||||||
heuristicResultQuery = context.heuristicResult.payload.query.toLocaleLowerCase();
|
heuristicResultQuery = context.heuristicResult.payload.query.toLocaleLowerCase();
|
||||||
} else if (
|
|
||||||
context.heuristicResult.type == UrlbarUtils.RESULT_TYPE.OMNIBOX &&
|
|
||||||
context.heuristicResult.payload.content
|
|
||||||
) {
|
|
||||||
heuristicResultOmniboxContent = context.heuristicResult.payload.content.toLocaleLowerCase();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,10 +135,17 @@ class MuxerUnifiedComplete extends UrlbarMuxer {
|
||||||
UrlbarPrefs.get("maxHistoricalSearchSuggestions"),
|
UrlbarPrefs.get("maxHistoricalSearchSuggestions"),
|
||||||
context.maxResults
|
context.maxResults
|
||||||
);
|
);
|
||||||
|
let hasUnifiedComplete = false;
|
||||||
|
|
||||||
// Do the first pass through the results. We only collect info for the
|
// Do the first pass through the results. We only collect info for the
|
||||||
// second pass here.
|
// second pass here.
|
||||||
for (let result of context.results) {
|
for (let result of context.results) {
|
||||||
|
// Keep track of whether UnifiedComplete has returned results. We will
|
||||||
|
// quit early if it hasn't.
|
||||||
|
if (result.providerName == "UnifiedComplete") {
|
||||||
|
hasUnifiedComplete = true;
|
||||||
|
}
|
||||||
|
|
||||||
// The "Search in a Private Window" result should only be shown when there
|
// The "Search in a Private Window" result should only be shown when there
|
||||||
// are other results and all of them are searches. It should not be shown
|
// are other results and all of them are searches. It should not be shown
|
||||||
// if the user typed an alias because that's an explicit engine choice.
|
// if the user typed an alias because that's an explicit engine choice.
|
||||||
|
@ -139,9 +186,24 @@ class MuxerUnifiedComplete extends UrlbarMuxer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Quit early if we're still waiting on UnifiedComplete. If it turns out
|
||||||
|
// UnifiedComplete doesn't need to return any results, it will call sort()
|
||||||
|
// regardless to unblock showing results.
|
||||||
|
if (
|
||||||
|
!hasUnifiedComplete &&
|
||||||
|
context.pendingHeuristicProviders.has("UnifiedComplete")
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Do the second pass through results to build the list of unsorted results.
|
// Do the second pass through results to build the list of unsorted results.
|
||||||
let unsortedResults = [];
|
let unsortedResults = [];
|
||||||
for (let result of context.results) {
|
for (let result of context.results) {
|
||||||
|
// Exclude low-ranked heuristic results.
|
||||||
|
if (result.heuristic && result != context.heuristicResult) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Exclude "Search in a Private Window" as determined in the first pass.
|
// Exclude "Search in a Private Window" as determined in the first pass.
|
||||||
if (
|
if (
|
||||||
result.type == UrlbarUtils.RESULT_TYPE.SEARCH &&
|
result.type == UrlbarUtils.RESULT_TYPE.SEARCH &&
|
||||||
|
@ -214,15 +276,6 @@ class MuxerUnifiedComplete extends UrlbarMuxer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exclude omnibox results that dupe the heuristic.
|
|
||||||
if (
|
|
||||||
!result.heuristic &&
|
|
||||||
result.type == UrlbarUtils.RESULT_TYPE.OMNIBOX &&
|
|
||||||
result.payload.content == heuristicResultOmniboxContent
|
|
||||||
) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Include this result.
|
// Include this result.
|
||||||
unsortedResults.push(result);
|
unsortedResults.push(result);
|
||||||
}
|
}
|
||||||
|
@ -272,6 +325,7 @@ class MuxerUnifiedComplete extends UrlbarMuxer {
|
||||||
}
|
}
|
||||||
|
|
||||||
context.results = sortedResults;
|
context.results = sortedResults;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -63,7 +63,7 @@ class ProviderHeuristicFallback extends UrlbarProvider {
|
||||||
* @returns {boolean} Whether this provider should be invoked for the search.
|
* @returns {boolean} Whether this provider should be invoked for the search.
|
||||||
*/
|
*/
|
||||||
isActive(queryContext) {
|
isActive(queryContext) {
|
||||||
return false; // TODO: Set to true in future part of this patch.
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -90,8 +90,17 @@ class ProviderUnifiedComplete extends UrlbarProvider {
|
||||||
acResult,
|
acResult,
|
||||||
urls
|
urls
|
||||||
);
|
);
|
||||||
for (let result of results) {
|
// The Muxer gives UnifiedComplete special status and waits for it to
|
||||||
addCallback(this, result);
|
// return results before sorting them. We need to know that
|
||||||
|
// UnifiedComplete has finished even if it isn't returning results, so we
|
||||||
|
// call addCallback with an empty result here, which is something only
|
||||||
|
// UnifiedComplete is allowed to do.
|
||||||
|
if (!results.length) {
|
||||||
|
addCallback(this, null);
|
||||||
|
} else {
|
||||||
|
for (let result of results) {
|
||||||
|
addCallback(this, result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.queries.delete(queryContext);
|
this.queries.delete(queryContext);
|
||||||
|
|
|
@ -366,6 +366,7 @@ class Query {
|
||||||
let queryPromises = [];
|
let queryPromises = [];
|
||||||
for (let provider of activeProviders) {
|
for (let provider of activeProviders) {
|
||||||
if (provider.type == UrlbarUtils.PROVIDER_TYPE.HEURISTIC) {
|
if (provider.type == UrlbarUtils.PROVIDER_TYPE.HEURISTIC) {
|
||||||
|
this.context.pendingHeuristicProviders.add(provider.name);
|
||||||
queryPromises.push(
|
queryPromises.push(
|
||||||
provider.tryMethod("startQuery", this.context, this.add.bind(this))
|
provider.tryMethod("startQuery", this.context, this.add.bind(this))
|
||||||
);
|
);
|
||||||
|
@ -436,13 +437,29 @@ class Query {
|
||||||
if (!(provider instanceof UrlbarProvider)) {
|
if (!(provider instanceof UrlbarProvider)) {
|
||||||
throw new Error("Invalid provider passed to the add callback");
|
throw new Error("Invalid provider passed to the add callback");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When this set is empty, we can display heuristic results early. We remove
|
||||||
|
// the provider from the list without checking result.heuristic since
|
||||||
|
// heuristic providers don't necessarily have to return heuristic results.
|
||||||
|
// We expect a provider with type HEURISTIC will return its heuristic
|
||||||
|
// result(s) first.
|
||||||
|
this.context.pendingHeuristicProviders.delete(provider.name);
|
||||||
|
|
||||||
// Stop returning results as soon as we've been canceled.
|
// Stop returning results as soon as we've been canceled.
|
||||||
if (this.canceled) {
|
if (this.canceled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let addResult = true;
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
addResult = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the result source should be filtered out. Pay attention to the
|
// Check if the result source should be filtered out. Pay attention to the
|
||||||
// heuristic result though, that is supposed to be added regardless.
|
// heuristic result though, that is supposed to be added regardless.
|
||||||
if (
|
if (
|
||||||
|
addResult &&
|
||||||
!this.acceptableSources.includes(result.source) &&
|
!this.acceptableSources.includes(result.source) &&
|
||||||
!result.heuristic &&
|
!result.heuristic &&
|
||||||
// Treat form history as searches for the purpose of acceptableSources.
|
// Treat form history as searches for the purpose of acceptableSources.
|
||||||
|
@ -450,35 +467,60 @@ class Query {
|
||||||
result.source != UrlbarUtils.RESULT_SOURCE.HISTORY ||
|
result.source != UrlbarUtils.RESULT_SOURCE.HISTORY ||
|
||||||
!this.acceptableSources.includes(UrlbarUtils.RESULT_SOURCE.SEARCH))
|
!this.acceptableSources.includes(UrlbarUtils.RESULT_SOURCE.SEARCH))
|
||||||
) {
|
) {
|
||||||
return;
|
addResult = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter out javascript results for safety. The provider is supposed to do
|
// Filter out javascript results for safety. The provider is supposed to do
|
||||||
// it, but we don't want to risk leaking these out.
|
// it, but we don't want to risk leaking these out.
|
||||||
if (
|
if (
|
||||||
|
addResult &&
|
||||||
result.type != UrlbarUtils.RESULT_TYPE.KEYWORD &&
|
result.type != UrlbarUtils.RESULT_TYPE.KEYWORD &&
|
||||||
result.payload.url &&
|
result.payload.url &&
|
||||||
result.payload.url.startsWith("javascript:") &&
|
result.payload.url.startsWith("javascript:") &&
|
||||||
!this.context.searchString.startsWith("javascript:") &&
|
!this.context.searchString.startsWith("javascript:") &&
|
||||||
UrlbarPrefs.get("filter.javascript")
|
UrlbarPrefs.get("filter.javascript")
|
||||||
) {
|
) {
|
||||||
return;
|
addResult = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We wait on UnifiedComplete to return a heuristic result. If it has no
|
||||||
|
// heuristic result to return, we still need to sort and display results, so
|
||||||
|
// we follow the usual codepath to muxer.sort. We only offer this for
|
||||||
|
// UnifiedComplete, so we check the provider's name here. This is a stopgap
|
||||||
|
// measure until bug 1648468 lands.
|
||||||
|
if (!addResult) {
|
||||||
|
if (provider.name == "UnifiedComplete") {
|
||||||
|
this._notifyResultsFromProvider(provider);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
result.providerName = provider.name;
|
result.providerName = provider.name;
|
||||||
|
result.providerType = provider.type;
|
||||||
this.context.results.push(result);
|
this.context.results.push(result);
|
||||||
if (result.heuristic) {
|
if (result.heuristic) {
|
||||||
this.context.heuristicResult = result;
|
this.context.allHeuristicResults.push(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._notifyResultsFromProvider(provider);
|
this._notifyResultsFromProvider(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
_notifyResultsFromProvider(provider) {
|
_notifyResultsFromProvider(provider) {
|
||||||
// If the provider is not of heuristic type, chunk results, to improve the
|
// We create two chunking timers: one for heuristic results, and one for
|
||||||
// dataflow and reduce UI flicker.
|
// other results. We expect heuristic providers to return their heuristic
|
||||||
|
// results before other results/providers in most cases. When all heuristic
|
||||||
|
// providers have returned some results, we fire the heuristic timer early.
|
||||||
|
// If the timer fires first, we stop waiting on the remaining heuristic
|
||||||
|
// providers.
|
||||||
|
// Both timers are used to reduce UI flicker.
|
||||||
if (provider.type == UrlbarUtils.PROVIDER_TYPE.HEURISTIC) {
|
if (provider.type == UrlbarUtils.PROVIDER_TYPE.HEURISTIC) {
|
||||||
this._notifyResults();
|
if (!this._heuristicProviderTimer) {
|
||||||
|
this._heuristicProviderTimer = new SkippableTimer({
|
||||||
|
name: "Heuristic provider timer",
|
||||||
|
callback: () => this._notifyResults(),
|
||||||
|
time: CHUNK_RESULTS_DELAY_MS,
|
||||||
|
logger,
|
||||||
|
});
|
||||||
|
}
|
||||||
} else if (!this._chunkTimer) {
|
} else if (!this._chunkTimer) {
|
||||||
this._chunkTimer = new SkippableTimer({
|
this._chunkTimer = new SkippableTimer({
|
||||||
name: "Query chunk timer",
|
name: "Query chunk timer",
|
||||||
|
@ -487,16 +529,33 @@ class Query {
|
||||||
logger,
|
logger,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// If all active heuristic providers have returned results, we can skip the
|
||||||
|
// heuristic results timer and start showing results immediately.
|
||||||
|
if (
|
||||||
|
this._heuristicProviderTimer &&
|
||||||
|
!this.context.pendingHeuristicProviders.size
|
||||||
|
) {
|
||||||
|
this._heuristicProviderTimer.fire().catch(Cu.reportError);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_notifyResults() {
|
_notifyResults() {
|
||||||
this.muxer.sort(this.context);
|
let sorted = this.muxer.sort(this.context);
|
||||||
|
|
||||||
|
if (this._heuristicProviderTimer) {
|
||||||
|
this._heuristicProviderTimer.cancel().catch(Cu.reportError);
|
||||||
|
this._heuristicProviderTimer = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (this._chunkTimer) {
|
if (this._chunkTimer) {
|
||||||
this._chunkTimer.cancel().catch(Cu.reportError);
|
this._chunkTimer.cancel().catch(Cu.reportError);
|
||||||
this._chunkTimer = null;
|
this._chunkTimer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!sorted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Before the muxer.sort call above, this.context.results should never be
|
// Before the muxer.sort call above, this.context.results should never be
|
||||||
// empty since this method is called when results are added. But the muxer
|
// empty since this method is called when results are added. But the muxer
|
||||||
// may have excluded one or more results from the final sorted list. For
|
// may have excluded one or more results from the final sorted list. For
|
||||||
|
|
|
@ -651,7 +651,7 @@ var UrlbarUtils = {
|
||||||
"usercontextid"
|
"usercontextid"
|
||||||
),
|
),
|
||||||
allowSearchSuggestions: false,
|
allowSearchSuggestions: false,
|
||||||
providers: ["UnifiedComplete"],
|
providers: ["UnifiedComplete", "HeuristicFallback"],
|
||||||
});
|
});
|
||||||
await UrlbarProvidersManager.startQuery(context);
|
await UrlbarProvidersManager.startQuery(context);
|
||||||
if (!context.heuristicResult) {
|
if (!context.heuristicResult) {
|
||||||
|
@ -1000,6 +1000,8 @@ class UrlbarQueryContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.lastResultCount = 0;
|
this.lastResultCount = 0;
|
||||||
|
this.allHeuristicResults = [];
|
||||||
|
this.pendingHeuristicProviders = new Set();
|
||||||
this.userContextId =
|
this.userContextId =
|
||||||
options.userContextId ||
|
options.userContextId ||
|
||||||
Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID;
|
Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID;
|
||||||
|
|
|
@ -598,7 +598,7 @@ class TestProvider extends UrlbarProvider {
|
||||||
*/
|
*/
|
||||||
constructor({
|
constructor({
|
||||||
results,
|
results,
|
||||||
name = "TestProvider" + Math.floor(Math.random() * 100000),
|
name = Math.floor(Math.random() * 100000),
|
||||||
type = UrlbarUtils.PROVIDER_TYPE.PROFILE,
|
type = UrlbarUtils.PROVIDER_TYPE.PROFILE,
|
||||||
priority = 0,
|
priority = 0,
|
||||||
addTimeout = 0,
|
addTimeout = 0,
|
||||||
|
@ -613,7 +613,7 @@ class TestProvider extends UrlbarProvider {
|
||||||
this._onCancel = onCancel;
|
this._onCancel = onCancel;
|
||||||
}
|
}
|
||||||
get name() {
|
get name() {
|
||||||
return this._name;
|
return "TestProvider" + this._name;
|
||||||
}
|
}
|
||||||
get type() {
|
get type() {
|
||||||
return this._type;
|
return this._type;
|
||||||
|
|
|
@ -21,19 +21,19 @@ add_task(async function urlToTip() {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Add a provider that returns a tip result when the search string is "testx".
|
// Add a provider that returns a tip result when the search string is "testx".
|
||||||
|
let tipResult = new UrlbarResult(
|
||||||
|
UrlbarUtils.RESULT_TYPE.TIP,
|
||||||
|
UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
|
||||||
|
{
|
||||||
|
text: "This is a test tip.",
|
||||||
|
buttonText: "OK",
|
||||||
|
helpUrl: "http://example.com/",
|
||||||
|
type: "test",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
tipResult.suggestedIndex = 1;
|
||||||
let provider = new UrlbarTestUtils.TestProvider({
|
let provider = new UrlbarTestUtils.TestProvider({
|
||||||
results: [
|
results: [tipResult],
|
||||||
new UrlbarResult(
|
|
||||||
UrlbarUtils.RESULT_TYPE.TIP,
|
|
||||||
UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
|
|
||||||
{
|
|
||||||
text: "This is a test tip.",
|
|
||||||
buttonText: "OK",
|
|
||||||
helpUrl: "http://example.com/",
|
|
||||||
type: "test",
|
|
||||||
}
|
|
||||||
),
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
provider.isActive = context => context.searchString == "testx";
|
provider.isActive = context => context.searchString == "testx";
|
||||||
UrlbarProvidersManager.registerProvider(provider);
|
UrlbarProvidersManager.registerProvider(provider);
|
||||||
|
@ -122,19 +122,19 @@ add_task(async function tipToURL() {
|
||||||
|
|
||||||
// Add a provider that returns a tip result when the search string is "test"
|
// Add a provider that returns a tip result when the search string is "test"
|
||||||
// or "testxx".
|
// or "testxx".
|
||||||
|
let tipResult = new UrlbarResult(
|
||||||
|
UrlbarUtils.RESULT_TYPE.TIP,
|
||||||
|
UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
|
||||||
|
{
|
||||||
|
text: "This is a test tip.",
|
||||||
|
buttonText: "OK",
|
||||||
|
helpUrl: "http://example.com/",
|
||||||
|
type: "test",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
tipResult.suggestedIndex = 1;
|
||||||
let provider = new UrlbarTestUtils.TestProvider({
|
let provider = new UrlbarTestUtils.TestProvider({
|
||||||
results: [
|
results: [tipResult],
|
||||||
new UrlbarResult(
|
|
||||||
UrlbarUtils.RESULT_TYPE.TIP,
|
|
||||||
UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
|
|
||||||
{
|
|
||||||
text: "This is a test tip.",
|
|
||||||
buttonText: "OK",
|
|
||||||
helpUrl: "http://example.com/",
|
|
||||||
type: "test",
|
|
||||||
}
|
|
||||||
),
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
provider.isActive = context =>
|
provider.isActive = context =>
|
||||||
["test", "testxx"].includes(context.searchString);
|
["test", "testxx"].includes(context.searchString);
|
||||||
|
|
|
@ -359,30 +359,16 @@ add_task(async function test_filter_priority() {
|
||||||
/**
|
/**
|
||||||
* A test provider.
|
* A test provider.
|
||||||
*/
|
*/
|
||||||
class TestProvider extends UrlbarProvider {
|
class TestProvider extends UrlbarTestUtils.TestProvider {
|
||||||
constructor(priority, shouldBeInvoked, namePart = "") {
|
constructor(priority, shouldBeInvoked, namePart = "") {
|
||||||
super();
|
super();
|
||||||
this._priority = priority;
|
this._priority = priority;
|
||||||
this._name = `Provider-${priority}` + namePart;
|
this._name = `${priority}` + namePart;
|
||||||
this._shouldBeInvoked = shouldBeInvoked;
|
this._shouldBeInvoked = shouldBeInvoked;
|
||||||
}
|
}
|
||||||
get name() {
|
|
||||||
return this._name;
|
|
||||||
}
|
|
||||||
get type() {
|
|
||||||
return UrlbarUtils.PROVIDER_TYPE.PROFILE;
|
|
||||||
}
|
|
||||||
isActive(context) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
getPriority(context) {
|
|
||||||
return this._priority;
|
|
||||||
}
|
|
||||||
async startQuery(context, add) {
|
async startQuery(context, add) {
|
||||||
Assert.ok(this._shouldBeInvoked, `${this.name} was invoked`);
|
Assert.ok(this._shouldBeInvoked, `${this.name} was invoked`);
|
||||||
}
|
}
|
||||||
cancelQuery(context) {}
|
|
||||||
pickResult(result) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test all possible orderings of the providers to make sure the logic that
|
// Test all possible orderings of the providers to make sure the logic that
|
||||||
|
|
|
@ -122,7 +122,7 @@ class TipProvider extends UrlbarProvider {
|
||||||
this._results = results;
|
this._results = results;
|
||||||
}
|
}
|
||||||
get name() {
|
get name() {
|
||||||
return "TestTipProvider";
|
return "TestProviderTip";
|
||||||
}
|
}
|
||||||
get type() {
|
get type() {
|
||||||
return UrlbarUtils.PROVIDER_TYPE.PROFILE;
|
return UrlbarUtils.PROVIDER_TYPE.PROFILE;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче