Bug 707749 - For document.write move the navigator forward to the new inner window. r=jst
authorBlake Kaplan <mrbkap@gmail.com>
Wed, 28 Dec 2011 14:39:55 +0100
changeset 84670 e4dd116797dc0a9fd1060508d450e79e676aa70b
parent 84667 97df9986ccf449b0e16f81364287b9b3b9936567
child 84671 8a498f3bae5c23bd361850eeddba2646f8911590
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjst
bugs707749
milestone12.0a1
Bug 707749 - For document.write move the navigator forward to the new inner window. r=jst
dom/base/Navigator.cpp
dom/base/Navigator.h
dom/base/nsGlobalWindow.cpp
dom/tests/mochitest/bugs/Makefile.in
dom/tests/mochitest/bugs/test_bug707749.html
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1030,16 +1030,24 @@ Navigator::SizeOf() const
   // TODO: add SizeOf() to nsGeolocation, bug 674115.
   size += mGeolocation ? sizeof(*mGeolocation.get()) : 0;
   // TODO: add SizeOf() to nsDesktopNotificationCenter, bug 674116.
   size += mNotification ? sizeof(*mNotification.get()) : 0;
 
   return size;
 }
 
+void
+Navigator::SetWindow(nsPIDOMWindow *aInnerWindow)
+{
+  NS_ASSERTION(aInnerWindow->IsInnerWindow(),
+               "Navigator must get an inner window!");
+  mWindow = do_GetWeakReference(aInnerWindow);
+}
+
 } // namespace dom
 } // namespace mozilla
 
 nsresult
 NS_GetNavigatorUserAgent(nsAString& aUserAgent)
 {
   nsresult rv;
 
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -98,16 +98,21 @@ public:
   nsPIDOMWindow *GetWindow();
 
   void RefreshMIMEArray();
 
   static bool HasDesktopNotificationSupport();
 
   PRInt64 SizeOf() const;
 
+  /**
+   * For use during document.write where our inner window changes.
+   */
+  void SetWindow(nsPIDOMWindow *aInnerWindow);
+
 private:
   bool IsSmsAllowed() const;
   bool IsSmsSupported() const;
 
   nsRefPtr<nsMimeTypeArray> mMimeTypes;
   nsRefPtr<nsPluginArray> mPlugins;
   nsRefPtr<nsGeolocation> mGeolocation;
   nsRefPtr<nsDesktopNotificationCenter> mNotification;
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1983,17 +1983,17 @@ nsGlobalWindow::SetNewDocument(nsIDocume
     // instead.
     if (!JS_TransplantObject(cx, mJSObject, mJSObject)) {
       return NS_ERROR_FAILURE;
     }
   } else {
     if (aState) {
       newInnerWindow = wsh->GetInnerWindow();
       mInnerWindowHolder = wsh->GetInnerWindowHolder();
-      
+
       NS_ASSERTION(newInnerWindow, "Got a state without inner window");
     } else if (thisChrome) {
       newInnerWindow = new nsGlobalChromeWindow(this);
       isChrome = true;
     } else if (mIsModalContentWindow) {
       newInnerWindow = new nsGlobalModalWindow(this);
     } else {
       newInnerWindow = new nsGlobalWindow(this);
@@ -2033,16 +2033,25 @@ nsGlobalWindow::SetNewDocument(nsIDocume
 
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
     if (currentInner && currentInner->mJSObject) {
       bool termFuncSet = false;
 
       if (oldDoc == aDocument) {
+        // Move the navigator from the old inner window to the new one since
+        // this is a document.write. This is safe from a same-origin point of
+        // view because document.write can only be used by the same origin.
+        newInnerWindow->mNavigator = currentInner->mNavigator;
+        currentInner->mNavigator = nsnull;
+        if (newInnerWindow->mNavigator) {
+          newInnerWindow->mNavigator->SetWindow(newInnerWindow);
+        }
+
         // Suspend the current context's request before Pop() resumes the old
         // context's request.
         JSAutoSuspendRequest asr(cx);
 
         // Pop our context here so that we get the correct one for the
         // termination function.
         cxPusher.Pop();
 
--- a/dom/tests/mochitest/bugs/Makefile.in
+++ b/dom/tests/mochitest/bugs/Makefile.in
@@ -147,12 +147,13 @@ include $(topsrcdir)/config/rules.mk
 		test_bug698551.html \
 		test_window_bar.html \
 		file_window_bar.html \
 		test_resize_move_windows.html \
 		test_devicemotion_multiple_listeners.html \
 		devicemotion_outer.html \
 		devicemotion_inner.html \
 		test_bug698061.html \
+		test_bug707749.html \
 		$(NULL)
 
 libs:: 	$(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/bugs/test_bug707749.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=707749
+-->
+<head>
+  <title>Test for Bug 707749</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=707749 ">Mozilla Bug 707749 </a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 707749 **/
+SimpleTest.waitForExplicitFinish();
+function loaded() {
+    $('ifr').contentDocument.open();
+    $('ifr').contentDocument.close();
+    ok(true, "Don't throw an exception from contentDocument.open()");
+    SimpleTest.finish();
+}
+
+</script>
+<iframe id="ifr" onload="loaded()" src="data:text/html,<script>navigator</script>"></iframe>
+</pre>
+</body>
+</html>
+