mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-27 01:27:30 +09: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:
parent
8e6d730463
commit
31283d993b
10 changed files with 110 additions and 6 deletions
|
|
@ -824,6 +824,10 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
aVisitor.mCanHandle = true;
|
aVisitor.mCanHandle = true;
|
||||||
aVisitor.mMayHaveListenerManager = HasListenerManager();
|
aVisitor.mMayHaveListenerManager = HasListenerManager();
|
||||||
|
|
||||||
|
if (IsInShadowTree()) {
|
||||||
|
aVisitor.mItemInShadowTree = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Don't propagate mouseover and mouseout events when mouse is moving
|
// Don't propagate mouseover and mouseout events when mouse is moving
|
||||||
// inside chrome access only content.
|
// inside chrome access only content.
|
||||||
bool isAnonForEvents = IsRootOfChromeAccessOnlySubtree();
|
bool isAnonForEvents = IsRootOfChromeAccessOnlySubtree();
|
||||||
|
|
|
||||||
|
|
@ -909,7 +909,8 @@ nsPIDOMWindow<T>::nsPIDOMWindow(nsPIDOMWindowOuter *aOuterWindow)
|
||||||
mOuterWindow(aOuterWindow),
|
mOuterWindow(aOuterWindow),
|
||||||
// Make sure no actual window ends up with mWindowID == 0
|
// Make sure no actual window ends up with mWindowID == 0
|
||||||
mWindowID(NextWindowID()), mHasNotifiedGlobalCreated(false),
|
mWindowID(NextWindowID()), mHasNotifiedGlobalCreated(false),
|
||||||
mMarkedCCGeneration(0), mServiceWorkersTestingEnabled(false)
|
mMarkedCCGeneration(0), mServiceWorkersTestingEnabled(false),
|
||||||
|
mEvent(nullptr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
|
|
@ -5245,6 +5246,16 @@ nsGlobalWindow::SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
|
||||||
SetOpenerWindow(outer, false);
|
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
|
void
|
||||||
nsGlobalWindow::GetStatusOuter(nsAString& aStatus)
|
nsGlobalWindow::GetStatusOuter(nsAString& aStatus)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -846,6 +846,7 @@ public:
|
||||||
already_AddRefed<nsPIDOMWindowOuter> GetOpener() override;
|
already_AddRefed<nsPIDOMWindowOuter> GetOpener() override;
|
||||||
void SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
|
void SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
|
||||||
mozilla::ErrorResult& aError);
|
mozilla::ErrorResult& aError);
|
||||||
|
void GetEvent(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval);
|
||||||
already_AddRefed<nsPIDOMWindowOuter> GetParentOuter();
|
already_AddRefed<nsPIDOMWindowOuter> GetParentOuter();
|
||||||
already_AddRefed<nsPIDOMWindowOuter> GetParent(mozilla::ErrorResult& aError);
|
already_AddRefed<nsPIDOMWindowOuter> GetParent(mozilla::ErrorResult& aError);
|
||||||
already_AddRefed<nsPIDOMWindowOuter> GetParent() override;
|
already_AddRefed<nsPIDOMWindowOuter> GetParent() override;
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,10 @@ protected:
|
||||||
// we have what it takes to do so.
|
// we have what it takes to do so.
|
||||||
void MaybeCreateDoc();
|
void MaybeCreateDoc();
|
||||||
|
|
||||||
|
// The event dispatch code sets and unsets this while keeping
|
||||||
|
// the event object alive.
|
||||||
|
nsIDOMEvent* mEvent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline bool IsLoadingOrRunningTimeout() const;
|
inline bool IsLoadingOrRunningTimeout() const;
|
||||||
|
|
||||||
|
|
@ -789,6 +793,17 @@ public:
|
||||||
return mInnerObjectsFreed;
|
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.
|
* Check whether this window is a secure context.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -264,6 +264,16 @@ public:
|
||||||
return mFlags.mRootOfClosedTree;
|
return mFlags.mRootOfClosedTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetItemInShadowTree(bool aSet)
|
||||||
|
{
|
||||||
|
mFlags.mItemInShadowTree = aSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsItemInShadowTree()
|
||||||
|
{
|
||||||
|
return mFlags.mItemInShadowTree;
|
||||||
|
}
|
||||||
|
|
||||||
void SetIsSlotInClosedTree(bool aSet)
|
void SetIsSlotInClosedTree(bool aSet)
|
||||||
{
|
{
|
||||||
mFlags.mIsSlotInClosedTree = aSet;
|
mFlags.mIsSlotInClosedTree = aSet;
|
||||||
|
|
@ -351,7 +361,8 @@ public:
|
||||||
mManager->HandleEvent(aVisitor.mPresContext, aVisitor.mEvent,
|
mManager->HandleEvent(aVisitor.mPresContext, aVisitor.mEvent,
|
||||||
&aVisitor.mDOMEvent,
|
&aVisitor.mDOMEvent,
|
||||||
CurrentTarget(),
|
CurrentTarget(),
|
||||||
&aVisitor.mEventStatus);
|
&aVisitor.mEventStatus,
|
||||||
|
IsItemInShadowTree());
|
||||||
NS_ASSERTION(aVisitor.mEvent->mCurrentTarget == nullptr,
|
NS_ASSERTION(aVisitor.mEvent->mCurrentTarget == nullptr,
|
||||||
"CurrentTarget should be null!");
|
"CurrentTarget should be null!");
|
||||||
}
|
}
|
||||||
|
|
@ -384,6 +395,7 @@ private:
|
||||||
bool mWantsPreHandleEvent : 1;
|
bool mWantsPreHandleEvent : 1;
|
||||||
bool mPreHandleEventOnly : 1;
|
bool mPreHandleEventOnly : 1;
|
||||||
bool mRootOfClosedTree : 1;
|
bool mRootOfClosedTree : 1;
|
||||||
|
bool mItemInShadowTree : 1;
|
||||||
bool mIsSlotInClosedTree : 1;
|
bool mIsSlotInClosedTree : 1;
|
||||||
bool mIsChromeHandler : 1;
|
bool mIsChromeHandler : 1;
|
||||||
private:
|
private:
|
||||||
|
|
@ -433,6 +445,7 @@ EventTargetChainItem::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
SetWantsPreHandleEvent(aVisitor.mWantsPreHandleEvent);
|
SetWantsPreHandleEvent(aVisitor.mWantsPreHandleEvent);
|
||||||
SetPreHandleEventOnly(aVisitor.mWantsPreHandleEvent && !aVisitor.mCanHandle);
|
SetPreHandleEventOnly(aVisitor.mWantsPreHandleEvent && !aVisitor.mCanHandle);
|
||||||
SetRootOfClosedTree(aVisitor.mRootOfClosedTree);
|
SetRootOfClosedTree(aVisitor.mRootOfClosedTree);
|
||||||
|
SetItemInShadowTree(aVisitor.mItemInShadowTree);
|
||||||
SetRetargetedRelatedTarget(aVisitor.mRetargetedRelatedTarget);
|
SetRetargetedRelatedTarget(aVisitor.mRetargetedRelatedTarget);
|
||||||
mItemFlags = aVisitor.mItemFlags;
|
mItemFlags = aVisitor.mItemFlags;
|
||||||
mItemData = aVisitor.mItemData;
|
mItemData = aVisitor.mItemData;
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,7 @@ public:
|
||||||
, mMayHaveListenerManager(true)
|
, mMayHaveListenerManager(true)
|
||||||
, mWantsPreHandleEvent(false)
|
, mWantsPreHandleEvent(false)
|
||||||
, mRootOfClosedTree(false)
|
, mRootOfClosedTree(false)
|
||||||
|
, mItemInShadowTree(false)
|
||||||
, mParentIsSlotInClosedTree(false)
|
, mParentIsSlotInClosedTree(false)
|
||||||
, mParentIsChromeHandler(false)
|
, mParentIsChromeHandler(false)
|
||||||
, mRelatedTargetRetargetedInCurrentScope(false)
|
, mRelatedTargetRetargetedInCurrentScope(false)
|
||||||
|
|
@ -147,6 +148,7 @@ public:
|
||||||
mMayHaveListenerManager = true;
|
mMayHaveListenerManager = true;
|
||||||
mWantsPreHandleEvent = false;
|
mWantsPreHandleEvent = false;
|
||||||
mRootOfClosedTree = false;
|
mRootOfClosedTree = false;
|
||||||
|
mItemInShadowTree = false;
|
||||||
mParentIsSlotInClosedTree = false;
|
mParentIsSlotInClosedTree = false;
|
||||||
mParentIsChromeHandler = false;
|
mParentIsChromeHandler = false;
|
||||||
// Note, we don't clear mRelatedTargetRetargetedInCurrentScope explicitly,
|
// Note, we don't clear mRelatedTargetRetargetedInCurrentScope explicitly,
|
||||||
|
|
@ -236,6 +238,12 @@ public:
|
||||||
*/
|
*/
|
||||||
bool mRootOfClosedTree;
|
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
|
* True if mParentTarget is HTMLSlotElement in a closed shadow tree and the
|
||||||
* current target is assigned to that slot.
|
* 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.
|
* Causes a check for event listeners and processing by them if they exist.
|
||||||
* @param an event listener
|
* @param an event listener
|
||||||
|
|
@ -1130,7 +1162,8 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
|
||||||
WidgetEvent* aEvent,
|
WidgetEvent* aEvent,
|
||||||
nsIDOMEvent** aDOMEvent,
|
nsIDOMEvent** aDOMEvent,
|
||||||
EventTarget* aCurrentTarget,
|
EventTarget* aCurrentTarget,
|
||||||
nsEventStatus* aEventStatus)
|
nsEventStatus* aEventStatus,
|
||||||
|
bool aItemInShadowTree)
|
||||||
{
|
{
|
||||||
//Set the value of the internal PreventDefault flag properly based on aEventStatus
|
//Set the value of the internal PreventDefault flag properly based on aEventStatus
|
||||||
if (!aEvent->DefaultPrevented() &&
|
if (!aEvent->DefaultPrevented() &&
|
||||||
|
|
@ -1222,9 +1255,18 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
|
||||||
listener = listenerHolder.ptr();
|
listener = listenerHolder.ptr();
|
||||||
hasRemovedListener = true;
|
hasRemovedListener = true;
|
||||||
}
|
}
|
||||||
|
nsCOMPtr<nsPIDOMWindowInner> innerWindow =
|
||||||
|
WindowFromListener(listener, aItemInShadowTree);
|
||||||
|
nsIDOMEvent* oldWindowEvent = nullptr;
|
||||||
|
if (innerWindow) {
|
||||||
|
oldWindowEvent = innerWindow->SetEvent(*aDOMEvent);
|
||||||
|
}
|
||||||
if (NS_FAILED(HandleEventSubType(listener, *aDOMEvent, aCurrentTarget))) {
|
if (NS_FAILED(HandleEventSubType(listener, *aDOMEvent, aCurrentTarget))) {
|
||||||
aEvent->mFlags.mExceptionWasRaised = true;
|
aEvent->mFlags.mExceptionWasRaised = true;
|
||||||
}
|
}
|
||||||
|
if (innerWindow) {
|
||||||
|
Unused << innerWindow->SetEvent(oldWindowEvent);
|
||||||
|
}
|
||||||
aEvent->mFlags.mInPassiveListener = false;
|
aEvent->mFlags.mInPassiveListener = false;
|
||||||
|
|
||||||
if (needsEndEventMarker) {
|
if (needsEndEventMarker) {
|
||||||
|
|
|
||||||
|
|
@ -350,7 +350,8 @@ public:
|
||||||
WidgetEvent* aEvent,
|
WidgetEvent* aEvent,
|
||||||
nsIDOMEvent** aDOMEvent,
|
nsIDOMEvent** aDOMEvent,
|
||||||
dom::EventTarget* aCurrentTarget,
|
dom::EventTarget* aCurrentTarget,
|
||||||
nsEventStatus* aEventStatus)
|
nsEventStatus* aEventStatus,
|
||||||
|
bool aItemInShadowTree)
|
||||||
{
|
{
|
||||||
if (mListeners.IsEmpty() || aEvent->PropagationStopped()) {
|
if (mListeners.IsEmpty() || aEvent->PropagationStopped()) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -371,7 +372,7 @@ public:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HandleEventInternal(aPresContext, aEvent, aDOMEvent, aCurrentTarget,
|
HandleEventInternal(aPresContext, aEvent, aDOMEvent, aCurrentTarget,
|
||||||
aEventStatus);
|
aEventStatus, aItemInShadowTree);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -482,7 +483,8 @@ protected:
|
||||||
WidgetEvent* aEvent,
|
WidgetEvent* aEvent,
|
||||||
nsIDOMEvent** aDOMEvent,
|
nsIDOMEvent** aDOMEvent,
|
||||||
dom::EventTarget* aCurrentTarget,
|
dom::EventTarget* aCurrentTarget,
|
||||||
nsEventStatus* aEventStatus);
|
nsEventStatus* aEventStatus,
|
||||||
|
bool aItemInShadowTree);
|
||||||
|
|
||||||
nsresult HandleEventSubType(Listener* aListener,
|
nsresult HandleEventSubType(Listener* aListener,
|
||||||
nsIDOMEvent* aDOMEvent,
|
nsIDOMEvent* aDOMEvent,
|
||||||
|
|
@ -573,6 +575,10 @@ public:
|
||||||
return typedHandler ? typedHandler->OnBeforeUnloadEventHandler() : nullptr;
|
return typedHandler ? typedHandler->OnBeforeUnloadEventHandler() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
already_AddRefed<nsPIDOMWindowInner> WindowFromListener(Listener* aListener,
|
||||||
|
bool aItemInShadowTree);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Helper method for implementing the various Get*EventHandler above. Will
|
* Helper method for implementing the various Get*EventHandler above. Will
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ interface nsIDOMCrypto;
|
||||||
[Throws] void stop();
|
[Throws] void stop();
|
||||||
[Throws, CrossOriginCallable, UnsafeInPrerendering] void focus();
|
[Throws, CrossOriginCallable, UnsafeInPrerendering] void focus();
|
||||||
[Throws, CrossOriginCallable] void blur();
|
[Throws, CrossOriginCallable] void blur();
|
||||||
|
[Replaceable, Pref="dom.window.event.enabled"] readonly attribute any event;
|
||||||
|
|
||||||
// other browsing contexts
|
// other browsing contexts
|
||||||
[Replaceable, Throws, CrossOriginReadable] readonly attribute WindowProxy frames;
|
[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.
|
// Whether module scripts (<script type="module">) are enabled for content.
|
||||||
pref("dom.moduleScripts.enabled", true);
|
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?
|
// Report details when a media source error occurs?
|
||||||
// Enabled by default in debug builds, otherwise should be explicitly enabled
|
// 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)
|
// by the user to prevent XO leaking of the response status (CVE-2020-15666)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue