Bug 668019 - prepend http:// to URL copy selection if URL has been selected (but not loaded) from location bar. r=gavin
authorDão Gottwald <dao@mozilla.com>
Tue, 20 Sep 2011 05:35:33 +0200
changeset 77178 575dcce289787d64b6ee6803b538d62210a38ce2
parent 77177 53cc8910cb1c947f2330aaca16c9476bd803fad6
child 77179 c0f7ee4b3358dc4b51ef2f3f01867098fa784cac
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewersgavin
bugs668019
milestone9.0a1
Bug 668019 - prepend http:// to URL copy selection if URL has been selected (but not loaded) from location bar. r=gavin
browser/base/content/browser.js
browser/base/content/test/browser_bug556061.js
browser/base/content/test/browser_urlbarCopying.js
browser/base/content/test/browser_urlbarTrimURLs.js
browser/base/content/urlbarBindings.xml
toolkit/content/widgets/autocomplete.xml
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2504,16 +2504,17 @@ function URLBarSetURI(aURI) {
       value = content.opener ? uri.spec : "";
     else
       value = losslessDecodeURI(uri);
 
     valid = (uri.spec != "about:blank");
   }
 
   gURLBar.value = value;
+  gURLBar.valueIsTyped = !valid;
   SetPageProxyState(valid ? "valid" : "invalid");
 }
 
 function losslessDecodeURI(aURI) {
   var value = aURI.spec;
   // Try to decode as UTF-8 if there's no encoding sequence that we would break.
   if (!/%25(?:3B|2F|3F|3A|40|26|3D|2B|24|2C|23)/i.test(value))
     try {
--- a/browser/base/content/test/browser_bug556061.js
+++ b/browser/base/content/test/browser_bug556061.js
@@ -58,16 +58,17 @@ function cleanup() {
   finish();
 }
 
 let tests = [
   {
     expected: testURL,
     setup: function() {
       gURLBar.value = testActionURL;
+      gURLBar.valueIsTyped = true;
       is(gURLBar.value, testActionURL, "gURLBar.value starts with correct value");
 
       // Focus the urlbar so we can select it all & copy
       gURLBar.focus();
       gURLBar.select();
       goDoCommand("cmd_copy");
     },
     success: function() {
@@ -98,16 +99,17 @@ let tests = [
       is(gURLBar.value, "", "gURLBar.value is now empty");
     }
   },
   {
     expected: testURL.substring(testURL.length - 10, testURL.length),
     setup: function() {
       // Reset urlbar value
       gURLBar.value = testActionURL;
+      gURLBar.valueIsTyped = true;
       // Sanity check that we have the right value
       is(gURLBar.value, testActionURL, "gURLBar.value starts with correct value");
 
       // Now just select part of the value & cut that.
       gURLBar.selectionStart = testURL.length - 10;
       gURLBar.selectionEnd = testURL.length;
       goDoCommand("cmd_cut");
     },
--- a/browser/base/content/test/browser_urlbarCopying.js
+++ b/browser/base/content/test/browser_urlbarCopying.js
@@ -121,18 +121,20 @@ function nextTest() {
   if (tests.length == 0)
     runTest(test, finish);
   else
     runTest(test, nextTest);
 }
 
 function runTest(test, cb) {
   function doCheck() {
-    if (test.setURL || test.loadURL)
+    if (test.setURL || test.loadURL) {
+      gURLBar.valueIsTyped = !!test.setURL;
       is(gURLBar.value, test.expectedURL, "url bar value set");
+    }
 
     testCopy(test.copyVal, test.copyExpected, cb);
   }
 
   if (test.loadURL) {
     loadURL(test.loadURL, doCheck);
   } else {
     if (test.setURL)
--- a/browser/base/content/test/browser_urlbarTrimURLs.js
+++ b/browser/base/content/test/browser_urlbarTrimURLs.js
@@ -1,14 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 function testVal(originalValue, targetValue) {
   gURLBar.value = originalValue;
+  gURLBar.valueIsTyped = false;
   is(gURLBar.value, targetValue || originalValue, "url bar value set");
 }
 
 function test() {
   const prefname = "browser.urlbar.trimURLs";
 
   gBrowser.selectedTab = gBrowser.addTab();
 
@@ -58,16 +59,17 @@ function test() {
 
   gBrowser.selectedBrowser.addEventListener("load", function () {
     gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
 
     is(gBrowser.currentURI.spec, "http://example.com/", "expected page should have loaded");
 
     testCopy("example.com", "http://example.com/", function () {
       SetPageProxyState("invalid");
+      gURLBar.valueIsTyped = true;
       testCopy("example.com", "example.com", finish);
     });
   }, true);
 
   gBrowser.loadURI("http://example.com/");
 }
 
 function testCopy(originalValue, targetValue, cb) {
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -180,16 +180,18 @@
           return returnValue;
         ]]></body>
       </method>
 
       <field name="_mayTrimURLs">true</field>
       <method name="trimValue">
         <parameter name="aURL"/>
         <body><![CDATA[
+          // This method must not modify the given URL such that calling
+          // nsIURIFixup::createFixupURI with the result will produce a different URI.
           return this._mayTrimURLs ? trimURL(aURL) : aURL;
         ]]></body>
       </method>
 
       <field name="_formattingEnabled">true</field>
       <method name="formatValue">
         <body><![CDATA[
           if (!this._formattingEnabled || this.focused)
@@ -492,23 +494,31 @@
       <method name="_getSelectedValueForClipboard">
         <body><![CDATA[
           // Grab the actual input field's value, not our value, which could include moz-action:
           var inputVal = this.inputField.value;
           var selectedVal = inputVal.substring(this.selectionStart, this.selectionEnd);
 
           // If the selection doesn't start at the beginning or URL bar is
           // modified, nothing else to do here.
-          if (this.getAttribute("pageproxystate") != "valid" || this.selectionStart > 0)
+          if (this.selectionStart > 0 || this.valueIsTyped)
             return selectedVal;
 
-          let uri = gBrowser.currentURI;
+          let uriFixup = Cc["@mozilla.org/docshell/urifixup;1"].getService(Ci.nsIURIFixup);
+
+          let uri;
+          try {
+            uri = uriFixup.createFixupURI(inputVal, Ci.nsIURIFixup.FIXUP_FLAG_NONE);
+          } catch (e) {}
+          if (!uri)
+            return selectedVal;
+
           // Only copy exposable URIs
           try {
-            uri = Cc["@mozilla.org/docshell/urifixup;1"].getService(Ci.nsIURIFixup).createExposableURI(uri);
+            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")) {
               // Parentheses are known to confuse third-party applications (bug 458565).
--- a/toolkit/content/widgets/autocomplete.xml
+++ b/toolkit/content/widgets/autocomplete.xml
@@ -260,16 +260,17 @@
             this.showHistoryPopup();
           else
             this.closePopup();
         ]]></setter>
       </property>
 
       <!-- =================== PUBLIC MEMBERS =================== -->
 
+      <field name="valueIsTyped">false</field>
       <property name="value">
         <getter><![CDATA[
           if (typeof this.onBeforeValueGet == "function") {
             var result = this.onBeforeValueGet();
             if (result)
               return result.value;
           }
           return this.inputField.value;
@@ -278,16 +279,17 @@
           this.mIgnoreInput = true;
 
           if (typeof this.onBeforeValueSet == "function")
             val = this.onBeforeValueSet(val);
 
           if (typeof this.trimValue == "function")
             val = this.trimValue(val);
 
+          this.valueIsTyped = false;
           this.inputField.value = val;
 
           if (typeof this.formatValue == "function")
             this.formatValue();
 
           this.mIgnoreInput = false;
           var event = document.createEvent('Events');
           event.initEvent('ValueChange', true, true);
@@ -554,16 +556,17 @@
         ]]></body>
       </method>
 
     </implementation>
 
     <handlers>
       <handler event="input"><![CDATA[
         if (!this.mIgnoreInput && this.mController.input == this) {
+          this.valueIsTyped = true;
           this.mController.handleText(true);
         }
         this.resetActionType();
       ]]></handler>
 
       <handler event="keypress" phase="capturing"
                action="return this.onKeyPress(event);"/>