Coverage Report

Created: 2018-09-25 14:53

/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