Bug 1480678 part 7 - Use CallbackObject's callback global for realm entering in more places. r=bz

This commit is contained in:
Jan de Mooij 2018-08-07 14:06:44 +02:00
parent 59ff5de1a2
commit 4af62d6c9e
8 changed files with 44 additions and 22 deletions

View File

@ -378,7 +378,7 @@ CallbackObjectHolderBase::ToXPCOMCallback(CallbackObject* aCallback,
return nullptr;
}
JSAutoRealmAllowCCW ar(cx, callback);
JSAutoRealm ar(cx, aCallback->CallbackGlobalOrNull());
RefPtr<nsXPCWrappedJS> wrappedJS;
nsresult rv =

View File

@ -366,7 +366,7 @@ protected:
// Put mAr after mAutoEntryScript so that we exit the realm before we
// pop the script settings stack. Though in practice we'll often manually
// order those two things.
Maybe<JSAutoRealmAllowCCW> mAr;
Maybe<JSAutoRealm> mAr;
// An ErrorResult to possibly re-throw exceptions on and whether
// we should re-throw them.

View File

@ -15290,7 +15290,7 @@ class CGJSImplClass(CGBindingImplClass):
}
// Now define it on our chrome object
JSAutoRealmAllowCCW ar(aCx, mImpl->CallbackOrNull());
JSAutoRealm ar(aCx, mImpl->CallbackGlobalOrNull());
if (!JS_WrapObject(aCx, &obj)) {
return nullptr;
}

View File

@ -1770,8 +1770,9 @@ Console::ProcessCallData(JSContext* aCx, ConsoleCallData* aData,
// tempted to do that anywhere else, talk to said module owner first.
// aCx and aArguments are in the same compartment.
JS::Rooted<JSObject*> targetScope(aCx, xpc::PrivilegedJunkScope());
if (NS_WARN_IF(!PopulateConsoleNotificationInTheTargetScope(aCx, aArguments,
xpc::PrivilegedJunkScope(),
targetScope,
&eventValue, aData))) {
return;
}
@ -1810,15 +1811,14 @@ Console::ProcessCallData(JSContext* aCx, ConsoleCallData* aData,
bool
Console::PopulateConsoleNotificationInTheTargetScope(JSContext* aCx,
const Sequence<JS::Value>& aArguments,
JSObject* aTargetScope,
JS::Handle<JSObject*> aTargetScope,
JS::MutableHandle<JS::Value> aEventValue,
ConsoleCallData* aData)
{
MOZ_ASSERT(aCx);
MOZ_ASSERT(aData);
MOZ_ASSERT(aTargetScope);
JS::Rooted<JSObject*> targetScope(aCx, aTargetScope);
MOZ_ASSERT(JS_IsGlobalObject(aTargetScope));
ConsoleStackEntry frame;
if (aData->mTopStackFrame) {
@ -1927,7 +1927,7 @@ Console::PopulateConsoleNotificationInTheTargetScope(JSContext* aCx,
aData->mCountValue);
}
JSAutoRealmAllowCCW ar2(aCx, targetScope);
JSAutoRealm ar2(aCx, aTargetScope);
if (NS_WARN_IF(!ToJSValue(aCx, event, aEventValue))) {
return false;
@ -2692,16 +2692,18 @@ Console::NotifyHandler(JSContext* aCx, const Sequence<JS::Value>& aArguments,
JS::Rooted<JS::Value> value(aCx);
JS::Rooted<JSObject*> callable(aCx, mConsoleEventNotifier->CallableOrNull());
if (NS_WARN_IF(!callable)) {
JS::Rooted<JSObject*> callableGlobal(aCx,
mConsoleEventNotifier->CallbackGlobalOrNull());
if (NS_WARN_IF(!callableGlobal)) {
return;
}
// aCx and aArguments are in the same compartment because this method is
// called directly when a Console.something() runs.
// mConsoleEventNotifier->Callable() is the scope where value will be sent to.
// mConsoleEventNotifier->CallbackGlobal() is the scope where value will be
// sent to.
if (NS_WARN_IF(!PopulateConsoleNotificationInTheTargetScope(aCx, aArguments,
callable,
callableGlobal,
&value,
aCallData))) {
return;

View File

@ -239,14 +239,14 @@ private:
// - the system-principal scope when we want to dispatch the ConsoleEvent to
// nsIConsoleAPIStorage (See the comment in Console.cpp about the use of
// xpc::PrivilegedJunkScope()
// - the mConsoleEventNotifier->Callable() scope when we want to notify this
// - the mConsoleEventNotifier->CallableGlobal() when we want to notify this
// handler about a new ConsoleEvent.
// - It can be the global from the JSContext when RetrieveConsoleEvents is
// called.
bool
PopulateConsoleNotificationInTheTargetScope(JSContext* aCx,
const Sequence<JS::Value>& aArguments,
JSObject* aTargetScope,
JS::Handle<JSObject*> aTargetScope,
JS::MutableHandle<JS::Value> aValue,
ConsoleCallData* aData);

View File

@ -1615,9 +1615,12 @@ EventListenerManager::GetListenerInfo(nsCOMArray<nsIEventListenerInfo>* aList)
}
JS::Rooted<JSObject*> callback(RootingCx());
JS::Rooted<JSObject*> callbackGlobal(RootingCx());
if (JSEventHandler* handler = listener.GetJSEventHandler()) {
if (handler->GetTypedEventHandler().HasEventHandler()) {
callback = handler->GetTypedEventHandler().Ptr()->CallableOrNull();
CallbackFunction* callbackFun = handler->GetTypedEventHandler().Ptr();
callback = callbackFun->CallableOrNull();
callbackGlobal = callbackFun->CallbackGlobalOrNull();
if (!callback) {
// This will be null for cross-compartment event listeners
// which have been destroyed.
@ -1625,7 +1628,9 @@ EventListenerManager::GetListenerInfo(nsCOMArray<nsIEventListenerInfo>* aList)
}
}
} else if (listener.mListenerType == Listener::eWebIDLListener) {
callback = listener.mListener.GetWebIDLCallback()->CallbackOrNull();
EventListener* listenerCallback = listener.mListener.GetWebIDLCallback();
callback = listenerCallback->CallbackOrNull();
callbackGlobal = listenerCallback->CallbackGlobalOrNull();
if (!callback) {
// This will be null for cross-compartment event listeners
// which have been destroyed.
@ -1634,7 +1639,7 @@ EventListenerManager::GetListenerInfo(nsCOMArray<nsIEventListenerInfo>* aList)
}
RefPtr<EventListenerInfo> info =
new EventListenerInfo(eventType, callback,
new EventListenerInfo(eventType, callback, callbackGlobal,
listener.mFlags.mCapture,
listener.mFlags.mAllowUntrustedEvents,
listener.mFlags.mInSystemGroup);

View File

@ -82,15 +82,22 @@ EventListenerChange::GetCountOfEventListenerChangesAffectingAccessibility(
EventListenerInfo::EventListenerInfo(const nsAString& aType,
JS::Handle<JSObject*> aScriptedListener,
JS::Handle<JSObject*> aScriptedListenerGlobal,
bool aCapturing,
bool aAllowsUntrusted,
bool aInSystemEventGroup)
: mType(aType)
, mScriptedListener(aScriptedListener)
, mScriptedListenerGlobal(aScriptedListenerGlobal)
, mCapturing(aCapturing)
, mAllowsUntrusted(aAllowsUntrusted)
, mInSystemEventGroup(aInSystemEventGroup)
{
if (aScriptedListener) {
MOZ_ASSERT(JS_IsGlobalObject(aScriptedListenerGlobal));
js::AssertSameCompartment(aScriptedListener, aScriptedListenerGlobal);
}
HoldJSObjects(this);
}
@ -106,10 +113,12 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(EventListenerInfo)
tmp->mScriptedListener = nullptr;
tmp->mScriptedListenerGlobal = nullptr;
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(EventListenerInfo)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mScriptedListener)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mScriptedListenerGlobal)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EventListenerInfo)
@ -152,7 +161,7 @@ NS_IMETHODIMP
EventListenerInfo::GetListenerObject(JSContext* aCx,
JS::MutableHandle<JS::Value> aObject)
{
Maybe<JSAutoRealmAllowCCW> ar;
Maybe<JSAutoRealm> ar;
GetJSVal(aCx, ar, aObject);
return NS_OK;
}
@ -165,12 +174,12 @@ NS_IMPL_ISUPPORTS(EventListenerService, nsIEventListenerService)
bool
EventListenerInfo::GetJSVal(JSContext* aCx,
Maybe<JSAutoRealmAllowCCW>& aAr,
Maybe<JSAutoRealm>& aAr,
JS::MutableHandle<JS::Value> aJSVal)
{
if (mScriptedListener) {
aJSVal.setObject(*mScriptedListener);
aAr.emplace(aCx, mScriptedListener);
aAr.emplace(aCx, mScriptedListenerGlobal);
return true;
}
@ -184,7 +193,7 @@ EventListenerInfo::ToSource(nsAString& aResult)
aResult.SetIsVoid(true);
AutoSafeJSContext cx;
Maybe<JSAutoRealmAllowCCW> ar;
Maybe<JSAutoRealm> ar;
JS::Rooted<JS::Value> v(cx);
if (GetJSVal(cx, ar, &v)) {
JSString* str = JS_ValueToSource(cx, v);

View File

@ -49,6 +49,7 @@ class EventListenerInfo final : public nsIEventListenerInfo
public:
EventListenerInfo(const nsAString& aType,
JS::Handle<JSObject*> aScriptedListener,
JS::Handle<JSObject*> aScriptedListenerGlobal,
bool aCapturing,
bool aAllowsUntrusted,
bool aInSystemEventGroup);
@ -61,11 +62,16 @@ protected:
virtual ~EventListenerInfo();
bool GetJSVal(JSContext* aCx,
Maybe<JSAutoRealmAllowCCW>& aAr,
Maybe<JSAutoRealm>& aAr,
JS::MutableHandle<JS::Value> aJSVal);
nsString mType;
JS::Heap<JSObject*> mScriptedListener; // May be null.
// mScriptedListener may be a cross-compartment wrapper so we cannot use it
// with JSAutoRealm because CCWs are not associated with a single realm. We
// use this global instead (must be same-compartment with mScriptedListener
// and must be non-null if mScriptedListener is non-null).
JS::Heap<JSObject*> mScriptedListenerGlobal;
bool mCapturing;
bool mAllowsUntrusted;
bool mInSystemEventGroup;