Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

/* Any copyright is dedicated to the Public Domain.
/**
* Tests Dismiss / Forget this site on the urlbar input field context menu for
* adaptive autofill heuristic results.
*/
"use strict";
const ADAPTIVE_URL = "https://example.com/adaptive-page";
const ORIGIN_URL = "https://example.com/";
const SEARCH_STRING = "exa";
const ADAPTIVE_INPUT = "exa";
const DISMISS_ID = "urlbar-input-dismiss-autofill";
const FORGET_ID = "urlbar-input-remove-from-history";
add_setup(async function () {
await PlacesUtils.history.clear();
await PlacesUtils.bookmarks.eraseEverything();
await SpecialPowers.pushPrefEnv({
set: [
["browser.urlbar.autoFill", true],
["browser.urlbar.autoFill.adaptiveHistory.enabled", true],
["browser.urlbar.autoFill.adaptiveHistory.minCharsThreshold", 0],
["browser.urlbar.autoFill.adaptiveHistory.useCountThreshold", 0],
["browser.urlbar.suggest.quicksuggest.sponsored", false],
["browser.urlbar.suggest.quicksuggest.nonsponsored", false],
],
});
registerCleanupFunction(async () => {
await PlacesUtils.history.clear();
await PlacesUtils.bookmarks.eraseEverything();
});
});
async function addAdaptiveHistoryEntry(url, input, useCount = 3) {
await PlacesTestUtils.addVisits({
uri: url,
transition: PlacesUtils.history.TRANSITIONS.TYPED,
});
for (let i = 0; i < useCount; i++) {
await UrlbarUtils.addToInputHistory(url, input);
}
}
async function showAutofillFor(win, value) {
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window: win,
value,
fireInputEvent: true,
});
}
async function readContextMenuItems(win) {
let textBox = win.gURLBar.querySelector("moz-input-box");
let cxmenu = textBox.menupopup;
let openPromise = BrowserTestUtils.waitForEvent(cxmenu, "popupshown");
EventUtils.synthesizeMouseAtCenter(
win.gURLBar.inputField,
{ type: "contextmenu", button: 2 },
win
);
await openPromise;
await new Promise(win.requestAnimationFrame);
let dismiss = textBox.getMenuItem(DISMISS_ID);
let forget = textBox.getMenuItem(FORGET_ID);
let state = {
dismissHidden: !dismiss || dismiss.hidden,
forgetHidden: !forget || forget.hidden,
};
let closePromise = BrowserTestUtils.waitForEvent(cxmenu, "popuphidden");
cxmenu.hidePopup();
await closePromise;
return state;
}
async function clickContextMenuItem(win, id) {
await UrlbarTestUtils.activateContextMenuItem(win, id);
}
add_task(async function dismiss_via_context_menu_blocks_adaptive_url() {
await PlacesUtils.history.clear();
await addAdaptiveHistoryEntry(ADAPTIVE_URL, ADAPTIVE_INPUT);
await showAutofillFor(window, SEARCH_STRING);
let { result } = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
Assert.equal(
result.autofill?.type,
"adaptive_url",
"Pre-condition: heuristic is adaptive_url autofill"
);
await clickContextMenuItem(window, DISMISS_ID);
let originId = await PlacesTestUtils.getDatabaseValue(
"moz_places",
"origin_id",
{ url: ADAPTIVE_URL }
);
await TestUtils.waitForCondition(async () => {
let val = await PlacesTestUtils.getDatabaseValue(
"moz_origins",
"block_pages_until_ms",
{ id: originId }
);
return val > Date.now();
}, "block_pages_until_ms should be set after context-menu dismiss");
let blockUntilMs = await PlacesTestUtils.getDatabaseValue(
"moz_origins",
"block_until_ms",
{ id: originId }
);
Assert.equal(
blockUntilMs,
null,
"Origin-level block should not be set when dismissing a page URL"
);
await UrlbarTestUtils.promisePopupClose(window);
await PlacesUtils.history.clear();
});
add_task(async function dismiss_via_context_menu_blocks_adaptive_origin() {
await PlacesUtils.history.clear();
await addAdaptiveHistoryEntry(ORIGIN_URL, ADAPTIVE_INPUT);
await showAutofillFor(window, SEARCH_STRING);
let { result } = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
Assert.equal(
result.autofill?.type,
"adaptive_origin",
"Pre-condition: heuristic is adaptive_origin autofill"
);
await clickContextMenuItem(window, DISMISS_ID);
let originId = await PlacesTestUtils.getDatabaseValue(
"moz_places",
"origin_id",
{ url: ORIGIN_URL }
);
await TestUtils.waitForCondition(async () => {
let val = await PlacesTestUtils.getDatabaseValue(
"moz_origins",
"block_until_ms",
{ id: originId }
);
return val > Date.now();
}, "block_until_ms should be set after context-menu dismiss of an origin");
await UrlbarTestUtils.promisePopupClose(window);
await PlacesUtils.history.clear();
});
add_task(async function dismiss_via_context_menu_blocks_origin_autofill() {
await PlacesUtils.history.clear();
// Plain origin autofill: typed visit, no adaptive entry. Frecency must be
// recalculated for the URL to be eligible for autofill.
await PlacesTestUtils.addVisits({
uri: ORIGIN_URL,
transition: PlacesUtils.history.TRANSITIONS.TYPED,
});
await PlacesFrecencyRecalculator.recalculateAnyOutdatedFrecencies();
await showAutofillFor(window, SEARCH_STRING);
let { result } = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
Assert.ok(result.heuristic, "Result should be the heuristic");
Assert.ok(result.autofill, "Result should be autofill");
Assert.notEqual(
result.autofill?.type,
"adaptive_origin",
"Pre-condition: heuristic is plain (non-adaptive) origin autofill"
);
await clickContextMenuItem(window, DISMISS_ID);
let originId = await PlacesTestUtils.getDatabaseValue(
"moz_places",
"origin_id",
{ url: ORIGIN_URL }
);
await TestUtils.waitForCondition(async () => {
let val = await PlacesTestUtils.getDatabaseValue(
"moz_origins",
"block_until_ms",
{ id: originId }
);
return val > Date.now();
}, "block_until_ms should be set after context-menu dismiss of plain origin autofill");
await UrlbarTestUtils.promisePopupClose(window);
await PlacesUtils.history.clear();
});
add_task(async function forget_via_context_menu_removes_from_history() {
await PlacesUtils.history.clear();
await addAdaptiveHistoryEntry(ADAPTIVE_URL, ADAPTIVE_INPUT);
await showAutofillFor(window, SEARCH_STRING);
let { result } = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
Assert.equal(
result.autofill?.type,
"adaptive_url",
"Pre-condition: heuristic is adaptive_url autofill"
);
await clickContextMenuItem(window, FORGET_ID);
await TestUtils.waitForCondition(async () => {
let page = await PlacesUtils.history.fetch(ADAPTIVE_URL);
return !page;
}, "URL should be removed from history after Forget");
await UrlbarTestUtils.promisePopupClose(window);
await PlacesUtils.history.clear();
});
add_task(async function dismiss_item_hidden_in_private_window() {
await PlacesUtils.history.clear();
await addAdaptiveHistoryEntry(ADAPTIVE_URL, ADAPTIVE_INPUT);
let privateWin = await BrowserTestUtils.openNewBrowserWindow({
private: true,
});
await showAutofillFor(privateWin, SEARCH_STRING);
let { dismissHidden, forgetHidden } = await readContextMenuItems(privateWin);
Assert.ok(dismissHidden, "Dismiss should be hidden in a private window");
// Forget (Remove from history) still applies in private windows because
// the underlying browsing history is shared with non-private profiles.
Assert.ok(
!forgetHidden,
"Forget should remain visible for non-origin URLs in a private window"
);
await UrlbarTestUtils.promisePopupClose(privateWin);
await BrowserTestUtils.closeWindow(privateWin);
await PlacesUtils.history.clear();
});
add_task(async function forget_item_hidden_for_origin_autofill() {
await PlacesUtils.history.clear();
await addAdaptiveHistoryEntry(ORIGIN_URL, ADAPTIVE_INPUT);
await showAutofillFor(window, SEARCH_STRING);
let { result } = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
Assert.equal(
result.autofill?.type,
"adaptive_origin",
"Pre-condition: origin-typed autofill"
);
let { dismissHidden, forgetHidden } = await readContextMenuItems(window);
Assert.ok(!dismissHidden, "Dismiss should be visible for origin autofill");
Assert.ok(forgetHidden, "Forget should be hidden for origin autofill");
await UrlbarTestUtils.promisePopupClose(window);
await PlacesUtils.history.clear();
});
add_task(async function context_menu_items_hidden_without_autofill_result() {
await PlacesUtils.history.clear();
await showAutofillFor(window, "no-match-string-xyz");
let { dismissHidden, forgetHidden } = await readContextMenuItems(window);
Assert.ok(
dismissHidden,
"Dismiss should be hidden when no autofill heuristic is showing"
);
Assert.ok(
forgetHidden,
"Forget should be hidden when no autofill heuristic is showing"
);
await UrlbarTestUtils.promisePopupClose(window);
});
add_task(async function dismiss_clears_backspace_entry() {
await PlacesUtils.history.clear();
await addAdaptiveHistoryEntry(ADAPTIVE_URL, ADAPTIVE_INPUT);
// Pre-populate a backspace entry for the page scope.
UrlbarUtils._backspaceBlocks.clear();
UrlbarUtils._backspaceBlocks.set("page:example.com", {
level: "url",
count: 1,
blockedAt: Date.now(),
});
await showAutofillFor(window, SEARCH_STRING);
await clickContextMenuItem(window, DISMISS_ID);
await TestUtils.waitForCondition(
() => !UrlbarUtils._backspaceBlocks.has("page:example.com"),
"Context-menu dismiss should clear the page-scope backspace entry"
);
await UrlbarTestUtils.promisePopupClose(window);
await PlacesUtils.history.clear();
UrlbarUtils._backspaceBlocks.clear();
});