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