diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp index cbc543b3c4b..e318f8204ba 100644 --- a/mozilla/docshell/base/nsDocShell.cpp +++ b/mozilla/docshell/base/nsDocShell.cpp @@ -5591,7 +5591,9 @@ nsDocShell::RestoreFromHistory() if (shell) shell->Thaw(); - return NS_OK; + nsCOMPtr win18 = do_QueryInterface(privWin); + NS_ENSURE_STATE(win18); + return win18->FireDelayedDOMEvents(); } NS_IMETHODIMP diff --git a/mozilla/dom/public/base/nsPIDOMWindow.h b/mozilla/dom/public/base/nsPIDOMWindow.h index 11861943134..7406696a237 100644 --- a/mozilla/dom/public/base/nsPIDOMWindow.h +++ b/mozilla/dom/public/base/nsPIDOMWindow.h @@ -333,8 +333,8 @@ protected: }; #define NS_PIDOMWINDOW_MOZILLA_1_8_BRANCH_IID \ -{ 0x9cb71447, 0x62c7, 0x423a, \ - { 0x91, 0xca, 0x71, 0x8a, 0x8c, 0xeb, 0xda, 0x76 } } +{ 0x7bf31d9e, 0xd17b, 0x47dc, \ + { 0xa6, 0xe4, 0x5f, 0xae, 0x29, 0x94, 0xf1, 0x07 } } class nsPIDOMWindow_MOZILLA_1_8_BRANCH : public nsPIDOMWindow { @@ -351,6 +351,12 @@ public: virtual void SetOpenerWindow(nsIDOMWindowInternal *aOpener, PRBool aOriginalOpener) = 0; + /** + * Fire any DOM notification events related to things that happened while + * the window was frozen. + */ + virtual nsresult FireDelayedDOMEvents() = 0; + protected: nsPIDOMWindow_MOZILLA_1_8_BRANCH(nsPIDOMWindow *aOuterWindow) : nsPIDOMWindow(aOuterWindow) diff --git a/mozilla/dom/src/base/nsGlobalWindow.cpp b/mozilla/dom/src/base/nsGlobalWindow.cpp index a846ad6ca8c..829d640d87b 100644 --- a/mozilla/dom/src/base/nsGlobalWindow.cpp +++ b/mozilla/dom/src/base/nsGlobalWindow.cpp @@ -5866,6 +5866,59 @@ nsGlobalWindow::Observe(nsISupports *aSubject, const char *aTopic, return NS_OK; } +PR_STATIC_CALLBACK(PLDHashOperator) +FirePendingStorageEvents(const nsAString& aKey, PRBool aData, void *userArg) +{ + nsGlobalWindow *win = NS_STATIC_CAST(nsGlobalWindow *, userArg); + + nsCOMPtr storage; + win->GetSessionStorage(getter_AddRefs(storage)); + + if (storage) { + win->Observe(storage, "dom-storage-changed", + aKey.IsEmpty() ? nsnull : PromiseFlatString(aKey).get()); + } + + return PL_DHASH_NEXT; +} + +nsresult +nsGlobalWindow::FireDelayedDOMEvents() +{ + FORWARD_TO_INNER(FireDelayedDOMEvents, (), NS_ERROR_UNEXPECTED); + + if (mPendingStorageEvents) { + // Fire pending storage events. + mPendingStorageEvents->EnumerateRead(FirePendingStorageEvents, this); + + delete mPendingStorageEvents; + mPendingStorageEvents = nsnull; + } + + nsCOMPtr node = + do_QueryInterface(GetDocShell()); + if (node) { + PRInt32 childCount = 0; + node->GetChildCount(&childCount); + + for (PRInt32 i = 0; i < childCount; ++i) { + nsCOMPtr childShell; + node->GetChildAt(i, getter_AddRefs(childShell)); + NS_ASSERTION(childShell, "null child shell"); + + nsCOMPtr pWin = do_GetInterface(childShell); + if (pWin) { + nsGlobalWindow *win = + NS_STATIC_CAST(nsGlobalWindow*, + NS_STATIC_CAST(nsPIDOMWindow*, pWin)); + win->FireDelayedDOMEvents(); + } + } + } + + return NS_OK; +} + //***************************************************************************** // nsGlobalWindow: Window Control Functions //***************************************************************************** @@ -7160,6 +7213,11 @@ nsGlobalWindow::SaveWindowState(nsISupports **aState) nsGlobalWindow *inner = GetCurrentInnerWindowInternal(); NS_ASSERTION(inner, "No inner window to save"); + // Don't do anything else to this inner window! After this point, all + // calls to SetTimeoutOrInterval will create entries in the timeout + // list that will only run after this window has come out of the bfcache. + inner->Freeze(); + // Remember the outer window's XPConnect prototype. nsCOMPtr ci = do_QueryInterface((nsIScriptGlobalObject *)this); @@ -7180,29 +7238,10 @@ nsGlobalWindow::SaveWindowState(nsISupports **aState) printf("saving window state, state = %p\n", (void*)state); #endif - // Don't do anything else to this inner window! - inner->Freeze(); - state.swap(*aState); return NS_OK; } -PR_STATIC_CALLBACK(PLDHashOperator) -FirePendingStorageEvents(const nsAString& aKey, PRBool aData, void *userArg) -{ - nsGlobalWindow *win = NS_STATIC_CAST(nsGlobalWindow *, userArg); - - nsCOMPtr storage; - win->GetSessionStorage(getter_AddRefs(storage)); - - if (storage) { - win->Observe(storage, "dom-storage-changed", - aKey.IsEmpty() ? nsnull : PromiseFlatString(aKey).get()); - } - - return PL_DHASH_NEXT; -} - nsresult nsGlobalWindow::RestoreWindowState(nsISupports *aState) { @@ -7266,15 +7305,6 @@ nsGlobalWindow::RestoreWindowState(nsISupports *aState) holder->DidRestoreWindow(); - if (inner->mPendingStorageEvents) { - // Fire pending storage events. - inner->mPendingStorageEvents->EnumerateRead(FirePendingStorageEvents, - inner); - - delete inner->mPendingStorageEvents; - inner->mPendingStorageEvents = nsnull; - } - return NS_OK; } @@ -7295,13 +7325,13 @@ nsGlobalWindow::SuspendTimeouts() if (t->mTimer) { t->mTimer->Cancel(); t->mTimer = nsnull; - } - // Drop the reference that the timer's closure had on this timeout, we'll - // add it back in ResumeTimeouts. Note that it shouldn't matter that we're - // passing null for the context, since this shouldn't actually release this - // timeout. - t->Release(nsnull); + // Drop the reference that the timer's closure had on this timeout, we'll + // add it back in ResumeTimeouts. Note that it shouldn't matter that we're + // passing null for the context, since this shouldn't actually release this + // timeout. + t->Release(nsnull); + } } // Suspend our children as well. @@ -7323,6 +7353,12 @@ nsGlobalWindow::SuspendTimeouts() NS_STATIC_CAST(nsPIDOMWindow*, pWin)); win->SuspendTimeouts(); + + NS_ASSERTION(win->IsOuterWindow(), "Expected outer window"); + nsGlobalWindow* inner = win->GetCurrentInnerWindowInternal(); + if (inner) { + inner->Freeze(); + } } } } @@ -7380,6 +7416,12 @@ nsGlobalWindow::ResumeTimeouts() NS_STATIC_CAST(nsGlobalWindow*, NS_STATIC_CAST(nsPIDOMWindow*, pWin)); + NS_ASSERTION(win->IsOuterWindow(), "Expected outer window"); + nsGlobalWindow* inner = win->GetCurrentInnerWindowInternal(); + if (inner) { + inner->Thaw(); + } + rv = win->ResumeTimeouts(); NS_ENSURE_SUCCESS(rv, rv); } diff --git a/mozilla/dom/src/base/nsGlobalWindow.h b/mozilla/dom/src/base/nsGlobalWindow.h index 7d8da4cdbc5..4ac54aafb4b 100644 --- a/mozilla/dom/src/base/nsGlobalWindow.h +++ b/mozilla/dom/src/base/nsGlobalWindow.h @@ -241,6 +241,8 @@ public: virtual NS_HIDDEN_(void) SetOpenerWindow(nsIDOMWindowInternal *aOpener, PRBool aOriginalOpener); + virtual NS_HIDDEN_(nsresult) FireDelayedDOMEvents(); + // nsIDOMViewCSS NS_DECL_NSIDOMVIEWCSS