Bug 1340108 - autofill match regardless of protocol and www. in prefill site, r?gijs draft
authorSvetlana Orlik <sveta.orlik.code@gmail.com>
Fri, 24 Feb 2017 14:05:06 +0300
changeset 490799 005e450d6c4e2e182ec8a05abd7ef722384c0554
parent 490433 1bc2ad020aee2830e0a7941f10958dbec108c254
child 490800 f585885162e4ee872aa28964fbfe5ef50f5159d1
push id47227
push userbmo:sveta.orlik.code@gmail.com
push dateWed, 01 Mar 2017 09:20:51 +0000
reviewersgijs
bugs1340108
milestone54.0a1
Bug 1340108 - autofill match regardless of protocol and www. in prefill site, r?gijs Still draft: autofill only MozReview-Commit-ID: 1POpbPzYJTe
toolkit/components/places/UnifiedComplete.js
toolkit/components/places/tests/unifiedcomplete/test_prefill_sites.js
toolkit/components/places/unifiedcomplete-top-urls.json
--- a/toolkit/components/places/UnifiedComplete.js
+++ b/toolkit/components/places/UnifiedComplete.js
@@ -551,16 +551,28 @@ XPCOMUtils.defineLazyGetter(this, "Prefs
 });
 
 // Prefill Sites related
 
 function PrefillSite(url, title) {
   this.uri = NetUtil.newURI(url);
   this.title = title;
   this._matchTitle = title.toLowerCase();
+  this._hasWWW = this.uri.host.startsWith("www.");
+  this._hostWithoutWWW = this._hasWWW ? this.uri.host.slice(4)
+                                      : this.uri.host;
+/**
+    dump(`++++++++++++++++++++++++++++++++++
+          url:${url}
+          this.uri.spec:${this.uri.spec}
+          this.uri.host:${this.uri.host}
+          this.uri.scheme:${this.uri.scheme}
+          `
+        );
+**/
 }
 
 /**
  * Storage object for Prefill Sites.
  *   add(url, title): adds a site to storage
  *   populate(sites) : populates the  storage with array of [url,title]
  *   sites[]: resulting array of sites (PrefillSite objects)
  */
@@ -1044,20 +1056,26 @@ Search.prototype = {
     if (!Prefs.prefillSitesEnabled)
       return;
     let profileCreationDate = yield ProfileAgeCreatedPromise;
     let daysSinceProfileCreation = (Date.now() - profileCreationDate) / MS_PER_DAY;
     if (daysSinceProfileCreation > Prefs.prefillSitesExpireDays)
       Services.prefs.setBoolPref("browser.urlbar.usepreloadedtopurls.enabled", false);
   },
 
-  // TODO: manage protocol and "www." like _matchSearchEngineUrl() does
+  // TODO: manage protocol
   _matchPrefillSites() {
     if (!Prefs.prefillSitesEnabled)
       return;
+
+    // In case user typed just "https://" or "www." or "https://www."
+    // - we do not put out the whole lot of sites
+    if (!this._searchString)
+      return;
+
     for (let site of PrefillSiteStorage.sites) {
       if (site.uri.host.includes(this._searchString) ||
           site._matchTitle.includes(this._searchString)) {
         let match = {
           value: site.uri.spec,
           comment: site.title,
           style: "prefill-site",
           finalCompleteValue: site.uri.spec,
@@ -1066,30 +1084,89 @@ Search.prototype = {
         this._addMatch(match);
       }
     }
   },
 
   _matchPrefillSiteForAutofill() {
     if (!Prefs.prefillSitesEnabled)
       return false;
+
+    let searchStringHasWWW = this._strippedPrefix.endsWith("www.");
+    let searchStringWWW = searchStringHasWWW ? "www." : "";
+
+    // Extract any stripped scheme (as user can type even "ftp://")
+    let searchStringSchemeFound = this._strippedPrefix.match(/^(\w+):\/\//i);
+    let searchStringScheme = searchStringSchemeFound ?
+                             searchStringSchemeFound[1].toLowerCase() : "";
+    if (!(searchStringScheme === "" ||
+          searchStringScheme === "https" ||
+          searchStringScheme === "http" ))
+      return false;
+
+    function matchStrict(site) {
+      return site.uri.host.startsWith(searchStringWWW + this._searchString) &&
+             (!searchStringScheme || searchStringScheme === site.uri.scheme)
+    }
+
+    function matchLoose(site) {
+      return site._hostWithoutWWW.startsWith(this._searchString) &&
+             (!searchStringScheme || searchStringScheme === site.uri.scheme)
+    }
+
+    // Strict match has priority
+    let site = PrefillSiteStorage.sites.find(matchStrict, this) ||
+               PrefillSiteStorage.sites.find(matchLoose, this);
+
+    if (!site)
+      return false;
+
+    let finalWWW = (site._hasWWW || searchStringHasWWW) ? "www." : "";
+    let match = {
+      // we show prefix just as user typed it
+      value: this._strippedPrefix + stripPrefix(site.uri.spec),
+      style: "autofill",
+      finalCompleteValue: site.uri.scheme + "://" + finalWWW
+                          + stripPrefix(site.uri.spec),
+      frecency: FRECENCY_DEFAULT,
+    };
+    this._result.setDefaultIndex(0);
+    this._addMatch(match);
+    return true;
+
+/*
     for (let site of PrefillSiteStorage.sites) {
-      if (site.uri.host.startsWith(this._searchString)) {
+      let schemeMatches = !searchStringScheme ||
+                            searchStringScheme == site.uri.scheme;
+
+      //let protocolMatches = (searchStringHasHTTP && (site.uri.scheme === "http")) ||
+      //                      (searchStringHasHTTPS && (site.uri.scheme === "https"));
+
+      if (site._hostWithoutWWW.startsWith(this._searchString) &&
+          schemeMatches
+ //          (!searchStringHasProtocol || (searchStringHasProtocol && protocolMatches))
+         ) {
+        // finalCompleteValue is where we go after Enter is pressed
+        // gets "www." if site has it OR user typed it
+        let finalWWW = (site._hasWWW || searchStringHasWWW) ? "www." : "";
         let match = {
-          value: stripPrefix(site.uri.spec),
+          // we show prefix just as user typed it
+          value: this._strippedPrefix + stripPrefix(site.uri.spec),
           style: "autofill",
-          finalCompleteValue: site.uri.spec,
+          finalCompleteValue: site.uri.scheme + "://" + finalWWW
+                              + stripPrefix(site.uri.spec),
           frecency: FRECENCY_DEFAULT,
         };
         this._result.setDefaultIndex(0);
         this._addMatch(match);
         return true;
       }
     }
     return false;
+*/
   },
 
   *_matchFirstHeuristicResult(conn) {
     // We always try to make the first result a special "heuristic" result.  The
     // heuristics below determine what type of result it will be, if any.
 
     let hasSearchTerms = this._searchTokens.length > 0;
 
@@ -1650,16 +1727,24 @@ Search.prototype = {
 
     if (this._addingHeuristicFirstMatch) {
       match.style += " heuristic";
     }
 
     match.icon = match.icon || "";
     match.finalCompleteValue = match.finalCompleteValue || "";
 
+/**
+    dump(`----------------------------------
+          match.value:${match.value}
+          match.comment:${match.comment}
+          match.icon:${match.icon}
+          match.style:${match.style}
+          match.finalCompleteValue:${match.finalCompleteValue}\n`);
+**/
     this._result.insertMatchAt(this._getInsertIndexForMatch(match),
                                match.value,
                                match.comment,
                                match.icon,
                                match.style,
                                match.finalCompleteValue);
 
     if (this._result.matchCount == 6)
--- a/toolkit/components/places/tests/unifiedcomplete/test_prefill_sites.js
+++ b/toolkit/components/places/tests/unifiedcomplete/test_prefill_sites.js
@@ -111,16 +111,91 @@ add_task(function* test_sorting_against_
       { uri: yahoooURI, title: "Yahooo",  style: ["prefill-site"] },
       { uri: gooogleURI, title: "Gooogle", style: ["prefill-site"] },
     ],
   });
 
   yield cleanup();
 });
 
+add_task(function* test_scheme_and_www() {
+  let https_www_site_URI = NetUtil.newURI("https://www.ooops-https-www.com/");
+  let https_____site_URI = NetUtil.newURI("https://ooops-https.com/");
+  // let http__www_site_URI = NetUtil.newURI("HTTP://www.ooops-HTTP-www.com/");
+  let http______site_URI = NetUtil.newURI("HTTP://ooops-HTTP.com/");
+
+  autocompleteObject.addPrefillSite(https_www_site_URI.spec, "Ooops");
+  autocompleteObject.addPrefillSite(https_____site_URI.spec, "Ooops");
+  // autocompleteObject.addPrefillSite(http__www_site_URI.spec, "Ooops");
+  autocompleteObject.addPrefillSite(http______site_URI.spec, "Ooops");
+
+  let tests =
+  // User typed
+  // autofilled
+  // completed
+  [
+    [// ftp: - ignore
+    "ftp://ooops",
+    "ftp://ooops",
+    "ftp://ooops",
+    ],
+    [// Strict match, no "www."
+    "ooops",
+    "ooops-https.com/",
+    "https://ooops-https.com/", // 2nd in list, but has priority as strict
+    ],
+    [// Strict match with "www."
+    "www.ooops",
+    "www.ooops-https-www.com/",
+    "https://www.ooops-https-www.com/",
+    ],
+    [// Loose match: search no "www.", result with "www."
+    "ooops-https-www",
+    "ooops-https-www.com/",
+    "https://www.ooops-https-www.com/",
+    ],
+    [// Loose match: search "www.", no-www site gets "www."
+    "www.ooops-https.",
+    "www.ooops-https.com/",
+    "https://www.ooops-https.com/",
+    ],
+    [// Explicit protocol, no "www."
+    "https://ooops",
+    "https://ooops-https.com/",
+    "https://ooops-https.com/",
+    ],
+    [// Explicit protocol, with "www."
+    "https://www.ooops",
+    "https://www.ooops-https-www.com/",
+    "https://www.ooops-https-www.com/",
+    ],
+    [// Explicit HTTP protocol, no-www site gets "www."
+    "http://www.ooops-http.",
+    "http://www.ooops-http.com/",
+    "http://www.ooops-http.com/",
+    ],
+    [// Wrong protocol
+    "http://ooops-https",
+    "http://ooops-https",
+    "http://ooops-https",
+    ],
+  ];
+
+  for (let test of tests) {
+    do_print("User types: " + test[0]);
+    yield check_autocomplete({
+      search: test[0],
+      autofilled: test[1].toLowerCase(),
+      completed: test[2].toLowerCase(),
+    });
+  }
+
+  yield cleanup();
+});
+
 add_task(function* test_data_file() {
   let response = yield fetch("chrome://global/content/unifiedcomplete-top-urls.json");
 
   do_print("Source file is supplied and fetched OK");
   Assert.ok(response.ok);
 
   do_print("The JSON is parsed");
   let sites = yield response.json();
@@ -129,14 +204,14 @@ add_task(function* test_data_file() {
   autocompleteObject.populatePrefillSiteStorage(sites);
 
   let lastSite = sites.pop();
   let uri = NetUtil.newURI(lastSite[0]);
 
   do_print("Storage is populated from JSON correctly");
   yield check_autocomplete({
     search: uri.host,
-    autofilled: stripPrefix(uri.spec),
+    autofilled: uri.host + "/",
     completed: uri.spec,
   });
 
   yield cleanup();
 });
--- a/toolkit/components/places/unifiedcomplete-top-urls.json
+++ b/toolkit/components/places/unifiedcomplete-top-urls.json
@@ -1,8 +1,11 @@
 [
   ["https://google.com/", "Google"],
   ["https://youtube.com/", "YouTube"],
   ["https://facebook.com/", "Facebook"],
   ["https://baidu.com/", "\u767E\u5EA6\u4E00\u4E0B\uFF0C\u4F60\u5C31\u77E5\u9053"],
   ["https://wikipedia.org/", "Wikipedia"],
   ["https://yahoo.com/", "Yahoo"]
+  ,["http://nonsecure.net/", "Non-secure site"]
+  ,["https://noprotocol.net", "No-protocol site"]
+  ,["https://www.worldwidewebsite.net", "World Wide Web site"]
 ]
\ No newline at end of file