Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: os == 'android'
- Manifest: toolkit/components/search/tests/xpcshell/xpcshell.toml
/* Any copyright is dedicated to the Public Domain.
"use strict";
async function getEngineNames() {
let engines = await Services.search.getEngines();
return engines.map(engine => engine._name);
}
add_setup(async function () {
let server = useHttpServer();
server.registerContentType("sjs", "sjs");
SearchTestUtils.setRemoteSettingsConfig([
{
identifier: "default",
},
},
{ identifier: "additional" },
]);
registerCleanupFunction(async () => {
Services.prefs.clearUserPref("browser.search.region");
});
});
add_task(async function basic_install_test() {
await Services.search.init();
await promiseAfterSettings();
// On first boot, we get the configuration defaults
Assert.deepEqual(await getEngineNames(), ["default", "additional"]);
// User installs a new search engine
let extension = await SearchTestUtils.installSearchExtension(
{
encoding: "windows-1252",
},
{ skipUnload: true }
);
Assert.deepEqual((await getEngineNames()).sort(), [
"Example",
"additional",
"default",
]);
let engine = await Services.search.getEngineByName("Example");
Assert.equal(
engine.wrappedJSObject.queryCharset,
"windows-1252",
"Should have the correct charset"
);
// User uninstalls their engine
await extension.awaitStartup();
await extension.unload();
await promiseAfterSettings();
Assert.deepEqual(await getEngineNames(), ["default", "additional"]);
});
add_task(async function test_install_duplicate_engine() {
let name = "default";
consoleAllowList.push(`An engine called ${name} already exists`);
let extension = await SearchTestUtils.installSearchExtension(
{
name,
},
{ skipUnload: true }
);
let engine = await Services.search.getEngineByName("default");
let submission = engine.getSubmission("foo");
Assert.equal(
submission.uri.spec,
"Should have not changed the app provided engine."
);
// User uninstalls their engine
await extension.unload();
});
add_task(async function test_load_favicon_invalid() {
let observed = TestUtils.consoleMessageObserved(msg => {
return msg.wrappedJSObject.arguments[0].includes(
"Content type does not match expected"
);
});
// User installs a new search engine
let extension = await SearchTestUtils.installSearchExtension(
{
favicon_url: `${gHttpURL}/head_search.js`,
},
{ skipUnload: true }
);
await observed;
let engine = await Services.search.getEngineByName("Example");
Assert.equal(
null,
await engine.getIconURL(),
"Should not have set an iconURI"
);
// User uninstalls their engine
await extension.awaitStartup();
await extension.unload();
await promiseAfterSettings();
});
add_task(async function test_load_favicon_invalid_redirect() {
let observed = TestUtils.consoleMessageObserved(msg => {
return msg.wrappedJSObject.arguments[0].includes(
"Content type does not match expected"
);
});
// User installs a new search engine
let extension = await SearchTestUtils.installSearchExtension(
{
favicon_url: `${gHttpURL}/sjs/iconsRedirect.sjs?type=invalid`,
},
{ skipUnload: true }
);
await observed;
let engine = await Services.search.getEngineByName("Example");
Assert.equal(
null,
await engine.getIconURL(),
"Should not have set an iconURI"
);
// User uninstalls their engine
await extension.awaitStartup();
await extension.unload();
await promiseAfterSettings();
});
add_task(async function test_load_favicon_redirect() {
let promiseIconChanged = SearchTestUtils.promiseSearchNotification(
SearchUtils.MODIFIED_TYPE.ICON_CHANGED,
SearchUtils.TOPIC_ENGINE_MODIFIED
);
// User installs a new search engine
let extension = await SearchTestUtils.installSearchExtension(
{
favicon_url: `${gHttpURL}/sjs/iconsRedirect.sjs`,
},
{ skipUnload: true }
);
let engine = await Services.search.getEngineByName("Example");
await promiseIconChanged;
Assert.ok(await engine.getIconURL(), "Should have set an iconURI");
Assert.ok(
(await engine.getIconURL()).startsWith("data:image/x-icon;base64,"),
"Should have saved the expected content type for the icon"
);
// User uninstalls their engine
await extension.awaitStartup();
await extension.unload();
await promiseAfterSettings();
});
// The size of the favicon_url is not explicitly stated in the manifest
// so we test if it is detected correctly for various file and url types.
add_task(async function test_load_icon_extension_url_ico() {
let promiseIconChanged = SearchTestUtils.promiseSearchNotification(
SearchUtils.MODIFIED_TYPE.ICON_CHANGED,
SearchUtils.TOPIC_ENGINE_MODIFIED
);
let response = await fetch(`${gHttpURL}/icons/remoteIcon.ico`);
let iconBuffer = await response.arrayBuffer();
let extension = await SearchTestUtils.installSearchExtension(
{
favicon_url: "icon.ico", // 16x16
icons: {
// These icons are not loaded because they have an explicit size.
48: "icon2.png",
49: "icon3.png",
},
},
{ skipUnload: true },
{ "icon.ico": iconBuffer }
);
let engine = Services.search.getEngineByName("Example");
await promiseIconChanged;
let iconMapObj = engine.wrappedJSObject._iconMapObj;
Assert.deepEqual(
Object.keys(iconMapObj).toSorted(),
["16", "48", "49"],
"Should have the correct 3 icons."
);
Assert.equal(
await engine.getIconURL(16),
"16x16 icon is correct."
);
Assert.equal(
await engine.getIconURL(48),
"48x48 icon is correct."
);
Assert.equal(
await engine.getIconURL(49),
"49x49 icon is correct."
);
Assert.equal(
await engine.getIconURL(50),
"Uses 49x49 icon for size 50."
);
// User uninstalls their engine
await extension.awaitStartup();
await extension.unload();
await promiseAfterSettings();
});
add_task(async function test_load_icon_extension_url_svg() {
let promiseIconChanged = SearchTestUtils.promiseSearchNotification(
SearchUtils.MODIFIED_TYPE.ICON_CHANGED,
SearchUtils.TOPIC_ENGINE_MODIFIED
);
let response = await fetch(`${gHttpURL}/icons/svgIcon.svg`);
let iconBuffer = await response.arrayBuffer();
let extension = await SearchTestUtils.installSearchExtension(
{
favicon_url: "icon.svg", // 16x16.
icons: {
// These icons are not loaded because they have an explicit size.
48: "icon2.png",
49: "icon3.png",
},
},
{ skipUnload: true },
{ "icon.svg": iconBuffer }
);
let engine = Services.search.getEngineByName("Example");
await promiseIconChanged;
let iconMapObj = engine.wrappedJSObject._iconMapObj;
Assert.deepEqual(
Object.keys(iconMapObj).toSorted(),
["16", "48", "49"],
"Should have the correct 3 icons."
);
Assert.equal(
await engine.getIconURL(16),
"16x16 icon is correct."
);
// User uninstalls their engine
await extension.awaitStartup();
await extension.unload();
await promiseAfterSettings();
});
add_task(async function test_load_icon_http_url_ico() {
let promiseIconChanged = SearchTestUtils.promiseSearchNotification(
SearchUtils.MODIFIED_TYPE.ICON_CHANGED,
SearchUtils.TOPIC_ENGINE_MODIFIED
);
let extension = await SearchTestUtils.installSearchExtension(
{
favicon_url: `${gHttpURL}/sjs/iconsRedirect.sjs`, //16x16
// These icons are not loaded because they have an explicit size.
icons: {
48: "icon.png",
49: "icon2.png",
},
},
{ skipUnload: true }
);
let engine = Services.search.getEngineByName("Example");
await promiseIconChanged;
let iconMapObj = engine.wrappedJSObject._iconMapObj;
Assert.deepEqual(
Object.keys(iconMapObj).toSorted(),
["16", "48", "49"],
"Should have the correct 3 icons."
);
Assert.ok(
iconMapObj[16].startsWith("data:image/x-icon;base64,"),
"Should have saved the expected content type for the 16x16 icon"
);
// User uninstalls their engine
await extension.awaitStartup();
await extension.unload();
await promiseAfterSettings();
});