Bug 1199934 - page shouldn't be able to trap/revert the location bar by hash/replacestate changes, r=jaws
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Wed, 13 Apr 2016 19:32:45 +0100
changeset 317448 67cd0f4372e924d0d9e7bc8c56fc41015191b09e
parent 317447 f5f9a967030d8104686224579294d5aeafff8b5a
child 317449 08763e0e411fce69e74a49422af5ba9345bb1ad8
push id9480
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 17:12:58 +0000
treeherdermozilla-aurora@0d6a91c76a9e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws
bugs1199934
milestone48.0a1
Bug 1199934 - page shouldn't be able to trap/revert the location bar by hash/replacestate changes, r=jaws MozReview-Commit-ID: HsmmHsUtU0h
browser/base/content/tabbrowser.xml
browser/base/content/test/urlbar/browser.ini
browser/base/content/test/urlbar/browser_urlbar_locationchange_urlbar_edit_dos.js
browser/base/content/test/urlbar/file_urlbar_edit_dos.html
toolkit/content/browser-child.js
toolkit/modules/RemoteWebProgress.jsm
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -753,21 +753,21 @@
                   !!(aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT);
                 // If userTypedClear > 0, the document loaded correctly and we should be
                 // clearing the user typed value. We also need to clear the typed value
                 // if the document failed to load, to make sure the urlbar reflects the
                 // failed URI (particularly for SSL errors). However, don't clear the value
                 // if the error page's URI is about:blank, because that causes complete
                 // loss of urlbar contents for invalid URI errors (see bug 867957).
                 // Another reason to clear the userTypedValue is if this was an anchor
-                // navigation.
+                // navigation initiated by the user.
                 if (this.mBrowser.userTypedClear > 0 ||
                     ((aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE) &&
                      aLocation.spec != "about:blank") ||
-                     isSameDocument) {
+                     (isSameDocument && this.mBrowser.inLoadURI)) {
                   this.mBrowser.userTypedValue = null;
                 }
 
                 // If the browser was playing audio, we should remove the playing state.
                 if (this.mTab.hasAttribute("soundplaying") && !isSameDocument) {
                   this.mTab.removeAttribute("soundplaying");
                   this.mTabBrowser._tabAttrModified(this.mTab, ["soundplaying"]);
                 }
--- a/browser/base/content/test/urlbar/browser.ini
+++ b/browser/base/content/test/urlbar/browser.ini
@@ -1,7 +1,10 @@
 [browser_moz_action_link.js]
 [browser_urlbar_blanking.js]
 support-files =
   file_blank_but_not_blank.html
+[browser_urlbar_locationchange_urlbar_edit_dos.js]
+support-files =
+  file_urlbar_edit_dos.html
 [browser_urlbar_stop_pending.js]
 support-files =
   slow-page.sjs
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/urlbar/browser_urlbar_locationchange_urlbar_edit_dos.js
@@ -0,0 +1,41 @@
+"use strict";
+
+function* checkURLBarValueStays(browser) {
+  gURLBar.select();
+  EventUtils.synthesizeKey("a", {});
+  is(gURLBar.value, "a", "URL bar value should match after sending a key");
+  yield new Promise(resolve => {
+    let listener = {
+      onLocationChange(aWebProgress, aRequest, aLocation, aFlags) {
+        ok(aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT,
+           "Should only get a same document location change");
+        gBrowser.selectedBrowser.removeProgressListener(filter);
+        filter = null;
+        resolve();
+      },
+    };
+    let filter = Cc["@mozilla.org/appshell/component/browser-status-filter;1"]
+                     .createInstance(Ci.nsIWebProgress);
+    filter.addProgressListener(listener, Ci.nsIWebProgress.NOTIFY_ALL);
+    gBrowser.selectedBrowser.addProgressListener(filter);
+  });
+  is(gURLBar.value, "a", "URL bar should not have been changed by location changes.");
+}
+
+add_task(function*() {
+  yield BrowserTestUtils.withNewTab({
+    gBrowser,
+    url: "http://example.com/browser/browser/base/content/test/urlbar/file_urlbar_edit_dos.html"
+  }, function*(browser) {
+    yield ContentTask.spawn(browser, "", function() {
+      content.wrappedJSObject.dos_hash();
+    });
+    yield checkURLBarValueStays(browser);
+    yield ContentTask.spawn(browser, "", function() {
+      content.clearTimeout(content.wrappedJSObject.dos_timeout);
+      content.wrappedJSObject.dos_pushState();
+    });
+    yield checkURLBarValueStays(browser);
+  });
+});
+
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/urlbar/file_urlbar_edit_dos.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Try editing the URL bar</title>
+<meta http-equiv="Content-Type" content="text/html;charset=utf-8"></meta>
+</head>
+<body>
+<script>
+var dos_timeout = null;
+function dos_hash() {
+  dos_timeout = setTimeout(function() {
+    location.hash = "#";
+  }, 50);
+}
+
+function dos_pushState() {
+  dos_timeout = setTimeout(function() {
+    history.pushState({}, "Some title", "");
+  }, 50);
+}
+</script>
+</body>
+</html>
--- a/toolkit/content/browser-child.js
+++ b/toolkit/content/browser-child.js
@@ -125,19 +125,19 @@ var WebProgressListener = {
     // It's possible that this state change was triggered by
     // loading an internal error page, for which the parent
     // will want to know some details, so we'll update it with
     // the documentURI.
     if (aWebProgress && aWebProgress.isTopLevel) {
       json.documentURI = content.document.documentURIObject.spec;
       json.charset = content.document.characterSet;
       json.mayEnableCharacterEncodingMenu = docShell.mayEnableCharacterEncodingMenu;
+      json.inLoadURI = WebNavigation.inLoadURI;
     }
 
-    json.inLoadURI = WebNavigation.inLoadURI;
     this._send("Content:StateChange", json, objects);
   },
 
   onProgressChange: function onProgressChange(aWebProgress, aRequest, aCurSelf, aMaxSelf, aCurTotal, aMaxTotal) {
     let json = this._setupJSON(aWebProgress, aRequest);
     let objects = this._setupObjects(aWebProgress, aRequest);
 
     json.curSelf = aCurSelf;
@@ -166,16 +166,17 @@ var WebProgressListener = {
 
     if (aWebProgress && aWebProgress.isTopLevel) {
       json.documentURI = content.document.documentURIObject.spec;
       json.title = content.document.title;
       json.charset = content.document.characterSet;
       json.mayEnableCharacterEncodingMenu = docShell.mayEnableCharacterEncodingMenu;
       json.principal = content.document.nodePrincipal;
       json.synthetic = content.document.mozSyntheticDocument;
+      json.inLoadURI = WebNavigation.inLoadURI;
 
       if (AppConstants.MOZ_CRASHREPORTER && CrashReporter.enabled) {
         let uri = aLocationURI.clone();
         try {
           // If the current URI contains a username/password, remove it.
           uri.userPass = "";
         } catch (ex) { /* Ignore failures on about: URIs. */ }
         CrashReporter.annotateCrashReport("URL", uri.spec);
--- a/toolkit/modules/RemoteWebProgress.jsm
+++ b/toolkit/modules/RemoteWebProgress.jsm
@@ -215,17 +215,19 @@ RemoteWebProgressManager.prototype = {
       request = new RemoteWebProgressRequest(json.requestURI,
                                              json.originalRequestURI,
                                              objects.request);
     }
 
     if (isTopLevel) {
       this._browser._contentWindow = objects.contentWindow;
       this._browser._documentContentType = json.documentContentType;
-      this._browser.inLoadURI = json.inLoadURI;
+      if (typeof json.inLoadURI != "undefined") {
+        this._browser.inLoadURI = json.inLoadURI;
+      }
       if (json.charset) {
         this._browser._characterSet = json.charset;
         this._browser._mayEnableCharacterEncodingMenu = json.mayEnableCharacterEncodingMenu;
       }
     }
 
     switch (aMessage.name) {
     case "Content:StateChange":