Bug 492560: Prevent modal dialogs from making the slow-script dialog coming up. r/sr=mrbkap

This commit is contained in:
Jonas Sicking 2009-06-11 17:52:47 -07:00
parent 6ef1850417
commit 68ee329da3
4 changed files with 83 additions and 8 deletions

View File

@ -4453,7 +4453,9 @@ nsGlobalWindow::Print()
printSettingsService->GetNewPrintSettings(getter_AddRefs(printSettings));
}
EnterModalState();
webBrowserPrint->Print(printSettings, nsnull);
LeaveModalState();
PRBool savePrintSettings =
nsContentUtils::GetBoolPref("print.save_print_settings", PR_FALSE);
@ -5640,6 +5642,13 @@ nsGlobalWindow::EnterModalState()
}
}
topWin->mModalStateDepth++;
JSContext *cx = nsContentUtils::GetCurrentJSContext();
nsIScriptContext *scx;
if (cx && (scx = GetScriptContextFromJSContext(cx))) {
scx->EnterModalState();
}
}
// static
@ -5743,6 +5752,13 @@ nsGlobalWindow::LeaveModalState()
mSuspendedDoc = nsnull;
}
}
JSContext *cx = nsContentUtils::GetCurrentJSContext();
nsIScriptContext *scx;
if (cx && (scx = GetScriptContextFromJSContext(cx))) {
scx->LeaveModalState();
}
}
PRBool

View File

@ -56,10 +56,10 @@ class nsScriptObjectHolder;
typedef void (*nsScriptTerminationFunc)(nsISupports* aRef);
// 87482b5e-e019-4df5-9bc2-b2a51b1f2d28
#define NS_ISCRIPTCONTEXT_IID \
{ /* {09316a0e-8d05-4d26-9efd-8f907a7c79d2} */ \
0x09316a0e, 0x8d05, 0x4d26, \
{ 0x9e, 0xfd, 0x8f, 0x90, 0x7a, 0x7c, 0x79, 0xd2 } }
{ 0x87482b5e, 0xe019, 0x4df5, \
{ 0x9b, 0xc2, 0xb2, 0xa5, 0x1b, 0x1f, 0x2d, 0x28 } }
/* This MUST match JSVERSION_DEFAULT. This version stuff if we don't
know what language we have is a little silly... */
@ -456,6 +456,9 @@ public:
*/
virtual nsresult DropScriptObject(void *object) = 0;
virtual nsresult HoldScriptObject(void *object) = 0;
virtual void EnterModalState() = 0;
virtual void LeaveModalState() = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptContext, NS_ISCRIPTCONTEXT_IID)

View File

@ -906,11 +906,13 @@ nsJSContext::DOMOperationCallback(JSContext *cx)
// ScriptEvaluated to be called, and clearing our operation callback time.
// See bug 302333.
PRTime callbackTime = ctx->mOperationCallbackTime;
PRTime modalStateTime = ctx->mModalStateTime;
MaybeGC(cx);
// Now restore the callback time and count, in case they got reset.
ctx->mOperationCallbackTime = callbackTime;
ctx->mModalStateTime = modalStateTime;
// Check to see if we are running OOM
nsCOMPtr<nsIMemory> mem;
@ -965,15 +967,20 @@ nsJSContext::DOMOperationCallback(JSContext *cx)
PRTime now = PR_Now();
if (LL_IS_ZERO(callbackTime)) {
if (callbackTime == 0) {
// Initialize mOperationCallbackTime to start timing how long the
// script has run
ctx->mOperationCallbackTime = now;
return JS_TRUE;
}
PRTime duration;
LL_SUB(duration, now, callbackTime);
if (ctx->mModalStateDepth) {
// We're waiting on a modal dialog, nothing more to do here.
return JS_TRUE;
}
PRTime duration = now - callbackTime;
// Check the amount of time this script has been running, or if the
// dialog is disabled.
@ -1153,6 +1160,46 @@ nsJSContext::DOMOperationCallback(JSContext *cx)
return JS_FALSE;
}
void
nsJSContext::EnterModalState()
{
if (!mModalStateDepth) {
mModalStateTime = mOperationCallbackTime ? PR_Now() : 0;
}
++mModalStateDepth;
}
void
nsJSContext::LeaveModalState()
{
if (!mModalStateDepth) {
NS_ERROR("Uh, mismatched LeaveModalState() call!");
return;
}
--mModalStateDepth;
// If we're still in a modal dialog, or mOperationCallbackTime is still
// uninitialized, do nothing.
if (mModalStateDepth || !mOperationCallbackTime) {
return;
}
// If mOperationCallbackTime was set when we entered the first dialog
// (and mModalStateTime is thus non-zero), adjust mOperationCallbackTime
// to account for time spent in the dialog.
// If mOperationCallbackTime got set while the modal dialog was open,
// simply set mOperationCallbackTime to the closing time of the dialog so
// that we never adjust mOperationCallbackTime to be in the future.
if (mModalStateTime) {
mOperationCallbackTime += PR_Now() - mModalStateTime;
}
else {
mOperationCallbackTime = PR_Now();
}
}
#define JS_OPTIONS_DOT_STR "javascript.options."
static const char js_options_dot_str[] = JS_OPTIONS_DOT_STR;
@ -1275,7 +1322,9 @@ nsJSContext::nsJSContext(JSRuntime *aRuntime) : mGCOnDestruction(PR_TRUE)
mNumEvaluations = 0;
mTerminations = nsnull;
mScriptsEnabled = PR_TRUE;
mOperationCallbackTime = LL_ZERO;
mOperationCallbackTime = 0;
mModalStateTime = 0;
mModalStateDepth = 0;
mProcessingScriptTag = PR_FALSE;
}
@ -3363,7 +3412,8 @@ nsJSContext::ScriptEvaluated(PRBool aTerminated)
}
if (aTerminated) {
mOperationCallbackTime = LL_ZERO;
mOperationCallbackTime = 0;
mModalStateTime = 0;
}
}

View File

@ -165,6 +165,9 @@ public:
virtual nsresult DropScriptObject(void *object);
virtual nsresult HoldScriptObject(void *object);
virtual void EnterModalState();
virtual void LeaveModalState();
NS_DECL_NSIXPCSCRIPTNOTIFY
static void LoadStart();
@ -288,6 +291,9 @@ private:
PRUint32 mDefaultJSOptions;
PRTime mOperationCallbackTime;
PRTime mModalStateTime;
PRUint32 mModalStateDepth;
// mGlobalWrapperRef is used only to hold a strong reference to the
// global object wrapper while the nsJSContext is alive. This cuts
// down on the number of rooting and unrooting calls XPConnect has