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 331545 67cd0f4372e924d0d9e7bc8c56fc41015191b09e
parent 331544 f5f9a967030d8104686224579294d5aeafff8b5a
child 331546 08763e0e411fce69e74a49422af5ba9345bb1ad8
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws
bugs1199934
milestone48.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 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":