Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/BasicEvents.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* This Source Code Form is subject to the terms of the Mozilla Public
3
 * License, v. 2.0. If a copy of the MPL was not distributed with this
4
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6
#ifndef mozilla_BasicEvents_h__
7
#define mozilla_BasicEvents_h__
8
9
#include <stdint.h>
10
11
#include "mozilla/dom/EventTarget.h"
12
#include "mozilla/EventForwards.h"
13
#include "mozilla/TimeStamp.h"
14
#include "nsCOMPtr.h"
15
#include "nsAtom.h"
16
#include "nsISupportsImpl.h"
17
#include "nsIWidget.h"
18
#include "nsString.h"
19
#include "Units.h"
20
21
#ifdef DEBUG
22
#include "nsXULAppAPI.h"
23
#endif // #ifdef DEBUG
24
25
namespace IPC {
26
template<typename T>
27
struct ParamTraits;
28
} // namespace IPC
29
30
namespace mozilla {
31
32
class EventTargetChainItem;
33
34
enum class CrossProcessForwarding
35
{
36
  // eStop prevents the event to be sent to remote process.
37
  eStop,
38
  // eAllow keeps current state of the event whether it's sent to remote
39
  // process.  In other words, eAllow does NOT mean that making the event
40
  // sent to remote process when IsCrossProcessForwardingStopped() returns
41
  // true.
42
  eAllow,
43
};
44
45
/******************************************************************************
46
 * mozilla::BaseEventFlags
47
 *
48
 * BaseEventFlags must be a POD struct for safe to use memcpy (including
49
 * in ParamTraits<BaseEventFlags>).  So don't make virtual methods, constructor,
50
 * destructor and operators.
51
 * This is necessary for VC which is NOT C++0x compiler.
52
 ******************************************************************************/
53
54
struct BaseEventFlags
55
{
56
public:
57
  // If mIsTrusted is true, the event is a trusted event.  Otherwise, it's
58
  // an untrusted event.
59
  bool    mIsTrusted : 1;
60
  // If mInBubblingPhase is true, the event is in bubbling phase or target
61
  // phase.
62
  bool    mInBubblingPhase : 1;
63
  // If mInCapturePhase is true, the event is in capture phase or target phase.
64
  bool    mInCapturePhase : 1;
65
  // If mInSystemGroup is true, the event is being dispatched in system group.
66
  bool    mInSystemGroup: 1;
67
  // If mCancelable is true, the event can be consumed.  I.e., calling
68
  // dom::Event::PreventDefault() can prevent the default action.
69
  bool    mCancelable : 1;
70
  // If mBubbles is true, the event can bubble.  Otherwise, cannot be handled
71
  // in bubbling phase.
72
  bool    mBubbles : 1;
73
  // If mPropagationStopped is true, dom::Event::StopPropagation() or
74
  // dom::Event::StopImmediatePropagation() has been called.
75
  bool    mPropagationStopped : 1;
76
  // If mImmediatePropagationStopped is true,
77
  // dom::Event::StopImmediatePropagation() has been called.
78
  // Note that mPropagationStopped must be true when this is true.
79
  bool    mImmediatePropagationStopped : 1;
80
  // If mDefaultPrevented is true, the event has been consumed.
81
  // E.g., dom::Event::PreventDefault() has been called or
82
  // the default action has been performed.
83
  bool    mDefaultPrevented : 1;
84
  // If mDefaultPreventedByContent is true, the event has been
85
  // consumed by content.
86
  // Note that mDefaultPrevented must be true when this is true.
87
  bool    mDefaultPreventedByContent : 1;
88
  // If mDefaultPreventedByChrome is true, the event has been
89
  // consumed by chrome.
90
  // Note that mDefaultPrevented must be true when this is true.
91
  bool    mDefaultPreventedByChrome : 1;
92
  // mMultipleActionsPrevented may be used when default handling don't want to
93
  // be prevented, but only one of the event targets should handle the event.
94
  // For example, when a <label> element is in another <label> element and
95
  // the first <label> element is clicked, that one may set this true.
96
  // Then, the second <label> element won't handle the event.
97
  bool    mMultipleActionsPrevented : 1;
98
  // If mIsBeingDispatched is true, the DOM event created from the event is
99
  // dispatching into the DOM tree and not completed.
100
  bool    mIsBeingDispatched : 1;
101
  // If mDispatchedAtLeastOnce is true, the event has been dispatched
102
  // as a DOM event and the dispatch has been completed.
103
  bool    mDispatchedAtLeastOnce : 1;
104
  // If mIsSynthesizedForTests is true, the event has been synthesized for
105
  // automated tests or something hacky approach of an add-on.
106
  bool    mIsSynthesizedForTests : 1;
107
  // If mExceptionWasRaised is true, one of the event handlers has raised an
108
  // exception.
109
  bool    mExceptionWasRaised : 1;
110
  // If mRetargetToNonNativeAnonymous is true and the target is in a non-native
111
  // native anonymous subtree, the event target is set to mOriginalTarget.
112
  bool    mRetargetToNonNativeAnonymous : 1;
113
  // If mNoContentDispatch is true, the event is never dispatched to the
114
  // event handlers which are added to the contents, onfoo attributes and
115
  // properties.  Note that this flag is ignored when
116
  // EventChainPreVisitor::mForceContentDispatch is set true.  For exapmle,
117
  // window and document object sets it true.  Therefore, web applications
118
  // can handle the event if they add event listeners to the window or the
119
  // document.
120
  // XXX This is an ancient and broken feature, don't use this for new bug
121
  //     as far as possible.
122
  bool    mNoContentDispatch : 1;
123
  // If mOnlyChromeDispatch is true, the event is dispatched to only chrome.
124
  bool    mOnlyChromeDispatch : 1;
125
  // Indicates if the key combination is reserved by chrome.  This is set by
126
  // MarkAsReservedByChrome().
127
  bool mIsReservedByChrome : 1;
128
  // If mOnlySystemGroupDispatchInContent is true, event listeners added to
129
  // the default group for non-chrome EventTarget won't be called.
130
  // Be aware, if this is true, EventDispatcher needs to check if each event
131
  // listener is added to chrome node, so, don't set this to true for the
132
  // events which are fired a lot of times like eMouseMove.
133
  bool    mOnlySystemGroupDispatchInContent : 1;
134
  // The event's action will be handled by APZ. The main thread should not
135
  // perform its associated action. This is currently only relevant for
136
  // wheel and touch events.
137
  bool mHandledByAPZ : 1;
138
  // True if the event is currently being handled by an event listener that
139
  // was registered as a passive listener.
140
  bool mInPassiveListener: 1;
141
  // If mComposed is true, the event fired by nodes in shadow DOM can cross the
142
  // boundary of shadow DOM and light DOM.
143
  bool mComposed : 1;
144
  // Similar to mComposed. Set it to true to allow events cross the boundary
145
  // between native non-anonymous content and native anonymouse content
146
  bool mComposedInNativeAnonymousContent : 1;
147
  // Set to true for events which are suppressed or delayed so that later a
148
  // DelayedEvent of it is dispatched. This is used when parent side process
149
  // the key event after content side, and may drop the event if the event
150
  // was suppressed or delayed in contents side.
151
  // It is also set to true for the events (in a DelayedInputEvent), which will
152
  // be dispatched afterwards.
153
  bool mIsSuppressedOrDelayed : 1;
154
  // Certain mouse events can be marked as positionless to return 0 from
155
  // coordinate related getters.
156
  bool mIsPositionless : 1;
157
158
  // Flags managing state of propagation between processes.
159
  // Note the the following flags shouldn't be referred directly.  Use utility
160
  // methods instead.
161
162
  // If mNoRemoteProcessDispatch is true, the event is not allowed to be sent
163
  // to remote process.
164
  bool mNoRemoteProcessDispatch : 1;
165
  // If mWantReplyFromContentProcess is true, the event will be redispatched
166
  // in the parent process after the content process has handled it. Useful
167
  // for when the parent process need the know first how the event was used
168
  // by content before handling it itself.
169
  bool mWantReplyFromContentProcess : 1;
170
  // If mPostedToRemoteProcess is true, the event has been posted to the
171
  // remote process (but it's not handled yet if it's not a duplicated event
172
  // instance).
173
  bool mPostedToRemoteProcess : 1;
174
175
  // If the event is being handled in target phase, returns true.
176
  inline bool InTargetPhase() const
177
0
  {
178
0
    return (mInBubblingPhase && mInCapturePhase);
179
0
  }
180
181
  /**
182
   * Helper methods for methods of DOM Event.
183
   */
184
  inline void StopPropagation()
185
0
  {
186
0
    mPropagationStopped = true;
187
0
  }
188
  inline void StopImmediatePropagation()
189
0
  {
190
0
    StopPropagation();
191
0
    mImmediatePropagationStopped = true;
192
0
  }
193
  inline void PreventDefault(bool aCalledByDefaultHandler = true)
194
0
  {
195
0
    if (!mCancelable) {
196
0
      return;
197
0
    }
198
0
    mDefaultPrevented = true;
199
0
    // Note that even if preventDefault() has already been called by chrome,
200
0
    // a call of preventDefault() by content needs to overwrite
201
0
    // mDefaultPreventedByContent to true because in such case, defaultPrevented
202
0
    // must be true when web apps check it after they call preventDefault().
203
0
    if (aCalledByDefaultHandler) {
204
0
      StopCrossProcessForwarding();
205
0
      mDefaultPreventedByChrome = true;
206
0
    } else {
207
0
      mDefaultPreventedByContent = true;
208
0
    }
209
0
  }
210
  // This should be used only before dispatching events into the DOM tree.
211
  inline void
212
  PreventDefaultBeforeDispatch(CrossProcessForwarding aCrossProcessForwarding)
213
0
  {
214
0
    if (!mCancelable) {
215
0
      return;
216
0
    }
217
0
    mDefaultPrevented = true;
218
0
    if (aCrossProcessForwarding == CrossProcessForwarding::eStop) {
219
0
      StopCrossProcessForwarding();
220
0
    }
221
0
  }
222
  inline bool DefaultPrevented() const
223
0
  {
224
0
    return mDefaultPrevented;
225
0
  }
226
  inline bool DefaultPreventedByContent() const
227
0
  {
228
0
    MOZ_ASSERT(!mDefaultPreventedByContent || DefaultPrevented());
229
0
    return mDefaultPreventedByContent;
230
0
  }
231
  inline bool IsTrusted() const
232
0
  {
233
0
    return mIsTrusted;
234
0
  }
235
  inline bool PropagationStopped() const
236
0
  {
237
0
    return mPropagationStopped;
238
0
  }
239
240
  // Helper methods to access flags managing state of propagation between
241
  // processes.
242
243
  /**
244
   * Prevent to be dispatched to remote process.
245
   */
246
  inline void StopCrossProcessForwarding()
247
0
  {
248
0
    MOZ_ASSERT(!mPostedToRemoteProcess);
249
0
    mNoRemoteProcessDispatch = true;
250
0
    mWantReplyFromContentProcess = false;
251
0
  }
252
  /**
253
   * Return true if the event shouldn't be dispatched to remote process.
254
   */
255
  inline bool IsCrossProcessForwardingStopped() const
256
0
  {
257
0
    return mNoRemoteProcessDispatch;
258
0
  }
259
  /**
260
   * Mark the event as waiting reply from remote process.
261
   * If the caller needs to win other keyboard event handlers in chrome,
262
   * the caller should call StopPropagation() too.
263
   * Otherwise, if the caller just needs to know if the event is consumed by
264
   * either content or chrome, it should just call this because the event
265
   * may be reserved by chrome and it needs to be dispatched into the DOM
266
   * tree in chrome for checking if it's reserved before being sent to any
267
   * remote processes.
268
   */
269
  inline void MarkAsWaitingReplyFromRemoteProcess()
270
0
  {
271
0
    MOZ_ASSERT(!mPostedToRemoteProcess);
272
0
    mNoRemoteProcessDispatch = false;
273
0
    mWantReplyFromContentProcess = true;
274
0
  }
275
  /**
276
   * Reset "waiting reply from remote process" state.  This is useful when
277
   * you dispatch a copy of an event coming from different process.
278
   */
279
  inline void ResetWaitingReplyFromRemoteProcessState()
280
0
  {
281
0
    if (IsWaitingReplyFromRemoteProcess()) {
282
0
      // FYI: mWantReplyFromContentProcess is also used for indicating
283
0
      //      "handled in remote process" state.  Therefore, only when
284
0
      //      IsWaitingReplyFromRemoteProcess() returns true, this should
285
0
      //      reset the flag.
286
0
      mWantReplyFromContentProcess = false;
287
0
    }
288
0
  }
289
  /**
290
   * Return true if the event handler should wait reply event.  I.e., if this
291
   * returns true, any event handler should do nothing with the event.
292
   */
293
  inline bool IsWaitingReplyFromRemoteProcess() const
294
0
  {
295
0
    return !mNoRemoteProcessDispatch && mWantReplyFromContentProcess;
296
0
  }
297
  /**
298
   * Mark the event as already handled in the remote process.  This should be
299
   * called when initializing reply events.
300
   */
301
  inline void MarkAsHandledInRemoteProcess()
302
0
  {
303
0
    mNoRemoteProcessDispatch = true;
304
0
    mWantReplyFromContentProcess = true;
305
0
    mPostedToRemoteProcess = false;
306
0
  }
307
  /**
308
   * Return true if the event has already been handled in the remote process.
309
   */
310
  inline bool IsHandledInRemoteProcess() const
311
0
  {
312
0
    return mNoRemoteProcessDispatch && mWantReplyFromContentProcess;
313
0
  }
314
  /**
315
   * Return true if the event should be sent back to its parent process.
316
   */
317
  inline bool WantReplyFromContentProcess() const
318
0
  {
319
0
    MOZ_ASSERT(!XRE_IsParentProcess());
320
0
    return IsWaitingReplyFromRemoteProcess();
321
0
  }
322
  /**
323
   * Mark the event has already posted to a remote process.
324
   */
325
  inline void MarkAsPostedToRemoteProcess()
326
0
  {
327
0
    MOZ_ASSERT(!IsCrossProcessForwardingStopped());
328
0
    mPostedToRemoteProcess = true;
329
0
  }
330
  /**
331
   * Reset the cross process dispatching state.  This should be used when a
332
   * process receives the event because the state is in the sender.
333
   */
334
  inline void ResetCrossProcessDispatchingState()
335
0
  {
336
0
    MOZ_ASSERT(!IsCrossProcessForwardingStopped());
337
0
    mPostedToRemoteProcess = false;
338
0
    // Ignore propagation state in the different process if it's marked as
339
0
    // "waiting reply from remote process" because the process needs to
340
0
    // stop propagation in the process until receiving a reply event.
341
0
    if (IsWaitingReplyFromRemoteProcess()) {
342
0
      mPropagationStopped = mImmediatePropagationStopped = false;
343
0
    }
344
0
  }
345
  /**
346
   * Return true if the event has been posted to a remote process.
347
   * Note that MarkAsPostedToRemoteProcess() is called by
348
   * ParamTraits<mozilla::WidgetEvent>.  Therefore, it *might* be possible
349
   * that posting the event failed even if this returns true.  But that must
350
   * really rare.  If that'd be problem for you, you should unmark this in
351
   * TabParent or somewhere.
352
   */
353
  inline bool HasBeenPostedToRemoteProcess() const
354
0
  {
355
0
    return mPostedToRemoteProcess;
356
0
  }
357
  /**
358
   * Mark the event is reserved by chrome.  I.e., shouldn't be dispatched to
359
   * content because it shouldn't be cancelable.
360
   */
361
  inline void MarkAsReservedByChrome()
362
0
  {
363
0
    MOZ_ASSERT(!mPostedToRemoteProcess);
364
0
    mIsReservedByChrome = true;
365
0
    // For reserved commands (such as Open New Tab), we don't need to wait for
366
0
    // the content to answer, neither to give a chance for content to override
367
0
    // its behavior.
368
0
    StopCrossProcessForwarding();
369
0
    // If the event is reserved by chrome, we shouldn't expose the event to
370
0
    // web contents because such events shouldn't be cancelable.  So, it's not
371
0
    // good behavior to fire such events but to ignore the defaultPrevented
372
0
    // attribute value in chrome.
373
0
    mOnlySystemGroupDispatchInContent = true;
374
0
  }
375
  /**
376
   * Return true if the event is reserved by chrome.
377
   */
378
  inline bool IsReservedByChrome() const
379
0
  {
380
0
    MOZ_ASSERT(!mIsReservedByChrome ||
381
0
               (IsCrossProcessForwardingStopped() &&
382
0
                mOnlySystemGroupDispatchInContent));
383
0
    return mIsReservedByChrome;
384
0
  }
385
386
  inline void Clear()
387
0
  {
388
0
    SetRawFlags(0);
389
0
  }
390
  // Get if either the instance's bit or the aOther's bit is true, the
391
  // instance's bit becomes true.  In other words, this works like:
392
  // eventFlags |= aOther;
393
  inline void Union(const BaseEventFlags& aOther)
394
0
  {
395
0
    RawFlags rawFlags = GetRawFlags() | aOther.GetRawFlags();
396
0
    SetRawFlags(rawFlags);
397
0
  }
398
399
private:
400
  typedef uint32_t RawFlags;
401
402
  inline void SetRawFlags(RawFlags aRawFlags)
403
0
  {
404
0
    static_assert(sizeof(BaseEventFlags) <= sizeof(RawFlags),
405
0
      "mozilla::EventFlags must not be bigger than the RawFlags");
406
0
    memcpy(this, &aRawFlags, sizeof(BaseEventFlags));
407
0
  }
408
  inline RawFlags GetRawFlags() const
409
0
  {
410
0
    RawFlags result = 0;
411
0
    memcpy(&result, this, sizeof(BaseEventFlags));
412
0
    return result;
413
0
  }
414
};
415
416
/******************************************************************************
417
 * mozilla::EventFlags
418
 ******************************************************************************/
419
420
struct EventFlags : public BaseEventFlags
421
{
422
  EventFlags()
423
0
  {
424
0
    Clear();
425
0
  }
426
};
427
428
/******************************************************************************
429
 * mozilla::WidgetEventTime
430
 ******************************************************************************/
431
432
class WidgetEventTime
433
{
434
public:
435
  // Elapsed time, in milliseconds, from a platform-specific zero time
436
  // to the time the message was created
437
  uint64_t mTime;
438
  // Timestamp when the message was created. Set in parallel to 'time' until we
439
  // determine if it is safe to drop 'time' (see bug 77992).
440
  TimeStamp mTimeStamp;
441
442
  WidgetEventTime()
443
    : mTime(0)
444
    , mTimeStamp(TimeStamp::Now())
445
0
  {
446
0
  }
447
448
  WidgetEventTime(uint64_t aTime,
449
                  TimeStamp aTimeStamp)
450
    : mTime(aTime)
451
    , mTimeStamp(aTimeStamp)
452
0
  {
453
0
  }
454
455
  void AssignEventTime(const WidgetEventTime& aOther)
456
0
  {
457
0
    mTime = aOther.mTime;
458
0
    mTimeStamp = aOther.mTimeStamp;
459
0
  }
460
};
461
462
/******************************************************************************
463
 * mozilla::WidgetEvent
464
 ******************************************************************************/
465
466
class WidgetEvent : public WidgetEventTime
467
{
468
private:
469
  void SetDefaultCancelableAndBubbles()
470
0
  {
471
0
    switch (mClass) {
472
0
      case eEditorInputEventClass:
473
0
        mFlags.mCancelable = false;
474
0
        mFlags.mBubbles = mFlags.mIsTrusted;
475
0
        break;
476
0
      case eMouseEventClass:
477
0
        mFlags.mCancelable = (mMessage != eMouseEnter &&
478
0
                              mMessage != eMouseLeave);
479
0
        mFlags.mBubbles = (mMessage != eMouseEnter &&
480
0
                           mMessage != eMouseLeave);
481
0
        break;
482
0
      case ePointerEventClass:
483
0
        mFlags.mCancelable = (mMessage != ePointerEnter &&
484
0
                              mMessage != ePointerLeave &&
485
0
                              mMessage != ePointerCancel &&
486
0
                              mMessage != ePointerGotCapture &&
487
0
                              mMessage != ePointerLostCapture);
488
0
        mFlags.mBubbles = (mMessage != ePointerEnter &&
489
0
                           mMessage != ePointerLeave);
490
0
        break;
491
0
      case eDragEventClass:
492
0
        mFlags.mCancelable = (mMessage != eDragExit &&
493
0
                              mMessage != eDragLeave &&
494
0
                              mMessage != eDragEnd);
495
0
        mFlags.mBubbles = true;
496
0
        break;
497
0
      case eSMILTimeEventClass:
498
0
        mFlags.mCancelable = false;
499
0
        mFlags.mBubbles = false;
500
0
        break;
501
0
      case eTransitionEventClass:
502
0
      case eAnimationEventClass:
503
0
        mFlags.mCancelable = false;
504
0
        mFlags.mBubbles = true;
505
0
        break;
506
0
      case eCompositionEventClass:
507
0
        // XXX compositionstart is cancelable in draft of DOM3 Events.
508
0
        //     However, it doesn't make sense for us, we cannot cancel
509
0
        //     composition when we send compositionstart event.
510
0
        mFlags.mCancelable = false;
511
0
        mFlags.mBubbles = true;
512
0
        break;
513
0
      default:
514
0
        if (mMessage == eResize) {
515
0
          mFlags.mCancelable = false;
516
0
        } else {
517
0
          mFlags.mCancelable = true;
518
0
        }
519
0
        mFlags.mBubbles = true;
520
0
        break;
521
0
    }
522
0
  }
523
524
protected:
525
  WidgetEvent(bool aIsTrusted,
526
              EventMessage aMessage,
527
              EventClassID aEventClassID)
528
    : WidgetEventTime()
529
    , mClass(aEventClassID)
530
    , mMessage(aMessage)
531
    , mRefPoint(0, 0)
532
    , mLastRefPoint(0, 0)
533
    , mFocusSequenceNumber(0)
534
    , mSpecifiedEventType(nullptr)
535
    , mPath(nullptr)
536
0
  {
537
0
    MOZ_COUNT_CTOR(WidgetEvent);
538
0
    mFlags.Clear();
539
0
    mFlags.mIsTrusted = aIsTrusted;
540
0
    SetDefaultCancelableAndBubbles();
541
0
    SetDefaultComposed();
542
0
    SetDefaultComposedInNativeAnonymousContent();
543
0
  }
544
545
  WidgetEvent()
546
    : WidgetEventTime()
547
    , mPath(nullptr)
548
0
  {
549
0
    MOZ_COUNT_CTOR(WidgetEvent);
550
0
  }
551
552
public:
553
  WidgetEvent(bool aIsTrusted, EventMessage aMessage)
554
    : WidgetEvent(aIsTrusted, aMessage, eBasicEventClass)
555
0
  {
556
0
  }
557
558
  virtual ~WidgetEvent()
559
0
  {
560
0
    MOZ_COUNT_DTOR(WidgetEvent);
561
0
  }
562
563
  WidgetEvent(const WidgetEvent& aOther)
564
    : WidgetEventTime()
565
0
  {
566
0
    MOZ_COUNT_CTOR(WidgetEvent);
567
0
    *this = aOther;
568
0
  }
569
0
  WidgetEvent& operator=(const WidgetEvent& aOther) = default;
570
571
  WidgetEvent(WidgetEvent&& aOther)
572
    : WidgetEventTime(std::move(aOther))
573
    , mClass(aOther.mClass)
574
    , mMessage(aOther.mMessage)
575
    , mRefPoint(std::move(aOther.mRefPoint))
576
    , mLastRefPoint(std::move(aOther.mLastRefPoint))
577
    , mFocusSequenceNumber(aOther.mFocusSequenceNumber)
578
    , mFlags(std::move(aOther.mFlags))
579
    , mSpecifiedEventType(std::move(aOther.mSpecifiedEventType))
580
    , mSpecifiedEventTypeString(std::move(aOther.mSpecifiedEventTypeString))
581
    , mTarget(std::move(aOther.mTarget))
582
    , mCurrentTarget(std::move(aOther.mCurrentTarget))
583
    , mOriginalTarget(std::move(aOther.mOriginalTarget))
584
    , mRelatedTarget(std::move(aOther.mRelatedTarget))
585
    , mOriginalRelatedTarget(std::move(aOther.mOriginalRelatedTarget))
586
    , mPath(std::move(aOther.mPath))
587
0
  {
588
0
    MOZ_COUNT_CTOR(WidgetEvent);
589
0
  }
590
  WidgetEvent& operator=(WidgetEvent&& aOther) = default;
591
592
  virtual WidgetEvent* Duplicate() const
593
0
  {
594
0
    MOZ_ASSERT(mClass == eBasicEventClass,
595
0
               "Duplicate() must be overridden by sub class");
596
0
    WidgetEvent* result = new WidgetEvent(false, mMessage);
597
0
    result->AssignEventData(*this, true);
598
0
    result->mFlags = mFlags;
599
0
    return result;
600
0
  }
601
602
  EventClassID mClass;
603
  EventMessage mMessage;
604
  // Relative to the widget of the event, or if there is no widget then it is
605
  // in screen coordinates. Not modified by layout code.
606
  LayoutDeviceIntPoint mRefPoint;
607
  // The previous mRefPoint, if known, used to calculate mouse movement deltas.
608
  LayoutDeviceIntPoint mLastRefPoint;
609
  // The sequence number of the last potentially focus changing event handled
610
  // by APZ. This is used to track when that event has been processed by content,
611
  // and focus can be reconfirmed for async keyboard scrolling.
612
  uint64_t mFocusSequenceNumber;
613
  // See BaseEventFlags definition for the detail.
614
  BaseEventFlags mFlags;
615
616
  // If JS creates an event with unknown event type or known event type but
617
  // for different event interface, the event type is stored to this.
618
  // NOTE: This is always used if the instance is a WidgetCommandEvent instance.
619
  RefPtr<nsAtom> mSpecifiedEventType;
620
621
  // nsAtom isn't available on non-main thread due to unsafe.  Therefore,
622
  // mSpecifiedEventTypeString is used instead of mSpecifiedEventType if
623
  // the event is created in non-main thread.
624
  nsString mSpecifiedEventTypeString;
625
626
  // Event targets, needed by DOM Events
627
  // Note that when you need event target for DOM event, you should use
628
  // Get*DOMEventTarget() instead of accessing these members directly.
629
  nsCOMPtr<dom::EventTarget> mTarget;
630
  nsCOMPtr<dom::EventTarget> mCurrentTarget;
631
  nsCOMPtr<dom::EventTarget> mOriginalTarget;
632
633
  /// The possible related target
634
  nsCOMPtr<dom::EventTarget> mRelatedTarget;
635
  nsCOMPtr<dom::EventTarget> mOriginalRelatedTarget;
636
637
  nsTArray<EventTargetChainItem>* mPath;
638
639
  dom::EventTarget* GetDOMEventTarget() const;
640
  dom::EventTarget* GetCurrentDOMEventTarget() const;
641
  dom::EventTarget* GetOriginalDOMEventTarget() const;
642
643
  void AssignEventData(const WidgetEvent& aEvent, bool aCopyTargets)
644
0
  {
645
0
    // mClass should be initialized with the constructor.
646
0
    // mMessage should be initialized with the constructor.
647
0
    mRefPoint = aEvent.mRefPoint;
648
0
    // mLastRefPoint doesn't need to be copied.
649
0
    mFocusSequenceNumber = aEvent.mFocusSequenceNumber;
650
0
    AssignEventTime(aEvent);
651
0
    // mFlags should be copied manually if it's necessary.
652
0
    mSpecifiedEventType = aEvent.mSpecifiedEventType;
653
0
    // mSpecifiedEventTypeString should be copied manually if it's necessary.
654
0
    mTarget = aCopyTargets ? aEvent.mTarget : nullptr;
655
0
    mCurrentTarget = aCopyTargets ? aEvent.mCurrentTarget : nullptr;
656
0
    mOriginalTarget = aCopyTargets ? aEvent.mOriginalTarget : nullptr;
657
0
    mRelatedTarget = aCopyTargets ? aEvent.mRelatedTarget : nullptr;
658
0
    mOriginalRelatedTarget =
659
0
      aCopyTargets ? aEvent.mOriginalRelatedTarget : nullptr;
660
0
  }
661
662
  /**
663
   * Helper methods for methods of DOM Event.
664
   */
665
0
  void StopPropagation() { mFlags.StopPropagation(); }
666
0
  void StopImmediatePropagation() { mFlags.StopImmediatePropagation(); }
667
  void PreventDefault(bool aCalledByDefaultHandler = true,
668
                      nsIPrincipal* aPrincipal = nullptr);
669
670
  void
671
  PreventDefaultBeforeDispatch(CrossProcessForwarding aCrossProcessForwarding)
672
0
  {
673
0
    mFlags.PreventDefaultBeforeDispatch(aCrossProcessForwarding);
674
0
  }
675
0
  bool DefaultPrevented() const { return mFlags.DefaultPrevented(); }
676
  bool DefaultPreventedByContent() const
677
0
  {
678
0
    return mFlags.DefaultPreventedByContent();
679
0
  }
680
0
  bool IsTrusted() const { return mFlags.IsTrusted(); }
681
0
  bool PropagationStopped() const { return mFlags.PropagationStopped(); }
682
683
  /**
684
   * Prevent to be dispatched to remote process.
685
   */
686
  inline void StopCrossProcessForwarding()
687
0
  {
688
0
    mFlags.StopCrossProcessForwarding();
689
0
  }
690
  /**
691
   * Return true if the event shouldn't be dispatched to remote process.
692
   */
693
  inline bool IsCrossProcessForwardingStopped() const
694
0
  {
695
0
    return mFlags.IsCrossProcessForwardingStopped();
696
0
  }
697
  /**
698
   * Mark the event as waiting reply from remote process.
699
   * Note that this also stops immediate propagation in current process.
700
   */
701
  inline void MarkAsWaitingReplyFromRemoteProcess()
702
0
  {
703
0
    mFlags.MarkAsWaitingReplyFromRemoteProcess();
704
0
  }
705
  /**
706
   * Reset "waiting reply from remote process" state.  This is useful when
707
   * you dispatch a copy of an event coming from different process.
708
   */
709
  inline void ResetWaitingReplyFromRemoteProcessState()
710
0
  {
711
0
    mFlags.ResetWaitingReplyFromRemoteProcessState();
712
0
  }
713
  /**
714
   * Return true if the event handler should wait reply event.  I.e., if this
715
   * returns true, any event handler should do nothing with the event.
716
   */
717
  inline bool IsWaitingReplyFromRemoteProcess() const
718
0
  {
719
0
    return mFlags.IsWaitingReplyFromRemoteProcess();
720
0
  }
721
  /**
722
   * Mark the event as already handled in the remote process.  This should be
723
   * called when initializing reply events.
724
   */
725
  inline void MarkAsHandledInRemoteProcess()
726
0
  {
727
0
    mFlags.MarkAsHandledInRemoteProcess();
728
0
  }
729
  /**
730
   * Return true if the event has already been handled in the remote process.
731
   * I.e., if this returns true, the event is a reply event.
732
   */
733
  inline bool IsHandledInRemoteProcess() const
734
0
  {
735
0
    return mFlags.IsHandledInRemoteProcess();
736
0
  }
737
  /**
738
   * Return true if the event should be sent back to its parent process.
739
   * So, usual event handlers shouldn't call this.
740
   */
741
  inline bool WantReplyFromContentProcess() const
742
0
  {
743
0
    return mFlags.WantReplyFromContentProcess();
744
0
  }
745
  /**
746
   * Mark the event has already posted to a remote process.
747
   */
748
  inline void MarkAsPostedToRemoteProcess()
749
0
  {
750
0
    mFlags.MarkAsPostedToRemoteProcess();
751
0
  }
752
  /**
753
   * Reset the cross process dispatching state.  This should be used when a
754
   * process receives the event because the state is in the sender.
755
   */
756
  inline void ResetCrossProcessDispatchingState()
757
0
  {
758
0
    mFlags.ResetCrossProcessDispatchingState();
759
0
  }
760
  /**
761
   * Return true if the event has been posted to a remote process.
762
   */
763
  inline bool HasBeenPostedToRemoteProcess() const
764
0
  {
765
0
    return mFlags.HasBeenPostedToRemoteProcess();
766
0
  }
767
  /**
768
   * Mark the event is reserved by chrome.  I.e., shouldn't be dispatched to
769
   * content because it shouldn't be cancelable.
770
   */
771
  inline void MarkAsReservedByChrome()
772
0
  {
773
0
    mFlags.MarkAsReservedByChrome();
774
0
  }
775
  /**
776
   * Return true if the event is reserved by chrome.
777
   */
778
  inline bool IsReservedByChrome() const
779
0
  {
780
0
    return mFlags.IsReservedByChrome();
781
0
  }
782
783
  /**
784
   * Utils for checking event types
785
   */
786
787
  /**
788
   * As*Event() returns the pointer of the instance only when the instance is
789
   * the class or one of its derived class.
790
   */
791
#define NS_ROOT_EVENT_CLASS(aPrefix, aName)
792
#define NS_EVENT_CLASS(aPrefix, aName) \
793
  virtual aPrefix##aName* As##aName(); \
794
  const aPrefix##aName* As##aName() const;
795
796
#include "mozilla/EventClassList.h"
797
798
#undef NS_EVENT_CLASS
799
#undef NS_ROOT_EVENT_CLASS
800
801
  /**
802
   * Returns true if the event is a query content event.
803
   */
804
  bool IsQueryContentEvent() const;
805
  /**
806
   * Returns true if the event is a selection event.
807
   */
808
  bool IsSelectionEvent() const;
809
  /**
810
   * Returns true if the event is a content command event.
811
   */
812
  bool IsContentCommandEvent() const;
813
  /**
814
   * Returns true if the event is a native event deliverer event for plugin.
815
   */
816
  bool IsNativeEventDelivererForPlugin() const;
817
818
  /**
819
   * Returns true if the event mMessage is one of mouse events.
820
   */
821
  bool HasMouseEventMessage() const;
822
  /**
823
   * Returns true if the event mMessage is one of drag events.
824
   */
825
  bool HasDragEventMessage() const;
826
  /**
827
   * Returns true if aMessage or mMessage is one of key events.
828
   */
829
  static bool IsKeyEventMessage(EventMessage aMessage);
830
  bool HasKeyEventMessage() const
831
0
  {
832
0
    return IsKeyEventMessage(mMessage);
833
0
  }
834
  /**
835
   * Returns true if the event mMessage is one of composition events or text
836
   * event.
837
   */
838
  bool HasIMEEventMessage() const;
839
  /**
840
   * Returns true if the event mMessage is one of plugin activation events.
841
   */
842
  bool HasPluginActivationEventMessage() const;
843
844
  /**
845
   * Returns true if the event can be sent to remote process.
846
   */
847
  bool CanBeSentToRemoteProcess() const;
848
  /**
849
   * Returns true if the original target is a remote process and the event
850
   * will be posted to the remote process later.
851
   */
852
  bool WillBeSentToRemoteProcess() const;
853
  /**
854
   * Returns true if the event is native event deliverer event for plugin and
855
   * it should be retarted to focused document.
856
   */
857
  bool IsRetargetedNativeEventDelivererForPlugin() const;
858
  /**
859
   * Returns true if the event is native event deliverer event for plugin and
860
   * it should NOT be retarted to focused document.
861
   */
862
  bool IsNonRetargetedNativeEventDelivererForPlugin() const;
863
  /**
864
   * Returns true if the event is related to IME handling.  It includes
865
   * IME events, query content events and selection events.
866
   * Be careful when you use this.
867
   */
868
  bool IsIMERelatedEvent() const;
869
870
  /**
871
   * Whether the event should be handled by the frame of the mouse cursor
872
   * position or not.  When it should be handled there (e.g., the mouse events),
873
   * this returns true.
874
   */
875
  bool IsUsingCoordinates() const;
876
  /**
877
   * Whether the event should be handled by the focused DOM window in the
878
   * same top level window's or not.  E.g., key events, IME related events
879
   * (including the query content events, they are used in IME transaction)
880
   * should be handled by the (last) focused window rather than the dispatched
881
   * window.
882
   *
883
   * NOTE: Even if this returns true, the event isn't going to be handled by the
884
   * application level active DOM window which is on another top level window.
885
   * So, when the event is fired on a deactive window, the event is going to be
886
   * handled by the last focused DOM window in the last focused window.
887
   */
888
  bool IsTargetedAtFocusedWindow() const;
889
  /**
890
   * Whether the event should be handled by the focused content or not.  E.g.,
891
   * key events, IME related events and other input events which are not handled
892
   * by the frame of the mouse cursor position.
893
   *
894
   * NOTE: Even if this returns true, the event isn't going to be handled by the
895
   * application level active DOM window which is on another top level window.
896
   * So, when the event is fired on a deactive window, the event is going to be
897
   * handled by the last focused DOM element of the last focused DOM window in
898
   * the last focused window.
899
   */
900
  bool IsTargetedAtFocusedContent() const;
901
  /**
902
   * Whether the event should cause a DOM event.
903
   */
904
  bool IsAllowedToDispatchDOMEvent() const;
905
  /**
906
   * Whether the event should be dispatched in system group.
907
   */
908
  bool IsAllowedToDispatchInSystemGroup() const;
909
  /**
910
   * Whether the event should be blocked for fingerprinting resistance.
911
   */
912
  bool IsBlockedForFingerprintingResistance() const;
913
  /**
914
   * Initialize mComposed
915
   */
916
  void SetDefaultComposed()
917
0
  {
918
0
    switch (mClass) {
919
0
      case eCompositionEventClass:
920
0
        mFlags.mComposed = mMessage == eCompositionStart ||
921
0
                           mMessage == eCompositionUpdate ||
922
0
                           mMessage == eCompositionEnd;
923
0
        break;
924
0
      case eDragEventClass:
925
0
        // All drag & drop events are composed
926
0
        mFlags.mComposed = mMessage == eDrag || mMessage == eDragEnd ||
927
0
                           mMessage == eDragEnter || mMessage == eDragExit ||
928
0
                           mMessage == eDragLeave || mMessage == eDragOver ||
929
0
                           mMessage == eDragStart || mMessage == eDrop;
930
0
        break;
931
0
      case eEditorInputEventClass:
932
0
        mFlags.mComposed = mMessage == eEditorInput;
933
0
        break;
934
0
      case eFocusEventClass:
935
0
        mFlags.mComposed = mMessage == eBlur || mMessage == eFocus ||
936
0
                           mMessage == eFocusOut || mMessage == eFocusIn;
937
0
        break;
938
0
      case eKeyboardEventClass:
939
0
        mFlags.mComposed = mMessage == eKeyDown || mMessage == eKeyUp ||
940
0
                           mMessage == eKeyPress;
941
0
        break;
942
0
      case eMouseEventClass:
943
0
        mFlags.mComposed = mMessage == eMouseClick ||
944
0
                           mMessage == eMouseDoubleClick ||
945
0
                           mMessage == eMouseAuxClick ||
946
0
                           mMessage == eMouseDown || mMessage == eMouseUp ||
947
0
                           mMessage == eMouseOver || mMessage == eMouseOut ||
948
0
                           mMessage == eMouseMove || mMessage == eContextMenu;
949
0
        break;
950
0
      case ePointerEventClass:
951
0
        // All pointer events are composed
952
0
        mFlags.mComposed = mMessage == ePointerDown ||
953
0
                           mMessage == ePointerMove || mMessage == ePointerUp ||
954
0
                           mMessage == ePointerCancel ||
955
0
                           mMessage == ePointerOver ||
956
0
                           mMessage == ePointerOut ||
957
0
                           mMessage == ePointerGotCapture ||
958
0
                           mMessage == ePointerLostCapture;
959
0
        break;
960
0
      case eTouchEventClass:
961
0
        // All touch events are composed
962
0
        mFlags.mComposed = mMessage == eTouchStart || mMessage == eTouchEnd ||
963
0
                           mMessage == eTouchMove || mMessage == eTouchCancel;
964
0
        break;
965
0
      case eUIEventClass:
966
0
        mFlags.mComposed = mMessage == eLegacyDOMFocusIn ||
967
0
                           mMessage == eLegacyDOMFocusOut ||
968
0
                           mMessage == eLegacyDOMActivate;
969
0
        break;
970
0
      case eWheelEventClass:
971
0
        // All wheel events are composed
972
0
        mFlags.mComposed = mMessage == eWheel;
973
0
        break;
974
0
      default:
975
0
        mFlags.mComposed = false;
976
0
        break;
977
0
    }
978
0
  }
979
980
  void SetComposed(const nsAString& aEventTypeArg)
981
0
  {
982
0
    mFlags.mComposed = // composition events
983
0
                       aEventTypeArg.EqualsLiteral("compositionstart") ||
984
0
                       aEventTypeArg.EqualsLiteral("compositionupdate") ||
985
0
                       aEventTypeArg.EqualsLiteral("compositionend") ||
986
0
                       // drag and drop events
987
0
                       aEventTypeArg.EqualsLiteral("dragstart") ||
988
0
                       aEventTypeArg.EqualsLiteral("drag") ||
989
0
                       aEventTypeArg.EqualsLiteral("dragenter") ||
990
0
                       aEventTypeArg.EqualsLiteral("dragexit") ||
991
0
                       aEventTypeArg.EqualsLiteral("dragleave") ||
992
0
                       aEventTypeArg.EqualsLiteral("dragover") ||
993
0
                       aEventTypeArg.EqualsLiteral("drop") ||
994
0
                       aEventTypeArg.EqualsLiteral("dropend") ||
995
0
                       // editor input events
996
0
                       aEventTypeArg.EqualsLiteral("input") ||
997
0
                       aEventTypeArg.EqualsLiteral("beforeinput") ||
998
0
                       // focus events
999
0
                       aEventTypeArg.EqualsLiteral("blur") ||
1000
0
                       aEventTypeArg.EqualsLiteral("focus") ||
1001
0
                       aEventTypeArg.EqualsLiteral("focusin") ||
1002
0
                       aEventTypeArg.EqualsLiteral("focusout") ||
1003
0
                       // keyboard events
1004
0
                       aEventTypeArg.EqualsLiteral("keydown") ||
1005
0
                       aEventTypeArg.EqualsLiteral("keyup") ||
1006
0
                       aEventTypeArg.EqualsLiteral("keypress") ||
1007
0
                       // mouse events
1008
0
                       aEventTypeArg.EqualsLiteral("click") ||
1009
0
                       aEventTypeArg.EqualsLiteral("dblclick") ||
1010
0
                       aEventTypeArg.EqualsLiteral("mousedown") ||
1011
0
                       aEventTypeArg.EqualsLiteral("mouseup") ||
1012
0
                       aEventTypeArg.EqualsLiteral("mouseenter") ||
1013
0
                       aEventTypeArg.EqualsLiteral("mouseleave") ||
1014
0
                       aEventTypeArg.EqualsLiteral("mouseover") ||
1015
0
                       aEventTypeArg.EqualsLiteral("mouseout") ||
1016
0
                       aEventTypeArg.EqualsLiteral("mousemove") ||
1017
0
                       aEventTypeArg.EqualsLiteral("contextmenu") ||
1018
0
                       // pointer events
1019
0
                       aEventTypeArg.EqualsLiteral("pointerdown") ||
1020
0
                       aEventTypeArg.EqualsLiteral("pointermove") ||
1021
0
                       aEventTypeArg.EqualsLiteral("pointerup") ||
1022
0
                       aEventTypeArg.EqualsLiteral("pointercancel") ||
1023
0
                       aEventTypeArg.EqualsLiteral("pointerover") ||
1024
0
                       aEventTypeArg.EqualsLiteral("pointerout") ||
1025
0
                       aEventTypeArg.EqualsLiteral("pointerenter") ||
1026
0
                       aEventTypeArg.EqualsLiteral("pointerleave") ||
1027
0
                       aEventTypeArg.EqualsLiteral("gotpointercapture") ||
1028
0
                       aEventTypeArg.EqualsLiteral("lostpointercapture") ||
1029
0
                       // touch events
1030
0
                       aEventTypeArg.EqualsLiteral("touchstart") ||
1031
0
                       aEventTypeArg.EqualsLiteral("touchend") ||
1032
0
                       aEventTypeArg.EqualsLiteral("touchmove") ||
1033
0
                       aEventTypeArg.EqualsLiteral("touchcancel") ||
1034
0
                       // UI legacy events
1035
0
                       aEventTypeArg.EqualsLiteral("DOMFocusIn") ||
1036
0
                       aEventTypeArg.EqualsLiteral("DOMFocusOut") ||
1037
0
                       aEventTypeArg.EqualsLiteral("DOMActivate") ||
1038
0
                       // wheel events
1039
0
                       aEventTypeArg.EqualsLiteral("wheel");
1040
0
  }
1041
1042
  void SetComposed(bool aComposed)
1043
0
  {
1044
0
    mFlags.mComposed = aComposed;
1045
0
  }
1046
1047
  void SetDefaultComposedInNativeAnonymousContent()
1048
0
  {
1049
0
    // For compatibility concerns, we set mComposedInNativeAnonymousContent to
1050
0
    // false for those events we want to stop propagation.
1051
0
    //
1052
0
    // nsVideoFrame may create anonymous image element which fires eLoad,
1053
0
    // eLoadStart, eLoadEnd, eLoadError. We don't want these events cross
1054
0
    // the boundary of NAC
1055
0
    mFlags.mComposedInNativeAnonymousContent = mMessage != eLoad &&
1056
0
                                               mMessage != eLoadStart &&
1057
0
                                               mMessage != eLoadEnd &&
1058
0
                                               mMessage != eLoadError;
1059
0
  }
1060
1061
  bool IsUserAction() const;
1062
};
1063
1064
/******************************************************************************
1065
 * mozilla::NativeEventData
1066
 *
1067
 * WidgetGUIEvent's mPluginEvent member used to be a void* pointer,
1068
 * used to reference external, OS-specific data structures.
1069
 *
1070
 * That void* pointer wasn't serializable by itself, causing
1071
 * certain plugin events not to function in e10s. See bug 586656.
1072
 *
1073
 * To make this serializable, we changed this void* pointer into
1074
 * a proper buffer, and copy these external data structures into this
1075
 * buffer.
1076
 *
1077
 * That buffer is NativeEventData::mBuffer below.
1078
 *
1079
 * We wrap this in that NativeEventData class providing operators to
1080
 * be compatible with existing code that was written around
1081
 * the old void* field.
1082
 ******************************************************************************/
1083
1084
class NativeEventData final
1085
{
1086
  nsTArray<uint8_t> mBuffer;
1087
1088
  friend struct IPC::ParamTraits<mozilla::NativeEventData>;
1089
1090
public:
1091
1092
  explicit operator bool() const
1093
0
  {
1094
0
    return !mBuffer.IsEmpty();
1095
0
  }
1096
1097
  template<typename T>
1098
  explicit operator const T*() const
1099
0
  {
1100
0
    return mBuffer.IsEmpty()
1101
0
           ? nullptr
1102
0
           : reinterpret_cast<const T*>(mBuffer.Elements());
1103
0
  }
1104
1105
  template <typename T>
1106
  void Copy(const T& other)
1107
0
  {
1108
0
    static_assert(!mozilla::IsPointer<T>::value, "Don't want a pointer!");
1109
0
    mBuffer.SetLength(sizeof(T));
1110
0
    memcpy(mBuffer.Elements(), &other, mBuffer.Length());
1111
0
  }
1112
1113
  void Clear()
1114
0
  {
1115
0
    mBuffer.Clear();
1116
0
  }
1117
};
1118
1119
/******************************************************************************
1120
 * mozilla::WidgetGUIEvent
1121
 ******************************************************************************/
1122
1123
class WidgetGUIEvent : public WidgetEvent
1124
{
1125
protected:
1126
  WidgetGUIEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
1127
                 EventClassID aEventClassID)
1128
    : WidgetEvent(aIsTrusted, aMessage, aEventClassID)
1129
    , mWidget(aWidget)
1130
0
  {
1131
0
  }
1132
1133
  WidgetGUIEvent()
1134
0
  {
1135
0
  }
1136
1137
public:
1138
0
  virtual WidgetGUIEvent* AsGUIEvent() override { return this; }
1139
1140
  WidgetGUIEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget)
1141
    : WidgetEvent(aIsTrusted, aMessage, eGUIEventClass)
1142
    , mWidget(aWidget)
1143
0
  {
1144
0
  }
1145
1146
  virtual WidgetEvent* Duplicate() const override
1147
0
  {
1148
0
    MOZ_ASSERT(mClass == eGUIEventClass,
1149
0
               "Duplicate() must be overridden by sub class");
1150
0
    // Not copying widget, it is a weak reference.
1151
0
    WidgetGUIEvent* result = new WidgetGUIEvent(false, mMessage, nullptr);
1152
0
    result->AssignGUIEventData(*this, true);
1153
0
    result->mFlags = mFlags;
1154
0
    return result;
1155
0
  }
1156
1157
  // Originator of the event
1158
  nsCOMPtr<nsIWidget> mWidget;
1159
1160
  /*
1161
   * Ideally though, we wouldn't allow arbitrary reinterpret_cast'ing here;
1162
   * instead, we would at least store type information here so that
1163
   * this class can't be used to reinterpret one structure type into another.
1164
   * We can also wonder if it would be possible to properly extend
1165
   * WidgetGUIEvent and other Event classes to remove the need for this
1166
   * mPluginEvent field.
1167
   */
1168
  typedef NativeEventData PluginEvent;
1169
1170
  // Event for NPAPI plugin
1171
  PluginEvent mPluginEvent;
1172
1173
  void AssignGUIEventData(const WidgetGUIEvent& aEvent, bool aCopyTargets)
1174
0
  {
1175
0
    AssignEventData(aEvent, aCopyTargets);
1176
0
1177
0
    // widget should be initialized with the constructor.
1178
0
1179
0
    mPluginEvent = aEvent.mPluginEvent;
1180
0
  }
1181
};
1182
1183
/******************************************************************************
1184
 * mozilla::Modifier
1185
 *
1186
 * All modifier keys should be defined here.  This is used for managing
1187
 * modifier states for DOM Level 3 or later.
1188
 ******************************************************************************/
1189
1190
enum Modifier
1191
{
1192
  MODIFIER_NONE       = 0x0000,
1193
  MODIFIER_ALT        = 0x0001,
1194
  MODIFIER_ALTGRAPH   = 0x0002,
1195
  MODIFIER_CAPSLOCK   = 0x0004,
1196
  MODIFIER_CONTROL    = 0x0008,
1197
  MODIFIER_FN         = 0x0010,
1198
  MODIFIER_FNLOCK     = 0x0020,
1199
  MODIFIER_META       = 0x0040,
1200
  MODIFIER_NUMLOCK    = 0x0080,
1201
  MODIFIER_SCROLLLOCK = 0x0100,
1202
  MODIFIER_SHIFT      = 0x0200,
1203
  MODIFIER_SYMBOL     = 0x0400,
1204
  MODIFIER_SYMBOLLOCK = 0x0800,
1205
  MODIFIER_OS         = 0x1000
1206
};
1207
1208
/******************************************************************************
1209
 * Modifier key names.
1210
 ******************************************************************************/
1211
1212
#define NS_DOM_KEYNAME_ALT        "Alt"
1213
#define NS_DOM_KEYNAME_ALTGRAPH   "AltGraph"
1214
#define NS_DOM_KEYNAME_CAPSLOCK   "CapsLock"
1215
#define NS_DOM_KEYNAME_CONTROL    "Control"
1216
#define NS_DOM_KEYNAME_FN         "Fn"
1217
#define NS_DOM_KEYNAME_FNLOCK     "FnLock"
1218
#define NS_DOM_KEYNAME_META       "Meta"
1219
#define NS_DOM_KEYNAME_NUMLOCK    "NumLock"
1220
#define NS_DOM_KEYNAME_SCROLLLOCK "ScrollLock"
1221
#define NS_DOM_KEYNAME_SHIFT      "Shift"
1222
#define NS_DOM_KEYNAME_SYMBOL     "Symbol"
1223
#define NS_DOM_KEYNAME_SYMBOLLOCK "SymbolLock"
1224
#define NS_DOM_KEYNAME_OS         "OS"
1225
1226
/******************************************************************************
1227
 * mozilla::Modifiers
1228
 ******************************************************************************/
1229
1230
typedef uint16_t Modifiers;
1231
1232
class MOZ_STACK_CLASS GetModifiersName final : public nsAutoCString
1233
{
1234
public:
1235
  explicit GetModifiersName(Modifiers aModifiers)
1236
0
  {
1237
0
    if (aModifiers & MODIFIER_ALT) {
1238
0
      AssignLiteral(NS_DOM_KEYNAME_ALT);
1239
0
    }
1240
0
    if (aModifiers & MODIFIER_ALTGRAPH) {
1241
0
      MaybeAppendSeparator();
1242
0
      AppendLiteral(NS_DOM_KEYNAME_ALTGRAPH);
1243
0
    }
1244
0
    if (aModifiers & MODIFIER_CAPSLOCK) {
1245
0
      MaybeAppendSeparator();
1246
0
      AppendLiteral(NS_DOM_KEYNAME_CAPSLOCK);
1247
0
    }
1248
0
    if (aModifiers & MODIFIER_CONTROL) {
1249
0
      MaybeAppendSeparator();
1250
0
      AppendLiteral(NS_DOM_KEYNAME_CONTROL);
1251
0
    }
1252
0
    if (aModifiers & MODIFIER_FN) {
1253
0
      MaybeAppendSeparator();
1254
0
      AppendLiteral(NS_DOM_KEYNAME_FN);
1255
0
    }
1256
0
    if (aModifiers & MODIFIER_FNLOCK) {
1257
0
      MaybeAppendSeparator();
1258
0
      AppendLiteral(NS_DOM_KEYNAME_FNLOCK);
1259
0
    }
1260
0
    if (aModifiers & MODIFIER_META) {
1261
0
      MaybeAppendSeparator();
1262
0
      AppendLiteral(NS_DOM_KEYNAME_META);
1263
0
    }
1264
0
    if (aModifiers & MODIFIER_NUMLOCK) {
1265
0
      MaybeAppendSeparator();
1266
0
      AppendLiteral(NS_DOM_KEYNAME_NUMLOCK);
1267
0
    }
1268
0
    if (aModifiers & MODIFIER_SCROLLLOCK) {
1269
0
      MaybeAppendSeparator();
1270
0
      AppendLiteral(NS_DOM_KEYNAME_SCROLLLOCK);
1271
0
    }
1272
0
    if (aModifiers & MODIFIER_SHIFT) {
1273
0
      MaybeAppendSeparator();
1274
0
      AppendLiteral(NS_DOM_KEYNAME_SHIFT);
1275
0
    }
1276
0
    if (aModifiers & MODIFIER_SYMBOL) {
1277
0
      MaybeAppendSeparator();
1278
0
      AppendLiteral(NS_DOM_KEYNAME_SYMBOL);
1279
0
    }
1280
0
    if (aModifiers & MODIFIER_SYMBOLLOCK) {
1281
0
      MaybeAppendSeparator();
1282
0
      AppendLiteral(NS_DOM_KEYNAME_SYMBOLLOCK);
1283
0
    }
1284
0
    if (aModifiers & MODIFIER_OS) {
1285
0
      MaybeAppendSeparator();
1286
0
      AppendLiteral(NS_DOM_KEYNAME_OS);
1287
0
    }
1288
0
    if (IsEmpty()) {
1289
0
      AssignLiteral("none");
1290
0
    }
1291
0
  }
1292
1293
private:
1294
  void MaybeAppendSeparator()
1295
0
  {
1296
0
    if (!IsEmpty()) {
1297
0
      AppendLiteral(" | ");
1298
0
    }
1299
0
  }
1300
};
1301
1302
/******************************************************************************
1303
 * mozilla::WidgetInputEvent
1304
 ******************************************************************************/
1305
1306
class WidgetInputEvent : public WidgetGUIEvent
1307
{
1308
protected:
1309
  WidgetInputEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
1310
                   EventClassID aEventClassID)
1311
    : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, aEventClassID)
1312
    , mModifiers(0)
1313
0
  {
1314
0
  }
1315
1316
  WidgetInputEvent()
1317
    : mModifiers(0)
1318
0
  {
1319
0
  }
1320
1321
public:
1322
0
  virtual WidgetInputEvent* AsInputEvent() override { return this; }
1323
1324
  WidgetInputEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget)
1325
    : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eInputEventClass)
1326
    , mModifiers(0)
1327
0
  {
1328
0
  }
1329
1330
  virtual WidgetEvent* Duplicate() const override
1331
0
  {
1332
0
    MOZ_ASSERT(mClass == eInputEventClass,
1333
0
               "Duplicate() must be overridden by sub class");
1334
0
    // Not copying widget, it is a weak reference.
1335
0
    WidgetInputEvent* result = new WidgetInputEvent(false, mMessage, nullptr);
1336
0
    result->AssignInputEventData(*this, true);
1337
0
    result->mFlags = mFlags;
1338
0
    return result;
1339
0
  }
1340
1341
1342
  /**
1343
   * Returns a modifier of "Accel" virtual modifier which is used for shortcut
1344
   * key.
1345
   */
1346
  static Modifier AccelModifier();
1347
1348
  /**
1349
   * GetModifier() returns a modifier flag which is activated by aDOMKeyName.
1350
   */
1351
  static Modifier GetModifier(const nsAString& aDOMKeyName);
1352
1353
  // true indicates the accel key on the environment is down
1354
  bool IsAccel() const
1355
0
  {
1356
0
    return ((mModifiers & AccelModifier()) != 0);
1357
0
  }
1358
1359
  // true indicates the shift key is down
1360
  bool IsShift() const
1361
0
  {
1362
0
    return ((mModifiers & MODIFIER_SHIFT) != 0);
1363
0
  }
1364
  // true indicates the control key is down
1365
  bool IsControl() const
1366
0
  {
1367
0
    return ((mModifiers & MODIFIER_CONTROL) != 0);
1368
0
  }
1369
  // true indicates the alt key is down
1370
  bool IsAlt() const
1371
0
  {
1372
0
    return ((mModifiers & MODIFIER_ALT) != 0);
1373
0
  }
1374
  // true indicates the meta key is down (or, on Mac, the Command key)
1375
  bool IsMeta() const
1376
0
  {
1377
0
    return ((mModifiers & MODIFIER_META) != 0);
1378
0
  }
1379
  // true indicates the win key is down on Windows. Or the Super or Hyper key
1380
  // is down on Linux.
1381
  bool IsOS() const
1382
0
  {
1383
0
    return ((mModifiers & MODIFIER_OS) != 0);
1384
0
  }
1385
  // true indicates the alt graph key is down
1386
  // NOTE: on Mac, the option key press causes both IsAlt() and IsAltGrpah()
1387
  //       return true.
1388
  bool IsAltGraph() const
1389
0
  {
1390
0
    return ((mModifiers & MODIFIER_ALTGRAPH) != 0);
1391
0
  }
1392
  // true indicates the CapLock LED is turn on.
1393
  bool IsCapsLocked() const
1394
0
  {
1395
0
    return ((mModifiers & MODIFIER_CAPSLOCK) != 0);
1396
0
  }
1397
  // true indicates the NumLock LED is turn on.
1398
  bool IsNumLocked() const
1399
0
  {
1400
0
    return ((mModifiers & MODIFIER_NUMLOCK) != 0);
1401
0
  }
1402
  // true indicates the ScrollLock LED is turn on.
1403
  bool IsScrollLocked() const
1404
0
  {
1405
0
    return ((mModifiers & MODIFIER_SCROLLLOCK) != 0);
1406
0
  }
1407
1408
  // true indicates the Fn key is down, but this is not supported by native
1409
  // key event on any platform.
1410
  bool IsFn() const
1411
0
  {
1412
0
    return ((mModifiers & MODIFIER_FN) != 0);
1413
0
  }
1414
  // true indicates the FnLock LED is turn on, but we don't know such
1415
  // keyboards nor platforms.
1416
  bool IsFnLocked() const
1417
0
  {
1418
0
    return ((mModifiers & MODIFIER_FNLOCK) != 0);
1419
0
  }
1420
  // true indicates the Symbol is down, but this is not supported by native
1421
  // key event on any platforms.
1422
  bool IsSymbol() const
1423
0
  {
1424
0
    return ((mModifiers & MODIFIER_SYMBOL) != 0);
1425
0
  }
1426
  // true indicates the SymbolLock LED is turn on, but we don't know such
1427
  // keyboards nor platforms.
1428
  bool IsSymbolLocked() const
1429
0
  {
1430
0
    return ((mModifiers & MODIFIER_SYMBOLLOCK) != 0);
1431
0
  }
1432
1433
  void InitBasicModifiers(bool aCtrlKey,
1434
                          bool aAltKey,
1435
                          bool aShiftKey,
1436
                          bool aMetaKey)
1437
0
  {
1438
0
    mModifiers = 0;
1439
0
    if (aCtrlKey) {
1440
0
      mModifiers |= MODIFIER_CONTROL;
1441
0
    }
1442
0
    if (aAltKey) {
1443
0
      mModifiers |= MODIFIER_ALT;
1444
0
    }
1445
0
    if (aShiftKey) {
1446
0
      mModifiers |= MODIFIER_SHIFT;
1447
0
    }
1448
0
    if (aMetaKey) {
1449
0
      mModifiers |= MODIFIER_META;
1450
0
    }
1451
0
  }
1452
1453
  Modifiers mModifiers;
1454
1455
  void AssignInputEventData(const WidgetInputEvent& aEvent, bool aCopyTargets)
1456
0
  {
1457
0
    AssignGUIEventData(aEvent, aCopyTargets);
1458
0
1459
0
    mModifiers = aEvent.mModifiers;
1460
0
  }
1461
};
1462
1463
/******************************************************************************
1464
 * mozilla::InternalUIEvent
1465
 *
1466
 * XXX Why this inherits WidgetGUIEvent rather than WidgetEvent?
1467
 ******************************************************************************/
1468
1469
class InternalUIEvent : public WidgetGUIEvent
1470
{
1471
protected:
1472
  InternalUIEvent()
1473
    : mDetail(0)
1474
    , mCausedByUntrustedEvent(false)
1475
0
  {
1476
0
  }
1477
1478
  InternalUIEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
1479
                  EventClassID aEventClassID)
1480
    : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, aEventClassID)
1481
    , mDetail(0)
1482
    , mCausedByUntrustedEvent(false)
1483
0
  {
1484
0
  }
1485
1486
  InternalUIEvent(bool aIsTrusted, EventMessage aMessage,
1487
                  EventClassID aEventClassID)
1488
    : WidgetGUIEvent(aIsTrusted, aMessage, nullptr, aEventClassID)
1489
    , mDetail(0)
1490
    , mCausedByUntrustedEvent(false)
1491
0
  {
1492
0
  }
1493
1494
public:
1495
0
  virtual InternalUIEvent* AsUIEvent() override { return this; }
1496
1497
  /**
1498
   * If the UIEvent is caused by another event (e.g., click event),
1499
   * aEventCausesThisEvent should be the event.  If there is no such event,
1500
   * this should be nullptr.
1501
   */
1502
  InternalUIEvent(bool aIsTrusted, EventMessage aMessage,
1503
                  const WidgetEvent* aEventCausesThisEvent)
1504
    : WidgetGUIEvent(aIsTrusted, aMessage, nullptr, eUIEventClass)
1505
    , mDetail(0)
1506
    , mCausedByUntrustedEvent(
1507
        aEventCausesThisEvent && !aEventCausesThisEvent->IsTrusted())
1508
0
  {
1509
0
  }
1510
1511
  virtual WidgetEvent* Duplicate() const override
1512
0
  {
1513
0
    MOZ_ASSERT(mClass == eUIEventClass,
1514
0
               "Duplicate() must be overridden by sub class");
1515
0
    InternalUIEvent* result = new InternalUIEvent(false, mMessage, nullptr);
1516
0
    result->AssignUIEventData(*this, true);
1517
0
    result->mFlags = mFlags;
1518
0
    return result;
1519
0
  }
1520
1521
  int32_t mDetail;
1522
  // mCausedByUntrustedEvent is true if the event is caused by untrusted event.
1523
  bool mCausedByUntrustedEvent;
1524
1525
  // If you check the event is a trusted event and NOT caused by an untrusted
1526
  // event, IsTrustable() returns what you expected.
1527
  bool IsTrustable() const
1528
0
  {
1529
0
    return IsTrusted() && !mCausedByUntrustedEvent;
1530
0
  }
1531
1532
  void AssignUIEventData(const InternalUIEvent& aEvent, bool aCopyTargets)
1533
0
  {
1534
0
    AssignGUIEventData(aEvent, aCopyTargets);
1535
0
1536
0
    mDetail = aEvent.mDetail;
1537
0
    mCausedByUntrustedEvent = aEvent.mCausedByUntrustedEvent;
1538
0
  }
1539
};
1540
1541
} // namespace mozilla
1542
1543
#endif // mozilla_BasicEvents_h__