mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 03:45:46 +00:00
Bug 218415 - Add window.event. r=smaug.
window.event is set on the wrong window when the target and the callback are from different realms and the callback is an XPCOM callback. MozReview-Commit-ID: HXeUIicdMuT --HG-- extra : rebase_source : 5852093c015844cf3cc49dcd7fe71c9ea881eef9
This commit is contained in:
parent
53fddbfeb5
commit
82805f2778
@ -878,6 +878,10 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
aVisitor.mCanHandle = true;
|
||||
aVisitor.mMayHaveListenerManager = HasListenerManager();
|
||||
|
||||
if (IsInShadowTree()) {
|
||||
aVisitor.mItemInShadowTree = true;
|
||||
}
|
||||
|
||||
// Don't propagate mouseover and mouseout events when mouse is moving
|
||||
// inside chrome access only content.
|
||||
bool isAnonForEvents = IsRootOfChromeAccessOnlySubtree();
|
||||
|
@ -918,8 +918,9 @@ nsGlobalWindowInner::nsGlobalWindowInner(nsGlobalWindowOuter *aOuterWindow)
|
||||
mCanSkipCCGeneration(0),
|
||||
mBeforeUnloadListenerCount(0)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
mIsInnerWindow = true;
|
||||
|
||||
AssertIsOnMainThread();
|
||||
nsLayoutStatics::AddRef();
|
||||
|
||||
// Initialize the PRCList (this).
|
||||
@ -3287,6 +3288,16 @@ nsGlobalWindowInner::SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
|
||||
SetOpenerWindow(outer, false);
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindowInner::GetEvent(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval)
|
||||
{
|
||||
if (mEvent) {
|
||||
Unused << nsContentUtils::WrapNative(aCx, mEvent, aRetval);
|
||||
} else {
|
||||
aRetval.setUndefined();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindowInner::GetStatus(nsAString& aStatus, ErrorResult& aError)
|
||||
{
|
||||
@ -8207,7 +8218,8 @@ nsPIDOMWindowInner::nsPIDOMWindowInner(nsPIDOMWindowOuter *aOuterWindow)
|
||||
mMarkedCCGeneration(0),
|
||||
mHasTriedToCacheTopInnerWindow(false),
|
||||
mNumOfIndexedDBDatabases(0),
|
||||
mNumOfOpenWebSockets(0)
|
||||
mNumOfOpenWebSockets(0),
|
||||
mEvent(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(aOuterWindow);
|
||||
}
|
||||
|
@ -671,6 +671,7 @@ public:
|
||||
mozilla::ErrorResult& aError);
|
||||
void SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
|
||||
mozilla::ErrorResult& aError);
|
||||
void GetEvent(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval);
|
||||
already_AddRefed<nsPIDOMWindowOuter> GetParent(mozilla::ErrorResult& aError);
|
||||
nsPIDOMWindowOuter* GetScriptableParent() override;
|
||||
nsPIDOMWindowOuter* GetScriptableParentOrNull() override;
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "mozilla/dom/ServiceWorkerRegistration.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsGlobalWindowInner.h"
|
||||
|
||||
using mozilla::MallocSizeOf;
|
||||
using mozilla::Maybe;
|
||||
@ -221,6 +222,15 @@ nsIGlobalObject::GetOrCreateServiceWorkerRegistration(const ServiceWorkerRegistr
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsPIDOMWindowInner*
|
||||
nsIGlobalObject::AsInnerWindow()
|
||||
{
|
||||
if (MOZ_LIKELY(mIsInnerWindow)) {
|
||||
return static_cast<nsPIDOMWindowInner*>(static_cast<nsGlobalWindowInner*>(this));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t
|
||||
nsIGlobalObject::ShallowSizeOfExcludingThis(MallocSizeOf aSizeOf) const
|
||||
{
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
class nsCycleCollectionTraversalCallback;
|
||||
class nsIPrincipal;
|
||||
class nsPIDOMWindowInner;
|
||||
|
||||
namespace mozilla {
|
||||
class DOMEventTargetHelper;
|
||||
@ -48,8 +49,12 @@ class nsIGlobalObject : public nsISupports,
|
||||
bool mIsDying;
|
||||
|
||||
protected:
|
||||
|
||||
bool mIsInnerWindow;
|
||||
|
||||
nsIGlobalObject()
|
||||
: mIsDying(false)
|
||||
, mIsInnerWindow(false)
|
||||
{}
|
||||
|
||||
public:
|
||||
@ -130,6 +135,8 @@ public:
|
||||
virtual RefPtr<mozilla::dom::ServiceWorkerRegistration>
|
||||
GetOrCreateServiceWorkerRegistration(const mozilla::dom::ServiceWorkerRegistrationDescriptor& aDescriptor);
|
||||
|
||||
// Returns a pointer to this object as an inner window if this is one or nullptr otherwise.
|
||||
nsPIDOMWindowInner* AsInnerWindow();
|
||||
protected:
|
||||
virtual ~nsIGlobalObject();
|
||||
|
||||
|
@ -251,6 +251,17 @@ public:
|
||||
mMayHavePointerEnterLeaveEventListener = true;
|
||||
}
|
||||
|
||||
// Sets the event for window.event. Does NOT take ownership, so
|
||||
// the caller is responsible for clearing the event before the
|
||||
// event gets deallocated. Pass nullptr to set window.event to
|
||||
// undefined. Returns the previous value.
|
||||
mozilla::dom::Event* SetEvent(mozilla::dom::Event* aEvent)
|
||||
{
|
||||
mozilla::dom::Event* old = mEvent;
|
||||
mEvent = aEvent;
|
||||
return old;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether this window is a secure context.
|
||||
*/
|
||||
@ -705,6 +716,10 @@ protected:
|
||||
// play audible media, or we've already been granted permission by the
|
||||
// user, this is non-null, and encapsulates the request.
|
||||
RefPtr<mozilla::AutoplayRequest> mAutoplayRequest;
|
||||
|
||||
// The event dispatch code sets and unsets this while keeping
|
||||
// the event object alive.
|
||||
mozilla::dom::Event* mEvent;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsPIDOMWindowInner, NS_PIDOMWINDOWINNER_IID)
|
||||
|
@ -321,6 +321,16 @@ public:
|
||||
return mFlags.mRootOfClosedTree;
|
||||
}
|
||||
|
||||
void SetItemInShadowTree(bool aSet)
|
||||
{
|
||||
mFlags.mItemInShadowTree = aSet;
|
||||
}
|
||||
|
||||
bool IsItemInShadowTree()
|
||||
{
|
||||
return mFlags.mItemInShadowTree;
|
||||
}
|
||||
|
||||
void SetIsSlotInClosedTree(bool aSet)
|
||||
{
|
||||
mFlags.mIsSlotInClosedTree = aSet;
|
||||
@ -408,7 +418,8 @@ public:
|
||||
mManager->HandleEvent(aVisitor.mPresContext, aVisitor.mEvent,
|
||||
&aVisitor.mDOMEvent,
|
||||
CurrentTarget(),
|
||||
&aVisitor.mEventStatus);
|
||||
&aVisitor.mEventStatus,
|
||||
IsItemInShadowTree());
|
||||
NS_ASSERTION(aVisitor.mEvent->mCurrentTarget == nullptr,
|
||||
"CurrentTarget should be null!");
|
||||
}
|
||||
@ -443,6 +454,7 @@ private:
|
||||
bool mWantsPreHandleEvent : 1;
|
||||
bool mPreHandleEventOnly : 1;
|
||||
bool mRootOfClosedTree : 1;
|
||||
bool mItemInShadowTree : 1;
|
||||
bool mIsSlotInClosedTree : 1;
|
||||
bool mIsChromeHandler : 1;
|
||||
private:
|
||||
@ -485,6 +497,7 @@ EventTargetChainItem::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
SetWantsPreHandleEvent(aVisitor.mWantsPreHandleEvent);
|
||||
SetPreHandleEventOnly(aVisitor.mWantsPreHandleEvent && !aVisitor.mCanHandle);
|
||||
SetRootOfClosedTree(aVisitor.mRootOfClosedTree);
|
||||
SetItemInShadowTree(aVisitor.mItemInShadowTree);
|
||||
SetRetargetedRelatedTarget(aVisitor.mRetargetedRelatedTarget);
|
||||
SetRetargetedTouchTarget(std::move(aVisitor.mRetargetedTouchTargets));
|
||||
mItemFlags = aVisitor.mItemFlags;
|
||||
|
@ -128,6 +128,7 @@ public:
|
||||
, mMayHaveListenerManager(true)
|
||||
, mWantsPreHandleEvent(false)
|
||||
, mRootOfClosedTree(false)
|
||||
, mItemInShadowTree(false)
|
||||
, mParentIsSlotInClosedTree(false)
|
||||
, mParentIsChromeHandler(false)
|
||||
, mRelatedTargetRetargetedInCurrentScope(false)
|
||||
@ -149,6 +150,7 @@ public:
|
||||
mMayHaveListenerManager = true;
|
||||
mWantsPreHandleEvent = false;
|
||||
mRootOfClosedTree = false;
|
||||
mItemInShadowTree = false;
|
||||
mParentIsSlotInClosedTree = false;
|
||||
mParentIsChromeHandler = false;
|
||||
// Note, we don't clear mRelatedTargetRetargetedInCurrentScope explicitly,
|
||||
@ -237,6 +239,12 @@ public:
|
||||
*/
|
||||
bool mRootOfClosedTree;
|
||||
|
||||
/**
|
||||
* If target is node and its root is a shadow root.
|
||||
* https://dom.spec.whatwg.org/#event-path-item-in-shadow-tree
|
||||
*/
|
||||
bool mItemInShadowTree;
|
||||
|
||||
/**
|
||||
* True if mParentTarget is HTMLSlotElement in a closed shadow tree and the
|
||||
* current target is assigned to that slot.
|
||||
|
@ -1161,6 +1161,32 @@ EventListenerManager::GetLegacyEventMessage(EventMessage aEventMessage) const
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<nsPIDOMWindowInner>
|
||||
EventListenerManager::WindowFromListener(Listener* aListener,
|
||||
bool aItemInShadowTree)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindowInner> innerWindow;
|
||||
if (!aItemInShadowTree) {
|
||||
if (aListener->mListener.HasWebIDLCallback()) {
|
||||
CallbackObject* callback = aListener->mListener.GetWebIDLCallback();
|
||||
nsIGlobalObject* global = nullptr;
|
||||
if (callback) {
|
||||
global = callback->IncumbentGlobalOrNull();
|
||||
}
|
||||
if (global) {
|
||||
innerWindow = global->AsInnerWindow(); // Can be nullptr
|
||||
}
|
||||
} else {
|
||||
// Can't get the global from
|
||||
// listener->mListener.GetXPCOMCallback().
|
||||
// In most cases, it would be the same as for
|
||||
// the target, so let's do that.
|
||||
innerWindow = GetInnerWindowForTarget(); // Can be nullptr
|
||||
}
|
||||
}
|
||||
return innerWindow.forget();
|
||||
}
|
||||
|
||||
/**
|
||||
* Causes a check for event listeners and processing by them if they exist.
|
||||
* @param an event listener
|
||||
@ -1171,7 +1197,8 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
|
||||
WidgetEvent* aEvent,
|
||||
Event** aDOMEvent,
|
||||
EventTarget* aCurrentTarget,
|
||||
nsEventStatus* aEventStatus)
|
||||
nsEventStatus* aEventStatus,
|
||||
bool aItemInShadowTree)
|
||||
{
|
||||
//Set the value of the internal PreventDefault flag properly based on aEventStatus
|
||||
if (!aEvent->DefaultPrevented() &&
|
||||
@ -1264,6 +1291,12 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsPIDOMWindowInner> innerWindow =
|
||||
WindowFromListener(listener, aItemInShadowTree);
|
||||
mozilla::dom::Event* oldWindowEvent = nullptr;
|
||||
if (innerWindow) {
|
||||
oldWindowEvent = innerWindow->SetEvent(*aDOMEvent);
|
||||
}
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
if (profiler_is_active()) {
|
||||
// Add a profiler label and a profiler marker for the actual
|
||||
@ -1297,6 +1330,9 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
|
||||
{
|
||||
rv = HandleEventSubType(listener, *aDOMEvent, aCurrentTarget);
|
||||
}
|
||||
if (innerWindow) {
|
||||
Unused << innerWindow->SetEvent(oldWindowEvent);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
aEvent->mFlags.mExceptionWasRaised = true;
|
||||
|
@ -369,7 +369,8 @@ public:
|
||||
WidgetEvent* aEvent,
|
||||
dom::Event** aDOMEvent,
|
||||
dom::EventTarget* aCurrentTarget,
|
||||
nsEventStatus* aEventStatus)
|
||||
nsEventStatus* aEventStatus,
|
||||
bool aItemInShadowTree)
|
||||
{
|
||||
if (mListeners.IsEmpty() || aEvent->PropagationStopped()) {
|
||||
return;
|
||||
@ -390,7 +391,7 @@ public:
|
||||
return;
|
||||
}
|
||||
HandleEventInternal(aPresContext, aEvent, aDOMEvent, aCurrentTarget,
|
||||
aEventStatus);
|
||||
aEventStatus, aItemInShadowTree);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -499,7 +500,8 @@ protected:
|
||||
WidgetEvent* aEvent,
|
||||
dom::Event** aDOMEvent,
|
||||
dom::EventTarget* aCurrentTarget,
|
||||
nsEventStatus* aEventStatus);
|
||||
nsEventStatus* aEventStatus,
|
||||
bool aItemInShadowTree);
|
||||
|
||||
nsresult HandleEventSubType(Listener* aListener,
|
||||
dom::Event* aDOMEvent,
|
||||
@ -590,6 +592,10 @@ public:
|
||||
return typedHandler ? typedHandler->OnBeforeUnloadEventHandler() : nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
already_AddRefed<nsPIDOMWindowInner> WindowFromListener(Listener* aListener,
|
||||
bool aItemInShadowTree);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Helper method for implementing the various Get*EventHandler above. Will
|
||||
|
@ -51,6 +51,7 @@ interface XULControllers;
|
||||
[Throws] void stop();
|
||||
[Throws, CrossOriginCallable] void focus();
|
||||
[Throws, CrossOriginCallable] void blur();
|
||||
[Replaceable] readonly attribute any event;
|
||||
|
||||
// other browsing contexts
|
||||
[Replaceable, Throws, CrossOriginReadable] readonly attribute WindowProxy frames;
|
||||
|
@ -1,25 +1,8 @@
|
||||
[event-global-extra.window.html]
|
||||
[window.event for constructors from another global: function EventTarget() {\n [native code\]\n}]
|
||||
expected: FAIL
|
||||
|
||||
[window.event for constructors from another global: function XMLHttpRequest() {\n [native code\]\n}]
|
||||
expected: FAIL
|
||||
|
||||
[window.event and element from another document]
|
||||
expected: FAIL
|
||||
|
||||
[window.event and moving an element post-dispatch]
|
||||
expected: FAIL
|
||||
prefs: [dom.webcomponents.shadowdom.enabled:true]
|
||||
|
||||
[window.event should not be affected by nodes moving post-dispatch]
|
||||
expected: FAIL
|
||||
|
||||
[Listener from a different global]
|
||||
expected: FAIL
|
||||
|
||||
[window.event for constructors from another global: EventTarget]
|
||||
expected: FAIL
|
||||
|
||||
[window.event for constructors from another global: XMLHttpRequest]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -1,19 +1,2 @@
|
||||
[event-global.html]
|
||||
[event exists on window, which is initially set to undefined]
|
||||
expected: FAIL
|
||||
|
||||
[window.event is only defined during dispatch]
|
||||
expected: FAIL
|
||||
|
||||
[window.event is undefined if the target is in a shadow tree (event dispatched outside shadow tree)]
|
||||
expected: FAIL
|
||||
|
||||
[window.event is undefined if the target is in a shadow tree (event dispatched inside shadow tree)]
|
||||
expected: FAIL
|
||||
|
||||
[window.event is set to the current event during dispatch]
|
||||
expected: FAIL
|
||||
|
||||
[window.event is set to the current event, which is the event passed to dispatch]
|
||||
expected: FAIL
|
||||
|
||||
prefs: [dom.webcomponents.shadowdom.enabled:true]
|
||||
|
@ -99,6 +99,3 @@
|
||||
[Event interface: new CustomEvent("foo") must inherit property "returnValue" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[Window interface: attribute event]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -1,7 +1,4 @@
|
||||
[track-remove-track.html]
|
||||
[Tests that the 'removetrack' event is fired when an out-of-band TextTrack is removed.]
|
||||
expected: FAIL
|
||||
|
||||
[Tests that the 'removetrack' event is NOT fired for inband TextTrack on a failed load.]
|
||||
expected: FAIL
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user