Bug 1476088 - Additional search submission telemetry. r=florian, a=RyanVM
authorMichael Kaply <mozilla@kaply.com>
Tue, 07 Aug 2018 09:45:19 -0500
changeset 473821 dad476171a76
parent 473820 d22d9ccbec14
child 473822 e6b8ec3c45a4
push id1751
push userryanvm@gmail.com
push date2018-08-07 17:02 +0000
treeherdermozilla-release@975058795980 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersflorian, RyanVM
bugs1476088
milestone61.0.2
Bug 1476088 - Additional search submission telemetry. r=florian, a=RyanVM
toolkit/components/search/nsSearchService.js
toolkit/components/search/tests/xpcshell/test_sendSubmissionURL.js
toolkit/components/search/tests/xpcshell/xpcshell.ini
toolkit/components/telemetry/docs/data/environment.rst
--- a/toolkit/components/search/nsSearchService.js
+++ b/toolkit/components/search/nsSearchService.js
@@ -1068,19 +1068,20 @@ function EngineURL(aType, aMethod, aTemp
     // case "file":
     // case "resource":
       this.template = aTemplate;
       break;
     default:
       FAIL("new EngineURL: template uses invalid scheme!", Cr.NS_ERROR_FAILURE);
   }
 
+  this.templateHost = templateURI.host;
   // If no resultDomain was specified in the engine definition file, use the
   // host from the template.
-  this.resultDomain = aResultDomain || templateURI.host;
+  this.resultDomain = aResultDomain || this.templateHost;
   // We never want to return a "www." prefix, so eventually strip it.
   if (this.resultDomain.startsWith("www.")) {
     this.resultDomain = this.resultDomain.substr(4);
   }
 }
 EngineURL.prototype = {
 
   addParam: function SRCH_EURL_addParam(aName, aValue, aPurpose) {
@@ -4194,16 +4195,43 @@ SearchService.prototype = {
             break;
           if (result.name == engineName) {
             sendSubmissionURL = true;
             break;
           }
         }
       }
 
+      if (!sendSubmissionURL) {
+        // ... or engines that are the same domain as a default engine.
+        let engineHost = engine._getURLOfType(URLTYPE_SEARCH_HTML).templateHost;
+        for (let name in this._engines) {
+          let innerEngine = this._engines[name];
+          if (!innerEngine._isDefault) {
+            continue;
+          }
+
+          let innerEngineURL = innerEngine._getURLOfType(URLTYPE_SEARCH_HTML);
+          if (innerEngineURL.templateHost == engineHost) {
+            sendSubmissionURL = true;
+            break;
+          }
+        }
+
+        if (!sendSubmissionURL) {
+          // ... or well known search domains.
+          //
+          // Starts with: www.google., search.aol., yandex.
+          // or
+          // Ends with: search.yahoo.com, .ask.com, .bing.com, .startpage.com, baidu.com, duckduckgo.com
+          const urlTest = /^(?:www\.google\.|search\.aol\.|yandex\.)|(?:search\.yahoo|\.ask|\.bing|\.startpage|\.baidu|\.duckduckgo)\.com$/;
+          sendSubmissionURL = urlTest.test(engineHost);
+        }
+      }
+
       if (sendSubmissionURL) {
         let uri = engine._getURLOfType("text/html")
                         .getSubmission("", engine, "searchbar").uri;
         uri = uri.mutate()
                  .setUserPass("") // Avoid reporting a username or password.
                  .finalize();
         result.submissionURL = uri.spec;
       }
new file mode 100644
--- /dev/null
+++ b/toolkit/components/search/tests/xpcshell/test_sendSubmissionURL.js
@@ -0,0 +1,58 @@
+/* Any copyright is dedicated to the Public Domain.
+ *    http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/*
+ * Tests covering sending submission URLs for major engines
+ */
+
+const SUBMISSION_YES = new Map([
+  ["Google1 Test", "https://www.google.com/search?q={searchTerms}"],
+  ["Google2 Test", "https://www.google.co.uk/search?q={searchTerms}"],
+  ["Yahoo1 Test", "https://search.yahoo.com/search?p={searchTerms}"],
+  ["Yahoo2 Test", "https://uk.search.yahoo.com/search?p={searchTerms}"],
+  ["AOL1 Test", "https://search.aol.com/aol/search?q={searchTerms}"],
+  ["AOL2 Test", "https://search.aol.co.uk/aol/search?q={searchTerms}"],
+  ["Yandex1 Test", "https://yandex.ru/search/?text={searchTerms}"],
+  ["Yandex2 Test", "https://yandex.com/search/?text{searchTerms}"],
+  ["Ask1 Test", "https://www.ask.com/web?q={searchTerms}"],
+  ["Ask2 Test", "https://fr.ask.com/web?q={searchTerms}"],
+  ["Bing Test", "https://www.bing.com/search?q={searchTerms}"],
+  ["Startpage Test", "https://www.startpage.com/do/search?query={searchTerms}"],
+  ["DuckDuckGo Test", "https://duckduckgo.com/?q={searchTerms}"],
+  ["Baidu Test", "https://www.baidu.com/s?wd={searchTerms}"],
+]);
+
+const SUBMISSION_NO = new Map([
+  ["Other1 Test", "https://example.com?q={searchTerms}"],
+  ["Other2 Test", "https://googlebutnotgoogle.com?q={searchTerms}"],
+]);
+
+function addAndMakeDefault(name, searchURL) {
+   Services.search.addEngineWithDetails(name, null, null, null, "GET", searchURL);
+   let engine = Services.search.getEngineByName(name);
+   Services.search.currentEngine = engine;
+   return engine;
+}
+
+add_task(async function test() {
+  Assert.ok(!Services.search.isInitialized);
+
+  await asyncInit();
+
+  let engineInfo;
+  let engine;
+
+  for (let [name, searchURL] of SUBMISSION_YES) {
+    engine = addAndMakeDefault(name, searchURL);
+    engineInfo = Services.search.getDefaultEngineInfo();
+    Assert.equal(engineInfo.submissionURL, searchURL.replace("{searchTerms}", ""));
+    Services.search.removeEngine(engine);
+  }
+
+ for (let [name, searchURL] of SUBMISSION_NO) {
+   engine = addAndMakeDefault(name, searchURL);
+   engineInfo = Services.search.getDefaultEngineInfo();
+   Assert.equal(engineInfo.submissionURL, null);
+   Services.search.removeEngine(engine);
+ }
+});
--- a/toolkit/components/search/tests/xpcshell/xpcshell.ini
+++ b/toolkit/components/search/tests/xpcshell/xpcshell.ini
@@ -93,8 +93,9 @@ tags = addons
 [test_addEngineWithDetails.js]
 [test_addEngineWithDetailsObject.js]
 [test_addEngineWithExtensionID.js]
 [test_chromeresource_icon1.js]
 [test_chromeresource_icon2.js]
 [test_engineUpdate.js]
 [test_paramSubstitution.js]
 [test_migrateWebExtensionEngine.js]
+[test_sendSubmissionURL.js]
--- a/toolkit/components/telemetry/docs/data/environment.rst
+++ b/toolkit/components/telemetry/docs/data/environment.rst
@@ -38,17 +38,17 @@ Structure:
         addonCompatibilityCheckEnabled: <bool>, // Whether application compatibility is respected for add-ons
         blocklistEnabled: <bool>, // true on failure
         isDefaultBrowser: <bool>, // null on failure and until session restore completes, not available on Android
         defaultSearchEngine: <string>, // e.g. "yahoo"
         defaultSearchEngineData: {, // data about the current default engine
           name: <string>, // engine name, e.g. "Yahoo"; or "NONE" if no default
           loadPath: <string>, // where the engine line is located; missing if no default
           origin: <string>, // 'default', 'verified', 'unverified', or 'invalid'; based on the presence and validity of the engine's loadPath verification hash.
-          submissionURL: <string> // missing if no default or for user-installed engines
+          submissionURL: <string> // set for default engines or well known search domains
         },
         searchCohort: <string>, // optional, contains an identifier for any active search A/B experiments
         e10sEnabled: <bool>, // whether e10s is on, i.e. browser tabs open by default in a different process
         telemetryEnabled: <bool>, // false on failure
         locale: <string>, // e.g. "it", null on failure
         update: {
           channel: <string>, // e.g. "release", null on failure
           enabled: <bool>, // true on failure