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.h421
1 files changed, 421 insertions, 0 deletions
diff --git a/dom/events/Event.h b/dom/events/Event.h
new file mode 100644
index 000000000..4ac6a68d5
--- /dev/null
+++ b/dom/events/Event.h
@@ -0,0 +1,421 @@
+/* -*- 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 "mozilla/Attributes.h"
+#include "mozilla/BasicEvents.h"
+#include "nsIDOMEvent.h"
+#include "nsISupports.h"
+#include "nsCOMPtr.h"
+#include "nsPIDOMWindow.h"
+#include "nsPoint.h"
+#include "nsCycleCollectionParticipant.h"
+#include "mozilla/dom/EventBinding.h"
+#include "nsIScriptGlobalObject.h"
+#include "Units.h"
+#include "js/TypeDecls.h"
+#include "nsIGlobalObject.h"
+
+class nsIContent;
+class nsIDOMEventTarget;
+class nsPresContext;
+
+namespace mozilla {
+namespace dom {
+
+class EventTarget;
+class EventMessageAutoOverride;
+class WantsPopupControlCheck;
+#define GENERATED_EVENT(EventClass_) class EventClass_;
+#include "mozilla/dom/GeneratedEventList.h"
+#undef GENERATED_EVENT
+// ExtendableEvent is a ServiceWorker event that is not
+// autogenerated since it has some extra methods.
+namespace workers {
+class ExtendableEvent;
+} // namespace workers
+
+// Dummy class so we can cast through it to get from nsISupports to
+// Event subclasses with only two non-ambiguous static casts.
+class EventBase : public nsIDOMEvent
+{
+};
+
+class Event : public EventBase,
+ public nsWrapperCache
+{
+public:
+ Event(EventTarget* aOwner,
+ nsPresContext* aPresContext,
+ WidgetEvent* aEvent);
+ explicit Event(nsPIDOMWindowInner* aWindow);
+
+protected:
+ virtual ~Event();
+
+private:
+ void ConstructorInit(EventTarget* aOwner,
+ nsPresContext* aPresContext,
+ WidgetEvent* aEvent);
+
+public:
+ static Event* FromSupports(nsISupports* aSupports)
+ {
+ nsIDOMEvent* event =
+ static_cast<nsIDOMEvent*>(aSupports);
+#ifdef DEBUG
+ {
+ nsCOMPtr<nsIDOMEvent> target_qi =
+ do_QueryInterface(aSupports);
+
+ // If this assertion fires the QI implementation for the object in
+ // question doesn't use the nsIDOMEvent pointer as the
+ // nsISupports pointer. That must be fixed, or we'll crash...
+ MOZ_ASSERT(target_qi == event, "Uh, fix QI!");
+ }
+#endif
+ return static_cast<Event*>(event);
+ }
+
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Event)
+
+ nsIGlobalObject* GetParentObject()
+ {
+ return mOwner;
+ }
+
+ virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override 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 workers::ExtendableEvent* AsExtendableEvent()
+ {
+ return nullptr;
+ }
+
+ // nsIDOMEvent Interface
+ NS_DECL_NSIDOMEVENT
+
+ void InitPresContextData(nsPresContext* aPresContext);
+
+ // Returns true if the event should be trusted.
+ bool Init(EventTarget* aGlobal);
+
+ static PopupControlState GetEventPopupControlState(WidgetEvent* aEvent,
+ nsIDOMEvent* aDOMEvent = nullptr);
+
+ static void PopupAllowedEventsChanged();
+
+ static void Shutdown();
+
+ static const char* 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 CSSIntPoint GetScreenCoords(nsPresContext* aPresContext,
+ WidgetEvent* aEvent,
+ LayoutDeviceIntPoint aPoint);
+ static CSSIntPoint GetOffsetCoords(nsPresContext* aPresContext,
+ WidgetEvent* aEvent,
+ LayoutDeviceIntPoint aPoint,
+ CSSIntPoint aDefaultPoint);
+
+ static already_AddRefed<Event> Constructor(const GlobalObject& aGlobal,
+ const nsAString& aType,
+ const EventInit& aParam,
+ ErrorResult& aRv);
+
+ // Implemented as xpidl method
+ // void GetType(nsString& aRetval) {}
+
+ EventTarget* GetTarget() const;
+ EventTarget* GetCurrentTarget() const;
+
+ uint16_t EventPhase() const;
+
+ // xpidl implementation
+ // void StopPropagation();
+
+ // xpidl implementation
+ // 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();
+ }
+
+ // xpidl implementation
+ // void PreventDefault();
+
+ // You MUST NOT call PreventDefaultJ(JSContext*) from C++ code. A call of
+ // this method always sets Event.defaultPrevented true for web contents.
+ // If default action handler calls this, web applications meet wrong
+ // defaultPrevented value.
+ virtual void PreventDefault(JSContext* aCx);
+
+ // You MUST NOT call DefaultPrevented(JSContext*) from C++ code. This may
+ // return false even if PreventDefault() has been called.
+ // See comments in its implementation for the detail.
+ bool DefaultPrevented(JSContext* aCx) const;
+
+ bool DefaultPrevented() const
+ {
+ return mEvent->DefaultPrevented();
+ }
+
+ bool DefaultPreventedByChrome() const
+ {
+ return mEvent->mFlags.mDefaultPreventedByChrome;
+ }
+
+ bool DefaultPreventedByContent() const
+ {
+ return mEvent->mFlags.mDefaultPreventedByContent;
+ }
+
+ bool MultipleActionsPrevented() const
+ {
+ return mEvent->mFlags.mMultipleActionsPrevented;
+ }
+
+ bool IsTrusted() const
+ {
+ return mEvent->IsTrusted();
+ }
+
+ bool IsSynthesized() const
+ {
+ return mEvent->mFlags.mIsSynthesizedForTests;
+ }
+
+ double TimeStamp() const;
+
+ EventTarget* GetOriginalTarget() const;
+ EventTarget* GetExplicitOriginalTarget() const;
+ EventTarget* GetComposedTarget() const;
+
+ bool GetPreventDefault() 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);
+
+ bool IsMainThreadEvent()
+ {
+ return mIsMainThreadEvent;
+ }
+
+ /**
+ * For a given current target, returns the related target adjusted with
+ * shadow DOM retargeting rules. Returns nullptr if related target
+ * is not adjusted.
+ */
+ static nsIContent* GetShadowRelatedTarget(nsIContent* aCurrentTarget,
+ nsIContent* aRelatedTarget);
+
+ void MarkUninitialized()
+ {
+ mEvent->mMessage = eVoidEvent;
+ mEvent->mSpecifiedEventTypeString.Truncate();
+ mEvent->mSpecifiedEventType = nullptr;
+ }
+
+protected:
+
+ // Internal helper functions
+ void SetEventType(const nsAString& aEventTypeArg);
+ already_AddRefed<nsIContent> GetTargetFromFrame();
+
+ friend class EventMessageAutoOverride;
+ friend class WantsPopupControlCheck;
+ void SetWantsPopupControlCheck(bool aCheck)
+ {
+ mWantsPopupControlCheck = aCheck;
+ }
+
+ bool GetWantsPopupControlCheck()
+ {
+ return IsTrusted() && mWantsPopupControlCheck;
+ }
+
+ /**
+ * IsChrome() returns true if aCx is chrome context or the event is created
+ * in chrome's thread. Otherwise, false.
+ */
+ bool IsChrome(JSContext* aCx) const;
+
+ void SetComposed(bool aComposed)
+ {
+ mEvent->SetComposed(aComposed);
+ }
+
+ 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 nsIDOMEvent must outlive this RAII helper.
+ */
+class MOZ_RAII EventMessageAutoOverride
+{
+public:
+ explicit EventMessageAutoOverride(nsIDOMEvent* aEvent,
+ EventMessage aOverridingMessage)
+ : mEvent(aEvent->InternalDOMEvent()),
+ 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(nsIDOMEvent* aEvent) :
+ mEvent(aEvent->InternalDOMEvent())
+ {
+ mOriginalWantsPopupControlCheck = mEvent->GetWantsPopupControlCheck();
+ mEvent->SetWantsPopupControlCheck(mEvent->IsTrusted());
+ }
+
+ ~WantsPopupControlCheck()
+ {
+ mEvent->SetWantsPopupControlCheck(mOriginalWantsPopupControlCheck);
+ }
+
+private:
+ Event* mEvent;
+ bool mOriginalWantsPopupControlCheck;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#define NS_FORWARD_TO_EVENT \
+ NS_FORWARD_NSIDOMEVENT(Event::) \
+ virtual void PreventDefault(JSContext* aCx) override { Event::PreventDefault(aCx); }
+
+#define NS_FORWARD_NSIDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION(_to) \
+ NS_IMETHOD GetType(nsAString& aType) override { return _to GetType(aType); } \
+ NS_IMETHOD GetTarget(nsIDOMEventTarget** aTarget) override { return _to GetTarget(aTarget); } \
+ NS_IMETHOD GetCurrentTarget(nsIDOMEventTarget** aCurrentTarget) override { return _to GetCurrentTarget(aCurrentTarget); } \
+ NS_IMETHOD GetEventPhase(uint16_t* aEventPhase) override { return _to GetEventPhase(aEventPhase); } \
+ NS_IMETHOD GetBubbles(bool* aBubbles) override { return _to GetBubbles(aBubbles); } \
+ NS_IMETHOD GetCancelable(bool* aCancelable) override { return _to GetCancelable(aCancelable); } \
+ NS_IMETHOD GetTimeStamp(DOMTimeStamp* aTimeStamp) override { return _to GetTimeStamp(aTimeStamp); } \
+ NS_IMETHOD StopPropagation(void) override { return _to StopPropagation(); } \
+ NS_IMETHOD StopCrossProcessForwarding(void) override { return _to StopCrossProcessForwarding(); } \
+ NS_IMETHOD PreventDefault(void) override { return _to PreventDefault(); } \
+ void InitEvent(const nsAString& eventTypeArg, bool canBubbleArg, bool cancelableArg) override { _to InitEvent(eventTypeArg, canBubbleArg, cancelableArg); } \
+ NS_IMETHOD GetDefaultPrevented(bool* aDefaultPrevented) override { return _to GetDefaultPrevented(aDefaultPrevented); } \
+ NS_IMETHOD StopImmediatePropagation(void) override { return _to StopImmediatePropagation(); } \
+ NS_IMETHOD GetOriginalTarget(nsIDOMEventTarget** aOriginalTarget) override { return _to GetOriginalTarget(aOriginalTarget); } \
+ NS_IMETHOD GetExplicitOriginalTarget(nsIDOMEventTarget** aExplicitOriginalTarget) override { return _to GetExplicitOriginalTarget(aExplicitOriginalTarget); } \
+ NS_IMETHOD GetPreventDefault(bool* aRetval) override { return _to GetPreventDefault(aRetval); } \
+ NS_IMETHOD GetIsTrusted(bool* aIsTrusted) override { return _to GetIsTrusted(aIsTrusted); } \
+ NS_IMETHOD SetTarget(nsIDOMEventTarget* aTarget) override { return _to SetTarget(aTarget); } \
+ NS_IMETHOD_(bool) IsDispatchStopped(void) override { return _to IsDispatchStopped(); } \
+ NS_IMETHOD_(WidgetEvent*) WidgetEventPtr(void) override { return _to WidgetEventPtr(); } \
+ NS_IMETHOD_(void) SetTrusted(bool aTrusted) override { _to SetTrusted(aTrusted); } \
+ NS_IMETHOD_(void) SetOwner(EventTarget* aOwner) override { _to SetOwner(aOwner); } \
+ NS_IMETHOD_(Event*) InternalDOMEvent() override { return _to InternalDOMEvent(); } \
+ NS_IMETHOD GetCancelBubble(bool* aCancelBubble) override { return _to GetCancelBubble(aCancelBubble); } \
+ NS_IMETHOD SetCancelBubble(bool aCancelBubble) override { return _to SetCancelBubble(aCancelBubble); }
+
+#define NS_FORWARD_TO_EVENT_NO_SERIALIZATION_NO_DUPLICATION \
+ NS_FORWARD_NSIDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION(Event::) \
+ virtual void PreventDefault(JSContext* aCx) override { Event::PreventDefault(aCx); }
+
+inline nsISupports*
+ToSupports(mozilla::dom::Event* e)
+{
+ return static_cast<nsIDOMEvent*>(e);
+}
+
+inline nsISupports*
+ToCanonicalSupports(mozilla::dom::Event* e)
+{
+ return static_cast<nsIDOMEvent*>(e);
+}
+
+already_AddRefed<mozilla::dom::Event>
+NS_NewDOMEvent(mozilla::dom::EventTarget* aOwner,
+ nsPresContext* aPresContext,
+ mozilla::WidgetEvent* aEvent);
+
+#endif // mozilla_dom_Event_h_