Bug 1093611 - AnchorElement.hash should be the encoded version of the href attribute's fragment r=smaug
☠☠ backed out by f81889645445 ☠ ☠
authorValentin Gosu <valentin.gosu@gmail.com>
Wed, 12 Nov 2014 03:14:04 +0200
changeset 217350 10a3cbe9e42f6c86834aed663bf07cbc3e31b901
parent 217349 feea8b1ea75fb079ea238c285a8e2399d01a080b
child 217351 3a3c05f46c5e9dc3ee529e701f212c785378b9fb
push id52273
push uservalentin.gosu@gmail.com
push dateTue, 25 Nov 2014 08:35:53 +0000
treeherdermozilla-inbound@3a3c05f46c5e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1093611
milestone36.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 1093611 - AnchorElement.hash should be the encoded version of the href attribute's fragment r=smaug
dom/base/Link.cpp
dom/base/URL.cpp
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
dom/base/nsLocation.cpp
modules/libpref/init/all.js
--- a/dom/base/Link.cpp
+++ b/dom/base/Link.cpp
@@ -436,18 +436,20 @@ Link::GetHash(nsAString &_hash, ErrorRes
     // Do not throw!  Not having a valid URI should result in an empty
     // string.
     return;
   }
 
   nsAutoCString ref;
   nsresult rv = uri->GetRef(ref);
   if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
-    NS_UnescapeURL(ref); // XXX may result in random non-ASCII bytes!
     _hash.Assign(char16_t('#'));
+    if (!nsContentUtils::ShouldEncodeURLHash()) {
+      NS_UnescapeURL(ref); // XXX may result in random non-ASCII bytes!
+    }
     AppendUTF8toUTF16(ref, _hash);
   }
 }
 
 void
 Link::ResetLinkState(bool aNotify, bool aHasHref)
 {
   nsLinkState defaultState;
--- a/dom/base/URL.cpp
+++ b/dom/base/URL.cpp
@@ -509,18 +509,20 @@ URL::SetSearchParams(URLSearchParams& aS
 void
 URL::GetHash(nsString& aHash, ErrorResult& aRv) const
 {
   aHash.Truncate();
 
   nsAutoCString ref;
   nsresult rv = mURI->GetRef(ref);
   if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
-    NS_UnescapeURL(ref); // XXX may result in random non-ASCII bytes!
     aHash.Assign(char16_t('#'));
+    if (!nsContentUtils::ShouldEncodeURLHash()) {
+      NS_UnescapeURL(ref); // XXX may result in random non-ASCII bytes!
+    }
     AppendUTF8toUTF16(ref, aHash);
   }
 }
 
 void
 URL::SetHash(const nsAString& aHash, ErrorResult& aRv)
 {
   mURI->SetRef(NS_ConvertUTF16toUTF8(aHash));
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -231,16 +231,17 @@ nsString* nsContentUtils::sModifierSepar
 
 bool nsContentUtils::sInitialized = false;
 bool nsContentUtils::sIsFullScreenApiEnabled = false;
 bool nsContentUtils::sTrustedFullScreenOnly = true;
 bool nsContentUtils::sFullscreenApiIsContentOnly = false;
 bool nsContentUtils::sIsPerformanceTimingEnabled = false;
 bool nsContentUtils::sIsResourceTimingEnabled = false;
 bool nsContentUtils::sIsExperimentalAutocompleteEnabled = false;
+bool nsContentUtils::sEncodeURLHash = true;
 
 uint32_t nsContentUtils::sHandlingInputTimeout = 1000;
 
 nsHtml5StringParser* nsContentUtils::sHTMLFragmentParser = nullptr;
 nsIParser* nsContentUtils::sXMLFragmentParser = nullptr;
 nsIFragmentContentSink* nsContentUtils::sXMLFragmentSink = nullptr;
 bool nsContentUtils::sFragmentParsingActive = false;
 
@@ -508,16 +509,19 @@ nsContentUtils::Init()
                                "dom.enable_performance", true);
 
   Preferences::AddBoolVarCache(&sIsResourceTimingEnabled,
                                "dom.enable_resource_timing", true);
 
   Preferences::AddBoolVarCache(&sIsExperimentalAutocompleteEnabled,
                                "dom.forms.autocomplete.experimental", false);
 
+  Preferences::AddBoolVarCache(&sEncodeURLHash,
+                               "dom.url.encode_hash", true);
+
   Preferences::AddUintVarCache(&sHandlingInputTimeout,
                                "dom.event.handling-user-input-time-limit",
                                1000);
 
 #if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
   Preferences::AddBoolVarCache(&sDOMWindowDumpEnabled,
                                "browser.dom.window.dump.enabled");
 #endif
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -1848,16 +1848,21 @@ public:
   /*
    * Returns true if the performance timing APIs are enabled.
    */
   static bool IsResourceTimingEnabled()
   {
     return sIsResourceTimingEnabled;
   }
 
+  static bool ShouldEncodeURLHash()
+  {
+    return sEncodeURLHash;
+  }
+
   /**
    * Returns true if the doc tree branch which contains aDoc contains any
    * plugins which we don't control event dispatch for, i.e. do any plugins
    * in the same tab as this document receive key events outside of our
    * control? This always returns false on MacOSX.
    */
   static bool HasPluginWithUncontrolledEventDispatch(nsIDocument* aDoc);
 
@@ -2299,16 +2304,17 @@ private:
   static bool sAllowXULXBL_for_file;
   static bool sIsFullScreenApiEnabled;
   static bool sTrustedFullScreenOnly;
   static bool sFullscreenApiIsContentOnly;
   static uint32_t sHandlingInputTimeout;
   static bool sIsPerformanceTimingEnabled;
   static bool sIsResourceTimingEnabled;
   static bool sIsExperimentalAutocompleteEnabled;
+  static bool sEncodeURLHash;
 
   static nsHtml5StringParser* sHTMLFragmentParser;
   static nsIParser* sXMLFragmentParser;
   static nsIFragmentContentSink* sXMLFragmentSink;
 
   /**
    * True if there's a fragment parser activation on the stack.
    */
--- a/dom/base/nsLocation.cpp
+++ b/dom/base/nsLocation.cpp
@@ -293,38 +293,46 @@ nsLocation::GetHash(nsAString& aHash)
   if (NS_FAILED(rv) || !uri) {
     return rv;
   }
 
   nsAutoCString ref;
   nsAutoString unicodeRef;
 
   rv = uri->GetRef(ref);
-  if (NS_SUCCEEDED(rv)) {
-    nsCOMPtr<nsITextToSubURI> textToSubURI(
-        do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv));
 
+  if (!nsContentUtils::ShouldEncodeURLHash()) {
     if (NS_SUCCEEDED(rv)) {
-      nsAutoCString charset;
-      uri->GetOriginCharset(charset);
-        
-      rv = textToSubURI->UnEscapeURIForUI(charset, ref, unicodeRef);
+      nsCOMPtr<nsITextToSubURI> textToSubURI(
+          do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv));
+
+      if (NS_SUCCEEDED(rv)) {
+        nsAutoCString charset;
+        uri->GetOriginCharset(charset);
+
+        rv = textToSubURI->UnEscapeURIForUI(charset, ref, unicodeRef);
+      }
+
+      if (NS_FAILED(rv)) {
+        // Oh, well.  No intl here!
+        NS_UnescapeURL(ref);
+        CopyASCIItoUTF16(ref, unicodeRef);
+        rv = NS_OK;
+      }
     }
-      
-    if (NS_FAILED(rv)) {
-      // Oh, well.  No intl here!
-      NS_UnescapeURL(ref);
-      CopyASCIItoUTF16(ref, unicodeRef);
-      rv = NS_OK;
+
+    if (NS_SUCCEEDED(rv) && !unicodeRef.IsEmpty()) {
+      aHash.Assign(char16_t('#'));
+      aHash.Append(unicodeRef);
     }
-  }
-
-  if (NS_SUCCEEDED(rv) && !unicodeRef.IsEmpty()) {
-    aHash.Assign(char16_t('#'));
-    aHash.Append(unicodeRef);
+  } else { // URL Hash should be encoded
+    if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
+      aHash.Assign(char16_t('#'));
+      AppendASCIItoUTF16(ref, aHash);
+    }
   }
 
   if (aHash == mCachedHash) {
     // Work around ShareThis stupidly polling location.hash every
     // 5ms all the time by handing out the same exact string buffer
     // we handed out last time.
     aHash = mCachedHash;
   } else {
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -156,16 +156,19 @@ pref("dom.keyboardevent.code.enabled", t
 #endif
 
 // Whether the WebCrypto API is enabled
 pref("dom.webcrypto.enabled", true);
 
 // Whether the UndoManager API is enabled
 pref("dom.undo_manager.enabled", false);
 
+// Whether URL,nsLocation,Link::GetHash should be percent encoded.
+pref("dom.url.encode_hash", true);
+
 // Whether to run add-on code in different compartments from browser code. This
 // causes a separate compartment for each (addon, global) combination, which may
 // significantly increase the number of compartments in the system.
 #ifdef NIGHTLY_BUILD
 pref("dom.compartment_per_addon", true);
 #else
 pref("dom.compartment_per_addon", false);
 #endif