Bug 1320061 - Add pref that allows users to copy unescaped URL from the URL bar r=mak77 draft
authorValentin Gosu <valentin.gosu@gmail.com>
Wed, 07 Dec 2016 10:18:46 -1000
changeset 454216 ff3d77e96732e415c5a6af942d0572de596a63bf
parent 454127 d7b6af32811bddcec10a47d24bd455a1ec1836fc
child 540656 e2262ba6e121e44d77e0f2657dc68a057e4884b2
push id39873
push usermak77@bonardo.net
push dateWed, 28 Dec 2016 16:31:04 +0000
reviewersmak77
bugs1320061
milestone53.0a1
Bug 1320061 - Add pref that allows users to copy unescaped URL from the URL bar r=mak77 MozReview-Commit-ID: CDnMnkqj8gW * * * Bug 1320061 - Add test for copying non-ascii URL from the urlbar MozReview-Commit-ID: 72jymxn6DJv
browser/app/profile/firefox.js
browser/base/content/test/urlbar/browser_urlbarCopying.js
browser/base/content/urlbarBindings.xml
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -313,16 +313,20 @@ pref("browser.urlbar.formatting.enabled"
 pref("browser.urlbar.trimURLs", true);
 
 #if defined(NIGHTLY_BUILD)
 pref("browser.urlbar.oneOffSearches", true);
 #else
 pref("browser.urlbar.oneOffSearches", false);
 #endif
 
+// If changed to true, copying the entire URL from the location bar will put the
+// human readable (percent-decoded) URL on the clipboard.
+pref("browser.urlbar.decodeURLsOnCopy", false);
+
 pref("browser.altClickSave", false);
 
 // Enable logging downloads operations to the Console.
 pref("browser.download.loglevel", "Error");
 
 // Number of milliseconds to wait for the http headers (and thus
 // the Content-Disposition filename) before giving up and falling back to
 // picking a filename without that info in hand so that the user sees some
--- a/browser/base/content/test/urlbar/browser_urlbarCopying.js
+++ b/browser/base/content/test/urlbar/browser_urlbarCopying.js
@@ -1,22 +1,32 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 const trimPref = "browser.urlbar.trimURLs";
 const phishyUserPassPref = "network.http.phishy-userpass-length";
+const decodeURLpref = "browser.urlbar.decodeURLsOnCopy";
+
+function toUnicode(input) {
+  let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
+                    .createInstance(Ci.nsIScriptableUnicodeConverter);
+  converter.charset = "UTF-8";
+
+  return converter.ConvertToUnicode(input);
+}
 
 function test() {
 
   let tab = gBrowser.selectedTab = gBrowser.addTab();
 
   registerCleanupFunction(function() {
     gBrowser.removeTab(tab);
     Services.prefs.clearUserPref(trimPref);
     Services.prefs.clearUserPref(phishyUserPassPref);
+    Services.prefs.clearUserPref(decodeURLpref);
     URLBarSetURI();
   });
 
   Services.prefs.setBoolPref(trimPref, true);
   Services.prefs.setIntPref(phishyUserPassPref, 32); // avoid prompting about phishing
 
   waitForExplicitFinish();
 
@@ -136,17 +146,27 @@ var tests = [
   },
   {
     copyVal: "<data:text/html,(>%C3%A9 %25P)",
     copyExpected: "data:text/html,("
   },
   {
     copyVal: "<data:text/html,(%C3%A9 %25P>)",
     copyExpected: "data:text/html,(%C3%A9 %25P",
-  }
+  },
+  {
+    setup: function() { Services.prefs.setBoolPref(decodeURLpref, true); },
+    loadURL: "http://example.com/%D0%B1%D0%B8%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D0%B8%D1%8F",
+    expectedURL: toUnicode("example.com/биография"),
+    copyExpected: toUnicode("http://example.com/биография")
+  },
+  {
+    copyVal: toUnicode("<example.com/би>ография"),
+    copyExpected: toUnicode("http://example.com/би")
+  },
 ];
 
 function nextTest() {
   let testCase = tests.shift();
   if (tests.length == 0)
     runTest(testCase, finish);
   else
     runTest(testCase, nextTest);
@@ -157,16 +177,20 @@ function runTest(testCase, cb) {
     if (testCase.setURL || testCase.loadURL) {
       gURLBar.valueIsTyped = !!testCase.setURL;
       is(gURLBar.textValue, testCase.expectedURL, "url bar value set");
     }
 
     testCopy(testCase.copyVal, testCase.copyExpected, cb);
   }
 
+  if (testCase.setup) {
+    testCase.setup();
+  }
+
   if (testCase.loadURL) {
     loadURL(testCase.loadURL, doCheck);
   } else {
     if (testCase.setURL)
       gURLBar.value = testCase.setURL;
     doCheck();
   }
 }
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -792,29 +792,27 @@ file, You can obtain one at http://mozil
             uri = uriFixup.createFixupURI(readerOriginalURL, Ci.nsIURIFixup.FIXUP_FLAG_NONE);
           }
 
           // Only copy exposable URIs
           try {
             uri = uriFixup.createExposableURI(uri);
           } catch (ex) {}
 
-          // If the entire URL is selected, just use the actual loaded URI.
-          if (inputVal == selectedVal) {
-            // ... but only if  isn't a javascript: or data: URI, since those
-            // are hard to read when encoded
-            if (!uri.schemeIs("javascript") && !uri.schemeIs("data")) {
-              selectedVal = uri.spec;
-            }
-
-            return selectedVal;
+          // If the entire URL is selected, just use the actual loaded URI,
+          // unless we want a decoded URI, or it's a data: or javascript: URI,
+          // since those are hard to read when encoded.
+          if (inputVal == selectedVal &&
+              !uri.schemeIs("javascript") && !uri.schemeIs("data") &&
+              !Services.prefs.getBoolPref("browser.urlbar.decodeURLsOnCopy")) {
+            return uri.spec;
           }
 
-          // Just the beginning of the URL is selected, check for a trimmed
-          // value
+          // Just the beginning of the URL is selected, or we want a decoded
+          // url. First check for a trimmed value.
           let spec = uri.spec;
           let trimmedSpec = this.trimValue(spec);
           if (spec != trimmedSpec) {
             // Prepend the portion that trimValue removed from the beginning.
             // This assumes trimValue will only truncate the URL at
             // the beginning or end (or both).
             let trimmedSegments = spec.split(trimmedSpec);
             selectedVal = trimmedSegments[0] + selectedVal;