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 index 8e41d9d4f34a..e4641f3a8836 100644 --- a/browser/components/extensions/test/xpcshell/test_ext_settings_overrides_search.js +++ b/browser/components/extensions/test/xpcshell/test_ext_settings_overrides_search.js @@ -195,3 +195,39 @@ add_task(async function test_extension_post_params() { 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"); +}); diff --git a/toolkit/components/search/SearchService.jsm b/toolkit/components/search/SearchService.jsm index 317b99207124..dc867f1b69b4 100644 --- a/toolkit/components/search/SearchService.jsm +++ b/toolkit/components/search/SearchService.jsm @@ -4057,7 +4057,9 @@ SearchService.prototype = { shortName: extension.id.split("@")[0], description: extension.manifest.description, searchForm: searchProvider.search_form, - template: searchProvider.search_url, + // AddonManager will sometimes encode the URL via `new URL()`. We want + // to ensure we're always dealing with decoded urls. + template: decodeURI(searchProvider.search_url), searchGetParams: searchProvider.search_url_get_params, searchPostParams: searchProvider.search_url_post_params, iconURL: searchProvider.favicon_url || preferredIconUrl, @@ -4065,6 +4067,7 @@ SearchService.prototype = { alias: searchProvider.keyword, extensionID: extension.id, isBuiltin: extension.addonData.builtIn, + // suggest_url doesn't currently get encoded. suggestURL: searchProvider.suggest_url, suggestPostParams: searchProvider.suggest_url_post_params, suggestGetParams: searchProvider.suggest_url_get_params,