1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef mozilla_dom_Event_h_
8 #define mozilla_dom_Event_h_
9 
10 #include "mozilla/Attributes.h"
11 #include "mozilla/BasicEvents.h"
12 #include "nsIDOMEvent.h"
13 #include "nsISupports.h"
14 #include "nsCOMPtr.h"
15 #include "nsPIDOMWindow.h"
16 #include "nsPoint.h"
17 #include "nsCycleCollectionParticipant.h"
18 #include "mozilla/dom/BindingDeclarations.h"
19 #include "mozilla/dom/EventBinding.h"
20 #include "nsIScriptGlobalObject.h"
21 #include "Units.h"
22 #include "js/TypeDecls.h"
23 #include "nsIGlobalObject.h"
24 
25 class nsIContent;
26 class nsIDOMEventTarget;
27 class nsPresContext;
28 
29 namespace mozilla {
30 namespace dom {
31 
32 class BeforeUnloadEvent;
33 class EventTarget;
34 class EventMessageAutoOverride;
35 // ExtendableEvent is a ServiceWorker event that is not
36 // autogenerated since it has some extra methods.
37 class ExtendableEvent;
38 class KeyboardEvent;
39 class TimeEvent;
40 class WantsPopupControlCheck;
41 #define GENERATED_EVENT(EventClass_) class EventClass_;
42 #include "mozilla/dom/GeneratedEventList.h"
43 #undef GENERATED_EVENT
44 
45 // Dummy class so we can cast through it to get from nsISupports to
46 // Event subclasses with only two non-ambiguous static casts.
47 class EventBase : public nsIDOMEvent {};
48 
49 class Event : public EventBase, public nsWrapperCache {
50  public:
51   Event(EventTarget* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent);
52   explicit Event(nsPIDOMWindowInner* aWindow);
53 
54  protected:
55   virtual ~Event();
56 
57  private:
58   void ConstructorInit(EventTarget* aOwner, nsPresContext* aPresContext,
59                        WidgetEvent* aEvent);
60 
61  public:
FromSupports(nsISupports * aSupports)62   static Event* FromSupports(nsISupports* aSupports) {
63     nsIDOMEvent* event = static_cast<nsIDOMEvent*>(aSupports);
64 #ifdef DEBUG
65     {
66       nsCOMPtr<nsIDOMEvent> target_qi = do_QueryInterface(aSupports);
67 
68       // If this assertion fires the QI implementation for the object in
69       // question doesn't use the nsIDOMEvent pointer as the
70       // nsISupports pointer. That must be fixed, or we'll crash...
71       MOZ_ASSERT(target_qi == event, "Uh, fix QI!");
72     }
73 #endif
74     return static_cast<Event*>(event);
75   }
76 
77   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Event)78   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Event)
79 
80   nsIGlobalObject* GetParentObject() { return mOwner; }
81 
82   JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) final;
83 
84   virtual JSObject* WrapObjectInternal(JSContext* aCx,
85                                        JS::Handle<JSObject*> aGivenProto);
86 
87 #define GENERATED_EVENT(EventClass_) \
88   virtual EventClass_* As##EventClass_() { return nullptr; }
89 #include "mozilla/dom/GeneratedEventList.h"
90 #undef GENERATED_EVENT
91 
92   // ExtendableEvent is a ServiceWorker event that is not
93   // autogenerated since it has some extra methods.
AsExtendableEvent()94   virtual ExtendableEvent* AsExtendableEvent() { return nullptr; }
95 
AsTimeEvent()96   virtual TimeEvent* AsTimeEvent() { return nullptr; }
97 
98   // BeforeUnloadEvent is not autogenerated because it has a setter.
AsBeforeUnloadEvent()99   virtual BeforeUnloadEvent* AsBeforeUnloadEvent() { return nullptr; }
100 
101   // KeyboardEvent has all sorts of non-autogeneratable bits so far.
AsKeyboardEvent()102   virtual KeyboardEvent* AsKeyboardEvent() { return nullptr; }
103 
104   // nsIDOMEvent Interface
105   NS_DECL_NSIDOMEVENT
106 
107   void InitPresContextData(nsPresContext* aPresContext);
108 
109   // Returns true if the event should be trusted.
110   bool Init(EventTarget* aGlobal);
111 
112   static PopupControlState GetEventPopupControlState(
113       WidgetEvent* aEvent, nsIDOMEvent* aDOMEvent = nullptr);
114 
115   static void PopupAllowedEventsChanged();
116 
117   static void Shutdown();
118 
119   static const char* GetEventName(EventMessage aEventType);
120   static CSSIntPoint GetClientCoords(nsPresContext* aPresContext,
121                                      WidgetEvent* aEvent,
122                                      LayoutDeviceIntPoint aPoint,
123                                      CSSIntPoint aDefaultPoint);
124   static CSSIntPoint GetPageCoords(nsPresContext* aPresContext,
125                                    WidgetEvent* aEvent,
126                                    LayoutDeviceIntPoint aPoint,
127                                    CSSIntPoint aDefaultPoint);
128   static CSSIntPoint GetScreenCoords(nsPresContext* aPresContext,
129                                      WidgetEvent* aEvent,
130                                      LayoutDeviceIntPoint aPoint);
131   static CSSIntPoint GetOffsetCoords(nsPresContext* aPresContext,
132                                      WidgetEvent* aEvent,
133                                      LayoutDeviceIntPoint aPoint,
134                                      CSSIntPoint aDefaultPoint);
135 
136   static already_AddRefed<Event> Constructor(EventTarget* aEventTarget,
137                                              const nsAString& aType,
138                                              const EventInit& aParam);
139 
140   static already_AddRefed<Event> Constructor(const GlobalObject& aGlobal,
141                                              const nsAString& aType,
142                                              const EventInit& aParam,
143                                              ErrorResult& aRv);
144 
145   // Implemented as xpidl method
146   // void GetType(nsString& aRetval) {}
147 
148   EventTarget* GetTarget() const;
149   static bool IsSrcElementEnabled(JSContext* /* unused */,
150                                   JSObject* /* unused */);
151   EventTarget* GetCurrentTarget() const;
152 
153   void ComposedPath(nsTArray<RefPtr<EventTarget>>& aPath);
154 
155   uint16_t EventPhase() const;
156 
157   // xpidl implementation
158   // void StopPropagation();
159 
160   // xpidl implementation
161   // void StopImmediatePropagation();
162 
Bubbles()163   bool Bubbles() const { return mEvent->mFlags.mBubbles; }
164 
Cancelable()165   bool Cancelable() const { return mEvent->mFlags.mCancelable; }
166 
Composed()167   bool Composed() const { return mEvent->mFlags.mComposed; }
168 
CancelBubble()169   bool CancelBubble() const { return mEvent->PropagationStopped(); }
170 
171   // xpidl implementation
172   // void PreventDefault();
173 
174   // You MUST NOT call PreventDefault(JSContext*, CallerType) from C++ code.  A
175   // call of this method always sets Event.defaultPrevented true for web
176   // contents.  If default action handler calls this, web applications see wrong
177   // defaultPrevented value.
178   virtual void PreventDefault(JSContext* aCx, CallerType aCallerType);
179 
180   // You MUST NOT call DefaultPrevented(CallerType) from C++ code.  This may
181   // return false even if PreventDefault() has been called.
182   // See comments in its implementation for the details.
183   bool DefaultPrevented(CallerType aCallerType) const;
184 
DefaultPrevented()185   bool DefaultPrevented() const { return mEvent->DefaultPrevented(); }
186 
DefaultPreventedByChrome()187   bool DefaultPreventedByChrome() const {
188     return mEvent->mFlags.mDefaultPreventedByChrome;
189   }
190 
DefaultPreventedByContent()191   bool DefaultPreventedByContent() const {
192     return mEvent->mFlags.mDefaultPreventedByContent;
193   }
194 
MultipleActionsPrevented()195   bool MultipleActionsPrevented() const {
196     return mEvent->mFlags.mMultipleActionsPrevented;
197   }
198 
IsTrusted()199   bool IsTrusted() const { return mEvent->IsTrusted(); }
200 
IsSynthesized()201   bool IsSynthesized() const { return mEvent->mFlags.mIsSynthesizedForTests; }
202 
203   double TimeStamp();
204 
205   EventTarget* GetOriginalTarget() const;
206   EventTarget* GetExplicitOriginalTarget() const;
207   EventTarget* GetComposedTarget() const;
208 
209   /**
210    * @param aCalledByDefaultHandler     Should be true when this is called by
211    *                                    C++ or Chrome.  Otherwise, e.g., called
212    *                                    by a call of Event.preventDefault() in
213    *                                    content script, false.
214    */
215   void PreventDefaultInternal(bool aCalledByDefaultHandler,
216                               nsIPrincipal* aPrincipal = nullptr);
217 
IsMainThreadEvent()218   bool IsMainThreadEvent() { return mIsMainThreadEvent; }
219 
MarkUninitialized()220   void MarkUninitialized() {
221     mEvent->mMessage = eVoidEvent;
222     mEvent->mSpecifiedEventTypeString.Truncate();
223     mEvent->mSpecifiedEventType = nullptr;
224   }
225 
226   /**
227    * For WidgetEvent, return it's type in string.
228    *
229    * @param aEvent is a WidgetEvent to get its type.
230    * @param aType is a string where to return the type.
231    */
232   static void GetWidgetEventType(WidgetEvent* aEvent, nsAString& aType);
233 
234  protected:
235   // Internal helper functions
236   void SetEventType(const nsAString& aEventTypeArg);
237   already_AddRefed<nsIContent> GetTargetFromFrame();
238 
239   friend class EventMessageAutoOverride;
240   friend class WantsPopupControlCheck;
SetWantsPopupControlCheck(bool aCheck)241   void SetWantsPopupControlCheck(bool aCheck) {
242     mWantsPopupControlCheck = aCheck;
243   }
244 
GetWantsPopupControlCheck()245   bool GetWantsPopupControlCheck() {
246     return IsTrusted() && mWantsPopupControlCheck;
247   }
248 
SetComposed(bool aComposed)249   void SetComposed(bool aComposed) { mEvent->SetComposed(aComposed); }
250 
251   already_AddRefed<EventTarget> EnsureWebAccessibleRelatedTarget(
252       EventTarget* aRelatedTarget);
253 
254   mozilla::WidgetEvent* mEvent;
255   RefPtr<nsPresContext> mPresContext;
256   nsCOMPtr<EventTarget> mExplicitOriginalTarget;
257   nsCOMPtr<nsIGlobalObject> mOwner;
258   bool mEventIsInternal;
259   bool mPrivateDataDuplicated;
260   bool mIsMainThreadEvent;
261   // True when popup control check should rely on event.type, not
262   // WidgetEvent.mMessage.
263   bool mWantsPopupControlCheck;
264 };
265 
266 /**
267  * RAII helper-class to override an event's message (i.e. its DOM-exposed
268  * type), for as long as the object is alive.  Restores the original
269  * EventMessage when destructed.
270  *
271  * Notable requirements:
272  *  - The original & overriding messages must be known (not eUnidentifiedEvent).
273  *  - The original & overriding messages must be different.
274  *  - The passed-in nsIDOMEvent must outlive this RAII helper.
275  */
276 class MOZ_RAII EventMessageAutoOverride {
277  public:
EventMessageAutoOverride(nsIDOMEvent * aEvent,EventMessage aOverridingMessage)278   explicit EventMessageAutoOverride(nsIDOMEvent* aEvent,
279                                     EventMessage aOverridingMessage)
280       : mEvent(aEvent->InternalDOMEvent()),
281         mOrigMessage(mEvent->mEvent->mMessage) {
282     MOZ_ASSERT(aOverridingMessage != mOrigMessage,
283                "Don't use this class if you're not actually overriding");
284     MOZ_ASSERT(aOverridingMessage != eUnidentifiedEvent,
285                "Only use this class with a valid overriding EventMessage");
286     MOZ_ASSERT(mOrigMessage != eUnidentifiedEvent &&
287                    mEvent->mEvent->mSpecifiedEventTypeString.IsEmpty(),
288                "Only use this class on events whose overridden type is "
289                "known (so we can restore it properly)");
290 
291     mEvent->mEvent->mMessage = aOverridingMessage;
292   }
293 
~EventMessageAutoOverride()294   ~EventMessageAutoOverride() { mEvent->mEvent->mMessage = mOrigMessage; }
295 
296  protected:
297   // Non-owning ref, which should be safe since we're a stack-allocated object
298   // with limited lifetime. Whoever creates us should keep mEvent alive.
299   Event* const MOZ_NON_OWNING_REF mEvent;
300   const EventMessage mOrigMessage;
301 };
302 
303 class MOZ_STACK_CLASS WantsPopupControlCheck {
304  public:
WantsPopupControlCheck(nsIDOMEvent * aEvent)305   explicit WantsPopupControlCheck(nsIDOMEvent* aEvent)
306       : mEvent(aEvent->InternalDOMEvent()) {
307     mOriginalWantsPopupControlCheck = mEvent->GetWantsPopupControlCheck();
308     mEvent->SetWantsPopupControlCheck(mEvent->IsTrusted());
309   }
310 
~WantsPopupControlCheck()311   ~WantsPopupControlCheck() {
312     mEvent->SetWantsPopupControlCheck(mOriginalWantsPopupControlCheck);
313   }
314 
315  private:
316   Event* mEvent;
317   bool mOriginalWantsPopupControlCheck;
318 };
319 
320 }  // namespace dom
321 }  // namespace mozilla
322 
323 #define NS_FORWARD_TO_EVENT                                           \
324   NS_FORWARD_NSIDOMEVENT(Event::)                                     \
325   virtual void PreventDefault(JSContext* aCx, CallerType aCallerType) \
326       override {                                                      \
327     Event::PreventDefault(aCx, aCallerType);                          \
328   }
329 
330 #define NS_FORWARD_NSIDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION(_to)            \
331   NS_IMETHOD GetType(nsAString& aType) override { return _to GetType(aType); } \
332   NS_IMETHOD GetTarget(nsIDOMEventTarget** aTarget) override {                 \
333     return _to GetTarget(aTarget);                                             \
334   }                                                                            \
335   NS_IMETHOD GetCurrentTarget(nsIDOMEventTarget** aCurrentTarget) override {   \
336     return _to GetCurrentTarget(aCurrentTarget);                               \
337   }                                                                            \
338   NS_IMETHOD GetEventPhase(uint16_t* aEventPhase) override {                   \
339     return _to GetEventPhase(aEventPhase);                                     \
340   }                                                                            \
341   NS_IMETHOD GetBubbles(bool* aBubbles) override {                             \
342     return _to GetBubbles(aBubbles);                                           \
343   }                                                                            \
344   NS_IMETHOD GetCancelable(bool* aCancelable) override {                       \
345     return _to GetCancelable(aCancelable);                                     \
346   }                                                                            \
347   NS_IMETHOD GetTimeStamp(DOMTimeStamp* aTimeStamp) override {                 \
348     return _to GetTimeStamp(aTimeStamp);                                       \
349   }                                                                            \
350   NS_IMETHOD StopPropagation(void) override { return _to StopPropagation(); }  \
351   NS_IMETHOD StopCrossProcessForwarding(void) override {                       \
352     return _to StopCrossProcessForwarding();                                   \
353   }                                                                            \
354   NS_IMETHOD PreventDefault(void) override { return _to PreventDefault(); }    \
355   void InitEvent(const nsAString& eventTypeArg, bool canBubbleArg,             \
356                  bool cancelableArg) override {                                \
357     _to InitEvent(eventTypeArg, canBubbleArg, cancelableArg);                  \
358   }                                                                            \
359   NS_IMETHOD GetDefaultPrevented(bool* aDefaultPrevented) override {           \
360     return _to GetDefaultPrevented(aDefaultPrevented);                         \
361   }                                                                            \
362   NS_IMETHOD StopImmediatePropagation(void) override {                         \
363     return _to StopImmediatePropagation();                                     \
364   }                                                                            \
365   NS_IMETHOD GetOriginalTarget(nsIDOMEventTarget** aOriginalTarget) override { \
366     return _to GetOriginalTarget(aOriginalTarget);                             \
367   }                                                                            \
368   NS_IMETHOD GetExplicitOriginalTarget(                                        \
369       nsIDOMEventTarget** aExplicitOriginalTarget) override {                  \
370     return _to GetExplicitOriginalTarget(aExplicitOriginalTarget);             \
371   }                                                                            \
372   NS_IMETHOD GetIsTrusted(bool* aIsTrusted) override {                         \
373     return _to GetIsTrusted(aIsTrusted);                                       \
374   }                                                                            \
375   NS_IMETHOD SetTarget(nsIDOMEventTarget* aTarget) override {                  \
376     return _to SetTarget(aTarget);                                             \
377   }                                                                            \
378   NS_IMETHOD_(bool) IsDispatchStopped(void) override {                         \
379     return _to IsDispatchStopped();                                            \
380   }                                                                            \
381   NS_IMETHOD_(WidgetEvent*) WidgetEventPtr(void) override {                    \
382     return _to WidgetEventPtr();                                               \
383   }                                                                            \
384   NS_IMETHOD_(void) SetTrusted(bool aTrusted) override {                       \
385     _to SetTrusted(aTrusted);                                                  \
386   }                                                                            \
387   NS_IMETHOD_(void) SetOwner(EventTarget* aOwner) override {                   \
388     _to SetOwner(aOwner);                                                      \
389   }                                                                            \
390   NS_IMETHOD_(Event*) InternalDOMEvent() override {                            \
391     return _to InternalDOMEvent();                                             \
392   }                                                                            \
393   NS_IMETHOD GetCancelBubble(bool* aCancelBubble) override {                   \
394     return _to GetCancelBubble(aCancelBubble);                                 \
395   }                                                                            \
396   NS_IMETHOD SetCancelBubble(bool aCancelBubble) override {                    \
397     return _to SetCancelBubble(aCancelBubble);                                 \
398   }
399 
400 #define NS_FORWARD_TO_EVENT_NO_SERIALIZATION_NO_DUPLICATION           \
401   NS_FORWARD_NSIDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION(Event::)     \
402   virtual void PreventDefault(JSContext* aCx, CallerType aCallerType) \
403       override {                                                      \
404     Event::PreventDefault(aCx, aCallerType);                          \
405   }
406 
ToSupports(mozilla::dom::Event * e)407 inline nsISupports* ToSupports(mozilla::dom::Event* e) {
408   return static_cast<nsIDOMEvent*>(e);
409 }
410 
ToCanonicalSupports(mozilla::dom::Event * e)411 inline nsISupports* ToCanonicalSupports(mozilla::dom::Event* e) {
412   return static_cast<nsIDOMEvent*>(e);
413 }
414 
415 already_AddRefed<mozilla::dom::Event> NS_NewDOMEvent(
416     mozilla::dom::EventTarget* aOwner, nsPresContext* aPresContext,
417     mozilla::WidgetEvent* aEvent);
418 
419 #endif  // mozilla_dom_Event_h_
420