tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Event.h (18947B)


      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 <cstdint>
     11 
     12 #include "Units.h"
     13 #include "js/TypeDecls.h"
     14 #include "mozilla/AlreadyAddRefed.h"
     15 #include "mozilla/Assertions.h"
     16 #include "mozilla/Attributes.h"
     17 #include "mozilla/BasicEvents.h"
     18 #include "mozilla/Maybe.h"
     19 #include "mozilla/RefPtr.h"
     20 #include "mozilla/WeakPtr.h"
     21 #include "mozilla/dom/BindingDeclarations.h"
     22 #include "nsCOMPtr.h"
     23 #include "nsCycleCollectionParticipant.h"
     24 #include "nsID.h"
     25 #include "nsISupports.h"
     26 #include "nsStringFwd.h"
     27 #include "nsWrapperCache.h"
     28 
     29 class PickleIterator;
     30 class nsCycleCollectionTraversalCallback;
     31 class nsIContent;
     32 class nsIGlobalObject;
     33 class nsIPrincipal;
     34 class nsPIDOMWindowInner;
     35 class nsPresContext;
     36 
     37 namespace IPC {
     38 class Message;
     39 class MessageReader;
     40 class MessageWriter;
     41 }  // namespace IPC
     42 
     43 namespace mozilla::dom {
     44 
     45 class BeforeUnloadEvent;
     46 class CustomEvent;
     47 class Document;
     48 class DragEvent;
     49 class EventTarget;
     50 class EventMessageAutoOverride;
     51 // ExtendableEvent is a ServiceWorker event that is not
     52 // autogenerated since it has some extra methods.
     53 class ExtendableEvent;
     54 class KeyboardEvent;
     55 class MouseEvent;
     56 class MessageEvent;
     57 class PointerEvent;
     58 class TimeEvent;
     59 class ToggleEvent;
     60 class UIEvent;
     61 class WantsPopupControlCheck;
     62 class XULCommandEvent;
     63 struct EventInit;
     64 
     65 #define GENERATED_EVENT(EventClass_) class EventClass_;
     66 #include "mozilla/dom/GeneratedEventList.h"
     67 #undef GENERATED_EVENT
     68 
     69 // IID for Event
     70 #define NS_EVENT_IID \
     71  {0x71139716, 0x4d91, 0x4dee, {0xba, 0xf9, 0xe3, 0x3b, 0x80, 0xc1, 0x61, 0x61}}
     72 
     73 class Event : public nsISupports, public nsWrapperCache {
     74 public:
     75  NS_INLINE_DECL_STATIC_IID(NS_EVENT_IID)
     76 
     77  Event(EventTarget* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent);
     78  explicit Event(nsPIDOMWindowInner* aWindow);
     79 
     80 protected:
     81  virtual ~Event();
     82 
     83  void LastRelease();
     84 
     85 private:
     86  void ConstructorInit(EventTarget* aOwner, nsPresContext* aPresContext,
     87                       WidgetEvent* aEvent);
     88 
     89  void UpdateDefaultPreventedOnContentForDragEvent();
     90 
     91 public:
     92  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     93  NS_DECL_CYCLE_COLLECTION_SKIPPABLE_WRAPPERCACHE_CLASS(Event)
     94 
     95  nsIGlobalObject* GetParentObject() const { return mOwner; }
     96 
     97  JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) final;
     98 
     99  virtual JSObject* WrapObjectInternal(JSContext* aCx,
    100                                       JS::Handle<JSObject*> aGivenProto);
    101 
    102 #define GENERATED_EVENT(EventClass_) \
    103  virtual EventClass_* As##EventClass_() { return nullptr; }
    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  virtual ExtendableEvent* AsExtendableEvent() { return nullptr; }
    110 
    111  virtual TimeEvent* AsTimeEvent() { return nullptr; }
    112 
    113  // BeforeUnloadEvent is not autogenerated because it has a setter.
    114  virtual BeforeUnloadEvent* AsBeforeUnloadEvent() { return nullptr; }
    115 
    116  // KeyboardEvent has all sorts of non-autogeneratable bits so far.
    117  virtual KeyboardEvent* AsKeyboardEvent() { return nullptr; }
    118 
    119  // DragEvent has a non-autogeneratable initDragEvent.
    120  virtual DragEvent* AsDragEvent() { return nullptr; }
    121 
    122  // XULCommandEvent has a non-autogeneratable initCommandEvent.
    123  virtual XULCommandEvent* AsXULCommandEvent() { return nullptr; }
    124 
    125  // MouseEvent has a non-autogeneratable initMouseEvent and other
    126  // non-autogeneratable methods.
    127  virtual MouseEvent* AsMouseEvent() { return nullptr; }
    128 
    129  virtual PointerEvent* AsPointerEvent() { return nullptr; }
    130 
    131  // UIEvent has a non-autogeneratable initUIEvent.
    132  virtual UIEvent* AsUIEvent() { return nullptr; }
    133 
    134  // CustomEvent has a non-autogeneratable initCustomEvent.
    135  virtual CustomEvent* AsCustomEvent() { return nullptr; }
    136 
    137  // MessageEvent has a non-autogeneratable initMessageEvent and more.
    138  virtual MessageEvent* AsMessageEvent() { return nullptr; }
    139 
    140  // ToggleEvent has a non-autogeneratable initToggleEvent.
    141  virtual ToggleEvent* AsToggleEvent() { return nullptr; }
    142 
    143  void InitEvent(const nsAString& aEventTypeArg, bool aCanBubble,
    144                 bool aCancelable) {
    145    InitEvent(aEventTypeArg, aCanBubble ? CanBubble::eYes : CanBubble::eNo,
    146              aCancelable ? Cancelable::eYes : Cancelable::eNo);
    147  }
    148 
    149  void InitEvent(const nsAString& aEventTypeArg, mozilla::CanBubble,
    150                 mozilla::Cancelable,
    151                 mozilla::Composed = mozilla::Composed::eDefault);
    152 
    153  void SetTarget(EventTarget* aTarget);
    154  virtual void DuplicatePrivateData();
    155  bool IsDispatchStopped();
    156  WidgetEvent* WidgetEventPtr();
    157  const WidgetEvent* WidgetEventPtr() const {
    158    return const_cast<Event*>(this)->WidgetEventPtr();
    159  }
    160  virtual void Serialize(IPC::MessageWriter* aWriter,
    161                         bool aSerializeInterfaceType);
    162  virtual bool Deserialize(IPC::MessageReader* aReader);
    163  void SetOwner(EventTarget* aOwner);
    164  void StopCrossProcessForwarding();
    165  void SetTrusted(bool aTrusted);
    166 
    167  // When listening to chrome EventTargets, in the parent process, nsWindowRoot
    168  // might receive events we've already handled via
    169  // InProcessBrowserChildMessageManager, and handlers should call this to avoid
    170  // handling the same event twice.
    171  bool ShouldIgnoreChromeEventTargetListener() const;
    172 
    173  void InitPresContextData(nsPresContext* aPresContext);
    174 
    175  // Returns true if the event should be trusted.
    176  bool Init(EventTarget* aGlobal);
    177 
    178  static const char16_t* GetEventName(EventMessage aEventType);
    179 
    180  /**
    181   * Return clientX and clientY values for aEvent fired at
    182   * aWidgetOrScreenRelativePoint. If you do not want fractional values as
    183   * the result, you should floor aWidgetRelativePoint and aDefaultClientPoint
    184   * before calling this method like defined by the Pointer Events spec.
    185   * https://w3c.github.io/pointerevents/#event-coordinates
    186   * And finally round the result to the integer.
    187   * Note that if you want fractional values and the source of
    188   * aWidgetOrScreenRelativePoint and aDefaultClientPoint is an untrusted
    189   * event, the result may not be representable with floats, i.e., CSSPoint.
    190   * However, if it's trusted point, the result is representable with floats
    191   * because we use CSSPoint to convert to/from app units.
    192   *
    193   * Note that if and only if aEvent->mWidget is nullptr,
    194   * aWidgetOrScreenRelativePoint is treated as screen point because it's
    195   * impossible to compute screen point from widget relative point without the
    196   * widget.
    197   */
    198  static CSSDoublePoint GetClientCoords(
    199      nsPresContext* aPresContext, WidgetEvent* aEvent,
    200      const LayoutDeviceDoublePoint& aWidgetOrScreenRelativePoint,
    201      const CSSDoublePoint& aDefaultClientPoint);
    202 
    203  /**
    204   * Return pageX and pageY values for aEvent fired at
    205   * aWidgetOrScreenRelativePoint, which are client point + scroll position
    206   * of the root scrollable frame. If you do not want fractional values as the
    207   * result, you should floor aWidgetOrScreenRelativePoint and
    208   * aDefaultClientPoint before calling this method like defined by the Pointer
    209   * Events spec. https://w3c.github.io/pointerevents/#event-coordinates And
    210   * finally round the result to the integer. Note that if you want fractional
    211   * values and the source of aWidgetOrScreenRelativePoint and
    212   * aDefaultClientPoint is an untrusted event, the result may not be
    213   * representable with floats, i.e., CSSPoint.  However, if it's trusted point,
    214   * the result is representable with floats because we use CSSPoint to convert
    215   * to/from app units.
    216   *
    217   * Note that if and only if aEvent->mWidget is nullptr,
    218   * aWidgetOrScreenRelativePoint is treated as screen point because it's
    219   * impossible to compute screen point from widget relative point without the
    220   * widget.
    221   */
    222  static CSSDoublePoint GetPageCoords(
    223      nsPresContext* aPresContext, WidgetEvent* aEvent,
    224      const LayoutDeviceDoublePoint& aWidgetOrScreenRelativePoint,
    225      const CSSDoublePoint& aDefaultClientPoint);
    226 
    227  /**
    228   * Return screenX and screenY values for aEvent fired at
    229   * aWidgetOrScreenRelativePoint. If aEvent does not support exposing the
    230   * ref point, this returns Nothing. If you do not want fractional values as
    231   * the result, you should floor aWidgetOrScreenRelativePoint and
    232   * aDefaultClientPoint before calling this method like defined by the Pointer
    233   * Events spec. https://w3c.github.io/pointerevents/#event-coordinates And
    234   * finally round the result to the integer. Note that if you want fractional
    235   * values and the source of aWidgetOrScreenRelativePoint and
    236   * aDefaultClientPoint is an untrusted event, the result may not be
    237   * representable with floats, i.e., CSSPoint.  However, if it's trusted point,
    238   * the result is representable with floats because we use CSSPoint to convert
    239   * to/from app units.
    240   *
    241   * Note that if and only if aEvent->mWidget is nullptr,
    242   * aWidgetOrScreenRelativePoint is treated as screen point because it's
    243   * impossible to compute screen point from widget relative point without the
    244   * widget.
    245   */
    246  static Maybe<CSSDoublePoint> GetScreenCoords(
    247      nsPresContext* aPresContext, WidgetEvent* aEvent,
    248      const LayoutDeviceDoublePoint& aWidgetOrScreenRelativePoint);
    249 
    250  /**
    251   * Return offsetX and offsetY values for aEvent fired at
    252   * aWidgetOrScreenRelativePoint, which are offset in the target element.
    253   * If you do not want fractional values as the result, you should floor
    254   * aWidgetOrScreenRelativePoint and aDefaultClientPoint before calling
    255   * this method like defined by the Pointer Events spec.
    256   * https://w3c.github.io/pointerevents/#event-coordinates And finally round
    257   * the result to the integer. Note that if you want fractional values and the
    258   * source of aWidgetOrScreenRelativePoint and aDefaultClientPoint is an
    259   * untrusted event, the result may not be representable with floats, i.e.,
    260   * CSSPoint. However, if it's trusted point, the result is representable with
    261   * floats because we use CSSPoint to convert to/from app units.
    262   *
    263   * Note that if and only if aEvent->mWidget is nullptr,
    264   * aWidgetOrScreenRelativePoint is treated as screen point because it's
    265   * impossible to compute screen point from widget relative point without the
    266   * widget.
    267   *
    268   * Be aware, this may flush the layout.
    269   */
    270  MOZ_CAN_RUN_SCRIPT
    271  static CSSDoublePoint GetOffsetCoords(
    272      nsPresContext* aPresContext, WidgetEvent* aEvent,
    273      const LayoutDeviceDoublePoint& aWidgetOrScreenRelativePoint,
    274      const CSSDoublePoint& aDefaultClientPoint);
    275 
    276  static already_AddRefed<Event> Constructor(EventTarget* aEventTarget,
    277                                             const nsAString& aType,
    278                                             const EventInit& aParam);
    279 
    280  static already_AddRefed<Event> Constructor(const GlobalObject& aGlobal,
    281                                             const nsAString& aType,
    282                                             const EventInit& aParam);
    283 
    284  void GetType(nsAString& aType) const;
    285 
    286  EventTarget* GetTarget() const;
    287  EventTarget* GetCurrentTarget() const;
    288 
    289  // This method returns the document which is associated with the event target.
    290  already_AddRefed<Document> GetDocument() const;
    291 
    292  void ComposedPath(nsTArray<RefPtr<EventTarget>>& aPath);
    293 
    294  uint16_t EventPhase() const;
    295 
    296  void StopPropagation();
    297 
    298  void StopImmediatePropagation();
    299 
    300  bool Bubbles() const { return mEvent->mFlags.mBubbles; }
    301 
    302  bool Cancelable() const { return mEvent->mFlags.mCancelable; }
    303 
    304  bool Composed() const { return mEvent->mFlags.mComposed; }
    305 
    306  bool CancelBubble() const { return mEvent->PropagationStopped(); }
    307  void SetCancelBubble(bool aCancelBubble) {
    308    if (aCancelBubble) {
    309      mEvent->StopPropagation();
    310    }
    311  }
    312 
    313  // For C++ consumers only!
    314  void PreventDefault();
    315 
    316  // You MUST NOT call PreventDefault(JSContext*, CallerType) from C++ code.  A
    317  // call of this method always sets Event.defaultPrevented true for web
    318  // contents.  If default action handler calls this, web applications see wrong
    319  // defaultPrevented value.
    320  virtual void PreventDefault(JSContext* aCx, CallerType aCallerType);
    321 
    322  // You MUST NOT call DefaultPrevented(CallerType) from C++ code.  This may
    323  // return false even if PreventDefault() has been called.
    324  // See comments in its implementation for the details.
    325  bool DefaultPrevented(CallerType aCallerType) const;
    326 
    327  bool DefaultPrevented() const { return mEvent->DefaultPrevented(); }
    328 
    329  bool DefaultPreventedByChrome() const {
    330    return mEvent->mFlags.mDefaultPreventedByChrome;
    331  }
    332 
    333  bool DefaultPreventedByContent() const {
    334    return mEvent->mFlags.mDefaultPreventedByContent;
    335  }
    336 
    337  void PreventMultipleActions() {
    338    mEvent->mFlags.mMultipleActionsPrevented = true;
    339  }
    340 
    341  bool MultipleActionsPrevented() const {
    342    return mEvent->mFlags.mMultipleActionsPrevented;
    343  }
    344 
    345  bool ReturnValue(CallerType aCallerType) const;
    346 
    347  void SetReturnValue(bool aReturnValue, CallerType aCallerType);
    348 
    349  bool IsTrusted() const { return mEvent->IsTrusted(); }
    350 
    351  bool IsSynthesized() const { return mEvent->mFlags.mIsSynthesizedForTests; }
    352 
    353  bool IsSafeToBeDispatchedAsynchronously() const {
    354    // If mEvent is not created by dom::Event nor its subclasses, its lifetime
    355    // is not guaranteed.  So, only when mEventIsInternal is true, it's safe
    356    // to be dispatched asynchronously.
    357    return mEventIsInternal;
    358  }
    359 
    360  double TimeStamp();
    361 
    362  EventTarget* GetOriginalTarget() const;
    363  EventTarget* GetOriginalTarget(CallerType aCallerType) const;
    364  EventTarget* GetExplicitOriginalTarget() const;
    365  EventTarget* GetComposedTarget() const;
    366 
    367  /**
    368   * @param aCalledByDefaultHandler     Should be true when this is called by
    369   *                                    C++ or Chrome.  Otherwise, e.g., called
    370   *                                    by a call of Event.preventDefault() in
    371   *                                    content script, false.
    372   */
    373  void PreventDefaultInternal(bool aCalledByDefaultHandler,
    374                              nsIPrincipal* aPrincipal = nullptr);
    375 
    376  bool IsMainThreadEvent() { return mIsMainThreadEvent; }
    377 
    378  void MarkUninitialized() {
    379    mEvent->mMessage = eVoidEvent;
    380    mEvent->mSpecifiedEventTypeString.Truncate();
    381    mEvent->mSpecifiedEventType = nullptr;
    382  }
    383 
    384  /**
    385   * For WidgetEvent, return it's type in string.
    386   *
    387   * @param aEvent is a WidgetEvent to get its type.
    388   * @param aType is a string where to return the type.
    389   */
    390  static void GetWidgetEventType(WidgetEvent* aEvent, nsAString& aType);
    391 
    392  void RequestReplyFromRemoteContent() {
    393    mEvent->MarkAsWaitingReplyFromRemoteProcess();
    394  }
    395 
    396  bool IsWaitingReplyFromRemoteContent() const {
    397    return mEvent->IsWaitingReplyFromRemoteProcess();
    398  }
    399 
    400  bool IsReplyEventFromRemoteContent() const {
    401    return mEvent->IsHandledInRemoteProcess();
    402  }
    403 
    404  static bool IsDragExitEnabled(JSContext* aCx, JSObject* aGlobal);
    405 
    406 protected:
    407  // Internal helper functions
    408  void SetEventType(const nsAString& aEventTypeArg);
    409  nsIContent* GetTargetFromFrame();
    410 
    411  friend class EventMessageAutoOverride;
    412  friend class PopupBlocker;
    413  friend class WantsPopupControlCheck;
    414  void SetWantsPopupControlCheck(bool aCheck) {
    415    mWantsPopupControlCheck = aCheck;
    416  }
    417 
    418  bool GetWantsPopupControlCheck() {
    419    return IsTrusted() && mWantsPopupControlCheck;
    420  }
    421 
    422  void SetComposed(bool aComposed) { mEvent->SetComposed(aComposed); }
    423 
    424  already_AddRefed<EventTarget> EnsureWebAccessibleRelatedTarget(
    425      EventTarget* aRelatedTarget);
    426 
    427  [[nodiscard]] MOZ_CAN_RUN_SCRIPT static nsIFrame*
    428  GetPrimaryFrameOfEventTarget(const nsPresContext& aPresContext,
    429                               const WidgetEvent& aEvent);
    430 
    431  mozilla::WidgetEvent* mEvent;
    432  // When the private data of this event is duplicated, mPresContext is
    433  // cleared by Event::DuplicatePrivateData().  However, only
    434  // MouseEvent::DuplicatePrivateData() restores mPresContext after calling
    435  // Event::DuplicatePrivateData() to compute the offset point later.
    436  // Therefore, only `MouseEvent` and its subclasses may keep storing
    437  // mPresContext until destroyed.
    438  WeakPtr<nsPresContext> mPresContext;
    439  nsCOMPtr<EventTarget> mExplicitOriginalTarget;
    440  nsCOMPtr<nsIGlobalObject> mOwner;
    441  bool mEventIsInternal;
    442  bool mPrivateDataDuplicated;
    443  bool mIsMainThreadEvent;
    444  // True when popup control check should rely on event.type, not
    445  // WidgetEvent.mMessage.
    446  bool mWantsPopupControlCheck;
    447 };
    448 
    449 /**
    450 * RAII helper-class to override an event's message (i.e. its DOM-exposed
    451 * type), for as long as the object is alive.  Restores the original
    452 * EventMessage when destructed.
    453 *
    454 * Notable requirements:
    455 *  - The original & overriding messages must be known (not eUnidentifiedEvent).
    456 *  - The original & overriding messages must be different.
    457 *  - The passed-in Event must outlive this RAII helper.
    458 */
    459 class MOZ_RAII EventMessageAutoOverride {
    460 public:
    461  explicit EventMessageAutoOverride(Event* aEvent,
    462                                    EventMessage aOverridingMessage)
    463      : mEvent(aEvent), mOrigMessage(mEvent->mEvent->mMessage) {
    464    MOZ_ASSERT(aOverridingMessage != mOrigMessage,
    465               "Don't use this class if you're not actually overriding");
    466    MOZ_ASSERT(aOverridingMessage != eUnidentifiedEvent,
    467               "Only use this class with a valid overriding EventMessage");
    468    MOZ_ASSERT(mOrigMessage != eUnidentifiedEvent &&
    469                   mEvent->mEvent->mSpecifiedEventTypeString.IsEmpty(),
    470               "Only use this class on events whose overridden type is "
    471               "known (so we can restore it properly)");
    472 
    473    mEvent->mEvent->mMessage = aOverridingMessage;
    474  }
    475 
    476  ~EventMessageAutoOverride() { mEvent->mEvent->mMessage = mOrigMessage; }
    477 
    478 protected:
    479  // Non-owning ref, which should be safe since we're a stack-allocated object
    480  // with limited lifetime. Whoever creates us should keep mEvent alive.
    481  Event* const MOZ_NON_OWNING_REF mEvent;
    482  const EventMessage mOrigMessage;
    483 };
    484 
    485 class MOZ_STACK_CLASS WantsPopupControlCheck {
    486 public:
    487  explicit WantsPopupControlCheck(Event* aEvent) : mEvent(aEvent) {
    488    mOriginalWantsPopupControlCheck = mEvent->GetWantsPopupControlCheck();
    489    mEvent->SetWantsPopupControlCheck(mEvent->IsTrusted());
    490  }
    491 
    492  ~WantsPopupControlCheck() {
    493    mEvent->SetWantsPopupControlCheck(mOriginalWantsPopupControlCheck);
    494  }
    495 
    496 private:
    497  Event* mEvent;
    498  bool mOriginalWantsPopupControlCheck;
    499 };
    500 
    501 }  // namespace mozilla::dom
    502 
    503 already_AddRefed<mozilla::dom::Event> NS_NewDOMEvent(
    504    mozilla::dom::EventTarget* aOwner, nsPresContext* aPresContext,
    505    mozilla::WidgetEvent* aEvent);
    506 
    507 #endif  // mozilla_dom_Event_h_