summaryrefslogtreecommitdiffstats
path: root/browser/components/extensions/test/xpcshell/test_ext_settings_overrides_search.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/extensions/test/xpcshell/test_ext_settings_overrides_search.js')
-rw-r--r--browser/components/extensions/test/xpcshell/test_ext_settings_overrides_search.js585
1 files changed, 585 insertions, 0 deletions
diff --git a/browser/components/extensions/test/xpcshell/test_ext_settings_overrides_search.js b/browser/components/extensions/test/xpcshell/test_ext_settings_overrides_search.js
new file mode 100644
index 0000000000..2c94569dbd
--- /dev/null
+++ b/browser/components/extensions/test/xpcshell/test_ext_settings_overrides_search.js
@@ -0,0 +1,585 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+
+"use strict";
+
+const { AddonTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/AddonTestUtils.sys.mjs"
+);
+const { setTimeout } = ChromeUtils.importESModule(
+ "resource://gre/modules/Timer.sys.mjs"
+);
+
+let delay = () => new Promise(resolve => setTimeout(resolve, 0));
+
+const kSearchFormURL = "https://example.com/searchform";
+const kSearchEngineURL = "https://example.com/?search={searchTerms}";
+const kSearchSuggestURL = "https://example.com/?suggest={searchTerms}";
+const kSearchTerm = "foo";
+const kSearchTermIntl = "日";
+const URLTYPE_SUGGEST_JSON = "application/x-suggestions+json";
+
+AddonTestUtils.init(this);
+AddonTestUtils.createAppInfo(
+ "xpcshell@tests.mozilla.org",
+ "XPCShell",
+ "42",
+ "42"
+);
+
+add_task(async function setup() {
+ await AddonTestUtils.promiseStartupManager();
+ await Services.search.init();
+});
+
+add_task(async function test_extension_adding_engine() {
+ let ext1 = ExtensionTestUtils.loadExtension({
+ manifest: {
+ icons: {
+ 16: "foo.ico",
+ 32: "foo32.ico",
+ },
+ chrome_settings_overrides: {
+ search_provider: {
+ name: "MozSearch",
+ keyword: "MozSearch",
+ search_form: kSearchFormURL,
+ search_url: kSearchEngineURL,
+ suggest_url: kSearchSuggestURL,
+ },
+ },
+ },
+ useAddonManager: "temporary",
+ });
+
+ await ext1.startup();
+ await AddonTestUtils.waitForSearchProviderStartup(ext1);
+
+ let engine = Services.search.getEngineByName("MozSearch");
+ ok(engine, "Engine should exist.");
+
+ let { baseURI } = ext1.extension;
+ equal(engine.iconURI.spec, baseURI.resolve("foo.ico"), "icon path matches");
+ let icons = engine.getIcons();
+ equal(icons.length, 2, "both icons avialable");
+ equal(icons[0].url, baseURI.resolve("foo.ico"), "icon path matches");
+ equal(icons[1].url, baseURI.resolve("foo32.ico"), "icon path matches");
+
+ let expectedSuggestURL = kSearchSuggestURL.replace(
+ "{searchTerms}",
+ kSearchTerm
+ );
+ let submissionSuggest = engine.getSubmission(
+ kSearchTerm,
+ URLTYPE_SUGGEST_JSON
+ );
+ let encodedSubmissionURL = engine.getSubmission(kSearchTermIntl).uri.spec;
+ let testSubmissionURL = kSearchEngineURL.replace(
+ "{searchTerms}",
+ encodeURIComponent(kSearchTermIntl)
+ );
+ equal(
+ encodedSubmissionURL,
+ testSubmissionURL,
+ "Encoded UTF-8 URLs should match"
+ );
+
+ equal(
+ submissionSuggest.uri.spec,
+ expectedSuggestURL,
+ "Suggest URLs should match"
+ );
+
+ equal(engine.searchForm, kSearchFormURL, "Search form URLs should match");
+ await ext1.unload();
+ await delay();
+
+ engine = Services.search.getEngineByName("MozSearch");
+ ok(!engine, "Engine should not exist");
+});
+
+add_task(async function test_extension_adding_engine_with_spaces() {
+ let ext1 = ExtensionTestUtils.loadExtension({
+ manifest: {
+ chrome_settings_overrides: {
+ search_provider: {
+ name: "MozSearch ",
+ keyword: "MozSearch",
+ search_url: "https://example.com/?q={searchTerms}",
+ },
+ },
+ },
+ useAddonManager: "temporary",
+ });
+
+ await ext1.startup();
+ await AddonTestUtils.waitForSearchProviderStartup(ext1);
+
+ let engine = Services.search.getEngineByName("MozSearch");
+ ok(engine, "Engine should exist.");
+
+ await ext1.unload();
+ await delay();
+
+ engine = Services.search.getEngineByName("MozSearch");
+ ok(!engine, "Engine should not exist");
+});
+
+add_task(async function test_upgrade_default_position_engine() {
+ let ext1 = ExtensionTestUtils.loadExtension({
+ manifest: {
+ chrome_settings_overrides: {
+ search_provider: {
+ name: "MozSearch",
+ keyword: "MozSearch",
+ search_url: "https://example.com/?q={searchTerms}",
+ },
+ },
+ browser_specific_settings: {
+ gecko: {
+ id: "testengine@mozilla.com",
+ },
+ },
+ version: "0.1",
+ },
+ useAddonManager: "temporary",
+ });
+
+ await ext1.startup();
+ await AddonTestUtils.waitForSearchProviderStartup(ext1);
+
+ let engine = Services.search.getEngineByName("MozSearch");
+ await Services.search.setDefault(
+ engine,
+ Ci.nsISearchService.CHANGE_REASON_UNKNOWN
+ );
+ await Services.search.moveEngine(engine, 1);
+
+ await ext1.upgrade({
+ manifest: {
+ chrome_settings_overrides: {
+ search_provider: {
+ name: "MozSearch",
+ keyword: "MozSearch",
+ search_url: "https://example.com/?q={searchTerms}",
+ },
+ },
+ browser_specific_settings: {
+ gecko: {
+ id: "testengine@mozilla.com",
+ },
+ },
+ version: "0.2",
+ },
+ useAddonManager: "temporary",
+ });
+ await AddonTestUtils.waitForSearchProviderStartup(ext1);
+
+ engine = Services.search.getEngineByName("MozSearch");
+ equal(
+ Services.search.defaultEngine,
+ engine,
+ "Default engine should still be MozSearch"
+ );
+ equal(
+ (await Services.search.getEngines()).map(e => e.name).indexOf(engine.name),
+ 1,
+ "Engine is in position 1"
+ );
+
+ await ext1.unload();
+ await delay();
+
+ engine = Services.search.getEngineByName("MozSearch");
+ ok(!engine, "Engine should not exist");
+});
+
+add_task(async function test_extension_get_params() {
+ let ext1 = ExtensionTestUtils.loadExtension({
+ manifest: {
+ chrome_settings_overrides: {
+ search_provider: {
+ name: "MozSearch",
+ keyword: "MozSearch",
+ search_url: kSearchEngineURL,
+ search_url_get_params: "foo=bar&bar=foo",
+ suggest_url: kSearchSuggestURL,
+ suggest_url_get_params: "foo=bar&bar=foo",
+ },
+ },
+ },
+ useAddonManager: "temporary",
+ });
+
+ await ext1.startup();
+ await AddonTestUtils.waitForSearchProviderStartup(ext1);
+
+ let engine = Services.search.getEngineByName("MozSearch");
+ ok(engine, "Engine should exist.");
+
+ let url = engine.wrappedJSObject._getURLOfType("text/html");
+ equal(url.method, "GET", "Search URLs method is GET");
+
+ let expectedURL = kSearchEngineURL.replace("{searchTerms}", kSearchTerm);
+ let submission = engine.getSubmission(kSearchTerm);
+ equal(
+ submission.uri.spec,
+ `${expectedURL}&foo=bar&bar=foo`,
+ "Search URLs should match"
+ );
+
+ let expectedSuggestURL = kSearchSuggestURL.replace(
+ "{searchTerms}",
+ kSearchTerm
+ );
+ let submissionSuggest = engine.getSubmission(
+ kSearchTerm,
+ URLTYPE_SUGGEST_JSON
+ );
+ equal(
+ submissionSuggest.uri.spec,
+ `${expectedSuggestURL}&foo=bar&bar=foo`,
+ "Suggest URLs should match"
+ );
+
+ await ext1.unload();
+});
+
+add_task(async function test_extension_post_params() {
+ let ext1 = ExtensionTestUtils.loadExtension({
+ manifest: {
+ chrome_settings_overrides: {
+ search_provider: {
+ name: "MozSearch",
+ keyword: "MozSearch",
+ search_url: kSearchEngineURL,
+ search_url_post_params: "foo=bar&bar=foo",
+ suggest_url: kSearchSuggestURL,
+ suggest_url_post_params: "foo=bar&bar=foo",
+ },
+ },
+ },
+ useAddonManager: "temporary",
+ });
+
+ await ext1.startup();
+ await AddonTestUtils.waitForSearchProviderStartup(ext1);
+
+ let engine = Services.search.getEngineByName("MozSearch");
+ ok(engine, "Engine should exist.");
+
+ let url = engine.wrappedJSObject._getURLOfType("text/html");
+ equal(url.method, "POST", "Search URLs method is POST");
+
+ let expectedURL = kSearchEngineURL.replace("{searchTerms}", kSearchTerm);
+ let submission = engine.getSubmission(kSearchTerm);
+ equal(submission.uri.spec, expectedURL, "Search URLs should match");
+ // postData is a nsIMIMEInputStream which contains a nsIStringInputStream.
+ equal(
+ submission.postData.data.data,
+ "foo=bar&bar=foo",
+ "Search postData should match"
+ );
+
+ let expectedSuggestURL = kSearchSuggestURL.replace(
+ "{searchTerms}",
+ kSearchTerm
+ );
+ let submissionSuggest = engine.getSubmission(
+ kSearchTerm,
+ URLTYPE_SUGGEST_JSON
+ );
+ equal(
+ submissionSuggest.uri.spec,
+ expectedSuggestURL,
+ "Suggest URLs should match"
+ );
+ equal(
+ submissionSuggest.postData.data.data,
+ "foo=bar&bar=foo",
+ "Suggest postData should match"
+ );
+
+ await ext1.unload();
+});
+
+add_task(async function test_extension_no_query_params() {
+ const ext1 = ExtensionTestUtils.loadExtension({
+ manifest: {
+ chrome_settings_overrides: {
+ search_provider: {
+ name: "MozSearch",
+ keyword: "MozSearch",
+ search_url: "https://example.com/{searchTerms}",
+ suggest_url: "https://example.com/suggest/{searchTerms}",
+ },
+ },
+ },
+ useAddonManager: "temporary",
+ });
+
+ await ext1.startup();
+ await AddonTestUtils.waitForSearchProviderStartup(ext1);
+
+ let engine = Services.search.getEngineByName("MozSearch");
+ ok(engine, "Engine should exist.");
+
+ const encodedSubmissionURL = engine.getSubmission(kSearchTermIntl).uri.spec;
+ const testSubmissionURL =
+ "https://example.com/" + encodeURIComponent(kSearchTermIntl);
+ equal(
+ encodedSubmissionURL,
+ testSubmissionURL,
+ "Encoded UTF-8 URLs should match"
+ );
+
+ const expectedSuggestURL = "https://example.com/suggest/" + kSearchTerm;
+ let submissionSuggest = engine.getSubmission(
+ kSearchTerm,
+ URLTYPE_SUGGEST_JSON
+ );
+ equal(
+ submissionSuggest.uri.spec,
+ expectedSuggestURL,
+ "Suggest URLs should match"
+ );
+
+ await ext1.unload();
+ await delay();
+
+ engine = Services.search.getEngineByName("MozSearch");
+ ok(!engine, "Engine should not exist");
+});
+
+add_task(async function test_extension_empty_suggestUrl() {
+ let ext1 = ExtensionTestUtils.loadExtension({
+ manifest: {
+ default_locale: "en",
+ chrome_settings_overrides: {
+ search_provider: {
+ name: "MozSearch",
+ keyword: "MozSearch",
+ search_url: kSearchEngineURL,
+ search_url_post_params: "foo=bar&bar=foo",
+ suggest_url: "__MSG_suggestUrl__",
+ suggest_url_get_params: "__MSG_suggestUrlGetParams__",
+ },
+ },
+ },
+ useAddonManager: "temporary",
+ files: {
+ "_locales/en/messages.json": {
+ suggestUrl: {
+ message: "",
+ },
+ suggestUrlGetParams: {
+ message: "",
+ },
+ },
+ },
+ });
+
+ await ext1.startup();
+ await AddonTestUtils.waitForSearchProviderStartup(ext1);
+
+ let engine = Services.search.getEngineByName("MozSearch");
+ ok(engine, "Engine should exist.");
+
+ let url = engine.wrappedJSObject._getURLOfType("text/html");
+ equal(url.method, "POST", "Search URLs method is POST");
+
+ let expectedURL = kSearchEngineURL.replace("{searchTerms}", kSearchTerm);
+ let submission = engine.getSubmission(kSearchTerm);
+ equal(submission.uri.spec, expectedURL, "Search URLs should match");
+ // postData is a nsIMIMEInputStream which contains a nsIStringInputStream.
+ equal(
+ submission.postData.data.data,
+ "foo=bar&bar=foo",
+ "Search postData should match"
+ );
+
+ let submissionSuggest = engine.getSubmission(
+ kSearchTerm,
+ URLTYPE_SUGGEST_JSON
+ );
+ ok(!submissionSuggest, "There should be no suggest URL.");
+
+ await ext1.unload();
+});
+
+add_task(async function test_extension_empty_suggestUrl_with_params() {
+ let ext1 = ExtensionTestUtils.loadExtension({
+ manifest: {
+ default_locale: "en",
+ chrome_settings_overrides: {
+ search_provider: {
+ name: "MozSearch",
+ keyword: "MozSearch",
+ search_url: kSearchEngineURL,
+ search_url_post_params: "foo=bar&bar=foo",
+ suggest_url: "__MSG_suggestUrl__",
+ suggest_url_get_params: "__MSG_suggestUrlGetParams__",
+ },
+ },
+ },
+ useAddonManager: "temporary",
+ files: {
+ "_locales/en/messages.json": {
+ suggestUrl: {
+ message: "",
+ },
+ suggestUrlGetParams: {
+ message: "abc",
+ },
+ },
+ },
+ });
+
+ await ext1.startup();
+ await AddonTestUtils.waitForSearchProviderStartup(ext1);
+
+ let engine = Services.search.getEngineByName("MozSearch");
+ ok(engine, "Engine should exist.");
+
+ let url = engine.wrappedJSObject._getURLOfType("text/html");
+ equal(url.method, "POST", "Search URLs method is POST");
+
+ let expectedURL = kSearchEngineURL.replace("{searchTerms}", kSearchTerm);
+ let submission = engine.getSubmission(kSearchTerm);
+ equal(submission.uri.spec, expectedURL, "Search URLs should match");
+ // postData is a nsIMIMEInputStream which contains a nsIStringInputStream.
+ equal(
+ submission.postData.data.data,
+ "foo=bar&bar=foo",
+ "Search postData should match"
+ );
+
+ let submissionSuggest = engine.getSubmission(
+ kSearchTerm,
+ URLTYPE_SUGGEST_JSON
+ );
+ ok(!submissionSuggest, "There should be no suggest URL.");
+
+ await ext1.unload();
+});
+
+async function checkBadUrl(searchProviderKey, urlValue) {
+ let normalized = await ExtensionTestUtils.normalizeManifest({
+ chrome_settings_overrides: {
+ search_provider: {
+ name: "MozSearch",
+ keyword: "MozSearch",
+ search_url: "https://example.com/",
+ [searchProviderKey]: urlValue,
+ },
+ },
+ });
+
+ ok(
+ /Error processing chrome_settings_overrides\.search_provider[^:]*: .* must match/.test(
+ normalized.error
+ ),
+ `Expected error for ${searchProviderKey}:${urlValue} "${normalized.error}"`
+ );
+}
+
+async function checkValidUrl(urlValue) {
+ let normalized = await ExtensionTestUtils.normalizeManifest({
+ chrome_settings_overrides: {
+ search_provider: {
+ name: "MozSearch",
+ keyword: "MozSearch",
+ search_form: urlValue,
+ search_url: urlValue,
+ suggest_url: urlValue,
+ },
+ },
+ });
+ equal(normalized.error, undefined, `Valid search_provider url: ${urlValue}`);
+}
+
+add_task(async function test_extension_not_allow_http() {
+ await checkBadUrl("search_form", "http://example.com/{searchTerms}");
+ await checkBadUrl("search_url", "http://example.com/{searchTerms}");
+ await checkBadUrl("suggest_url", "http://example.com/{searchTerms}");
+});
+
+add_task(async function test_manifest_disallows_http_localhost_prefix() {
+ await checkBadUrl("search_url", "http://localhost.example.com");
+ await checkBadUrl("search_url", "http://localhost.example.com/");
+ await checkBadUrl("search_url", "http://127.0.0.1.example.com/");
+ await checkBadUrl("search_url", "http://localhost:1234@example.com/");
+});
+
+add_task(async function test_manifest_allow_http_for_localhost() {
+ await checkValidUrl("http://localhost");
+ await checkValidUrl("http://localhost/");
+ await checkValidUrl("http://localhost:/");
+ await checkValidUrl("http://localhost:1/");
+ await checkValidUrl("http://localhost:65535/");
+
+ await checkValidUrl("http://127.0.0.1");
+ await checkValidUrl("http://127.0.0.1:");
+ await checkValidUrl("http://127.0.0.1:/");
+ await checkValidUrl("http://127.0.0.1/");
+ await checkValidUrl("http://127.0.0.1:80/");
+
+ await checkValidUrl("http://[::1]");
+ await checkValidUrl("http://[::1]:");
+ await checkValidUrl("http://[::1]:/");
+ await checkValidUrl("http://[::1]/");
+ await checkValidUrl("http://[::1]:80/");
+});
+
+add_task(async function test_extension_allow_http_for_localhost() {
+ let ext1 = ExtensionTestUtils.loadExtension({
+ manifest: {
+ chrome_settings_overrides: {
+ search_provider: {
+ name: "MozSearch",
+ keyword: "MozSearch",
+ search_url: "http://localhost/{searchTerms}",
+ suggest_url: "http://localhost/suggest/{searchTerms}",
+ },
+ },
+ },
+ useAddonManager: "temporary",
+ });
+
+ await ext1.startup();
+ await AddonTestUtils.waitForSearchProviderStartup(ext1);
+
+ let engine = Services.search.getEngineByName("MozSearch");
+ ok(engine, "Engine should exist.");
+
+ await ext1.unload();
+});
+
+add_task(async function test_search_favicon_mv3() {
+ Services.prefs.setBoolPref("extensions.manifestV3.enabled", true);
+ let normalized = await ExtensionTestUtils.normalizeManifest({
+ manifest_version: 3,
+ chrome_settings_overrides: {
+ search_provider: {
+ name: "HTTP Icon in MV3",
+ search_url: "https://example.org/",
+ favicon_url: "https://example.org/icon.png",
+ },
+ },
+ });
+ Assert.ok(
+ normalized.error.endsWith("must be a relative URL"),
+ "Should have an error"
+ );
+ normalized = await ExtensionTestUtils.normalizeManifest({
+ manifest_version: 3,
+ chrome_settings_overrides: {
+ search_provider: {
+ name: "HTTP Icon in MV3",
+ search_url: "https://example.org/",
+ favicon_url: "/icon.png",
+ },
+ },
+ });
+ Assert.ok(!normalized.error, "Should not have an error");
+});