360 lines
12 KiB
JavaScript
360 lines
12 KiB
JavaScript
/* 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/. */
|
|
|
|
const { UrlbarSearchUtils } = ChromeUtils.importESModule(
|
|
"resource:///modules/UrlbarSearchUtils.sys.mjs"
|
|
);
|
|
const { updateAppInfo } = ChromeUtils.importESModule(
|
|
"resource://testing-common/AppInfo.sys.mjs"
|
|
);
|
|
|
|
let baconEngineExtension;
|
|
|
|
add_setup(async function () {
|
|
updateAppInfo({
|
|
name: "firefox",
|
|
});
|
|
});
|
|
|
|
add_task(async function () {
|
|
await UrlbarSearchUtils.init();
|
|
// Tell the search service we are running in the US. This also has the
|
|
// desired side-effect of preventing our geoip lookup.
|
|
Services.prefs.setCharPref("browser.search.region", "US");
|
|
|
|
Services.search.restoreDefaultEngines();
|
|
Services.search.resetToAppDefaultEngine();
|
|
});
|
|
|
|
add_task(async function search_engine_match() {
|
|
let engine = await Services.search.getDefault();
|
|
let domain = engine.searchUrlDomain;
|
|
let token = domain.substr(0, 1);
|
|
let matchedEngine = (
|
|
await UrlbarSearchUtils.enginesForDomainPrefix(token)
|
|
)[0];
|
|
Assert.equal(matchedEngine, engine);
|
|
});
|
|
|
|
add_task(async function no_match() {
|
|
Assert.equal(
|
|
0,
|
|
(await UrlbarSearchUtils.enginesForDomainPrefix("test")).length
|
|
);
|
|
});
|
|
|
|
add_task(async function hide_search_engine_nomatch() {
|
|
let engine = await Services.search.getDefault();
|
|
let domain = engine.searchUrlDomain;
|
|
let token = domain.substr(0, 1);
|
|
let promiseTopic = promiseSearchTopic("engine-changed");
|
|
await Promise.all([Services.search.removeEngine(engine), promiseTopic]);
|
|
Assert.ok(engine.hidden);
|
|
let matchedEngines = await UrlbarSearchUtils.enginesForDomainPrefix(token);
|
|
Assert.ok(
|
|
!matchedEngines.length || matchedEngines[0].searchUrlDomain != domain
|
|
);
|
|
engine.hidden = false;
|
|
await TestUtils.waitForCondition(
|
|
async () => (await UrlbarSearchUtils.enginesForDomainPrefix(token)).length
|
|
);
|
|
let matchedEngine2 = (
|
|
await UrlbarSearchUtils.enginesForDomainPrefix(token)
|
|
)[0];
|
|
Assert.ok(matchedEngine2);
|
|
await Services.search.setDefault(
|
|
engine,
|
|
Ci.nsISearchService.CHANGE_REASON_UNKNOWN
|
|
);
|
|
});
|
|
|
|
add_task(async function onlyEnabled_option_nomatch() {
|
|
let defaultEngine = await Services.search.getDefault();
|
|
let domain = defaultEngine.searchUrlDomain;
|
|
let token = domain.substr(0, 1);
|
|
defaultEngine.hideOneOffButton = true;
|
|
|
|
let matchedEngines = await UrlbarSearchUtils.enginesForDomainPrefix(token);
|
|
Assert.notEqual(matchedEngines[0], defaultEngine);
|
|
|
|
defaultEngine.hideOneOffButton = false;
|
|
matchedEngines = await UrlbarSearchUtils.enginesForDomainPrefix(token);
|
|
Assert.equal(matchedEngines[0].searchUrlDomain, domain);
|
|
Assert.equal(matchedEngines[0], defaultEngine);
|
|
});
|
|
|
|
add_task(async function add_search_engine_match() {
|
|
Assert.equal(
|
|
0,
|
|
(await UrlbarSearchUtils.enginesForDomainPrefix("bacon")).length
|
|
);
|
|
baconEngineExtension = await SearchTestUtils.installSearchExtension(
|
|
{
|
|
name: "bacon",
|
|
keyword: "pork",
|
|
search_url: "https://www.bacon.moz/",
|
|
},
|
|
{ skipUnload: true }
|
|
);
|
|
let matchedEngine = (
|
|
await UrlbarSearchUtils.enginesForDomainPrefix("bacon")
|
|
)[0];
|
|
Assert.ok(matchedEngine);
|
|
Assert.equal(matchedEngine.name, "bacon");
|
|
Assert.equal(await matchedEngine.getIconURL(), null);
|
|
info("also type part of the public suffix");
|
|
matchedEngine = (
|
|
await UrlbarSearchUtils.enginesForDomainPrefix("bacon.m")
|
|
)[0];
|
|
Assert.ok(matchedEngine);
|
|
Assert.equal(matchedEngine.name, "bacon");
|
|
Assert.equal(await matchedEngine.getIconURL(), null);
|
|
});
|
|
|
|
add_task(async function match_multiple_search_engines() {
|
|
Assert.equal(
|
|
0,
|
|
(await UrlbarSearchUtils.enginesForDomainPrefix("baseball")).length
|
|
);
|
|
await SearchTestUtils.installSearchExtension({
|
|
name: "baseball",
|
|
search_url: "https://www.baseball.moz/",
|
|
});
|
|
let matchedEngines = await UrlbarSearchUtils.enginesForDomainPrefix("ba");
|
|
Assert.equal(
|
|
matchedEngines.length,
|
|
2,
|
|
"enginesForDomainPrefix returned two engines."
|
|
);
|
|
Assert.equal(matchedEngines[0].name, "bacon");
|
|
Assert.equal(matchedEngines[1].name, "baseball");
|
|
});
|
|
|
|
add_task(async function test_aliased_search_engine_match() {
|
|
Assert.equal(null, await UrlbarSearchUtils.engineForAlias("sober"));
|
|
// Lower case
|
|
let matchedEngine = await UrlbarSearchUtils.engineForAlias("pork");
|
|
Assert.ok(matchedEngine);
|
|
Assert.equal(matchedEngine.name, "bacon");
|
|
Assert.ok(matchedEngine.aliases.includes("pork"));
|
|
Assert.equal(await matchedEngine.getIconURL(), null);
|
|
// Upper case
|
|
matchedEngine = await UrlbarSearchUtils.engineForAlias("PORK");
|
|
Assert.ok(matchedEngine);
|
|
Assert.equal(matchedEngine.name, "bacon");
|
|
Assert.ok(matchedEngine.aliases.includes("pork"));
|
|
Assert.equal(await matchedEngine.getIconURL(), null);
|
|
// Cap case
|
|
matchedEngine = await UrlbarSearchUtils.engineForAlias("Pork");
|
|
Assert.ok(matchedEngine);
|
|
Assert.equal(matchedEngine.name, "bacon");
|
|
Assert.ok(matchedEngine.aliases.includes("pork"));
|
|
Assert.equal(await matchedEngine.getIconURL(), null);
|
|
});
|
|
|
|
add_task(async function test_aliased_search_engine_match_upper_case_alias() {
|
|
Assert.equal(
|
|
0,
|
|
(await UrlbarSearchUtils.enginesForDomainPrefix("patch")).length
|
|
);
|
|
await SearchTestUtils.installSearchExtension({
|
|
name: "patch",
|
|
keyword: "PR",
|
|
search_url: "https://www.patch.moz/",
|
|
});
|
|
// lower case
|
|
let matchedEngine = await UrlbarSearchUtils.engineForAlias("pr");
|
|
Assert.ok(matchedEngine);
|
|
Assert.equal(matchedEngine.name, "patch");
|
|
Assert.ok(matchedEngine.aliases.includes("PR"));
|
|
Assert.equal(await matchedEngine.getIconURL(), null);
|
|
// Upper case
|
|
matchedEngine = await UrlbarSearchUtils.engineForAlias("PR");
|
|
Assert.ok(matchedEngine);
|
|
Assert.equal(matchedEngine.name, "patch");
|
|
Assert.ok(matchedEngine.aliases.includes("PR"));
|
|
Assert.equal(await matchedEngine.getIconURL(), null);
|
|
// Cap case
|
|
matchedEngine = await UrlbarSearchUtils.engineForAlias("Pr");
|
|
Assert.ok(matchedEngine);
|
|
Assert.equal(matchedEngine.name, "patch");
|
|
Assert.ok(matchedEngine.aliases.includes("PR"));
|
|
Assert.equal(await matchedEngine.getIconURL(), null);
|
|
});
|
|
|
|
add_task(async function remove_search_engine_nomatch() {
|
|
let promiseTopic = promiseSearchTopic("engine-removed");
|
|
await Promise.all([baconEngineExtension.unload(), promiseTopic]);
|
|
Assert.equal(
|
|
0,
|
|
(await UrlbarSearchUtils.enginesForDomainPrefix("bacon")).length
|
|
);
|
|
});
|
|
|
|
add_task(async function test_builtin_aliased_search_engine_match() {
|
|
let engine = await UrlbarSearchUtils.engineForAlias("@google");
|
|
Assert.ok(engine);
|
|
Assert.equal(engine.name, "Google");
|
|
let promiseTopic = promiseSearchTopic("engine-changed");
|
|
await Promise.all([Services.search.removeEngine(engine), promiseTopic]);
|
|
let matchedEngine = await UrlbarSearchUtils.engineForAlias("@google");
|
|
Assert.ok(!matchedEngine);
|
|
engine.hidden = false;
|
|
await TestUtils.waitForCondition(() =>
|
|
UrlbarSearchUtils.engineForAlias("@google")
|
|
);
|
|
engine = await UrlbarSearchUtils.engineForAlias("@google");
|
|
Assert.ok(engine);
|
|
});
|
|
|
|
add_task(async function test_serps_are_equivalent() {
|
|
info("Subset URL has extraneous parameters.");
|
|
let url1 = "https://example.com/search?q=test&type=images";
|
|
let url2 = "https://example.com/search?q=test";
|
|
Assert.ok(!UrlbarSearchUtils.serpsAreEquivalent(url1, url2));
|
|
info("Superset URL has extraneous parameters.");
|
|
Assert.ok(UrlbarSearchUtils.serpsAreEquivalent(url2, url1));
|
|
|
|
info("Same keys, different values.");
|
|
url1 = "https://example.com/search?q=test&type=images";
|
|
url2 = "https://example.com/search?q=test123&type=maps";
|
|
Assert.ok(!UrlbarSearchUtils.serpsAreEquivalent(url1, url2));
|
|
Assert.ok(!UrlbarSearchUtils.serpsAreEquivalent(url2, url1));
|
|
|
|
info("Subset matching isn't strict (URL is subset of itself).");
|
|
Assert.ok(UrlbarSearchUtils.serpsAreEquivalent(url1, url1));
|
|
|
|
info("Origin and pathname are ignored.");
|
|
url1 = "https://example.com/search?q=test";
|
|
url2 = "https://example-1.com/maps?q=test";
|
|
Assert.ok(UrlbarSearchUtils.serpsAreEquivalent(url1, url2));
|
|
Assert.ok(UrlbarSearchUtils.serpsAreEquivalent(url2, url1));
|
|
|
|
info("Params can be optionally ignored");
|
|
url1 = "https://example.com/search?q=test&abc=123&foo=bar";
|
|
url2 = "https://example.com/search?q=test";
|
|
Assert.ok(!UrlbarSearchUtils.serpsAreEquivalent(url1, url2));
|
|
Assert.ok(UrlbarSearchUtils.serpsAreEquivalent(url1, url2, ["abc", "foo"]));
|
|
});
|
|
|
|
add_task(async function test_get_root_domain_from_engine() {
|
|
let extension = await SearchTestUtils.installSearchExtension(
|
|
{
|
|
name: "TestEngine2",
|
|
search_url: "https://example.com/",
|
|
},
|
|
{ skipUnload: true }
|
|
);
|
|
let engine = Services.search.getEngineByName("TestEngine2");
|
|
Assert.equal(UrlbarSearchUtils.getRootDomainFromEngine(engine), "example");
|
|
await extension.unload();
|
|
|
|
extension = await SearchTestUtils.installSearchExtension(
|
|
{
|
|
name: "TestEngine",
|
|
search_url: "https://www.subdomain.othersubdomain.example.com",
|
|
},
|
|
{ skipUnload: true }
|
|
);
|
|
engine = Services.search.getEngineByName("TestEngine");
|
|
Assert.equal(UrlbarSearchUtils.getRootDomainFromEngine(engine), "example");
|
|
await extension.unload();
|
|
|
|
// We let engines with URL ending in .test through even though its not a valid
|
|
// TLD.
|
|
extension = await SearchTestUtils.installSearchExtension(
|
|
{
|
|
name: "TestMalformed",
|
|
search_url: "https://mochi.test/",
|
|
search_url_get_params: "search={searchTerms}",
|
|
},
|
|
{ skipUnload: true }
|
|
);
|
|
engine = Services.search.getEngineByName("TestMalformed");
|
|
Assert.equal(UrlbarSearchUtils.getRootDomainFromEngine(engine), "mochi");
|
|
await extension.unload();
|
|
|
|
// We return the domain for engines with a malformed URL.
|
|
extension = await SearchTestUtils.installSearchExtension(
|
|
{
|
|
name: "TestMalformed",
|
|
search_url: "https://subdomain.foobar/",
|
|
search_url_get_params: "search={searchTerms}",
|
|
},
|
|
{ skipUnload: true }
|
|
);
|
|
engine = Services.search.getEngineByName("TestMalformed");
|
|
Assert.equal(
|
|
UrlbarSearchUtils.getRootDomainFromEngine(engine),
|
|
"subdomain.foobar"
|
|
);
|
|
await extension.unload();
|
|
});
|
|
|
|
add_task(async function matchAllDomainLevels() {
|
|
let baseHostname = "matchalldomainlevels";
|
|
Assert.equal(
|
|
(await UrlbarSearchUtils.enginesForDomainPrefix(baseHostname)).length,
|
|
0,
|
|
`Sanity check: No engines initially match ${baseHostname}`
|
|
);
|
|
|
|
// Install engines with the following domains. When we match engines below,
|
|
// perfectly matching domains should come before partially matching domains.
|
|
let baseDomain = `${baseHostname}.com`;
|
|
let perfectDomains = [baseDomain, `www.${baseDomain}`];
|
|
let partialDomains = [`foo.${baseDomain}`, `foo.bar.${baseDomain}`];
|
|
|
|
// Install engines with partially matching domains first so that the test
|
|
// isn't incidentally passing because engines are installed in the order it
|
|
// ultimately expects them in. Wait for each engine to finish installing
|
|
// before starting the next one to avoid intermittent out-of-order failures.
|
|
let extensions = [];
|
|
for (let list of [partialDomains, perfectDomains]) {
|
|
for (let domain of list) {
|
|
let ext = await SearchTestUtils.installSearchExtension(
|
|
{
|
|
name: domain,
|
|
search_url: `https://${domain}/`,
|
|
},
|
|
{ skipUnload: true }
|
|
);
|
|
extensions.push(ext);
|
|
}
|
|
}
|
|
|
|
// Perfect matches come before partial matches.
|
|
let expectedDomains = [...perfectDomains, ...partialDomains];
|
|
|
|
// Do searches for the following strings. Each should match all the engines
|
|
// installed above.
|
|
let searchStrings = [baseHostname, baseHostname + "."];
|
|
for (let searchString of searchStrings) {
|
|
info(`Searching for "${searchString}"`);
|
|
let engines = await UrlbarSearchUtils.enginesForDomainPrefix(searchString, {
|
|
matchAllDomainLevels: true,
|
|
});
|
|
// Domain names are saved in engine names.
|
|
let actualDomains = engines.map(e => e.name);
|
|
Assert.deepEqual(
|
|
actualDomains,
|
|
expectedDomains,
|
|
"Expected matching engine names/domains in the expected order"
|
|
);
|
|
}
|
|
|
|
await Promise.all(extensions.map(e => e.unload()));
|
|
});
|
|
|
|
function promiseSearchTopic(expectedVerb) {
|
|
return new Promise(resolve => {
|
|
Services.obs.addObserver(function observe(subject, topic, verb) {
|
|
info("browser-search-engine-modified: " + verb);
|
|
if (verb == expectedVerb) {
|
|
Services.obs.removeObserver(observe, "browser-search-engine-modified");
|
|
resolve();
|
|
}
|
|
}, "browser-search-engine-modified");
|
|
});
|
|
}
|