Bug 1336988: Correctly handle dead callback objects when iterating over event listeners. r=peterv

MozReview-Commit-ID: 5vGlPL1p3uh

--HG--
extra : rebase_source : 7e33d93472faa1c047361addf8b15f8a78639255
This commit is contained in:
Kris Maglione 2017-02-06 11:34:56 -08:00
parent 287248920a
commit d0f62ee58a
4 changed files with 19 additions and 3 deletions

View File

@ -365,6 +365,9 @@ CallbackObjectHolderBase::ToXPCOMCallback(CallbackObject* aCallback,
JSContext* cx = jsapi.cx();
JS::Rooted<JSObject*> callback(cx, aCallback->CallbackOrNull());
if (!callback) {
return nullptr;
}
JSAutoCompartment ac(cx, callback);
RefPtr<nsXPCWrappedJS> wrappedJS;

View File

@ -511,8 +511,11 @@ public:
nsCOMPtr<nsISupports> supp =
CallbackObjectHolderBase::ToXPCOMCallback(GetWebIDLCallback(),
NS_GET_TEMPLATE_IID(XPCOMCallbackT));
// ToXPCOMCallback already did the right QI for us.
return supp.forget().downcast<XPCOMCallbackT>();
if (supp) {
// ToXPCOMCallback already did the right QI for us.
return supp.forget().downcast<XPCOMCallbackT>();
}
return nullptr;
}
// Try to return a WebIDLCallbackT version of this object.

View File

@ -1572,10 +1572,16 @@ EventListenerManager::GetListenerInfo(nsCOMArray<nsIEventListenerInfo>* aList)
} else {
eventType.Assign(Substring(nsDependentAtomString(listener.mTypeAtom), 2));
}
nsCOMPtr<nsIDOMEventListener> callback = listener.mListener.ToXPCOMCallback();
if (!callback) {
// This will be null for cross-compartment event listeners which have been
// destroyed.
continue;
}
// EventListenerInfo is defined in XPCOM, so we have to go ahead
// and convert to an XPCOM callback here...
RefPtr<EventListenerInfo> info =
new EventListenerInfo(eventType, listener.mListener.ToXPCOMCallback(),
new EventListenerInfo(eventType, callback.forget(),
listener.mFlags.mCapture,
listener.mFlags.mAllowUntrustedEvents,
listener.mFlags.mInSystemGroup);

View File

@ -67,6 +67,7 @@ add_task(function*() {
// Force cycle collection, which should cause our callback reference
// to be dropped, and dredge up potential issues there.
Cu.forceGC();
Cu.forceCC();
@ -76,6 +77,9 @@ add_task(function*() {
yield fromTestPromise;
do_print("Got event from test");
let listeners = Services.els.getListenerInfoFor(window);
ok(!listeners.some(info => info.type == "FromTest"),
"No 'FromTest' listeners returned for nuked sandbox");
webnav.close();
});