diff --git a/content/base/src/nsGkAtomList.h b/content/base/src/nsGkAtomList.h index 9ec7c4b4cab..d1a314b7c51 100755 --- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -740,7 +740,7 @@ GK_ATOM(screen, "screen") GK_ATOM(screenX, "screenX") GK_ATOM(screenY, "screenY") GK_ATOM(script, "script") -GK_ATOM(scriptEnabledBeforePrintPreview, "scriptEnabledBeforePrintPreview") +GK_ATOM(scriptEnabledBeforePrintOrPreview, "scriptEnabledBeforePrintOrPreview") GK_ATOM(scrollbar, "scrollbar") GK_ATOM(scrollbarbutton, "scrollbarbutton") GK_ATOM(scrollbox, "scrollbox") diff --git a/dom/public/base/nsPIDOMWindow.h b/dom/public/base/nsPIDOMWindow.h index a86283f6bae..1362dc9c701 100644 --- a/dom/public/base/nsPIDOMWindow.h +++ b/dom/public/base/nsPIDOMWindow.h @@ -76,8 +76,8 @@ class nsScriptObjectHolder; class nsXBLPrototypeHandler; #define NS_PIDOMWINDOW_IID \ -{ 0x909852b5, 0xb9e6, 0x4d94, \ - { 0x8d, 0xe3, 0x05, 0x16, 0x34, 0x80, 0x0b, 0x73 } } +{ 0xc9c187f9, 0x2104, 0x4c2c, \ + { 0xb4, 0xd7, 0xc1, 0xb1, 0x9d, 0xa5, 0xc7, 0xd8 } } class nsPIDOMWindow : public nsIDOMWindowInternal { @@ -269,6 +269,8 @@ public: // Restore the window state from aState. virtual nsresult RestoreWindowState(nsISupports *aState) = 0; + // Suspend timeouts in this and in child windows. + virtual void SuspendTimeouts() = 0; // Resume suspended timeouts in this window and in child windows. virtual nsresult ResumeTimeouts() = 0; diff --git a/dom/src/base/nsGlobalWindow.cpp b/dom/src/base/nsGlobalWindow.cpp index fc5e1cd3109..ef11d11979f 100644 --- a/dom/src/base/nsGlobalWindow.cpp +++ b/dom/src/base/nsGlobalWindow.cpp @@ -605,6 +605,7 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow) mFireOfflineStatusChangeEventOnThaw(PR_FALSE), mCreatingInnerWindow(PR_FALSE), mIsChrome(PR_FALSE), + mTimersSuspended(PR_FALSE), mTimeoutInsertionPoint(nsnull), mTimeoutPublicIdCounter(1), mTimeoutFiringDepth(0), @@ -8382,6 +8383,11 @@ nsGlobalWindow::SuspendTimeouts() { FORWARD_TO_INNER_VOID(SuspendTimeouts, ()); + if (mTimersSuspended) { + return; + } + mTimersSuspended = PR_TRUE; + PRTime now = PR_Now(); for (nsTimeout *t = FirstTimeout(); IsTimeout(t); t = t->Next()) { // Change mWhen to be the time remaining for this timer. @@ -8437,6 +8443,11 @@ nsGlobalWindow::ResumeTimeouts() { FORWARD_TO_INNER(ResumeTimeouts, (), NS_ERROR_NOT_INITIALIZED); + if (!mTimersSuspended) { + return NS_OK; + } + mTimersSuspended = PR_FALSE; + // Restore all of the timeouts, using the stored time remaining // (stored in timeout->mWhen). diff --git a/dom/src/base/nsGlobalWindow.h b/dom/src/base/nsGlobalWindow.h index ce1116a65d8..68a169d1820 100644 --- a/dom/src/base/nsGlobalWindow.h +++ b/dom/src/base/nsGlobalWindow.h @@ -300,6 +300,7 @@ public: virtual NS_HIDDEN_(nsresult) SaveWindowState(nsISupports **aState); virtual NS_HIDDEN_(nsresult) RestoreWindowState(nsISupports *aState); + virtual NS_HIDDEN_(void) SuspendTimeouts(); virtual NS_HIDDEN_(nsresult) ResumeTimeouts(); virtual NS_HIDDEN_(nsresult) FireDelayedDOMEvents(); virtual NS_HIDDEN_(PRBool) IsFrozen() const @@ -599,8 +600,6 @@ protected: already_AddRefed GetMainWidget(); - void SuspendTimeouts(); - void Freeze() { NS_ASSERTION(!IsFrozen(), "Double-freezing?"); @@ -674,6 +673,8 @@ protected: // Fast way to tell if this is a chrome window (without having to QI). PRPackedBool mIsChrome : 1; + PRPackedBool mTimersSuspended : 1; + nsCOMPtr mContext; nsWeakPtr mOpener; nsCOMPtr mControllers; diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 5f00f437a65..ef5e30fa49c 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -1939,7 +1939,7 @@ PresShell::SetPrefNoScriptRule() ((mPresContext->Type() == nsPresContext::eContext_PrintPreview || mPresContext->Type() == nsPresContext::eContext_Print) && NS_PTR_TO_INT32(mDocument->GetProperty( - nsGkAtoms::scriptEnabledBeforePrintPreview))); + nsGkAtoms::scriptEnabledBeforePrintOrPreview))); if (scriptEnabled) { if (!mPrefStyleSheet) { diff --git a/layout/printing/nsPrintEngine.cpp b/layout/printing/nsPrintEngine.cpp index ff9898560ef..9778df34871 100644 --- a/layout/printing/nsPrintEngine.cpp +++ b/layout/printing/nsPrintEngine.cpp @@ -213,6 +213,35 @@ static void DumpPrintObjectsTreeLayout(nsPrintObject * aPO,nsIDeviceContext * aD #define DUMP_DOC_TREELAYOUT #endif +class nsScriptSuppressor +{ +public: + nsScriptSuppressor(nsPrintEngine* aPrintEngine) + : mPrintEngine(aPrintEngine), mSuppressed(PR_FALSE) {} + + ~nsScriptSuppressor() { Unsuppress(); } + + void Suppress() + { + if (mPrintEngine) { + mSuppressed = PR_TRUE; + mPrintEngine->TurnScriptingOn(PR_FALSE); + } + } + + void Unsuppress() + { + if (mPrintEngine && mSuppressed) { + mPrintEngine->TurnScriptingOn(PR_TRUE); + } + mSuppressed = PR_FALSE; + } + + void Disconnect() { mPrintEngine = nsnull; } +protected: + nsRefPtr mPrintEngine; + PRBool mSuppressed; +}; // Class IDs static NS_DEFINE_CID(kViewManagerCID, NS_VIEW_MANAGER_CID); @@ -557,11 +586,13 @@ nsPrintEngine::DoCommonPrint(PRBool aIsPrintPreview, (do_CreateInstance("@mozilla.org/gfx/devicecontextspec;1", &rv)); NS_ENSURE_SUCCESS(rv, rv); + nsScriptSuppressor scriptSuppressor(this); if (!aIsPrintPreview) { #ifdef NS_DEBUG mPrt->mDebugFilePtr = mDebugFile; #endif + scriptSuppressor.Suppress(); PRBool printSilently; mPrt->mPrintSettings->GetPrintSilent(&printSilently); @@ -713,6 +744,9 @@ nsPrintEngine::DoCommonPrint(PRBool aIsPrintPreview, } } + // We will enable scripting later after printing has finished. + scriptSuppressor.Disconnect(); + return NS_OK; } @@ -2712,6 +2746,7 @@ nsPrintEngine::DonePrintingPages(nsPrintObject* aPO, nsresult aResult) FirePrintCompletionEvent(); } + TurnScriptingOn(PR_TRUE); SetIsPrinting(PR_FALSE); // Release reference to mPagePrintTimer; the timer object destroys itself @@ -2993,6 +3028,13 @@ nsPrintEngine::FindSmallestSTF() void nsPrintEngine::TurnScriptingOn(PRBool aDoTurnOn) { + if (mIsDoingPrinting && aDoTurnOn && mDocViewerPrint && + mDocViewerPrint->GetIsPrintPreview()) { + // We don't want to turn scripting on if print preview is shown still after + // printing. + return; + } + nsPrintData* prt = mPrt; #ifdef NS_PRINT_PREVIEW if (!prt) { @@ -3016,25 +3058,32 @@ nsPrintEngine::TurnScriptingOn(PRBool aDoTurnOn) nsIScriptGlobalObject *scriptGlobalObj = doc->GetScriptGlobalObject(); if (scriptGlobalObj) { + nsCOMPtr window = do_QueryInterface(scriptGlobalObj); + NS_ASSERTION(window, "Can't get nsPIDOMWindow"); nsIScriptContext *scx = scriptGlobalObj->GetContext(); NS_ASSERTION(scx, "Can't get nsIScriptContext"); + nsresult propThere = NS_PROPTABLE_PROP_NOT_THERE; + doc->GetProperty(nsGkAtoms::scriptEnabledBeforePrintOrPreview, + &propThere); if (aDoTurnOn) { - doc->DeleteProperty(nsGkAtoms::scriptEnabledBeforePrintPreview); + if (propThere != NS_PROPTABLE_PROP_NOT_THERE) { + doc->DeleteProperty(nsGkAtoms::scriptEnabledBeforePrintOrPreview); + scx->SetScriptsEnabled(PR_TRUE, PR_FALSE); + window->ResumeTimeouts(); + } } else { // Have to be careful, because people call us over and over again with // aDoTurnOn == PR_FALSE. So don't set the property if it's already // set, since in that case we'd set it to the wrong value. - nsresult propThere; - doc->GetProperty(nsGkAtoms::scriptEnabledBeforePrintPreview, - &propThere); if (propThere == NS_PROPTABLE_PROP_NOT_THERE) { // Stash the current value of IsScriptEnabled on the document, so // that layout code running in print preview doesn't get confused. - doc->SetProperty(nsGkAtoms::scriptEnabledBeforePrintPreview, + doc->SetProperty(nsGkAtoms::scriptEnabledBeforePrintOrPreview, NS_INT32_TO_PTR(doc->IsScriptEnabled())); + scx->SetScriptsEnabled(PR_FALSE, PR_FALSE); + window->SuspendTimeouts(); } } - scx->SetScriptsEnabled(aDoTurnOn, PR_TRUE); } } }