summaryrefslogtreecommitdiffstats
path: root/dom/events/Event.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/events/Event.h')
-rw-r--r--dom/events/Event.h409
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_