Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test runs only with pattern: os != 'android'
- Manifest: browser/components/urlbar/tests/unit/xpcshell.toml
/* Any copyright is dedicated to the Public Domain.
// Tests the fallback origin result that appears when an adaptive autofill
// result is a deep URL. When the autofilled URL has a path (e.g.
// appear in the results if it exists in history with positive frecency.
"use strict";
testEngine_setup();
async function addVisitAndRecalculate(
uri,
transition = PlacesUtils.history.TRANSITION_TYPED
) {
await PlacesTestUtils.addVisits({ uri, transition });
await PlacesFrecencyRecalculator.recalculateAnyOutdatedFrecencies();
}
async function addInputHistory(url, input, useCount = 4) {
await PlacesUtils.withConnectionWrapper("addInputHistory", async db => {
await db.execute(
`INSERT OR REPLACE INTO moz_inputhistory (place_id, input, use_count)
VALUES (
(SELECT id FROM moz_places WHERE url_hash = hash(:url) AND url = :url),
:input,
:useCount
)`,
{ url, input: input.toLowerCase(), useCount }
);
});
}
add_setup(async function () {
UrlbarPrefs.set("autoFill.adaptiveHistory.enabled", true);
registerCleanupFunction(() => {
UrlbarPrefs.set("autoFill.adaptiveHistory.enabled", false);
});
});
// When adaptive autofill suggests a deep URL and the root origin exists in
// history, the origin should appear as a second result.
add_task(async function deep_url_shows_origin_fallback() {
await addVisitAndRecalculate(deepUrl);
await addVisitAndRecalculate(originUrl);
await addInputHistory(deepUrl, "exa");
let context = createContext("exa", { isPrivate: false });
await check_results({
context,
autofilled: "example.com/path",
matches: [
makeVisitResult(context, {
uri: deepUrl,
heuristic: true,
}),
makeVisitResult(context, {
uri: originUrl,
tags: null,
isAutofillFallback: true,
}),
],
});
await PlacesUtils.history.clear();
});
// When the autofilled URL is already an origin, no fallback should appear.
add_task(async function origin_autofill_no_fallback() {
await addVisitAndRecalculate(originUrl);
await addInputHistory(originUrl, "exa");
let context = createContext("exa", { isPrivate: false });
await check_results({
context,
autofilled: "example.com/",
matches: [
makeVisitResult(context, {
uri: originUrl,
heuristic: true,
}),
],
});
await PlacesUtils.history.clear();
});
// When the origin has not been visited (does not exist in moz_places), no
// fallback should appear.
add_task(async function deep_url_no_fallback_without_origin_visit() {
await addVisitAndRecalculate(deepUrl);
await addInputHistory(deepUrl, "exa");
let context = createContext("exa", { isPrivate: false });
await check_results({
context,
autofilled: "example.com/path",
matches: [
makeVisitResult(context, {
uri: deepUrl,
heuristic: true,
}),
],
});
await PlacesUtils.history.clear();
});
// When the origin exists but has frecency <= 0, no fallback should appear.
add_task(async function deep_url_no_fallback_when_origin_frecency_zero() {
await addVisitAndRecalculate(deepUrl);
await addVisitAndRecalculate(originUrl);
await addInputHistory(deepUrl, "exa");
await PlacesUtils.withConnectionWrapper("setFrecency", db =>
db.execute(
`UPDATE moz_places SET frecency = 0 WHERE url_hash = hash(:url) AND url = :url`,
{ url: originUrl }
)
);
let context = createContext("exa", { isPrivate: false });
await check_results({
context,
autofilled: "example.com/path",
matches: [
makeVisitResult(context, {
uri: deepUrl,
heuristic: true,
}),
],
});
await PlacesUtils.history.clear();
});
// When the origin is blocked via block_until_ms (future timestamp), no fallback
// should appear.
add_task(async function deep_url_no_fallback_when_origin_blocked() {
await addVisitAndRecalculate(deepUrl);
await addVisitAndRecalculate(originUrl);
await addInputHistory(deepUrl, "exa");
let futureMs = Date.now() + 365 * 24 * 60 * 60 * 1000;
await UrlbarUtils.blockOriginAutofill(originUrl, futureMs);
let context = createContext("exa", { isPrivate: false });
// The fallback origin should NOT appear from the autofill provider, but the
// origin may still appear as a regular history result from UrlbarProviderPlaces.
await check_results({
context,
autofilled: "example.com/path",
matches: [
makeVisitResult(context, {
uri: deepUrl,
heuristic: true,
}),
makeVisitResult(context, {
uri: originUrl,
}),
],
});
await PlacesUtils.history.clear();
});
// When the origin's block_until_ms is in the past (expired), the fallback
// should appear.
add_task(async function deep_url_fallback_when_block_expired() {
await addVisitAndRecalculate(deepUrl);
await addVisitAndRecalculate(originUrl);
await addInputHistory(deepUrl, "exa");
let pastMs = Date.now() - 1000;
await UrlbarUtils.blockOriginAutofill(originUrl, pastMs);
let context = createContext("exa", { isPrivate: false });
await check_results({
context,
autofilled: "example.com/path",
matches: [
makeVisitResult(context, {
uri: deepUrl,
heuristic: true,
}),
makeVisitResult(context, {
uri: originUrl,
tags: null,
isAutofillFallback: true,
}),
],
});
await PlacesUtils.history.clear();
});
// Fallback should work with https URLs.
add_task(async function deep_url_https_fallback() {
await addVisitAndRecalculate(deepUrl);
await addVisitAndRecalculate(originUrl);
await addInputHistory(deepUrl, "exa");
let context = createContext("exa", { isPrivate: false });
await check_results({
context,
autofilled: "example.com/app/dashboard",
matches: [
makeVisitResult(context, {
uri: deepUrl,
heuristic: true,
}),
makeVisitResult(context, {
uri: originUrl,
tags: null,
isAutofillFallback: true,
}),
],
});
await PlacesUtils.history.clear();
});
// When adaptive autofill is disabled, no fallback should appear even with a
// deep URL (since adaptive autofill itself won't fire).
add_task(async function no_fallback_when_adaptive_disabled() {
UrlbarPrefs.set("autoFill.adaptiveHistory.enabled", false);
await addVisitAndRecalculate(deepUrl);
await addVisitAndRecalculate(originUrl);
await addInputHistory(deepUrl, "exa");
let context = createContext("exa", { isPrivate: false });
await check_results({
context,
autofilled: "example.com/",
matches: [
makeVisitResult(context, {
uri: originUrl,
heuristic: true,
}),
makeVisitResult(context, {
uri: deepUrl,
}),
],
});
await PlacesUtils.history.clear();
UrlbarPrefs.set("autoFill.adaptiveHistory.enabled", true);
});
// Fallback should work with www URLs where the user omits www.
add_task(async function deep_url_www_fallback() {
await addVisitAndRecalculate(deepUrl);
await addVisitAndRecalculate(originUrl);
await addInputHistory(deepUrl, "exa");
let context = createContext("exa", { isPrivate: false });
await check_results({
context,
autofilled: "example.com/path",
matches: [
makeVisitResult(context, {
uri: deepUrl,
heuristic: true,
}),
makeVisitResult(context, {
uri: originUrl,
tags: null,
isAutofillFallback: true,
}),
],
});
await PlacesUtils.history.clear();
});
// When the results panel is full of history results, the fallback origin should
// still appear even if its frecency is very low (just above 0).
add_task(async function fallback_with_full_panel_low_frecency() {
let maxResults = UrlbarPrefs.get("maxRichResults");
await addVisitAndRecalculate(deepUrl);
await addVisitAndRecalculate(originUrl);
await addInputHistory(deepUrl, "e");
// Set the origin's frecency to 1 (just above the > 0 threshold).
await PlacesUtils.withConnectionWrapper("setFrecency", db =>
db.execute(
`UPDATE moz_places SET frecency = 1
WHERE url_hash = hash(:url) AND url = :url`,
{ url: originUrl }
)
);
// Add enough other history entries to fill the panel beyond maxResults.
let otherUrls = [];
for (let i = 0; i < maxResults; i++) {
otherUrls.push(url);
await addVisitAndRecalculate(url);
}
let context = createContext("e", { isPrivate: false });
await check_results({
context,
autofilled: "example.com/path",
matches: [
makeVisitResult(context, {
uri: deepUrl,
heuristic: true,
}),
makeVisitResult(context, {
uri: originUrl,
tags: null,
isAutofillFallback: true,
}),
...otherUrls
.reverse()
.slice(0, maxResults - 2)
.map(url =>
makeVisitResult(context, {
uri: url,
title: `test visit for ${url}`,
})
),
],
});
await PlacesUtils.history.clear();
});
// When search suggestions are shown first and adaptive autofill suggests a deep
// URL, the fallback origin should appear in the history group after suggestions.
add_task(async function fallback_with_search_suggestions_first() {
await addVisitAndRecalculate(deepUrl);
await addVisitAndRecalculate(originUrl);
await addInputHistory(deepUrl, "exa");
Services.prefs.setBoolPref("browser.urlbar.suggest.searches", true);
Services.prefs.setBoolPref("browser.search.suggest.enabled", true);
Services.prefs.setBoolPref("browser.urlbar.showSearchSuggestionsFirst", true);
let context = createContext("exa", { isPrivate: false });
await check_results({
context,
autofilled: "example.com/path",
matches: [
makeVisitResult(context, {
uri: deepUrl,
heuristic: true,
}),
makeSearchResult(context, {
engineName: "Suggestions",
suggestion: "exa",
}),
makeSearchResult(context, {
engineName: "Suggestions",
suggestion: "exa foo",
}),
makeSearchResult(context, {
engineName: "Suggestions",
suggestion: "exa bar",
}),
makeVisitResult(context, {
uri: originUrl,
tags: null,
isAutofillFallback: true,
}),
],
});
Services.prefs.clearUserPref("browser.urlbar.suggest.searches");
Services.prefs.clearUserPref("browser.search.suggest.enabled");
Services.prefs.clearUserPref("browser.urlbar.showSearchSuggestionsFirst");
await PlacesUtils.history.clear();
});
// When search suggestions are shown last (history first), the fallback origin
// should appear in the history group before search suggestions.
add_task(async function fallback_with_search_suggestions_last() {
await addVisitAndRecalculate(deepUrl);
await addVisitAndRecalculate(originUrl);
await addInputHistory(deepUrl, "exa");
Services.prefs.setBoolPref("browser.urlbar.suggest.searches", true);
Services.prefs.setBoolPref("browser.search.suggest.enabled", true);
Services.prefs.setBoolPref(
"browser.urlbar.showSearchSuggestionsFirst",
false
);
let context = createContext("exa", { isPrivate: false });
await check_results({
context,
autofilled: "example.com/path",
matches: [
makeVisitResult(context, {
uri: deepUrl,
heuristic: true,
}),
makeVisitResult(context, {
uri: originUrl,
tags: null,
isAutofillFallback: true,
}),
makeSearchResult(context, {
engineName: "Suggestions",
suggestion: "exa",
}),
makeSearchResult(context, {
engineName: "Suggestions",
suggestion: "exa foo",
}),
makeSearchResult(context, {
engineName: "Suggestions",
suggestion: "exa bar",
}),
],
});
Services.prefs.clearUserPref("browser.urlbar.suggest.searches");
Services.prefs.clearUserPref("browser.search.suggest.enabled");
Services.prefs.clearUserPref("browser.urlbar.showSearchSuggestionsFirst");
await PlacesUtils.history.clear();
});