diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
commit | 0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d (patch) | |
tree | a31f07c9bcca9d56ce61e9a1ffd30ef350d513aa /dom/events/Event.h | |
parent | Initial commit. (diff) | |
download | firefox-esr-upstream/115.8.0esr.tar.xz firefox-esr-upstream/115.8.0esr.zip |
Adding upstream version 115.8.0esr.upstream/115.8.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/events/Event.h')
-rw-r--r-- | dom/events/Event.h | 409 |
1 files changed, 409 insertions, 0 deletions
diff --git a/dom/events/Event.h b/dom/events/Event.h new file mode 100644 index 0000000000..2b68a46f5f --- /dev/null +++ b/dom/events/Event.h @@ -0,0 +1,409 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_Event_h_ +#define mozilla_dom_Event_h_ + +#include <cstdint> +#include "Units.h" +#include "js/TypeDecls.h" +#include "mozilla/AlreadyAddRefed.h" +#include "mozilla/Assertions.h" +#include "mozilla/Attributes.h" +#include "mozilla/BasicEvents.h" +#include "mozilla/RefPtr.h" +#include "mozilla/Maybe.h" +#include "mozilla/dom/BindingDeclarations.h" +#include "nsCOMPtr.h" +#include "nsCycleCollectionParticipant.h" +#include "nsID.h" +#include "nsISupports.h" +#include "nsStringFwd.h" +#include "nsWrapperCache.h" + +class PickleIterator; +class nsCycleCollectionTraversalCallback; +class nsIContent; +class nsIGlobalObject; +class nsIPrincipal; +class nsPIDOMWindowInner; +class nsPresContext; + +namespace IPC { +class Message; +class MessageReader; +class MessageWriter; +} // namespace IPC + +namespace mozilla::dom { + +class BeforeUnloadEvent; +class CustomEvent; +class Document; +class DragEvent; +class EventTarget; +class EventMessageAutoOverride; +// ExtendableEvent is a ServiceWorker event that is not +// autogenerated since it has some extra methods. +class ExtendableEvent; +class KeyboardEvent; +class MouseEvent; +class MessageEvent; +class TimeEvent; +class UIEvent; +class WantsPopupControlCheck; +class XULCommandEvent; +struct EventInit; + +#define GENERATED_EVENT(EventClass_) class EventClass_; +#include "mozilla/dom/GeneratedEventList.h" +#undef GENERATED_EVENT + +// IID for Event +#define NS_EVENT_IID \ + { \ + 0x71139716, 0x4d91, 0x4dee, { \ + 0xba, 0xf9, 0xe3, 0x3b, 0x80, 0xc1, 0x61, 0x61 \ + } \ + } + +class Event : public nsISupports, public nsWrapperCache { + public: + NS_DECLARE_STATIC_IID_ACCESSOR(NS_EVENT_IID) + + Event(EventTarget* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent); + explicit Event(nsPIDOMWindowInner* aWindow); + + protected: + virtual ~Event(); + + private: + void ConstructorInit(EventTarget* aOwner, nsPresContext* aPresContext, + WidgetEvent* aEvent); + + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(Event) + + nsIGlobalObject* GetParentObject() const { return mOwner; } + + JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) final; + + virtual JSObject* WrapObjectInternal(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto); + +#define GENERATED_EVENT(EventClass_) \ + virtual EventClass_* As##EventClass_() { return nullptr; } +#include "mozilla/dom/GeneratedEventList.h" +#undef GENERATED_EVENT + + // ExtendableEvent is a ServiceWorker event that is not + // autogenerated since it has some extra methods. + virtual ExtendableEvent* AsExtendableEvent() { return nullptr; } + + virtual TimeEvent* AsTimeEvent() { return nullptr; } + + // BeforeUnloadEvent is not autogenerated because it has a setter. + virtual BeforeUnloadEvent* AsBeforeUnloadEvent() { return nullptr; } + + // KeyboardEvent has all sorts of non-autogeneratable bits so far. + virtual KeyboardEvent* AsKeyboardEvent() { return nullptr; } + + // DragEvent has a non-autogeneratable initDragEvent. + virtual DragEvent* AsDragEvent() { return nullptr; } + + // XULCommandEvent has a non-autogeneratable initCommandEvent. + virtual XULCommandEvent* AsXULCommandEvent() { return nullptr; } + + // MouseEvent has a non-autogeneratable initMouseEvent and other + // non-autogeneratable methods. + virtual MouseEvent* AsMouseEvent() { return nullptr; } + + // UIEvent has a non-autogeneratable initUIEvent. + virtual UIEvent* AsUIEvent() { return nullptr; } + + // CustomEvent has a non-autogeneratable initCustomEvent. + virtual CustomEvent* AsCustomEvent() { return nullptr; } + + // MessageEvent has a non-autogeneratable initMessageEvent and more. + virtual MessageEvent* AsMessageEvent() { return nullptr; } + + void InitEvent(const nsAString& aEventTypeArg, bool aCanBubble, + bool aCancelable) { + InitEvent(aEventTypeArg, aCanBubble ? CanBubble::eYes : CanBubble::eNo, + aCancelable ? Cancelable::eYes : Cancelable::eNo); + } + + void InitEvent(const nsAString& aEventTypeArg, mozilla::CanBubble, + mozilla::Cancelable, + mozilla::Composed = mozilla::Composed::eDefault); + + void SetTarget(EventTarget* aTarget); + virtual void DuplicatePrivateData(); + bool IsDispatchStopped(); + WidgetEvent* WidgetEventPtr(); + const WidgetEvent* WidgetEventPtr() const { + return const_cast<Event*>(this)->WidgetEventPtr(); + } + virtual void Serialize(IPC::MessageWriter* aWriter, + bool aSerializeInterfaceType); + virtual bool Deserialize(IPC::MessageReader* aReader); + void SetOwner(EventTarget* aOwner); + void StopCrossProcessForwarding(); + void SetTrusted(bool aTrusted); + + // When listening to chrome EventTargets, in the parent process, nsWindowRoot + // might receive events we've already handled via + // InProcessBrowserChildMessageManager, and handlers should call this to avoid + // handling the same event twice. + bool ShouldIgnoreChromeEventTargetListener() const; + + void InitPresContextData(nsPresContext* aPresContext); + + // Returns true if the event should be trusted. + bool Init(EventTarget* aGlobal); + + static const char16_t* GetEventName(EventMessage aEventType); + static CSSIntPoint GetClientCoords(nsPresContext* aPresContext, + WidgetEvent* aEvent, + LayoutDeviceIntPoint aPoint, + CSSIntPoint aDefaultPoint); + static CSSIntPoint GetPageCoords(nsPresContext* aPresContext, + WidgetEvent* aEvent, + LayoutDeviceIntPoint aPoint, + CSSIntPoint aDefaultPoint); + static Maybe<CSSIntPoint> GetScreenCoords(nsPresContext* aPresContext, + WidgetEvent* aEvent, + LayoutDeviceIntPoint aPoint); + MOZ_CAN_RUN_SCRIPT_BOUNDARY + static CSSIntPoint GetOffsetCoords(nsPresContext* aPresContext, + WidgetEvent* aEvent, + LayoutDeviceIntPoint aPoint, + CSSIntPoint aDefaultPoint); + + static already_AddRefed<Event> Constructor(EventTarget* aEventTarget, + const nsAString& aType, + const EventInit& aParam); + + static already_AddRefed<Event> Constructor(const GlobalObject& aGlobal, + const nsAString& aType, + const EventInit& aParam); + + void GetType(nsAString& aType) const; + + EventTarget* GetTarget() const; + EventTarget* GetCurrentTarget() const; + + // This method returns the document which is associated with the event target. + already_AddRefed<Document> GetDocument() const; + + void ComposedPath(nsTArray<RefPtr<EventTarget>>& aPath); + + uint16_t EventPhase() const; + + void StopPropagation(); + + void StopImmediatePropagation(); + + bool Bubbles() const { return mEvent->mFlags.mBubbles; } + + bool Cancelable() const { return mEvent->mFlags.mCancelable; } + + bool Composed() const { return mEvent->mFlags.mComposed; } + + bool CancelBubble() const { return mEvent->PropagationStopped(); } + void SetCancelBubble(bool aCancelBubble) { + if (aCancelBubble) { + mEvent->StopPropagation(); + } + } + + // For C++ consumers only! + void PreventDefault(); + + // You MUST NOT call PreventDefault(JSContext*, CallerType) from C++ code. A + // call of this method always sets Event.defaultPrevented true for web + // contents. If default action handler calls this, web applications see wrong + // defaultPrevented value. + virtual void PreventDefault(JSContext* aCx, CallerType aCallerType); + + // You MUST NOT call DefaultPrevented(CallerType) from C++ code. This may + // return false even if PreventDefault() has been called. + // See comments in its implementation for the details. + bool DefaultPrevented(CallerType aCallerType) const; + + bool DefaultPrevented() const { return mEvent->DefaultPrevented(); } + + bool DefaultPreventedByChrome() const { + return mEvent->mFlags.mDefaultPreventedByChrome; + } + + bool DefaultPreventedByContent() const { + return mEvent->mFlags.mDefaultPreventedByContent; + } + + void PreventMultipleActions() { + mEvent->mFlags.mMultipleActionsPrevented = true; + } + + bool MultipleActionsPrevented() const { + return mEvent->mFlags.mMultipleActionsPrevented; + } + + bool ReturnValue(CallerType aCallerType) const; + + void SetReturnValue(bool aReturnValue, CallerType aCallerType); + + bool IsTrusted() const { return mEvent->IsTrusted(); } + + bool IsSynthesized() const { return mEvent->mFlags.mIsSynthesizedForTests; } + + bool IsSafeToBeDispatchedAsynchronously() const { + // If mEvent is not created by dom::Event nor its subclasses, its lifetime + // is not guaranteed. So, only when mEventIsInternal is true, it's safe + // to be dispatched asynchronously. + return mEventIsInternal; + } + + double TimeStamp(); + + EventTarget* GetOriginalTarget() const; + EventTarget* GetExplicitOriginalTarget() const; + EventTarget* GetComposedTarget() const; + + /** + * @param aCalledByDefaultHandler Should be true when this is called by + * C++ or Chrome. Otherwise, e.g., called + * by a call of Event.preventDefault() in + * content script, false. + */ + void PreventDefaultInternal(bool aCalledByDefaultHandler, + nsIPrincipal* aPrincipal = nullptr); + + bool IsMainThreadEvent() { return mIsMainThreadEvent; } + + void MarkUninitialized() { + mEvent->mMessage = eVoidEvent; + mEvent->mSpecifiedEventTypeString.Truncate(); + mEvent->mSpecifiedEventType = nullptr; + } + + /** + * For WidgetEvent, return it's type in string. + * + * @param aEvent is a WidgetEvent to get its type. + * @param aType is a string where to return the type. + */ + static void GetWidgetEventType(WidgetEvent* aEvent, nsAString& aType); + + void RequestReplyFromRemoteContent() { + mEvent->MarkAsWaitingReplyFromRemoteProcess(); + } + + bool IsWaitingReplyFromRemoteContent() const { + return mEvent->IsWaitingReplyFromRemoteProcess(); + } + + bool IsReplyEventFromRemoteContent() const { + return mEvent->IsHandledInRemoteProcess(); + } + + static bool IsDragExitEnabled(JSContext* aCx, JSObject* aGlobal); + + protected: + // Internal helper functions + void SetEventType(const nsAString& aEventTypeArg); + already_AddRefed<nsIContent> GetTargetFromFrame(); + + friend class EventMessageAutoOverride; + friend class PopupBlocker; + friend class WantsPopupControlCheck; + void SetWantsPopupControlCheck(bool aCheck) { + mWantsPopupControlCheck = aCheck; + } + + bool GetWantsPopupControlCheck() { + return IsTrusted() && mWantsPopupControlCheck; + } + + void SetComposed(bool aComposed) { mEvent->SetComposed(aComposed); } + + already_AddRefed<EventTarget> EnsureWebAccessibleRelatedTarget( + EventTarget* aRelatedTarget); + + mozilla::WidgetEvent* mEvent; + RefPtr<nsPresContext> mPresContext; + nsCOMPtr<EventTarget> mExplicitOriginalTarget; + nsCOMPtr<nsIGlobalObject> mOwner; + bool mEventIsInternal; + bool mPrivateDataDuplicated; + bool mIsMainThreadEvent; + // True when popup control check should rely on event.type, not + // WidgetEvent.mMessage. + bool mWantsPopupControlCheck; +}; + +/** + * RAII helper-class to override an event's message (i.e. its DOM-exposed + * type), for as long as the object is alive. Restores the original + * EventMessage when destructed. + * + * Notable requirements: + * - The original & overriding messages must be known (not eUnidentifiedEvent). + * - The original & overriding messages must be different. + * - The passed-in Event must outlive this RAII helper. + */ +class MOZ_RAII EventMessageAutoOverride { + public: + explicit EventMessageAutoOverride(Event* aEvent, + EventMessage aOverridingMessage) + : mEvent(aEvent), mOrigMessage(mEvent->mEvent->mMessage) { + MOZ_ASSERT(aOverridingMessage != mOrigMessage, + "Don't use this class if you're not actually overriding"); + MOZ_ASSERT(aOverridingMessage != eUnidentifiedEvent, + "Only use this class with a valid overriding EventMessage"); + MOZ_ASSERT(mOrigMessage != eUnidentifiedEvent && + mEvent->mEvent->mSpecifiedEventTypeString.IsEmpty(), + "Only use this class on events whose overridden type is " + "known (so we can restore it properly)"); + + mEvent->mEvent->mMessage = aOverridingMessage; + } + + ~EventMessageAutoOverride() { mEvent->mEvent->mMessage = mOrigMessage; } + + protected: + // Non-owning ref, which should be safe since we're a stack-allocated object + // with limited lifetime. Whoever creates us should keep mEvent alive. + Event* const MOZ_NON_OWNING_REF mEvent; + const EventMessage mOrigMessage; +}; + +class MOZ_STACK_CLASS WantsPopupControlCheck { + public: + explicit WantsPopupControlCheck(Event* aEvent) : mEvent(aEvent) { + mOriginalWantsPopupControlCheck = mEvent->GetWantsPopupControlCheck(); + mEvent->SetWantsPopupControlCheck(mEvent->IsTrusted()); + } + + ~WantsPopupControlCheck() { + mEvent->SetWantsPopupControlCheck(mOriginalWantsPopupControlCheck); + } + + private: + Event* mEvent; + bool mOriginalWantsPopupControlCheck; +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(Event, NS_EVENT_IID) + +} // namespace mozilla::dom + +already_AddRefed<mozilla::dom::Event> NS_NewDOMEvent( + mozilla::dom::EventTarget* aOwner, nsPresContext* aPresContext, + mozilla::WidgetEvent* aEvent); + +#endif // mozilla_dom_Event_h_ |