/* 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/. */ /* * Tests searchTermFromResult API. */ let CONFIG_V2 = [ { recordType: "engine", identifier: "engine-purposes", base: { name: "Test Engine With Purposes", urls: { search: { base: "https://www.example.com/search", params: [ { name: "pc", value: "FIREFOX" }, { name: "channel", experimentConfig: "testChannelEnabled", }, ], searchTermParamName: "q", }, }, }, variants: [ { environment: { allRegionsAndLocales: true }, }, ], }, ]; let defaultEngine; // The test string contains special characters to ensure // that they are encoded/decoded properly. const TERM = "c;,?:@&=+$-_.!~*'()# d\u00E8f"; const TERM_ENCODED = "c%3B%2C%3F%3A%40%26%3D%2B%24-_.!~*'()%23+d%C3%A8f"; add_setup(async function () { SearchTestUtils.setRemoteSettingsConfig(CONFIG_V2); await Services.search.init(); defaultEngine = Services.search.getEngineByName("Test Engine With Purposes"); }); add_task(async function test_searchTermFromResult() { // Internationalized Domain Name search engine. await SearchTestUtils.installSearchExtension({ name: "idn_addParam", keyword: "idn_addParam", search_url: "https://www.xn--bcher-kva.ch/search", }); let engineEscapedIDN = Services.search.getEngineByName("idn_addParam"); // Setup server for french engine. await useHttpServer(""); // For ISO-8859-1 encoding testing. let engineISOCharset = await SearchTestUtils.installOpenSearchEngine({ url: `${gHttpURL}/opensearch/fr-domain-iso8859-1.xml`, }); // For Windows-1252 encoding testing. await SearchTestUtils.installSearchExtension({ name: "bacon_addParam", keyword: "bacon_addParam", encoding: "windows-1252", search_url: "https://www.bacon.test/find", }); let engineWinCharset = Services.search.getEngineByName("bacon_addParam"); // For providers with non-encoded characters in their path. await SearchTestUtils.installSearchExtension({ name: "characters_with_accents_in_path", keyword: "characters_with_accents_in_path", search_url: "https://fr.example.org/âêîôû:ÂÊÎÔÛ", }); let engineWithAccentsInPath = Services.search.getEngineByName( "characters_with_accents_in_path" ); // Verify getValidEngineUrl returns a URL that can return a search term. let testUrl = getValidEngineUrl(); Assert.equal( getTerm(testUrl), TERM, "Should get term from a url generated by getSubmission." ); testUrl = getValidEngineUrl(); testUrl.pathname = "/SEARCH"; Assert.equal( getTerm(testUrl), "", "Should not get term if the path is not the same case as the engine." ); let url = `https://www.xn--bcher-kva.ch/search?q=${TERM_ENCODED}`; Assert.equal( getTerm(url, engineEscapedIDN), TERM, "Should get term from IDNs urls." ); url = `http://www.google.fr/search?q=caf%E8+au+lait&ie=iso-8859-1&oe=iso-8859-1`; Assert.equal( getTerm(url, engineISOCharset), "caf\u00E8 au lait", "Should get term from ISO-8859-1 encoded url containing a search term." ); url = `http://www.google.fr/search?&ie=iso-8859-1&oe=iso-8859-1&q=`; Assert.equal( getTerm(url, engineISOCharset), "", "Should get a blank string from ISO-8859-1 encoded url missing a search term" ); url = "https://www.bacon.test/find?q=caf%E8+au+lait"; Assert.equal( getTerm(url, engineWinCharset), "caf\u00E8 au lait", "Should get term from Windows-1252 encoded url containing a search term." ); url = "https://www.bacon.test/find?q="; Assert.equal( getTerm(url, engineWinCharset), "", "Should get a blank string from Windows-1252 encoded url missing a search term." ); url = "https://fr.example.org/âêîôû:ÂÊÎÔÛ?q=aàâäéèêëïôöùûüÿçæ"; Assert.equal( getTerm(url, engineWithAccentsInPath), "aàâäéèêëïôöùûüÿçæ", "Should get term from path containing accent marks." ); url = "about:blank"; Assert.equal(getTerm(url), "", "Should get a blank string from about:blank."); url = "about:newtab"; Assert.equal( getTerm(url), "", "Should get a blank string from about:newtab." ); }); // Use a version of the url that should return a term and make minute // modifications that should cause it to return a blank value. add_task(async function test_searchTermFromResult_blank() { let url = getValidEngineUrl(); url.searchParams.set("hello", "world"); Assert.equal( getTerm(url), "", "Should get a blank string from url containing query param name not recognized by the engine." ); url = getValidEngineUrl(); url.protocol = "http"; Assert.equal( getTerm(url), "", "Should get a blank string from url that has a different scheme from the engine." ); url = getValidEngineUrl(); url.protocol = "http"; Assert.equal( getTerm(url), "", "Should get a blank string from url that has a different path from the engine." ); url = getValidEngineUrl(); url.host = "images.example.com"; Assert.equal( getTerm(url), "", "Should get a blank string from url that has a different host from the engine." ); url = getValidEngineUrl(); url.host = "example.com"; Assert.equal( getTerm(url), "", "Should get a blank string from url that has a different host from the engine." ); url = getValidEngineUrl(); url.searchParams.set("form", "MOZUNKNOWN"); Assert.equal( getTerm(url), "", "Should get a blank string from a url that has an un-recognized form value." ); url = getValidEngineUrl(); url.searchParams.set("q", ""); Assert.equal( getTerm(url), "", "Should get a blank string from a url with a missing search query value." ); url = getValidEngineUrl(); url.searchParams.delete("q"); Assert.equal( getTerm(url), "", "Should get a blank string from a url with a missing search query name." ); url = getValidEngineUrl(); url.searchParams.delete("pc"); Assert.equal( getTerm(url), "", "Should get a blank string from a url with a missing a query parameter." ); }); add_task(async function test_searchTermFromResult_prefParam() { const defaultBranch = Services.prefs.getDefaultBranch( SearchUtils.BROWSER_SEARCH_PREF ); defaultBranch.setCharPref("param.testChannelEnabled", "yes"); let url = getValidEngineUrl(true); Assert.equal(getTerm(url), TERM, "Should get term after pref is turned on."); url.searchParams.delete("channel"); Assert.equal( getTerm(url), "", "Should get a blank string if pref is on and channel param is missing." ); defaultBranch.setCharPref("param.testChannelEnabled", ""); url = getValidEngineUrl(true); Assert.equal(getTerm(url), TERM, "Should get term after pref is turned off."); url.searchParams.set("channel", "yes"); Assert.equal( getTerm(url), "", "Should get a blank string if pref is turned off but channel param is present." ); }); // searchTermFromResult attempts to look into the template of a search // engine if query params aren't present in the url.params, so make sure // it works properly and fails gracefully. add_task(async function test_searchTermFromResult_paramsInSearchUrl() { await SearchTestUtils.installSearchExtension({ name: "engine_params_in_search_url", search_url: "https://example.com/?q={searchTerms}&pc=firefox", search_url_get_params: "", }); let testEngine = Services.search.getEngineByName( "engine_params_in_search_url" ); let url = `https://example.com/?q=${TERM_ENCODED}&pc=firefox`; Assert.equal( getTerm(url, testEngine), TERM, "Should get term from an engine with params in its search url." ); url = `https://example.com/?q=${TERM_ENCODED}`; Assert.equal( getTerm(url, testEngine), "", "Should get a blank string when not all params are present." ); await SearchTestUtils.installSearchExtension({ name: "engine_params_in_search_url_without_delimiter", search_url: "https://example.com/q={searchTerms}", search_url_get_params: "", }); testEngine = Services.search.getEngineByName( "engine_params_in_search_url_without_delimiter" ); url = `https://example.com/?q=${TERM_ENCODED}&pc=firefox&page=1`; Assert.equal( getTerm(url, testEngine), "", "Should get a blank string from an engine with no params and no delimiter in its url." ); }); function getTerm(url, searchEngine = defaultEngine) { return searchEngine.searchTermFromResult(Services.io.newURI(url.toString())); } // Return a new instance of a submission URL so that it can modified // and tested again. Allow callers to force the cache to update, especially // if the engine is expected to have updated. function getValidEngineUrl(updateCache = false) { if (updateCache || !this._submissionUrl) { this._submissionUrl = defaultEngine.getSubmission(TERM, null).uri.spec; } return new URL(this._submissionUrl); }