/work/obj-fuzz/dist/include/mozilla/EventDispatcher.h
Line | Count | Source (jump to first uncovered line) |
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 | | #ifdef MOZILLA_INTERNAL_API |
8 | | #ifndef mozilla_EventDispatcher_h_ |
9 | | #define mozilla_EventDispatcher_h_ |
10 | | |
11 | | #include "mozilla/dom/BindingDeclarations.h" |
12 | | #include "mozilla/dom/Touch.h" |
13 | | #include "mozilla/EventForwards.h" |
14 | | #include "mozilla/Maybe.h" |
15 | | #include "nsCOMPtr.h" |
16 | | #include "nsTArray.h" |
17 | | |
18 | | // Microsoft's API Name hackery sucks |
19 | | #undef CreateEvent |
20 | | |
21 | | class nsIContent; |
22 | | class nsPresContext; |
23 | | |
24 | | template<class E> class nsCOMArray; |
25 | | |
26 | | namespace mozilla { |
27 | | namespace dom { |
28 | | class Event; |
29 | | class EventTarget; |
30 | | } // namespace dom |
31 | | |
32 | | /** |
33 | | * About event dispatching: |
34 | | * When either EventDispatcher::Dispatch or |
35 | | * EventDispatcher::DispatchDOMEvent is called an event target chain is |
36 | | * created. EventDispatcher creates the chain by calling GetEventTargetParent |
37 | | * on each event target and the creation continues until either the mCanHandle |
38 | | * member of the EventChainPreVisitor object is false or the mParentTarget |
39 | | * does not point to a new target. The event target chain is created in the |
40 | | * heap. |
41 | | * |
42 | | * If the event needs retargeting, mEventTargetAtParent must be set in |
43 | | * GetEventTargetParent. |
44 | | * |
45 | | * The capture, target and bubble phases of the event dispatch are handled |
46 | | * by iterating through the event target chain. Iteration happens twice, |
47 | | * first for the default event group and then for the system event group. |
48 | | * While dispatching the event for the system event group PostHandleEvent |
49 | | * is called right after calling event listener for the current event target. |
50 | | */ |
51 | | |
52 | | class EventChainVisitor |
53 | | { |
54 | | public: |
55 | | EventChainVisitor(nsPresContext* aPresContext, |
56 | | WidgetEvent* aEvent, |
57 | | dom::Event* aDOMEvent, |
58 | | nsEventStatus aEventStatus = nsEventStatus_eIgnore) |
59 | | : mPresContext(aPresContext) |
60 | | , mEvent(aEvent) |
61 | | , mDOMEvent(aDOMEvent) |
62 | | , mEventStatus(aEventStatus) |
63 | | , mItemFlags(0) |
64 | 0 | { |
65 | 0 | } |
66 | | |
67 | | /** |
68 | | * The prescontext, possibly nullptr. |
69 | | */ |
70 | | nsPresContext* const mPresContext; |
71 | | |
72 | | /** |
73 | | * The WidgetEvent which is being dispatched. Never nullptr. |
74 | | */ |
75 | | WidgetEvent* const mEvent; |
76 | | |
77 | | /** |
78 | | * The DOM Event assiciated with the mEvent. Possibly nullptr if a DOM Event |
79 | | * is not (yet) created. |
80 | | */ |
81 | | dom::Event* mDOMEvent; |
82 | | |
83 | | /** |
84 | | * The status of the event. |
85 | | * @see nsEventStatus.h |
86 | | */ |
87 | | nsEventStatus mEventStatus; |
88 | | |
89 | | /** |
90 | | * Bits for items in the event target chain. |
91 | | * Set in GetEventTargetParent() and used in PostHandleEvent(). |
92 | | * |
93 | | * @note These bits are different for each item in the event target chain. |
94 | | * It is up to the Pre/PostHandleEvent implementation to decide how to |
95 | | * use these bits. |
96 | | * |
97 | | * @note Using uint16_t because that is used also in EventTargetChainItem. |
98 | | */ |
99 | | uint16_t mItemFlags; |
100 | | |
101 | | /** |
102 | | * Data for items in the event target chain. |
103 | | * Set in GetEventTargetParent() and used in PostHandleEvent(). |
104 | | * |
105 | | * @note This data is different for each item in the event target chain. |
106 | | * It is up to the Pre/PostHandleEvent implementation to decide how to |
107 | | * use this. |
108 | | */ |
109 | | nsCOMPtr<nsISupports> mItemData; |
110 | | }; |
111 | | |
112 | | class EventChainPreVisitor : public EventChainVisitor |
113 | | { |
114 | | public: |
115 | | EventChainPreVisitor(nsPresContext* aPresContext, |
116 | | WidgetEvent* aEvent, |
117 | | dom::Event* aDOMEvent, |
118 | | nsEventStatus aEventStatus, |
119 | | bool aIsInAnon, |
120 | | dom::EventTarget* aTargetInKnownToBeHandledScope) |
121 | | : EventChainVisitor(aPresContext, aEvent, aDOMEvent, aEventStatus) |
122 | | , mCanHandle(true) |
123 | | , mAutomaticChromeDispatch(true) |
124 | | , mForceContentDispatch(false) |
125 | | , mRelatedTargetIsInAnon(false) |
126 | | , mOriginalTargetIsInAnon(aIsInAnon) |
127 | | , mWantsWillHandleEvent(false) |
128 | | , mMayHaveListenerManager(true) |
129 | | , mWantsPreHandleEvent(false) |
130 | | , mRootOfClosedTree(false) |
131 | | , mItemInShadowTree(false) |
132 | | , mParentIsSlotInClosedTree(false) |
133 | | , mParentIsChromeHandler(false) |
134 | | , mRelatedTargetRetargetedInCurrentScope(false) |
135 | | , mIgnoreBecauseOfShadowDOM(false) |
136 | | , mParentTarget(nullptr) |
137 | | , mEventTargetAtParent(nullptr) |
138 | | , mRetargetedRelatedTarget(nullptr) |
139 | | , mTargetInKnownToBeHandledScope(aTargetInKnownToBeHandledScope) |
140 | 0 | { |
141 | 0 | } |
142 | | |
143 | | void Reset() |
144 | 0 | { |
145 | 0 | mItemFlags = 0; |
146 | 0 | mItemData = nullptr; |
147 | 0 | mCanHandle = true; |
148 | 0 | mAutomaticChromeDispatch = true; |
149 | 0 | mForceContentDispatch = false; |
150 | 0 | mWantsWillHandleEvent = false; |
151 | 0 | mMayHaveListenerManager = true; |
152 | 0 | mWantsPreHandleEvent = false; |
153 | 0 | mRootOfClosedTree = false; |
154 | 0 | mItemInShadowTree = false; |
155 | 0 | mParentIsSlotInClosedTree = false; |
156 | 0 | mParentIsChromeHandler = false; |
157 | 0 | // Note, we don't clear mRelatedTargetRetargetedInCurrentScope explicitly, |
158 | 0 | // since it is used during event path creation to indicate whether |
159 | 0 | // relatedTarget may need to be retargeted. |
160 | 0 | mIgnoreBecauseOfShadowDOM = false; |
161 | 0 | mParentTarget = nullptr; |
162 | 0 | mEventTargetAtParent = nullptr; |
163 | 0 | mRetargetedRelatedTarget = nullptr; |
164 | 0 | mRetargetedTouchTargets.reset(); |
165 | 0 | } |
166 | | |
167 | | dom::EventTarget* GetParentTarget() |
168 | 0 | { |
169 | 0 | return mParentTarget; |
170 | 0 | } |
171 | | |
172 | | void SetParentTarget(dom::EventTarget* aParentTarget, bool aIsChromeHandler) |
173 | 0 | { |
174 | 0 | mParentTarget = aParentTarget; |
175 | 0 | if (mParentTarget) { |
176 | 0 | mParentIsChromeHandler = aIsChromeHandler; |
177 | 0 | } |
178 | 0 | } |
179 | | |
180 | | void IgnoreCurrentTargetBecauseOfShadowDOMRetargeting() |
181 | 0 | { |
182 | 0 | mCanHandle = false; |
183 | 0 | mIgnoreBecauseOfShadowDOM = true; |
184 | 0 | SetParentTarget(nullptr, false); |
185 | 0 | mEventTargetAtParent = nullptr; |
186 | 0 | } |
187 | | |
188 | | /** |
189 | | * Member that must be set in GetEventTargetParent by event targets. If set to |
190 | | * false, indicates that this event target will not be handling the event and |
191 | | * construction of the event target chain is complete. The target that sets |
192 | | * mCanHandle to false is NOT included in the event target chain. |
193 | | */ |
194 | | bool mCanHandle; |
195 | | |
196 | | /** |
197 | | * If mCanHandle is false and mAutomaticChromeDispatch is also false |
198 | | * event will not be dispatched to the chrome event handler. |
199 | | */ |
200 | | bool mAutomaticChromeDispatch; |
201 | | |
202 | | /** |
203 | | * If mForceContentDispatch is set to true, |
204 | | * content dispatching is not disabled for this event target. |
205 | | * FIXME! This is here for backward compatibility. Bug 329119 |
206 | | */ |
207 | | bool mForceContentDispatch; |
208 | | |
209 | | /** |
210 | | * true if it is known that related target is or is a descendant of an |
211 | | * element which is anonymous for events. |
212 | | */ |
213 | | bool mRelatedTargetIsInAnon; |
214 | | |
215 | | /** |
216 | | * true if the original target of the event is inside anonymous content. |
217 | | * This is set before calling GetEventTargetParent on event targets. |
218 | | */ |
219 | | bool mOriginalTargetIsInAnon; |
220 | | |
221 | | /** |
222 | | * Whether or not EventTarget::WillHandleEvent will be |
223 | | * called. Default is false; |
224 | | */ |
225 | | bool mWantsWillHandleEvent; |
226 | | |
227 | | /** |
228 | | * If it is known that the current target doesn't have a listener manager |
229 | | * when GetEventTargetParent is called, set this to false. |
230 | | */ |
231 | | bool mMayHaveListenerManager; |
232 | | |
233 | | /** |
234 | | * Whether or not EventTarget::PreHandleEvent will be called. Default is |
235 | | * false; |
236 | | */ |
237 | | bool mWantsPreHandleEvent; |
238 | | |
239 | | /** |
240 | | * True if the current target is either closed ShadowRoot or root of |
241 | | * chrome only access tree (for example native anonymous content). |
242 | | */ |
243 | | bool mRootOfClosedTree; |
244 | | |
245 | | /** |
246 | | * If target is node and its root is a shadow root. |
247 | | * https://dom.spec.whatwg.org/#event-path-item-in-shadow-tree |
248 | | */ |
249 | | bool mItemInShadowTree; |
250 | | |
251 | | /** |
252 | | * True if mParentTarget is HTMLSlotElement in a closed shadow tree and the |
253 | | * current target is assigned to that slot. |
254 | | */ |
255 | | bool mParentIsSlotInClosedTree; |
256 | | |
257 | | /** |
258 | | * True if mParentTarget is a chrome handler in the event path. |
259 | | */ |
260 | | bool mParentIsChromeHandler; |
261 | | |
262 | | /** |
263 | | * True if event's related target has been already retargeted in the |
264 | | * current 'scope'. This should be set to false initially and whenever |
265 | | * event path creation crosses shadow boundary. |
266 | | */ |
267 | | bool mRelatedTargetRetargetedInCurrentScope; |
268 | | |
269 | | /** |
270 | | * True if Shadow DOM relatedTarget retargeting causes the current item |
271 | | * to not show up in the event path. |
272 | | */ |
273 | | bool mIgnoreBecauseOfShadowDOM; |
274 | | private: |
275 | | /** |
276 | | * Parent item in the event target chain. |
277 | | */ |
278 | | dom::EventTarget* mParentTarget; |
279 | | |
280 | | public: |
281 | | /** |
282 | | * If the event needs to be retargeted, this is the event target, |
283 | | * which should be used when the event is handled at mParentTarget. |
284 | | */ |
285 | | dom::EventTarget* mEventTargetAtParent; |
286 | | |
287 | | /** |
288 | | * If the related target of the event needs to be retargeted, set this |
289 | | * to a new EventTarget. |
290 | | */ |
291 | | dom::EventTarget* mRetargetedRelatedTarget; |
292 | | |
293 | | /** |
294 | | * If mEvent is a WidgetTouchEvent and its mTouches needs retargeting, |
295 | | * set the targets to this array. The array should contain one entry per |
296 | | * each object in WidgetTouchEvent::mTouches. |
297 | | */ |
298 | | mozilla::Maybe<nsTArray<RefPtr<dom::EventTarget>>> mRetargetedTouchTargets; |
299 | | |
300 | | /** |
301 | | * Set to the value of mEvent->mTarget of the previous scope in case of |
302 | | * Shadow DOM or such, and if there is no anonymous content this just points |
303 | | * to the initial target. |
304 | | */ |
305 | | dom::EventTarget* mTargetInKnownToBeHandledScope; |
306 | | }; |
307 | | |
308 | | class EventChainPostVisitor : public mozilla::EventChainVisitor |
309 | | { |
310 | | public: |
311 | | explicit EventChainPostVisitor(EventChainVisitor& aOther) |
312 | | : EventChainVisitor(aOther.mPresContext, aOther.mEvent, |
313 | | aOther.mDOMEvent, aOther.mEventStatus) |
314 | 0 | { |
315 | 0 | } |
316 | | }; |
317 | | |
318 | | /** |
319 | | * If an EventDispatchingCallback object is passed to Dispatch, |
320 | | * its HandleEvent method is called after handling the default event group, |
321 | | * before handling the system event group. |
322 | | * This is used in nsPresShell. |
323 | | */ |
324 | | class MOZ_STACK_CLASS EventDispatchingCallback |
325 | | { |
326 | | public: |
327 | | virtual void HandleEvent(EventChainPostVisitor& aVisitor) = 0; |
328 | | }; |
329 | | |
330 | | /** |
331 | | * The generic class for event dispatching. |
332 | | * Must not be used outside Gecko! |
333 | | */ |
334 | | class EventDispatcher |
335 | | { |
336 | | public: |
337 | | /** |
338 | | * aTarget should QI to EventTarget. |
339 | | * If the target of aEvent is set before calling this method, the target of |
340 | | * aEvent is used as the target (unless there is event |
341 | | * retargeting) and the originalTarget of the DOM Event. |
342 | | * aTarget is always used as the starting point for constructing the event |
343 | | * target chain, no matter what the value of aEvent->mTarget is. |
344 | | * In other words, aEvent->mTarget is only a property of the event and it has |
345 | | * nothing to do with the construction of the event target chain. |
346 | | * Neither aTarget nor aEvent is allowed to be nullptr. |
347 | | * |
348 | | * If aTargets is non-null, event target chain will be created, but |
349 | | * event won't be handled. In this case aEvent->mMessage should be |
350 | | * eVoidEvent. |
351 | | * @note Use this method when dispatching a WidgetEvent. |
352 | | */ |
353 | | static nsresult Dispatch(nsISupports* aTarget, |
354 | | nsPresContext* aPresContext, |
355 | | WidgetEvent* aEvent, |
356 | | dom::Event* aDOMEvent = nullptr, |
357 | | nsEventStatus* aEventStatus = nullptr, |
358 | | EventDispatchingCallback* aCallback = nullptr, |
359 | | nsTArray<dom::EventTarget*>* aTargets = nullptr); |
360 | | |
361 | | /** |
362 | | * Dispatches an event. |
363 | | * If aDOMEvent is not nullptr, it is used for dispatching |
364 | | * (aEvent can then be nullptr) and (if aDOMEvent is not |trusted| already), |
365 | | * the |trusted| flag is set based on the UniversalXPConnect capability. |
366 | | * Otherwise this works like EventDispatcher::Dispatch. |
367 | | * @note Use this method when dispatching a dom::Event. |
368 | | */ |
369 | | static nsresult DispatchDOMEvent(nsISupports* aTarget, |
370 | | WidgetEvent* aEvent, |
371 | | dom::Event* aDOMEvent, |
372 | | nsPresContext* aPresContext, |
373 | | nsEventStatus* aEventStatus); |
374 | | |
375 | | /** |
376 | | * Creates a DOM Event. Returns null if the event type is unsupported. |
377 | | */ |
378 | | static already_AddRefed<dom::Event> CreateEvent(dom::EventTarget* aOwner, |
379 | | nsPresContext* aPresContext, |
380 | | WidgetEvent* aEvent, |
381 | | const nsAString& aEventType, |
382 | | dom::CallerType aCallerType = |
383 | | dom::CallerType::System); |
384 | | |
385 | | static void GetComposedPathFor(WidgetEvent* aEvent, |
386 | | nsTArray<RefPtr<dom::EventTarget>>& aPath); |
387 | | |
388 | | /** |
389 | | * Called at shutting down. |
390 | | */ |
391 | | static void Shutdown(); |
392 | | }; |
393 | | |
394 | | } // namespace mozilla |
395 | | |
396 | | #endif // mozilla_EventDispatcher_h_ |
397 | | #endif |