mirror of
https://github.com/roytam1/UXP.git
synced 2026-05-26 14:54:25 +00:00
Issue #595 - Implement window.event
This MSIE extension is still technically part of the standard*, although its use is discouraged. This API will also likely never go away based on some comments at this issue on MDN content**. Note that this uses a different approach for getting the inner window. * https://dom.spec.whatwg.org/#interface-window-extensions ** https://github.com/mdn/content/issues/21848 Spec PR: https://github.com/whatwg/dom/pull/407 Spec discussion: https://github.com/whatwg/dom/issues/334 Partially based on https://bugzilla.mozilla.org/show_bug.cgi?id=218415
This commit is contained in:
@@ -824,6 +824,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();
|
||||
|
||||
@@ -909,7 +909,8 @@ nsPIDOMWindow<T>::nsPIDOMWindow(nsPIDOMWindowOuter *aOuterWindow)
|
||||
mOuterWindow(aOuterWindow),
|
||||
// Make sure no actual window ends up with mWindowID == 0
|
||||
mWindowID(NextWindowID()), mHasNotifiedGlobalCreated(false),
|
||||
mMarkedCCGeneration(0), mServiceWorkersTestingEnabled(false)
|
||||
mMarkedCCGeneration(0), mServiceWorkersTestingEnabled(false),
|
||||
mEvent(nullptr)
|
||||
{}
|
||||
|
||||
template<class T>
|
||||
@@ -5245,6 +5246,16 @@ nsGlobalWindow::SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
|
||||
SetOpenerWindow(outer, false);
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::GetEvent(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval)
|
||||
{
|
||||
if (mEvent) {
|
||||
Unused << nsContentUtils::WrapNative(aCx, mEvent, aRetval);
|
||||
} else {
|
||||
aRetval.setUndefined();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::GetStatusOuter(nsAString& aStatus)
|
||||
{
|
||||
|
||||
@@ -846,6 +846,7 @@ public:
|
||||
already_AddRefed<nsPIDOMWindowOuter> GetOpener() override;
|
||||
void SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
|
||||
mozilla::ErrorResult& aError);
|
||||
void GetEvent(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval);
|
||||
already_AddRefed<nsPIDOMWindowOuter> GetParentOuter();
|
||||
already_AddRefed<nsPIDOMWindowOuter> GetParent(mozilla::ErrorResult& aError);
|
||||
already_AddRefed<nsPIDOMWindowOuter> GetParent() override;
|
||||
|
||||
@@ -194,6 +194,10 @@ protected:
|
||||
// we have what it takes to do so.
|
||||
void MaybeCreateDoc();
|
||||
|
||||
// The event dispatch code sets and unsets this while keeping
|
||||
// the event object alive.
|
||||
nsIDOMEvent* mEvent;
|
||||
|
||||
public:
|
||||
inline bool IsLoadingOrRunningTimeout() const;
|
||||
|
||||
@@ -789,6 +793,17 @@ public:
|
||||
return mInnerObjectsFreed;
|
||||
}
|
||||
|
||||
// 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.
|
||||
nsIDOMEvent* SetEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
nsIDOMEvent* old = mEvent;
|
||||
mEvent = aEvent;
|
||||
return old;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether this window is a secure context.
|
||||
*/
|
||||
|
||||
@@ -264,6 +264,16 @@ public:
|
||||
return mFlags.mRootOfClosedTree;
|
||||
}
|
||||
|
||||
void SetItemInShadowTree(bool aSet)
|
||||
{
|
||||
mFlags.mItemInShadowTree = aSet;
|
||||
}
|
||||
|
||||
bool IsItemInShadowTree()
|
||||
{
|
||||
return mFlags.mItemInShadowTree;
|
||||
}
|
||||
|
||||
void SetIsSlotInClosedTree(bool aSet)
|
||||
{
|
||||
mFlags.mIsSlotInClosedTree = aSet;
|
||||
@@ -351,7 +361,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!");
|
||||
}
|
||||
@@ -384,6 +395,7 @@ private:
|
||||
bool mWantsPreHandleEvent : 1;
|
||||
bool mPreHandleEventOnly : 1;
|
||||
bool mRootOfClosedTree : 1;
|
||||
bool mItemInShadowTree : 1;
|
||||
bool mIsSlotInClosedTree : 1;
|
||||
bool mIsChromeHandler : 1;
|
||||
private:
|
||||
@@ -433,6 +445,7 @@ EventTargetChainItem::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
SetWantsPreHandleEvent(aVisitor.mWantsPreHandleEvent);
|
||||
SetPreHandleEventOnly(aVisitor.mWantsPreHandleEvent && !aVisitor.mCanHandle);
|
||||
SetRootOfClosedTree(aVisitor.mRootOfClosedTree);
|
||||
SetItemInShadowTree(aVisitor.mItemInShadowTree);
|
||||
SetRetargetedRelatedTarget(aVisitor.mRetargetedRelatedTarget);
|
||||
mItemFlags = aVisitor.mItemFlags;
|
||||
mItemData = aVisitor.mItemData;
|
||||
|
||||
@@ -125,6 +125,7 @@ public:
|
||||
, mMayHaveListenerManager(true)
|
||||
, mWantsPreHandleEvent(false)
|
||||
, mRootOfClosedTree(false)
|
||||
, mItemInShadowTree(false)
|
||||
, mParentIsSlotInClosedTree(false)
|
||||
, mParentIsChromeHandler(false)
|
||||
, mRelatedTargetRetargetedInCurrentScope(false)
|
||||
@@ -147,6 +148,7 @@ public:
|
||||
mMayHaveListenerManager = true;
|
||||
mWantsPreHandleEvent = false;
|
||||
mRootOfClosedTree = false;
|
||||
mItemInShadowTree = false;
|
||||
mParentIsSlotInClosedTree = false;
|
||||
mParentIsChromeHandler = false;
|
||||
// Note, we don't clear mRelatedTargetRetargetedInCurrentScope explicitly,
|
||||
@@ -236,6 +238,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.
|
||||
|
||||
@@ -1120,6 +1120,38 @@ 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();
|
||||
nsGlobalWindow* win;
|
||||
if (callback) {
|
||||
// Find the real underlying callback.
|
||||
JSObject* realCallback =
|
||||
js::UncheckedUnwrap(callback->CallbackPreserveColor());
|
||||
// Get the global for this callback.
|
||||
win = mIsMainThreadELM ?
|
||||
xpc::WindowGlobalOrNull(realCallback) :
|
||||
nullptr;
|
||||
}
|
||||
if (win && win->IsInnerWindow()) {
|
||||
innerWindow = win->AsInner(); // 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
|
||||
@@ -1130,7 +1162,8 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
|
||||
WidgetEvent* aEvent,
|
||||
nsIDOMEvent** aDOMEvent,
|
||||
EventTarget* aCurrentTarget,
|
||||
nsEventStatus* aEventStatus)
|
||||
nsEventStatus* aEventStatus,
|
||||
bool aItemInShadowTree)
|
||||
{
|
||||
//Set the value of the internal PreventDefault flag properly based on aEventStatus
|
||||
if (!aEvent->DefaultPrevented() &&
|
||||
@@ -1222,9 +1255,18 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
|
||||
listener = listenerHolder.ptr();
|
||||
hasRemovedListener = true;
|
||||
}
|
||||
nsCOMPtr<nsPIDOMWindowInner> innerWindow =
|
||||
WindowFromListener(listener, aItemInShadowTree);
|
||||
nsIDOMEvent* oldWindowEvent = nullptr;
|
||||
if (innerWindow) {
|
||||
oldWindowEvent = innerWindow->SetEvent(*aDOMEvent);
|
||||
}
|
||||
if (NS_FAILED(HandleEventSubType(listener, *aDOMEvent, aCurrentTarget))) {
|
||||
aEvent->mFlags.mExceptionWasRaised = true;
|
||||
}
|
||||
if (innerWindow) {
|
||||
Unused << innerWindow->SetEvent(oldWindowEvent);
|
||||
}
|
||||
aEvent->mFlags.mInPassiveListener = false;
|
||||
|
||||
if (needsEndEventMarker) {
|
||||
|
||||
@@ -350,7 +350,8 @@ public:
|
||||
WidgetEvent* aEvent,
|
||||
nsIDOMEvent** aDOMEvent,
|
||||
dom::EventTarget* aCurrentTarget,
|
||||
nsEventStatus* aEventStatus)
|
||||
nsEventStatus* aEventStatus,
|
||||
bool aItemInShadowTree)
|
||||
{
|
||||
if (mListeners.IsEmpty() || aEvent->PropagationStopped()) {
|
||||
return;
|
||||
@@ -371,7 +372,7 @@ public:
|
||||
return;
|
||||
}
|
||||
HandleEventInternal(aPresContext, aEvent, aDOMEvent, aCurrentTarget,
|
||||
aEventStatus);
|
||||
aEventStatus, aItemInShadowTree);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -482,7 +483,8 @@ protected:
|
||||
WidgetEvent* aEvent,
|
||||
nsIDOMEvent** aDOMEvent,
|
||||
dom::EventTarget* aCurrentTarget,
|
||||
nsEventStatus* aEventStatus);
|
||||
nsEventStatus* aEventStatus,
|
||||
bool aItemInShadowTree);
|
||||
|
||||
nsresult HandleEventSubType(Listener* aListener,
|
||||
nsIDOMEvent* aDOMEvent,
|
||||
@@ -573,6 +575,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
|
||||
|
||||
@@ -50,6 +50,7 @@ interface nsIDOMCrypto;
|
||||
[Throws] void stop();
|
||||
[Throws, CrossOriginCallable, UnsafeInPrerendering] void focus();
|
||||
[Throws, CrossOriginCallable] void blur();
|
||||
[Replaceable, Pref="dom.window.event.enabled"] readonly attribute any event;
|
||||
|
||||
// other browsing contexts
|
||||
[Replaceable, Throws, CrossOriginReadable] readonly attribute WindowProxy frames;
|
||||
|
||||
@@ -5244,6 +5244,9 @@ pref("prompts.content_handling_dialog_modal.enabled", false);
|
||||
// Whether module scripts (<script type="module">) are enabled for content.
|
||||
pref("dom.moduleScripts.enabled", true);
|
||||
|
||||
// Whether read-only Window property event is enabled for content.
|
||||
pref("dom.window.event.enabled", false);
|
||||
|
||||
// Report details when a media source error occurs?
|
||||
// Enabled by default in debug builds, otherwise should be explicitly enabled
|
||||
// by the user to prevent XO leaking of the response status (CVE-2020-15666)
|
||||
|
||||
Reference in New Issue
Block a user