/* 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 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_task(async function setup() { await SearchTestUtils.useTestEngines("data", null, [ { webExtension: { id: "engine-purposes@search.mozilla.org", }, appliesTo: [ { included: { everywhere: true }, default: "yes", }, ], }, ]); await AddonTestUtils.promiseStartupManager(); await Services.search.init(); defaultEngine = Services.search.getEngineByName("Test Engine With Purposes"); }); add_task(async function test_searchTermFromResult_withAllPurposes() { for (let purpose of Object.values(SearchUtils.PARAM_PURPOSES)) { let uri = defaultEngine.getSubmission(TERM, null, purpose).uri; let searchTerm = defaultEngine.searchTermFromResult(uri); Assert.equal( searchTerm, TERM, `Should return the correct url for purpose: ${purpose}` ); } }); 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.promiseNewSearchEngine({ url: `${gDataUrl}engine-fr.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"); // 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), TERM, "Should get term even if 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 = "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." ); url = getValidEngineUrl(); url.searchParams.delete("form"); 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); }