Bug 1254230 kinda-fix. Make sure to never send script errors with stacks attached to the console service if the associated windows have already had FreeInnerObjects called on them. r=bholley

This commit is contained in:
Boris Zbarsky 2016-03-08 17:21:40 -05:00
parent 2e2d6cac3d
commit 3e5ab54341
6 changed files with 38 additions and 10 deletions

View File

@ -548,7 +548,8 @@ AutoJSAPI::ReportException()
if (inner && jsReport.report()->errorNumber != JSMSG_OUT_OF_MEMORY) {
DispatchScriptErrorEvent(inner, JS_GetRuntime(cx()), xpcReport, exn);
} else {
JS::Rooted<JSObject*> stack(cx(), xpc::FindExceptionStack(cx(), exn));
JS::Rooted<JSObject*> stack(cx(),
xpc::FindExceptionStackForConsoleReport(cx(), inner, exn));
xpcReport->LogToConsoleWithStack(stack);
}
} else {

View File

@ -612,6 +612,7 @@ nsPIDOMWindow<T>::nsPIDOMWindow(nsPIDOMWindowOuter *aOuterWindow)
mMayHavePaintEventListener(false), mMayHaveTouchEventListener(false),
mMayHaveMouseEnterLeaveEventListener(false),
mMayHavePointerEnterLeaveEventListener(false),
mInnerObjectsFreed(false),
mIsModalContentWindow(false),
mIsActive(false), mIsBackground(false),
mAudioMuted(false), mAudioVolume(1.0), mAudioCaptured(false),
@ -1171,7 +1172,6 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
#endif
mShowFocusRingForContent(false),
mFocusByKeyOccurred(false),
mInnerObjectsFreed(false),
mHasGamepad(false),
#ifdef MOZ_GAMEPAD
mHasSeenGamepadInput(false),

View File

@ -1731,10 +1731,6 @@ protected:
// should be displayed.
bool mFocusByKeyOccurred : 1;
// Ensure that a call to ResumeTimeouts() after FreeInnerObjects() does nothing.
// This member is only used by inner windows.
bool mInnerObjectsFreed : 1;
// Inner windows only.
// Indicates whether this window wants gamepad input events
bool mHasGamepad : 1;

View File

@ -231,12 +231,20 @@ namespace xpc {
//
// Note that the returned object is _not_ wrapped into the compartment of cx.
JSObject*
FindExceptionStack(JSContext* cx, JS::HandleValue exceptionValue)
FindExceptionStackForConsoleReport(JSContext* cx,
nsPIDOMWindowInner* win,
JS::HandleValue exceptionValue)
{
if (!exceptionValue.isObject()) {
return nullptr;
}
if (win && win->InnerObjectsFreed()) {
// Pretend like we have no stack, so we don't end up keeping the global
// alive via the stack.
return nullptr;
}
JS::RootedObject exceptionObject(cx, &exceptionValue.toObject());
JSAutoCompartment ac(cx, exceptionObject);
JS::RootedObject stackObject(cx, ExceptionStackOrNull(cx, exceptionObject));
@ -472,7 +480,8 @@ public:
}
JSContext* cx = jsapi.cx();
JS::Rooted<JS::Value> exn(cx, mError);
JS::RootedObject stack(cx, xpc::FindExceptionStack(cx, exn));
JS::RootedObject stack(cx,
xpc::FindExceptionStackForConsoleReport(cx, win, exn));
mReport->LogToConsoleWithStack(stack);
} else {
mReport->LogToConsole();
@ -555,7 +564,8 @@ SystemErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
if (!win || JSREPORT_IS_WARNING(xpcReport->mFlags) ||
report->errorNumber == JSMSG_OUT_OF_MEMORY)
{
JS::Rooted<JSObject*> stack(cx, xpc::FindExceptionStack(cx, exception));
JS::Rooted<JSObject*> stack(cx,
xpc::FindExceptionStackForConsoleReport(cx, win, exception));
xpcReport->LogToConsoleWithStack(stack);
return;
}

View File

@ -630,6 +630,12 @@ protected:
bool mMayHaveMouseEnterLeaveEventListener;
bool mMayHavePointerEnterLeaveEventListener;
// Used to detect whether we have called FreeInnerObjects() (e.g. to ensure
// that a call to ResumeTimeouts() after FreeInnerObjects() does nothing).
// This member is only used by inner windows.
bool mInnerObjectsFreed;
// This variable is used on both inner and outer windows (and they
// should match).
bool mIsModalContentWindow;
@ -779,6 +785,13 @@ public:
mMayHavePointerEnterLeaveEventListener = true;
}
/**
* Check whether this has had inner objects freed.
*/
bool InnerObjectsFreed() const
{
return mInnerObjectsFreed;
}
protected:
void CreatePerformanceObjectIfNeeded();

View File

@ -550,8 +550,16 @@ DispatchScriptErrorEvent(nsPIDOMWindowInner* win, JSRuntime* rt, xpc::ErrorRepor
// passed-in value does NOT necessarily have to be in the same compartment as
// the passed-in JSContext. The returned stack, if any, may also not be in the
// same compartment as either cx or exceptionValue.
//
// The "win" argument passed in here should be the same as the window whose
// WindowID() is used to initialize the xpc::ErrorReport. This may be null, of
// course. If it's not null, this function may return a null stack object if
// the window is far enough gone, because in those cases we don't want to have
// the stack in the console message keeping the window alive.
JSObject*
FindExceptionStack(JSContext* cx, JS::HandleValue exceptionValue);
FindExceptionStackForConsoleReport(JSContext* cx,
nsPIDOMWindowInner* win,
JS::HandleValue exceptionValue);
// Return a name for the compartment.
// This function makes reasonable efforts to make this name both mostly human-readable