https://bugzilla.mozilla.org/show_bug.cgi?id=333714
https://bugzilla.mozilla.org/show_bug.cgi?id=1621570

So this has been fucked up for Linux users on purpose. Let's hope someone will
do to Marco Bonardo what he deserves for this.

--- Waterfox-G6.0b1/browser/app/profile/firefox.js
+++ Waterfox-G6.0b1/browser/app/profile/firefox.js
@@ -336,16 +336,27 @@
 #ifdef XP_MACOSX
   pref("browser.fullscreen.autohide", false);
 #else
   pref("browser.fullscreen.autohide", true);
 #endif
 
 pref("browser.overlink-delay", 80);
 
+#ifdef UNIX_BUT_NOT_MAC
+  pref("browser.urlbar.clickSelectsAll", false);
+#else
+  pref("browser.urlbar.clickSelectsAll", true);
+#endif
+#ifdef UNIX_BUT_NOT_MAC
+  pref("browser.urlbar.doubleClickSelectsAll", true);
+#else
+  pref("browser.urlbar.doubleClickSelectsAll", false);
+#endif
+
 pref("browser.theme.colorway-closet", true);
 
 // Whether expired built-in colorways themes that are active or retained
 // should be allowed to check for updates and be updated to an AMO hosted
 // theme with the same id (as part of preparing to remove from mozilla-central
 // all the expired built-in colorways themes, after existing users have been
 // migrated to colorways themes hosted on AMO).
 pref("browser.theme.colorway-migration", true);
--- Waterfox-G6.0b1/browser/components/search/content/searchbar.js
+++ Waterfox-G6.0b1/browser/components/search/content/searchbar.js
@@ -446,25 +446,26 @@
       this.destroy();
       while (this.firstChild) {
         this.firstChild.remove();
       }
     }
 
     /**
      * Determines if we should select all the text in the searchbar based on the
-     * searchbar state, and whether the selection is empty.
+     * clickSelectsAll pref, searchbar state, and whether the selection is empty.
      */
     _maybeSelectAll() {
       if (
         !this._preventClickSelectsAll &&
+	UrlbarPrefs.get("clickSelectsAll") &&
         document.activeElement == this._textbox &&
         this._textbox.selectionStart == this._textbox.selectionEnd
       ) {
-        this.select();
+        this._textbox.editor.selectAll();
       }
     }
 
     _setupEventListeners() {
       this.addEventListener("click", event => {
         this._maybeSelectAll();
       });
 
@@ -559,16 +560,21 @@
         // Hide popup when icon is clicked while popup is open
         if (isIconClick && this.textbox.popup.popupOpen) {
           this.textbox.popup.closePopup();
         } else if (isIconClick || this._textbox.value) {
           // Open the suggestions whenever clicking on the search icon or if there
           // is text in the textbox.
           this.openSuggestionsPanel(true);
         }
+
+        if (event.detail == 2 && UrlbarPrefs.get("doubleClickSelectsAll")) {
+          this._textbox.editor.selectAll();
+          event.preventDefault();
+        }
       });
     }
 
     _setupTextboxEventListeners() {
       this.textbox.addEventListener("input", event => {
         this.textbox.popup.removeAttribute("showonlysettings");
       });
 
--- Waterfox-G6.0b1/browser/components/urlbar/tests/browser/browser_doubleClickSelectsAll.js
+++ Waterfox-G6.0b1/browser/components/urlbar/tests/browser/browser_doubleClickSelectsAll.js
@@ -0,0 +1,45 @@
+/* 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/. */
+
+function doubleClick(target) {
+  let promise = BrowserTestUtils.waitForEvent(target, "dblclick");
+  EventUtils.synthesizeMouseAtCenter(
+    target,
+    { clickCount: 1 },
+    target.ownerGlobal
+  );
+  EventUtils.synthesizeMouseAtCenter(
+    target,
+    { clickCount: 2 },
+    target.ownerGlobal
+  );
+  return promise;
+}
+
+add_task(async function() {
+  await SpecialPowers.pushPrefEnv({
+    set: [
+      ["browser.urlbar.clickSelectsAll", false],
+      ["browser.urlbar.doubleClickSelectsAll", true],
+    ],
+  });
+
+  let url = "about:mozilla";
+  let win = await BrowserTestUtils.openNewBrowserWindow();
+  await BrowserTestUtils.openNewForegroundTab({ gBrowser: win.gBrowser, url });
+
+  await doubleClick(win.gURLBar.inputField);
+  is(
+    win.gURLBar.selectionStart,
+    0,
+    "Selection should start at the beginning of the urlbar value"
+  );
+  is(
+    win.gURLBar.selectionEnd,
+    url.length,
+    "Selection should end at the end of the urlbar value"
+  );
+
+  win.close();
+});
--- Waterfox-G6.0b1/browser/components/urlbar/tests/browser/browser.ini
+++ Waterfox-G6.0b1/browser/components/urlbar/tests/browser/browser.ini
@@ -110,16 +110,17 @@
 [browser_customizeMode.js]
 [browser_cutting.js]
 [browser_decode.js]
 [browser_delete.js]
 [browser_deleteAllText.js]
 [browser_display_selectedAction_Extensions.js]
 [browser_dns_first_for_single_words.js]
 skip-if = verify && os == 'linux' # Bug 1581635
+[browser_doubleClickSelectsAll.js]
 [browser_downArrowKeySearch.js]
 https_first_disabled = true
 [browser_dragdropURL.js]
 [browser_dynamicResults.js]
 https_first_disabled = true
 support-files =
   dynamicResult0.css
   dynamicResult1.css
--- Waterfox-G6.0b1/browser/components/urlbar/tests/browser/browser_retainedResultsOnFocus.js
+++ Waterfox-G6.0b1/browser/components/urlbar/tests/browser/browser_retainedResultsOnFocus.js
@@ -66,17 +66,20 @@
   info("Focus with the mouse.");
   promiseState = checkPanelStatePersists(win, false);
   EventUtils.synthesizeMouseAtCenter(win.gURLBar.inputField, {}, win);
   await promiseState;
 }
 
 add_setup(async function () {
   await SpecialPowers.pushPrefEnv({
-    set: [["browser.urlbar.autoFill", true]],
+    set: [
+	["browser.urlbar.autoFill", true],
+	["browser.urlbar.clickSelectsAll", true]
+    ],
   });
   // Add some history for the empty panel and autofill.
   await PlacesTestUtils.addVisits([
     {
       uri: "https://example.com/",
       transition: PlacesUtils.history.TRANSITIONS.TYPED,
     },
     {
--- Waterfox-G6.0b1/browser/components/urlbar/tests/browser/browser_urlbar_selection.js
+++ Waterfox-G6.0b1/browser/components/urlbar/tests/browser/browser_urlbar_selection.js
@@ -57,103 +57,98 @@
     toX,
     toY,
     { type: "mouseup" },
     target.ownerGlobal
   );
   return promise;
 }
 
-function resetPrimarySelection(val = "") {
-  if (
-    Services.clipboard.isClipboardTypeSupported(
-      Services.clipboard.kSelectionClipboard
-    )
-  ) {
-    // Reset the clipboard.
-    clipboardHelper.copyStringToClipboard(
-      val,
-      Services.clipboard.kSelectionClipboard
-    );
-  }
-}
-
-function checkPrimarySelection(expectedVal = "") {
-  if (
-    Services.clipboard.isClipboardTypeSupported(
-      Services.clipboard.kSelectionClipboard
-    )
-  ) {
-    let primaryAsText = SpecialPowers.getClipboardData(
-      "text/plain",
-      SpecialPowers.Ci.nsIClipboard.kSelectionClipboard
-    );
-    Assert.equal(primaryAsText, expectedVal);
-  }
-}
-
 add_setup(async function () {
+  SpecialPowers.pushPrefEnv({
+    set: [["browser.urlbar.clickSelectsAll", true]],
+  });
+
   // On macOS, we must "warm up" the Urlbar to get the first test to pass.
   gURLBar.value = "";
   await click(gURLBar.inputField);
   gURLBar.blur();
 });
 
 add_task(async function leftClickSelectsAll() {
-  resetPrimarySelection();
   gURLBar.value = exampleSearch;
   await click(gURLBar.inputField);
   Assert.equal(
     gURLBar.selectionStart,
     0,
     "The entire search term should be selected."
   );
   Assert.equal(
     gURLBar.selectionEnd,
     exampleSearch.length,
     "The entire search term should be selected."
   );
   gURLBar.blur();
-  checkPrimarySelection();
 });
 
 add_task(async function leftClickSelectsUrl() {
-  resetPrimarySelection();
   gURLBar.value = exampleUrl;
   await click(gURLBar.inputField);
   Assert.equal(gURLBar.selectionStart, 0, "The entire url should be selected.");
   Assert.equal(
     gURLBar.selectionEnd,
     exampleUrl.length,
     "The entire url should be selected."
   );
   gURLBar.blur();
-  checkPrimarySelection();
+});
+
+// Test to ensure that the doubleClickSelectsAll pref does not interfere with
+// single click behaviour (Double CSA itself is tested in
+// urlbar/tests/browser_doubleClickSelectsAll.js).
+add_task(async function bothPrefsEnabled() {
+  Services.prefs.setBoolPref("browser.urlbar.doubleClickSelectsAll", true);
+  gURLBar.value = exampleSearch;
+  await click(gURLBar.inputField);
+  Assert.equal(
+    gURLBar.selectionStart,
+    0,
+    "The entire search term should be selected."
+  );
+  Assert.equal(
+    gURLBar.selectionEnd,
+    exampleSearch.length,
+    "The entire search term should be selected."
+  );
+  gURLBar.blur();
+  Services.prefs.clearUserPref("browser.urlbar.doubleClickSelectsAll");
 });
 
 add_task(async function rightClickSelectsAll() {
+  // The text should be selected even when the pref is disabled.
+  await SpecialPowers.pushPrefEnv({
+    set: [["browser.urlbar.clickSelectsAll", false]],
+  });
+
+
   gURLBar.inputField.focus();
   gURLBar.value = exampleUrl;
 
   // Remove the selection so the focus() call above doesn't influence the test.
   gURLBar.selectionStart = gURLBar.selectionEnd = 0;
 
-  resetPrimarySelection();
-
   await openContextMenu(gURLBar.inputField);
 
   Assert.equal(gURLBar.selectionStart, 0, "The entire URL should be selected.");
   Assert.equal(
     gURLBar.selectionEnd,
     exampleUrl.length,
     "The entire URL should be selected."
   );
 
-  checkPrimarySelection();
-
   let contextMenu = gURLBar.querySelector("moz-input-box").menupopup;
 
   // While the context menu is open, test the "Select All" button.
   let contextMenuItem = contextMenu.firstElementChild;
   while (
     contextMenuItem.nextElementSibling &&
     contextMenuItem.getAttribute("cmd") != "cmd_selectAll"
   ) {
@@ -181,106 +176,90 @@
   Assert.equal(
     gURLBar.selectionEnd,
     exampleUrl.length,
     "The entire URL should be selected after clicking selectAll button."
   );
 
   gURLBar.querySelector("moz-input-box").menupopup.hidePopup();
   gURLBar.blur();
-  checkPrimarySelection(gURLBar.value);
   await SpecialPowers.popPrefEnv();
 });
 
 add_task(async function contextMenuDoesNotCancelSelection() {
   gURLBar.inputField.focus();
   gURLBar.value = exampleUrl;
 
   gURLBar.selectionStart = 3;
   gURLBar.selectionEnd = 7;
 
-  resetPrimarySelection();
-
   await openContextMenu(gURLBar.inputField);
 
   Assert.equal(
     gURLBar.selectionStart,
     3,
     "The selection should not have changed."
   );
   Assert.equal(
     gURLBar.selectionEnd,
     7,
     "The selection should not have changed."
   );
 
   gURLBar.querySelector("moz-input-box").menupopup.hidePopup();
   gURLBar.blur();
-  checkPrimarySelection();
 });
 
 add_task(async function dragSelect() {
-  resetPrimarySelection();
   gURLBar.value = exampleSearch.repeat(10);
   // Drags from an artibrary offset of 30 to test for bug 1562145: that the
   // selection does not start at the beginning.
   await drag(gURLBar.inputField, 30, 0, 60, 0);
   Assert.greater(
     gURLBar.selectionStart,
     0,
     "Selection should not start at the beginning of the string."
   );
 
-  let selectedVal = gURLBar.value.substring(
-    gURLBar.selectionStart,
-    gURLBar.selectionEnd
-  );
   gURLBar.blur();
-  checkPrimarySelection(selectedVal);
 });
 
 /**
  * Testing for bug 1571018: that the entire Urlbar isn't selected when the
  * Urlbar is dragged following a selectsAll event then a blur.
  */
 add_task(async function dragAfterSelectAll() {
-  resetPrimarySelection();
   gURLBar.value = exampleSearch.repeat(10);
   await click(gURLBar.inputField);
   Assert.equal(
     gURLBar.selectionStart,
     0,
     "The entire search term should be selected."
   );
   Assert.equal(
     gURLBar.selectionEnd,
     exampleSearch.repeat(10).length,
     "The entire search term should be selected."
   );
 
   gURLBar.blur();
-  checkPrimarySelection();
 
   // The offset of 30 is arbitrary.
   await drag(gURLBar.inputField, 30, 0, 60, 0);
 
   Assert.notEqual(
     gURLBar.selectionStart,
     0,
     "Only part of the search term should be selected."
   );
   Assert.notEqual(
     gURLBar.selectionEnd,
     exampleSearch.repeat(10).length,
     "Only part of the search term should be selected."
   );
-
-  checkPrimarySelection(
-    gURLBar.value.substring(gURLBar.selectionStart, gURLBar.selectionEnd)
-  );
 });
 
 /**
  * Testing for bug 1571018: that the entire Urlbar is selected when the Urlbar
  * is refocused following a partial text selection then a blur.
  */
 add_task(async function selectAllAfterDrag() {
   gURLBar.value = exampleSearch;
--- Waterfox-G6.0b1/browser/components/urlbar/UrlbarInput.sys.mjs
+++ Waterfox-G6.0b1/browser/components/urlbar/UrlbarInput.sys.mjs
@@ -3161,26 +3161,29 @@
     if (this.getAttribute("pageproxystate") == "valid") {
       this.value = "";
       this.setPageProxyState("invalid", true);
     }
   }
 
   /**
    * Determines if we should select all the text in the Urlbar based on the
-   *  Urlbar state, and whether the selection is empty.
+   *  clickSelectsAll pref, Urlbar state, and whether the selection is empty.
+   *  @param {boolean} [ignoreClickSelectsAllPref]
+   * 	     If true, the browser.urlbar.clickSelectsAll pref will be ignored.
    */
-  _maybeSelectAll() {
+  _maybeSelectAll(ignoreClickSelectsAllPref = false) {
     if (
       !this._preventClickSelectsAll &&
+      (ignoreClickSelectsAllPref || UrlbarPrefs.get("clickSelectsAll")) &&
       this._compositionState != lazy.UrlbarUtils.COMPOSITION.COMPOSING &&
       this.document.activeElement == this.inputField &&
       this.inputField.selectionStart == this.inputField.selectionEnd
     ) {
-      this.select();
+      this.editor.selectAll();
     }
   }
 
   // Event handlers below.
 
   _on_command(event) {
     // Something is executing a command, likely causing a focus change. This
     // should not be recorded as an abandonment. If the user is selecting a
@@ -3299,17 +3302,19 @@
   _on_contextmenu(event) {
     this.addSearchEngineHelper.refreshContextMenu(event);
 
     // Context menu opened via keyboard shortcut.
     if (!event.button) {
       return;
     }
 
-    this._maybeSelectAll();
+    // If the user right clicks, we select all regardless of the value of
+    // the browser.urlbar.clickSelectsAll pref.
+    this._maybeSelectAll(/* ignoreClickSelectsAllPref */ event.button == 2);
   }
 
   _on_focus(event) {
     if (!this._hideFocus) {
       this.setAttribute("focused", "true");
     }
 
     // When the search term matches the SERP, the URL bar is in a valid
@@ -3338,17 +3343,17 @@
         this.inputField.value = this._focusUntrimmedValue =
           this._untrimmedValue;
       }
     }
 
     if (this.focusedViaMousedown) {
       this.view.autoOpen({ event });
     } else if (this.inputField.hasAttribute("refocused-by-panel")) {
-      this._maybeSelectAll();
+      this._maybeSelectAll(true);
     }
 
     this._updateUrlTooltip();
     this.formatValue();
 
     // Hide popup notifications, to reduce visual noise.
     if (
       this.getAttribute("pageproxystate") != "valid" &&
@@ -3399,17 +3404,20 @@
         }
 
         // Clear any previous selection unless we are focused, to ensure it
         // doesn't affect drag selection.
         if (this.focusedViaMousedown) {
           this.inputField.setSelectionRange(0, 0);
         }
 
-        if (event.target.id == SEARCH_BUTTON_ID) {
+        if (event.detail == 2 && UrlbarPrefs.get("doubleClickSelectsAll")) {
+          this.editor.selectAll();
+          event.preventDefault();
+        } else if (event.target.id == SEARCH_BUTTON_ID) {
           this._preventClickSelectsAll = true;
           this.search(lazy.UrlbarTokenizer.RESTRICT.SEARCH);
         } else {
           // Do not suppress the focus border if we are already focused. If we
           // did, we'd hide the focus border briefly then show it again if the
           // user has Top Sites disabled, creating a flashing effect.
           this.view.autoOpen({
             event,
--- Waterfox-G6.0b1/browser/components/urlbar/UrlbarPrefs.sys.mjs
+++ Waterfox-G6.0b1/browser/components/urlbar/UrlbarPrefs.sys.mjs
@@ -63,16 +63,21 @@
   // autofilled even if the user hasn't actually visited them.
   ["autoFill.searchEngines", false],
 
   // Affects the frecency threshold of the autofill algorithm.  The threshold is
   // the mean of all origin frecencies plus one standard deviation multiplied by
   // this value.  See UrlbarProviderPlaces.
   ["autoFill.stddevMultiplier", [0.0, "float"]],
 
+  // 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 best match results can be blocked. This pref is a fallback for the
   // Nimbus variable `bestMatchBlockingEnabled`.
   ["bestMatch.blockingEnabled", true],
 
   // Whether the best match feature is enabled.
   ["bestMatch.enabled", true],
 
   // Whether to show a link for using the search functionality provided by the
@@ -94,16 +99,21 @@
   // "heuristic" result).  We fetch it as fast as possible.
   ["delay", 50],
 
   // Some performance tests disable this because extending the urlbar needs
   // layout information that we can't get before the first paint. (Or we could
   // but this would mean flushing layout.)
   ["disableExtendForTests", false],
 
+  // If true, this optimizes for replacing the full URL rather than selecting a
+  // portion of it. This also copies the urlbar value to the selection
+  // clipboard on systems that support it.
+  ["doubleClickSelectsAll", false],
+
   // Ensure we use trailing dots for DNS lookups for single words that could
   // be hosts.
   ["dnsResolveFullyQualifiedNames", true],
 
   // Controls when to DNS resolve single word search strings, after they were
   // searched for. If the string is resolved as a valid host, show a
   // "Did you mean to go to 'host'" prompt.
   // 0 - never resolve; 1 - use heuristics (default); 2 - always resolve
--- Waterfox-G6.0b1/modules/libpref/init/all.js
+++ Waterfox-G6.0b1/modules/libpref/init/all.js
@@ -2821,16 +2821,18 @@
   pref("network.protocol-handler.warn-external.file", false);
   pref("browser.drag_out_of_frame_style", 1);
 
   // Middle-mouse handling
   pref("middlemouse.paste", true);
   pref("middlemouse.openNewWindow", true);
   pref("middlemouse.scrollbarPosition", true);
 
+  pref("browser.urlbar.clickSelectsAll", false);
+
   // Tab focus model bit field:
   // 1 focuses text controls, 2 focuses other form elements, 4 adds links.
   // Leave this at the default, 7, to match mozilla1.0-era user expectations.
   // pref("accessibility.tabfocus", 1);
 
   pref("helpers.global_mime_types_file", "/etc/mime.types");
   pref("helpers.global_mailcap_file", "/etc/mailcap");
   pref("helpers.private_mime_types_file", "~/.mime.types");
