Bug 608669: Make chrome-document-global-created be properly dispatched on newly opened windows. r=jst a=blocker
authorJonas Sicking <jonas@sicking.cc>
Tue, 23 Nov 2010 00:50:56 -0800
changeset 58025 4b9ba5049e6619edba5854435c9e1a7c0033051c
parent 58024 42e9a38ecf63280ab20fa00e9c739207a1f29977
child 58026 e6dadb378a1a7ec25079718c4cf4247d4fbb7c66
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewersjst, blocker
bugs608669
milestone2.0b8pre
Bug 608669: Make chrome-document-global-created be properly dispatched on newly opened windows. r=jst a=blocker
docshell/test/chrome/Makefile.in
docshell/test/chrome/bug608669.xul
docshell/test/chrome/test_bug608669.xul
dom/base/nsGlobalWindow.cpp
dom/base/nsPIDOMWindow.h
--- a/docshell/test/chrome/Makefile.in
+++ b/docshell/test/chrome/Makefile.in
@@ -95,16 +95,18 @@ include $(topsrcdir)/config/rules.mk
 		bug364461_window.xul \
 		test_bug396519.xul \
 		bug396519_window.xul \
 		test_bug396649.xul \
 		bug396649_window.xul \
 		test_bug582176.xul \
 		bug582176_window.xul \
 		test_bug428288.html \
+		test_bug608669.xul \
+		bug608669.xul \
 		test_bug449778.xul \
 		bug449778_window.xul \
 		test_bug449780.xul \
 		bug449780_window.xul \
 		test_bug454235.xul \
 		bug454235-subframe.xul \
 		test_bug456980.xul \
 		$(NULL)
new file mode 100644
--- /dev/null
+++ b/docshell/test/chrome/bug608669.xul
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<window title="Mozilla Bug 608669 - Blank page"
+  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <description flex="1" value="This window is intentionally left blank"/>
+</window>
new file mode 100644
--- /dev/null
+++ b/docshell/test/chrome/test_bug608669.xul
@@ -0,0 +1,120 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=608669
+-->
+<window title="Mozilla Bug 608669"
+  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml">
+  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=608669"
+     target="_blank">Mozilla Bug 608669</a>
+  </body>
+
+  <!-- test code goes here -->
+  <script type="application/javascript"><![CDATA[
+
+var gOrigMaxTotalViewers = undefined;
+function setCachePref(enabled) {
+  var prefBranch = Components.classes["@mozilla.org/preferences-service;1"]
+                             .getService(Components.interfaces.nsIPrefBranch);
+  if (enabled) {
+    is(typeof gOrigMaxTotalViewers, "undefined", "don't double-enable bfcache");
+    prefBranch.setBoolPref("browser.sessionhistory.cache_subframes", true);
+    gOrigMaxTotalViewers = prefBranch.getIntPref("browser.sessionhistory.max_total_viewers");
+    prefBranch.setIntPref("browser.sessionhistory.max_total_viewers", 10);
+  }
+  else {
+    is(typeof gOrigMaxTotalViewers, "number", "don't double-disable bfcache");
+    prefBranch.setIntPref("browser.sessionhistory.max_total_viewers", gOrigMaxTotalViewers);
+    gOrigMaxTotalViewers = undefined;
+    try {
+      prefBranch.clearUserPref("browser.sessionhistory.cache_subframes");
+    } catch (e) { /* Pref didn't exist, meh */ }
+  }
+}
+
+
+
+    /** Test for Bug 608669 **/
+SimpleTest.waitForExplicitFinish();
+
+addLoadEvent(nextTest);
+
+gen = doTest();
+
+function nextTest() {
+  gen.next();
+}
+
+function doTest() {
+  var container = document.getElementById('container');
+
+  setCachePref(true);
+
+  var notificationCount = 0;
+  var observer = {
+    observe: function(aSubject, aTopic, aData) {
+      is(aTopic, "chrome-document-global-created",
+         "correct topic");
+      is(aData, "null",
+         "correct data");
+      notificationCount++;
+    }
+  };
+
+  var os = Components.classes["@mozilla.org/observer-service;1"].
+    getService(Components.interfaces.nsIObserverService);
+  os.addObserver(observer, "chrome-document-global-created", false);
+  os.addObserver(observer, "content-document-global-created", false);
+
+  is(notificationCount, 0, "initial count");
+
+  // create a new iframe
+  var iframe = document.createElement("iframe");
+  container.appendChild(iframe);
+  iframe.contentWindow.x = "y";
+  is(notificationCount, 1, "after created iframe");
+  
+  // Try loading in an iframe
+  iframe.setAttribute("src", "bug608669.xul");
+  iframe.onload = nextTest;
+  yield;
+  is(notificationCount, 1, "after first load");
+  is(iframe.contentWindow.x, "y", "reused window");
+
+  // Try loading again in an iframe
+  iframe.setAttribute("src", "bug608669.xul?x");
+  iframe.onload = nextTest;
+  yield;
+  is(notificationCount, 2, "after second load");
+  is("x" in iframe.contentWindow, false, "didn't reuse window");
+
+  // Open a new window using window.open
+  popup = window.open("bug608669.xul", "bug 608669",
+                      "chrome,width=600,height=600");
+  popup.onload = nextTest;
+  yield;
+  is(notificationCount, 3, "after window.open load");
+  popup.close();
+
+  setCachePref(false);
+  os.removeObserver(observer, "chrome-document-global-created");
+  os.removeObserver(observer, "content-document-global-created");
+  SimpleTest.finish();
+  yield;
+}
+
+
+
+  ]]></script>
+  <vbox id="container" flex="1">
+    <description>Below will an iframe be added</description>
+  </vbox>
+</window>
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -732,17 +732,17 @@ NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(n
 nsPIDOMWindow::nsPIDOMWindow(nsPIDOMWindow *aOuterWindow)
 : mFrameElement(nsnull), mDocShell(nsnull), mModalStateDepth(0),
   mRunningTimeout(nsnull), mMutationBits(0), mIsDocumentLoaded(PR_FALSE),
   mIsHandlingResizeEvent(PR_FALSE), mIsInnerWindow(aOuterWindow != nsnull),
   mMayHavePaintEventListener(PR_FALSE), mMayHaveTouchEventListener(PR_FALSE),
   mMayHaveAudioAvailableEventListener(PR_FALSE), mIsModalContentWindow(PR_FALSE),
   mIsActive(PR_FALSE), mInnerWindow(nsnull), mOuterWindow(aOuterWindow),
   // Make sure no actual window ends up with mWindowID == 0
-  mWindowID(++gNextWindowID)
+  mWindowID(++gNextWindowID), mHasNotifiedGlobalCreated(PR_FALSE)
  {}
 
 nsPIDOMWindow::~nsPIDOMWindow() {}
 
 //*****************************************************************************
 // nsOuterWindowProxy: Outer Window Proxy
 //*****************************************************************************
 
@@ -2200,19 +2200,33 @@ nsGlobalWindow::SetNewDocument(nsIDocume
     // Give the new inner window our chrome event handler (since it
     // doesn't have one).
     newInnerWindow->mChromeEventHandler = mChromeEventHandler;
   }
 
   mContext->GC();
   mContext->DidInitializeContext();
 
-  if (!aState && !reUseInnerWindow) {
-    nsContentUtils::AddScriptRunner(
-      NS_NewRunnableMethod(this, &nsGlobalWindow::DispatchDOMWindowCreated));
+  if (newInnerWindow && !newInnerWindow->mHasNotifiedGlobalCreated && mDoc) {
+    // We should probably notify. However if this is the, arguably bad,
+    // situation when we're creating a temporary non-chrome-about-blank
+    // document in a chrome docshell, don't notify just yet. Instead wait
+    // until we have a real chrome doc.
+    nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(mDocShell));
+    PRInt32 itemType = nsIDocShellTreeItem::typeContent;
+    if (treeItem) {
+      treeItem->GetItemType(&itemType);
+    }
+
+    if (itemType != nsIDocShellTreeItem::typeChrome ||
+        nsContentUtils::IsSystemPrincipal(mDoc->NodePrincipal())) {
+      newInnerWindow->mHasNotifiedGlobalCreated = PR_TRUE;
+      nsContentUtils::AddScriptRunner(
+        NS_NewRunnableMethod(this, &nsGlobalWindow::DispatchDOMWindowCreated));
+    }
   }
 
   return NS_OK;
 }
 
 void
 nsGlobalWindow::DispatchDOMWindowCreated()
 {
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -615,16 +615,20 @@ protected:
 
   // the element within the document that is currently focused when this
   // window is active
   nsCOMPtr<nsIContent> mFocusedNode;
 
   // A unique (as long as our 64-bit counter doesn't roll over) id for
   // this window.
   PRUint64 mWindowID;
+
+  // This is only used by the inner window. Set to true once we've sent
+  // the (chrome|content)-document-global-created notification.
+  PRPackedBool mHasNotifiedGlobalCreated;
 };
 
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsPIDOMWindow, NS_PIDOMWINDOW_IID)
 
 #ifdef _IMPL_NS_LAYOUT
 PopupControlState
 PushPopupControlState(PopupControlState aState, PRBool aForce);