tor-browser

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

EventDispatcher.h (13416B)


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