Bug 1512652 - Implement URL canonizing via Ctrl key. r=Standard8
authorDão Gottwald <dao@mozilla.com>
Tue, 22 Jan 2019 19:17:04 +0000
changeset 514869 f8a289c9c4819cfc9ef35666d54a907398ff6259
parent 514868 f6c286fcd4a56a52b768d48c1eacea1fcf20a967
child 514870 217865622f7a145aab2909995002191d729c442a
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersStandard8
bugs1512652
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1512652 - Implement URL canonizing via Ctrl key. r=Standard8 Differential Revision: https://phabricator.services.mozilla.com/D17060
browser/components/urlbar/UrlbarInput.jsm
browser/components/urlbar/UrlbarPrefs.jsm
--- a/browser/components/urlbar/UrlbarInput.jsm
+++ b/browser/components/urlbar/UrlbarInput.jsm
@@ -237,17 +237,17 @@ class UrlbarInput {
     openParams.postData = null;
     openParams.allowInheritPrincipal = false;
 
     // TODO: Work out how we get the user selection behavior, probably via passing
     // it in, since we don't have the old autocomplete controller to work with.
     // BrowserUsageTelemetry.recordUrlbarSelectedResultMethod(
     //   event, this.userSelectionBehavior);
 
-    url = url.trim();
+    url = this._maybeCanonizeURL(event, url) || url.trim();
 
     try {
       new URL(url);
     } catch (ex) {
       let browser = this.window.gBrowser.selectedBrowser;
       let lastLocationChange = browser.lastLocationChange;
 
       UrlbarUtils.getShortcutOrURIAndPostData(url).then(data => {
@@ -289,16 +289,19 @@ class UrlbarInput {
     //   event, this.userSelectionBehavior);
 
     let where = this._whereToOpen(event);
     let openParams = {
       postData: null,
       allowInheritPrincipal: false,
     };
 
+    // TODO bug 1521702: Call _maybeCanonizeURL for autofilled results with the
+    // typed string (not the autofilled one).
+
     let url = result.payload.url;
 
     switch (result.type) {
       case UrlbarUtils.MATCH_TYPE.TAB_SWITCH: {
         if (this._overrideDefaultAction(event)) {
           where = "current";
           break;
         }
@@ -311,16 +314,22 @@ class UrlbarInput {
 
         if (this.window.switchToTabHavingURI(Services.io.newURI(result.payload.url), false, loadOpts) &&
             prevTab.isEmpty) {
           this.window.gBrowser.removeTab(prevTab);
         }
         return;
       }
       case UrlbarUtils.MATCH_TYPE.SEARCH: {
+        url = this._maybeCanonizeURL(event,
+                result.payload.suggestion || result.payload.query);
+        if (url) {
+          break;
+        }
+
         const actionDetails = {
           isSuggestion: !!result.payload.suggestion,
           alias: result.payload.keyword,
         };
         const engine = Services.search.getEngineByName(result.payload.engine);
 
         [url, openParams.postData] = this._getSearchQueryUrl(
           engine, result.payload.suggestion || result.payload.query);
@@ -592,16 +601,60 @@ class UrlbarInput {
     let details = searchActionDetails;
     details.isOneOff = isOneOff;
     details.type = eventType;
 
     this.window.BrowserSearch.recordSearchInTelemetry(engine, "urlbar", details);
   }
 
   /**
+   * If appropriate, this prefixes a search string with 'www.' and suffixes it
+   * with browser.fixup.alternate.suffix prior to navigating.
+   *
+   * @param {Event} event
+   *   The event that triggered this query.
+   * @param {string} value
+   *   The search string that should be canonized.
+   * @returns {string}
+   *   Returns the canonized URL if available and null otherwise.
+   */
+  _maybeCanonizeURL(event, value) {
+    // Only add the suffix when the URL bar value isn't already "URL-like",
+    // and only if we get a keyboard event, to match user expectations.
+    if (!(event instanceof KeyboardEvent) ||
+        !event.ctrlKey ||
+        !UrlbarPrefs.get("ctrlCanonizesURLs") ||
+        !/^\s*[^.:\/\s]+(?:\/.*|\s*)$/i.test(value)) {
+      return null;
+    }
+
+    let suffix = Services.prefs.getCharPref("browser.fixup.alternate.suffix");
+    if (!suffix.endsWith("/")) {
+      suffix += "/";
+    }
+
+    // trim leading/trailing spaces (bug 233205)
+    value = value.trim();
+
+    // Tack www. and suffix on.  If user has appended directories, insert
+    // suffix before them (bug 279035).  Be careful not to get two slashes.
+    let firstSlash = value.indexOf("/");
+    if (firstSlash >= 0) {
+      value = value.substring(0, firstSlash) + suffix +
+              value.substring(firstSlash + 1);
+    } else {
+      value = value + suffix;
+    }
+    value = "http://www." + value;
+
+    this.value = value;
+    return value;
+  }
+
+  /**
    * Loads the url in the appropriate place.
    *
    * @param {string} url
    *   The URL to open.
    * @param {string} openUILinkWhere
    *   Where we expect the result to be opened.
    * @param {object} params
    *   The parameters related to how and where the result will be opened.
@@ -676,17 +729,18 @@ class UrlbarInput {
   _whereToOpen(event) {
     let isMouseEvent = event instanceof MouseEvent;
     let reuseEmpty = !isMouseEvent;
     let where = undefined;
     if (!isMouseEvent && event && event.altKey) {
       // We support using 'alt' to open in a tab, because ctrl/shift
       // might be used for canonizing URLs:
       where = event.shiftKey ? "tabshifted" : "tab";
-    } else if (!isMouseEvent && this._ctrlCanonizesURLs && event && event.ctrlKey) {
+    } else if (!isMouseEvent && event && event.ctrlKey &&
+               UrlbarPrefs.get("ctrlCanonizesURLs")) {
       // If we're allowing canonization, and this is a key event with ctrl
       // pressed, open in current tab to allow ctrl-enter to canonize URL.
       where = "current";
     } else {
       where = this.window.whereToOpenLink(event, false, false);
     }
     if (UrlbarPrefs.get("openintab")) {
       if (where == "current") {
--- a/browser/components/urlbar/UrlbarPrefs.jsm
+++ b/browser/components/urlbar/UrlbarPrefs.jsm
@@ -39,16 +39,22 @@ const PREF_URLBAR_DEFAULTS = new Map([
   // this value.  See UnifiedComplete.
   ["autoFill.stddevMultiplier", [0.0, "getFloatPref"]],
 
   // If true, this optimizes for replacing the full URL rather than editing
   // part of it. This also copies the urlbar value to the selection clipboard
   // on systems that support it.
   ["clickSelectsAll", false],
 
+  // Whether using `ctrl` when hitting return/enter in the URL bar
+  // (or clicking 'go') should prefix 'www.' and suffix
+  // browser.fixup.alternate.suffix to the URL bar value prior to
+  // navigating.
+  ["ctrlCanonizesURLs", true],
+
   // Whether copying the entire URL from the location bar will put a human
   // readable (percent-decoded) URL on the clipboard.
   ["decodeURLsOnCopy", false],
 
   // The amount of time (ms) to wait after the user has stopped typing before
   // fetching results.  However, we ignore this for the very first result (the
   // "heuristic" result).  We fetch it as fast as possible.
   ["delay", 50],