Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: os == 'android'
- Manifest: browser/components/urlbar/tests/unit/xpcshell.toml
/* Any copyright is dedicated to the Public Domain.
/**
* Tests that visit-url and search engine heuristic results are returned by
* UrlbarProviderHeuristicFallback.
*/
const QUICKACTIONS_PREF = "browser.urlbar.suggest.quickactions";
const SUGGEST_ENABLED_PREF = "browser.search.suggest.enabled";
const PRIVATE_SEARCH_PREF = "browser.search.separatePrivateDefault.ui.enabled";
// We make sure that restriction tokens and search terms are correctly
// recognized when they are separated by each of these different types of spaces
// and combinations of spaces. U+3000 is the ideographic space in CJK and is
// commonly used by CJK speakers.
const TEST_SPACES = [" ", "\u3000", " \u3000", "\u3000 "];
testEngine_setup();
add_setup(async function () {
registerCleanupFunction(async () => {
Services.prefs.clearUserPref(QUICKACTIONS_PREF);
Services.prefs.clearUserPref(SUGGEST_ENABLED_PREF);
Services.prefs.clearUserPref(PRIVATE_SEARCH_PREF);
Services.prefs.clearUserPref("keyword.enabled");
});
Services.prefs.setBoolPref(QUICKACTIONS_PREF, false);
Services.prefs.setBoolPref(SUGGEST_ENABLED_PREF, false);
Services.prefs.setBoolPref(PRIVATE_SEARCH_PREF, false);
});
add_task(async function () {
info("visit url, no protocol");
let query = "mozilla.org";
let context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
fallbackTitle: `${query}/`,
heuristic: true,
}),
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
}),
],
});
info("visit url, no protocol but with 2 dots");
query = "www.mozilla.org";
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
fallbackTitle: `${query}/`,
heuristic: true,
}),
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
}),
],
});
info("visit url, no protocol, e-mail like");
query = "a@b.com";
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
fallbackTitle: `${query}/`,
heuristic: true,
}),
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
}),
],
});
info("visit url, with protocol but with 2 dots");
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
uri: `${query}/`,
fallbackTitle: `${query}/`,
heuristic: true,
}),
],
});
// info("visit url, with protocol but with 3 dots");
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
uri: `${query}/`,
fallbackTitle: `${query}/`,
heuristic: true,
}),
],
});
info("visit url, with protocol");
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
uri: `${query}/`,
fallbackTitle: `${query}/`,
heuristic: true,
}),
],
});
info("visit url, about: protocol (no host)");
query = "about:nonexistent";
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
uri: query,
fallbackTitle: query,
heuristic: true,
}),
],
});
info("visit url, with non-standard whitespace");
context = createContext(`${query}\u2028`, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
uri: `${query}/`,
fallbackTitle: `${query}/`,
heuristic: true,
}),
],
});
// This is distinct because of how we predict being able to url autofill via
// host lookups.
info("visit url, host matching visited host but not visited url");
await PlacesTestUtils.addVisits([
{
title: "Mozilla Wine",
transition: PlacesUtils.history.TRANSITION_TYPED,
},
]);
query = "mozilla.org/rum";
context = createContext(`${query}\u2028`, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
fallbackTitle: `${query}`,
heuristic: true,
}),
],
});
await PlacesUtils.history.clear();
// And hosts with no dot in them are special, due to requiring safelisting.
info("unknown host");
query = "firefox";
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
heuristic: true,
}),
],
});
info("string with known host");
query = "firefox/get";
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
heuristic: true,
}),
],
});
Services.prefs.setBoolPref("browser.fixup.domainwhitelist.firefox", true);
registerCleanupFunction(() => {
Services.prefs.clearUserPref("browser.fixup.domainwhitelist.firefox");
});
info("known host");
query = "firefox";
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
fallbackTitle: `${query}/`,
heuristic: true,
}),
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
}),
],
});
info("url with known host");
query = "firefox/get";
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
fallbackTitle: `${query}`,
heuristic: true,
}),
],
});
info("visit url, host matching visited host but not visited url, known host");
Services.prefs.setBoolPref("browser.fixup.domainwhitelist.mozilla", true);
registerCleanupFunction(() => {
Services.prefs.clearUserPref("browser.fixup.domainwhitelist.mozilla");
});
query = "mozilla/rum";
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
fallbackTitle: `${query}`,
heuristic: true,
}),
],
});
// ipv4 and ipv6 literal addresses should offer to visit.
info("visit url, ipv4 literal");
query = "127.0.0.1";
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
fallbackTitle: `${query}/`,
heuristic: true,
}),
],
});
info("visit url, ipv6 literal");
query = "[2001:db8::1]";
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
fallbackTitle: `${query}/`,
heuristic: true,
}),
],
});
// Setting keyword.enabled to false should always try to visit.
let keywordEnabled = Services.prefs.getBoolPref("keyword.enabled");
Services.prefs.setBoolPref("keyword.enabled", false);
registerCleanupFunction(() => {
Services.prefs.clearUserPref("keyword.enabled");
});
info("visit url, keyword.enabled = false");
query = "bacon";
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
fallbackTitle: `${query}/`,
heuristic: true,
}),
],
});
info("visit two word query, keyword.enabled = false");
query = "bacon lovers";
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
uri: query,
fallbackTitle: query,
heuristic: true,
}),
],
});
info("Forced search through a restriction token, keyword.enabled = false");
query = "?bacon";
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
heuristic: true,
query: "bacon",
}),
],
});
Services.prefs.setBoolPref("keyword.enabled", true);
info("visit two word query, keyword.enabled = true");
query = "bacon lovers";
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
heuristic: true,
}),
],
});
Services.prefs.setBoolPref("keyword.enabled", keywordEnabled);
info("visit url, scheme+host");
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
uri: `${query}/`,
fallbackTitle: `${query}/`,
heuristic: true,
}),
],
});
info("visit url, scheme+host");
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
uri: `${query}/`,
fallbackTitle: `${query}/`,
heuristic: true,
}),
],
});
info("visit url, host+port");
query = "example:8080";
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
fallbackTitle: `${query}/`,
heuristic: true,
}),
],
});
info("numerical operations that look like urls should search");
query = "123/12";
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
heuristic: true,
}),
],
});
info("numerical operations that look like urls should search");
query = "123.12/12.1";
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
heuristic: true,
}),
],
});
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
uri: query,
fallbackTitle: query,
heuristic: true,
}),
],
});
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
uri: query,
fallbackTitle: query,
heuristic: true,
}),
],
});
info("protocol with an extra slash");
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
heuristic: true,
}),
],
});
info("change default engine");
let originalTestEngine = Services.search.getEngineByName(
SUGGESTIONS_ENGINE_NAME
);
await SearchTestUtils.installSearchExtension({
name: "AliasEngine",
keyword: "alias",
});
let engine2 = Services.search.getEngineByName("AliasEngine");
Assert.notEqual(
Services.search.defaultEngine,
engine2,
"New engine shouldn't be the current engine yet"
);
await Services.search.setDefault(
engine2,
Ci.nsISearchService.CHANGE_REASON_UNKNOWN
);
query = "toronto";
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeSearchResult(context, {
engineName: "AliasEngine",
heuristic: true,
}),
],
});
await Services.search.setDefault(
originalTestEngine,
Ci.nsISearchService.CHANGE_REASON_UNKNOWN
);
info(
"Leading search-mode restriction tokens are removed from the search result."
);
for (let token of UrlbarTokenizer.SEARCH_MODE_RESTRICT) {
for (let spaces of TEST_SPACES) {
query = token + spaces + "query";
info("Testing: " + JSON.stringify({ query, spaces: codePoints(spaces) }));
let expectedQuery = query.substring(1).trimStart();
context = createContext(query, { isPrivate: false });
info(`Searching for "${query}", expecting "${expectedQuery}"`);
let payload = {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
heuristic: true,
query: expectedQuery,
alias: token,
};
if (token == UrlbarTokenizer.RESTRICT.SEARCH) {
payload.source = UrlbarUtils.RESULT_SOURCE.SEARCH;
payload.engineName = SUGGESTIONS_ENGINE_NAME;
}
await check_results({
context,
matches: [makeSearchResult(context, payload)],
});
}
}
info(
"Leading search-mode restriction tokens are removed from the search result with keyword.enabled = false."
);
Services.prefs.setBoolPref("keyword.enabled", false);
for (let token of UrlbarTokenizer.SEARCH_MODE_RESTRICT) {
for (let spaces of TEST_SPACES) {
query = token + spaces + "query";
info("Testing: " + JSON.stringify({ query, spaces: codePoints(spaces) }));
let expectedQuery = query.substring(1).trimStart();
context = createContext(query, { isPrivate: false });
info(`Searching for "${query}", expecting "${expectedQuery}"`);
let payload = {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
heuristic: true,
query: expectedQuery,
alias: token,
};
if (token == UrlbarTokenizer.RESTRICT.SEARCH) {
payload.source = UrlbarUtils.RESULT_SOURCE.SEARCH;
payload.engineName = SUGGESTIONS_ENGINE_NAME;
}
await check_results({
context,
matches: [makeSearchResult(context, payload)],
});
}
}
Services.prefs.clearUserPref("keyword.enabled");
info(
"Leading non-search-mode restriction tokens are not removed from the search result."
);
for (let token of Object.values(UrlbarTokenizer.RESTRICT)) {
if (UrlbarTokenizer.SEARCH_MODE_RESTRICT.has(token)) {
continue;
}
for (let spaces of TEST_SPACES) {
query = token + spaces + "query";
info("Testing: " + JSON.stringify({ query, spaces: codePoints(spaces) }));
let expectedQuery = query;
context = createContext(query, { isPrivate: false });
info(`Searching for "${query}", expecting "${expectedQuery}"`);
await check_results({
context,
matches: [
makeSearchResult(context, {
heuristic: true,
query: expectedQuery,
engineName: SUGGESTIONS_ENGINE_NAME,
}),
],
});
}
}
info(
"Test the format inputed is user@host, and the host is in domainwhitelist"
);
Services.prefs.setBoolPref("browser.fixup.domainwhitelist.test-host", true);
registerCleanupFunction(() => {
Services.prefs.clearUserPref("browser.fixup.domainwhitelist.test-host");
});
query = "any@test-host";
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
fallbackTitle: `${query}/`,
heuristic: true,
}),
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
}),
],
});
info(
"Test the format inputed is user@host, but the host is not in domainwhitelist"
);
query = "any@not-host";
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeSearchResult(context, {
heuristic: true,
query,
engineName: SUGGESTIONS_ENGINE_NAME,
}),
],
});
info(
"Test if the format of user:pass@host is handled as visit even if the host is not in domainwhitelist"
);
query = "user:pass@not-host";
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
fallbackTitle: "user:pass@not-host/",
heuristic: true,
}),
],
});
info("Test if the format of user@ipaddress is handled as visit");
query = "user@192.168.0.1";
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
fallbackTitle: "user@192.168.0.1/",
heuristic: true,
}),
makeSearchResult(context, {
heuristic: false,
query,
engineName: SUGGESTIONS_ENGINE_NAME,
}),
],
});
await PlacesUtils.history.clear();
// Check that punycode results are properly decoded before being displayed.
info("visit url, host matching visited host but not visited url");
await PlacesTestUtils.addVisits([
{
title: "test.пример.com",
transition: PlacesUtils.history.TRANSITION_TYPED,
},
]);
context = createContext("test", { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.HISTORY,
displayUrl: `test.пример.com`,
heuristic: true,
}),
],
});
await PlacesUtils.history.clear();
});
add_task(async function dont_fixup_urls_with_at_symbol() {
info("don't fixup search string if it contains no protocol and spaces.");
let query = "Lorem Ipsum @mozilla.org";
let context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
heuristic: true,
}),
],
});
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
fallbackTitle: `${query}/`,
heuristic: true,
}),
],
});
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
fallbackTitle: `${query}/`,
heuristic: true,
}),
],
});
query = "LoremIpsum@mozilla.org";
context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeVisitResult(context, {
source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
fallbackTitle: `${query}/`,
heuristic: true,
}),
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
}),
],
});
});
/**
* Returns an array of code points in the given string. Each code point is
* returned as a hexidecimal string.
*
* @param {string} str
* The code points of this string will be returned.
* @returns {Array}
* Array of code points in the string, where each is a hexidecimal string.
*/
function codePoints(str) {
return str.split("").map(s => s.charCodeAt(0).toString(16));
}