LCOV - code coverage report
Current view: top level - dom/events - EventDispatcher.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 312 522 59.8 %
Date: 2017-07-14 16:53:18 Functions: 33 40 82.5 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #include "nsPresContext.h"
       8             : #include "nsContentUtils.h"
       9             : #include "nsError.h"
      10             : #include <new>
      11             : #include "nsIContent.h"
      12             : #include "nsIDocument.h"
      13             : #include "nsINode.h"
      14             : #include "nsPIDOMWindow.h"
      15             : #include "AnimationEvent.h"
      16             : #include "BeforeUnloadEvent.h"
      17             : #include "ClipboardEvent.h"
      18             : #include "CommandEvent.h"
      19             : #include "CompositionEvent.h"
      20             : #include "DeviceMotionEvent.h"
      21             : #include "DragEvent.h"
      22             : #include "GeckoProfiler.h"
      23             : #include "KeyboardEvent.h"
      24             : #include "mozilla/ContentEvents.h"
      25             : #include "mozilla/dom/CloseEvent.h"
      26             : #include "mozilla/dom/CustomEvent.h"
      27             : #include "mozilla/dom/DeviceOrientationEvent.h"
      28             : #include "mozilla/dom/ErrorEvent.h"
      29             : #include "mozilla/dom/EventTarget.h"
      30             : #include "mozilla/dom/FocusEvent.h"
      31             : #include "mozilla/dom/HashChangeEvent.h"
      32             : #include "mozilla/dom/InputEvent.h"
      33             : #include "mozilla/dom/MessageEvent.h"
      34             : #include "mozilla/dom/MouseScrollEvent.h"
      35             : #include "mozilla/dom/MutationEvent.h"
      36             : #include "mozilla/dom/NotifyPaintEvent.h"
      37             : #include "mozilla/dom/PageTransitionEvent.h"
      38             : #include "mozilla/dom/PointerEvent.h"
      39             : #include "mozilla/dom/PopStateEvent.h"
      40             : #include "mozilla/dom/RootedDictionary.h"
      41             : #include "mozilla/dom/ScrollAreaEvent.h"
      42             : #include "mozilla/dom/SimpleGestureEvent.h"
      43             : #include "mozilla/dom/ScriptSettings.h"
      44             : #include "mozilla/dom/StorageEvent.h"
      45             : #include "mozilla/dom/TimeEvent.h"
      46             : #include "mozilla/dom/TouchEvent.h"
      47             : #include "mozilla/dom/TransitionEvent.h"
      48             : #include "mozilla/dom/WheelEvent.h"
      49             : #include "mozilla/dom/WorkerPrivate.h"
      50             : #include "mozilla/dom/XULCommandEvent.h"
      51             : #include "mozilla/EventDispatcher.h"
      52             : #include "mozilla/EventListenerManager.h"
      53             : #include "mozilla/InternalMutationEvent.h"
      54             : #include "mozilla/ipc/MessageChannel.h"
      55             : #include "mozilla/MiscEvents.h"
      56             : #include "mozilla/MouseEvents.h"
      57             : #include "mozilla/Telemetry.h"
      58             : #include "mozilla/TextEvents.h"
      59             : #include "mozilla/TouchEvents.h"
      60             : #include "mozilla/Unused.h"
      61             : 
      62             : #ifdef MOZ_TASK_TRACER
      63             : #include "GeckoTaskTracer.h"
      64             : #include "mozilla/dom/Element.h"
      65             : #include "mozilla/Likely.h"
      66             : using namespace mozilla::tasktracer;
      67             : #endif
      68             : 
      69             : namespace mozilla {
      70             : 
      71             : using namespace dom;
      72             : 
      73             : class ELMCreationDetector
      74             : {
      75             : public:
      76         499 :   ELMCreationDetector()
      77             :     // We can do this optimization only in the main thread.
      78         499 :     : mNonMainThread(!NS_IsMainThread())
      79         499 :     , mInitialCount(mNonMainThread ?
      80         998 :                       0 : EventListenerManager::sMainThreadCreatedCount)
      81             :   {
      82         499 :   }
      83             : 
      84        2812 :   bool MayHaveNewListenerManager()
      85             :   {
      86        5624 :     return mNonMainThread ||
      87        5624 :            mInitialCount != EventListenerManager::sMainThreadCreatedCount;
      88             :   }
      89             : 
      90         998 :   bool IsMainThread()
      91             :   {
      92         998 :     return !mNonMainThread;
      93             :   }
      94             : 
      95             : private:
      96             :   bool mNonMainThread;
      97             :   uint32_t mInitialCount;
      98             : };
      99             : 
     100           8 : static bool IsEventTargetChrome(EventTarget* aEventTarget,
     101             :                                 nsIDocument** aDocument = nullptr)
     102             : {
     103           8 :   if (aDocument) {
     104           8 :     *aDocument = nullptr;
     105             :   }
     106             : 
     107           8 :   if (NS_WARN_IF(!aEventTarget)) {
     108           0 :     return false;
     109             :   }
     110             : 
     111          16 :   nsCOMPtr<nsIDocument> doc = do_QueryInterface(aEventTarget);
     112           8 :   if (!doc) {
     113          16 :     nsCOMPtr<nsINode> node = do_QueryInterface(aEventTarget);
     114           8 :     if (node) {
     115           4 :       doc = node->OwnerDoc();
     116             :     } else {
     117           8 :       nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aEventTarget);
     118           4 :       if (!window) {
     119           0 :         return false;
     120             :       }
     121           4 :       doc = window->GetExtantDoc();
     122             :     }
     123           8 :     if (!doc) {
     124           0 :       return false;
     125             :     }
     126             :   }
     127           8 :   bool isChrome = nsContentUtils::IsChromeDoc(doc);
     128           8 :   if (aDocument) {
     129           8 :     doc.swap(*aDocument);
     130             :   }
     131           8 :   return isChrome;
     132             : }
     133             : 
     134             : 
     135             : // EventTargetChainItem represents a single item in the event target chain.
     136        2323 : class EventTargetChainItem
     137             : {
     138             : private:
     139             :   explicit EventTargetChainItem(EventTarget* aTarget);
     140             : public:
     141        2323 :   EventTargetChainItem()
     142        2323 :     : mItemFlags(0)
     143             :   {
     144        2323 :   }
     145             : 
     146        2323 :   static EventTargetChainItem* Create(nsTArray<EventTargetChainItem>& aChain,
     147             :                                       EventTarget* aTarget,
     148             :                                       EventTargetChainItem* aChild = nullptr)
     149             :   {
     150             :     // The last item which can handle the event must be aChild.
     151        2323 :     MOZ_ASSERT(GetLastCanHandleEventTarget(aChain) == aChild);
     152        2323 :     return new (aChain.AppendElement()) EventTargetChainItem(aTarget);
     153             :   }
     154             : 
     155           0 :   static void DestroyLast(nsTArray<EventTargetChainItem>& aChain,
     156             :                           EventTargetChainItem* aItem)
     157             :   {
     158           0 :     uint32_t lastIndex = aChain.Length() - 1;
     159           0 :     MOZ_ASSERT(&aChain[lastIndex] == aItem);
     160           0 :     aChain.RemoveElementAt(lastIndex);
     161           0 :   }
     162             : 
     163           0 :   static EventTargetChainItem* GetFirstCanHandleEventTarget(
     164             :                                  nsTArray<EventTargetChainItem>& aChain)
     165             :   {
     166           0 :     return &aChain[GetFirstCanHandleEventTargetIdx(aChain)];
     167             :   }
     168             : 
     169         892 :   static uint32_t GetFirstCanHandleEventTargetIdx(nsTArray<EventTargetChainItem>& aChain)
     170             :   {
     171             :     // aChain[i].PreHandleEventOnly() = true only when the target element wants
     172             :     // PreHandleEvent and set mCanHandle=false. So we find the first element
     173             :     // which can handle the event.
     174         892 :     for (uint32_t i = 0; i < aChain.Length(); ++i) {
     175         892 :       if (!aChain[i].PreHandleEventOnly()) {
     176         892 :         return i;
     177             :       }
     178             :     }
     179           0 :     MOZ_ASSERT(false);
     180             :     return 0;
     181             :   }
     182             : 
     183        2323 :   static EventTargetChainItem* GetLastCanHandleEventTarget(
     184             :                                  nsTArray<EventTargetChainItem>& aChain)
     185             :   {
     186             :     // Fine the last item which can handle the event.
     187        2323 :     for (int32_t i = aChain.Length() - 1; i >= 0; --i) {
     188        1824 :       if (!aChain[i].PreHandleEventOnly()) {
     189        1824 :         return &aChain[i];
     190             :       }
     191             :     }
     192         499 :     return nullptr;
     193             :   }
     194             : 
     195        2323 :   bool IsValid()
     196             :   {
     197        2323 :     NS_WARNING_ASSERTION(!!(mTarget), "Event target is not valid!");
     198        2323 :     return !!(mTarget);
     199             :   }
     200             : 
     201        7170 :   EventTarget* GetNewTarget()
     202             :   {
     203        7170 :     return mNewTarget;
     204             :   }
     205             : 
     206         590 :   void SetNewTarget(EventTarget* aNewTarget)
     207             :   {
     208         590 :     mNewTarget = aNewTarget;
     209         590 :   }
     210             : 
     211        2323 :   void SetForceContentDispatch(bool aForce)
     212             :   {
     213        2323 :     mFlags.mForceContentDispatch = aForce;
     214        2323 :   }
     215             : 
     216           0 :   bool ForceContentDispatch()
     217             :   {
     218           0 :     return mFlags.mForceContentDispatch;
     219             :   }
     220             : 
     221        2323 :   void SetWantsWillHandleEvent(bool aWants)
     222             :   {
     223        2323 :     mFlags.mWantsWillHandleEvent = aWants;
     224        2323 :   }
     225             : 
     226        6024 :   bool WantsWillHandleEvent()
     227             :   {
     228        6024 :     return mFlags.mWantsWillHandleEvent;
     229             :   }
     230             : 
     231        2323 :   void SetWantsPreHandleEvent(bool aWants)
     232             :   {
     233        2323 :     mFlags.mWantsPreHandleEvent = aWants;
     234        2323 :   }
     235             : 
     236        2171 :   bool WantsPreHandleEvent()
     237             :   {
     238        2171 :     return mFlags.mWantsPreHandleEvent;
     239             :   }
     240             : 
     241        2323 :   void SetPreHandleEventOnly(bool aWants)
     242             :   {
     243        2323 :     mFlags.mPreHandleEventOnly = aWants;
     244        2323 :   }
     245             : 
     246        9412 :   bool PreHandleEventOnly()
     247             :   {
     248        9412 :     return mFlags.mPreHandleEventOnly;
     249             :   }
     250             : 
     251        2323 :   void SetMayHaveListenerManager(bool aMayHave)
     252             :   {
     253        2323 :     mFlags.mMayHaveManager = aMayHave;
     254        2323 :   }
     255             : 
     256        4095 :   bool MayHaveListenerManager()
     257             :   {
     258        4095 :     return mFlags.mMayHaveManager;
     259             :   }
     260             : 
     261        3462 :   EventTarget* CurrentTarget()
     262             :   {
     263        3462 :     return mTarget;
     264             :   }
     265             : 
     266             :   /**
     267             :    * Dispatches event through the event target chain.
     268             :    * Handles capture, target and bubble phases both in default
     269             :    * and system event group and calls also PostHandleEvent for each
     270             :    * item in the chain.
     271             :    */
     272             :   static void HandleEventTargetChain(nsTArray<EventTargetChainItem>& aChain,
     273             :                                      EventChainPostVisitor& aVisitor,
     274             :                                      EventDispatchingCallback* aCallback,
     275             :                                      ELMCreationDetector& aCd);
     276             : 
     277             :   /**
     278             :    * Resets aVisitor object and calls GetEventTargetParent.
     279             :    * Copies mItemFlags and mItemData to the current EventTargetChainItem.
     280             :    */
     281             :   void GetEventTargetParent(EventChainPreVisitor& aVisitor);
     282             : 
     283             :   /**
     284             :    * Calls PreHandleEvent for those items which called SetWantsPreHandleEvent.
     285             :    */
     286             :   void PreHandleEvent(EventChainVisitor& aVisitor);
     287             : 
     288             :   /**
     289             :    * If the current item in the event target chain has an event listener
     290             :    * manager, this method calls EventListenerManager::HandleEvent().
     291             :    */
     292        6024 :   void HandleEvent(EventChainPostVisitor& aVisitor,
     293             :                    ELMCreationDetector& aCd)
     294             :   {
     295        6024 :     if (WantsWillHandleEvent()) {
     296           0 :       mTarget->WillHandleEvent(aVisitor);
     297             :     }
     298        6024 :     if (aVisitor.mEvent->PropagationStopped()) {
     299           0 :       return;
     300             :     }
     301       12048 :     if (aVisitor.mEvent->mFlags.mOnlySystemGroupDispatchInContent &&
     302        6024 :         !aVisitor.mEvent->mFlags.mInSystemGroup &&
     303           0 :         !IsCurrentTargetChrome()) {
     304           0 :       return;
     305             :     }
     306        6024 :     if (!mManager) {
     307        4095 :       if (!MayHaveListenerManager() && !aCd.MayHaveNewListenerManager()) {
     308        2812 :         return;
     309             :       }
     310        1283 :       mManager = mTarget->GetExistingListenerManager();
     311             :     }
     312        3212 :     if (mManager) {
     313        2944 :       NS_ASSERTION(aVisitor.mEvent->mCurrentTarget == nullptr,
     314             :                    "CurrentTarget should be null!");
     315        2944 :       mManager->HandleEvent(aVisitor.mPresContext, aVisitor.mEvent,
     316             :                             &aVisitor.mDOMEvent,
     317             :                             CurrentTarget(),
     318        2944 :                             &aVisitor.mEventStatus);
     319        2944 :       NS_ASSERTION(aVisitor.mEvent->mCurrentTarget == nullptr,
     320             :                    "CurrentTarget should be null!");
     321             :     }
     322             :   }
     323             : 
     324             :   /**
     325             :    * Copies mItemFlags and mItemData to aVisitor and calls PostHandleEvent.
     326             :    */
     327             :   void PostHandleEvent(EventChainPostVisitor& aVisitor);
     328             : 
     329             : private:
     330             :   nsCOMPtr<EventTarget>             mTarget;
     331             : 
     332             :   class EventTargetChainFlags
     333             :   {
     334             :   public:
     335        4646 :     explicit EventTargetChainFlags()
     336        4646 :     {
     337        4646 :       SetRawFlags(0);
     338        4646 :     }
     339             :     // Cached flags for each EventTargetChainItem which are set when calling
     340             :     // GetEventTargetParent to create event target chain. They are used to
     341             :     // manage or speedup event dispatching.
     342             :     bool mForceContentDispatch : 1;
     343             :     bool mWantsWillHandleEvent : 1;
     344             :     bool mMayHaveManager : 1;
     345             :     bool mChechedIfChrome : 1;
     346             :     bool mIsChromeContent : 1;
     347             :     bool mWantsPreHandleEvent : 1;
     348             :     bool mPreHandleEventOnly : 1;
     349             :   private:
     350             :     typedef uint32_t RawFlags;
     351        4646 :     void SetRawFlags(RawFlags aRawFlags)
     352             :     {
     353             :       static_assert(sizeof(EventTargetChainFlags) <= sizeof(RawFlags),
     354             :         "EventTargetChainFlags must not be bigger than the RawFlags");
     355        4646 :       memcpy(this, &aRawFlags, sizeof(EventTargetChainFlags));
     356        4646 :     }
     357             :   } mFlags;
     358             : 
     359             :   uint16_t                          mItemFlags;
     360             :   nsCOMPtr<nsISupports>             mItemData;
     361             :   // Event retargeting must happen whenever mNewTarget is non-null.
     362             :   nsCOMPtr<EventTarget>             mNewTarget;
     363             :   // Cache mTarget's event listener manager.
     364             :   RefPtr<EventListenerManager>    mManager;
     365             : 
     366           0 :   bool IsCurrentTargetChrome()
     367             :   {
     368           0 :     if (!mFlags.mChechedIfChrome) {
     369           0 :       mFlags.mChechedIfChrome = true;
     370           0 :       if (IsEventTargetChrome(mTarget)) {
     371           0 :         mFlags.mIsChromeContent = true;
     372             :       }
     373             :     }
     374           0 :     return mFlags.mIsChromeContent;
     375             :   }
     376             : };
     377             : 
     378        2323 : EventTargetChainItem::EventTargetChainItem(EventTarget* aTarget)
     379             :   : mTarget(aTarget)
     380        2323 :   , mItemFlags(0)
     381             : {
     382        2323 :   MOZ_ASSERT(!aTarget || mTarget == aTarget->GetTargetForEventTargetChain());
     383        2323 : }
     384             : 
     385             : void
     386        2323 : EventTargetChainItem::GetEventTargetParent(EventChainPreVisitor& aVisitor)
     387             : {
     388        2323 :   aVisitor.Reset();
     389        2323 :   Unused << mTarget->GetEventTargetParent(aVisitor);
     390        2323 :   SetForceContentDispatch(aVisitor.mForceContentDispatch);
     391        2323 :   SetWantsWillHandleEvent(aVisitor.mWantsWillHandleEvent);
     392        2323 :   SetMayHaveListenerManager(aVisitor.mMayHaveListenerManager);
     393        2323 :   SetWantsPreHandleEvent(aVisitor.mWantsPreHandleEvent);
     394        2323 :   SetPreHandleEventOnly(aVisitor.mWantsPreHandleEvent && !aVisitor.mCanHandle);
     395        2323 :   mItemFlags = aVisitor.mItemFlags;
     396        2323 :   mItemData = aVisitor.mItemData;
     397        2323 : }
     398             : 
     399             : void
     400        2171 : EventTargetChainItem::PreHandleEvent(EventChainVisitor& aVisitor)
     401             : {
     402        2171 :   if (!WantsPreHandleEvent()) {
     403        2171 :     return;
     404             :   }
     405           0 :   aVisitor.mItemFlags = mItemFlags;
     406           0 :   aVisitor.mItemData = mItemData;
     407           0 :   Unused << mTarget->PreHandleEvent(aVisitor);
     408             : }
     409             : 
     410             : void
     411        1287 : EventTargetChainItem::PostHandleEvent(EventChainPostVisitor& aVisitor)
     412             : {
     413        1287 :   aVisitor.mItemFlags = mItemFlags;
     414        1287 :   aVisitor.mItemData = mItemData;
     415        1287 :   mTarget->PostHandleEvent(aVisitor);
     416        1287 : }
     417             : 
     418             : void
     419         892 : EventTargetChainItem::HandleEventTargetChain(
     420             :                         nsTArray<EventTargetChainItem>& aChain,
     421             :                         EventChainPostVisitor& aVisitor,
     422             :                         EventDispatchingCallback* aCallback,
     423             :                         ELMCreationDetector& aCd)
     424             : {
     425             :   // Save the target so that it can be restored later.
     426        1784 :   nsCOMPtr<EventTarget> firstTarget = aVisitor.mEvent->mTarget;
     427         892 :   uint32_t chainLength = aChain.Length();
     428             :   uint32_t firstCanHandleEventTargetIdx =
     429         892 :     EventTargetChainItem::GetFirstCanHandleEventTargetIdx(aChain);
     430             : 
     431             :   // Capture
     432         892 :   aVisitor.mEvent->mFlags.mInCapturePhase = true;
     433         892 :   aVisitor.mEvent->mFlags.mInBubblingPhase = false;
     434        4240 :   for (uint32_t i = chainLength - 1; i > firstCanHandleEventTargetIdx; --i) {
     435        3348 :     EventTargetChainItem& item = aChain[i];
     436        3348 :     if (item.PreHandleEventOnly()) {
     437           0 :       continue;
     438             :     }
     439        6696 :     if ((!aVisitor.mEvent->mFlags.mNoContentDispatch ||
     440        6696 :          item.ForceContentDispatch()) &&
     441        3348 :         !aVisitor.mEvent->PropagationStopped()) {
     442        3348 :       item.HandleEvent(aVisitor, aCd);
     443             :     }
     444             : 
     445        3348 :     if (item.GetNewTarget()) {
     446             :       // item is at anonymous boundary. Need to retarget for the child items.
     447         474 :       for (uint32_t j = i; j > 0; --j) {
     448         474 :         uint32_t childIndex = j - 1;
     449         474 :         EventTarget* newTarget = aChain[childIndex].GetNewTarget();
     450         474 :         if (newTarget) {
     451         176 :           aVisitor.mEvent->mTarget = newTarget;
     452         176 :           break;
     453             :         }
     454             :       }
     455             :     }
     456             :   }
     457             : 
     458             :   // Target
     459         892 :   aVisitor.mEvent->mFlags.mInBubblingPhase = true;
     460         892 :   EventTargetChainItem& targetItem = aChain[firstCanHandleEventTargetIdx];
     461        2676 :   if (!aVisitor.mEvent->PropagationStopped() &&
     462         892 :       (!aVisitor.mEvent->mFlags.mNoContentDispatch ||
     463           0 :        targetItem.ForceContentDispatch())) {
     464         892 :     targetItem.HandleEvent(aVisitor, aCd);
     465             :   }
     466         892 :   if (aVisitor.mEvent->mFlags.mInSystemGroup) {
     467         443 :     targetItem.PostHandleEvent(aVisitor);
     468             :   }
     469             : 
     470             :   // Bubble
     471         892 :   aVisitor.mEvent->mFlags.mInCapturePhase = false;
     472        4240 :   for (uint32_t i = firstCanHandleEventTargetIdx + 1; i < chainLength; ++i) {
     473        3348 :     EventTargetChainItem& item = aChain[i];
     474        3348 :     if (item.PreHandleEventOnly()) {
     475           0 :       continue;
     476             :     }
     477        3348 :     EventTarget* newTarget = item.GetNewTarget();
     478        3348 :     if (newTarget) {
     479             :       // Item is at anonymous boundary. Need to retarget for the current item
     480             :       // and for parent items.
     481         176 :       aVisitor.mEvent->mTarget = newTarget;
     482             :     }
     483             : 
     484        3348 :     if (aVisitor.mEvent->mFlags.mBubbles || newTarget) {
     485        3568 :       if ((!aVisitor.mEvent->mFlags.mNoContentDispatch ||
     486        3568 :            item.ForceContentDispatch()) &&
     487        1784 :           !aVisitor.mEvent->PropagationStopped()) {
     488        1784 :         item.HandleEvent(aVisitor, aCd);
     489             :       }
     490        1784 :       if (aVisitor.mEvent->mFlags.mInSystemGroup) {
     491         844 :         item.PostHandleEvent(aVisitor);
     492             :       }
     493             :     }
     494             :   }
     495         892 :   aVisitor.mEvent->mFlags.mInBubblingPhase = false;
     496             : 
     497        1341 :   if (!aVisitor.mEvent->mFlags.mInSystemGroup &&
     498         449 :       aVisitor.mEvent->IsAllowedToDispatchInSystemGroup()) {
     499             :     // Dispatch to the system event group.  Make sure to clear the
     500             :     // STOP_DISPATCH flag since this resets for each event group.
     501         443 :     aVisitor.mEvent->mFlags.mPropagationStopped = false;
     502         443 :     aVisitor.mEvent->mFlags.mImmediatePropagationStopped = false;
     503             : 
     504             :     // Setting back the original target of the event.
     505         443 :     aVisitor.mEvent->mTarget = aVisitor.mEvent->mOriginalTarget;
     506             : 
     507             :     // Special handling if PresShell (or some other caller)
     508             :     // used a callback object.
     509         443 :     if (aCallback) {
     510           7 :       aCallback->HandleEvent(aVisitor);
     511             :     }
     512             : 
     513             :     // Retarget for system event group (which does the default handling too).
     514             :     // Setting back the target which was used also for default event group.
     515         443 :     aVisitor.mEvent->mTarget = firstTarget;
     516         443 :     aVisitor.mEvent->mFlags.mInSystemGroup = true;
     517             :     HandleEventTargetChain(aChain,
     518             :                            aVisitor,
     519             :                            aCallback,
     520         443 :                            aCd);
     521         443 :     aVisitor.mEvent->mFlags.mInSystemGroup = false;
     522             : 
     523             :     // After dispatch, clear all the propagation flags so that
     524             :     // system group listeners don't affect to the event.
     525         443 :     aVisitor.mEvent->mFlags.mPropagationStopped = false;
     526         443 :     aVisitor.mEvent->mFlags.mImmediatePropagationStopped = false;
     527             :   }
     528         892 : }
     529             : 
     530             : static nsTArray<EventTargetChainItem>* sCachedMainThreadChain = nullptr;
     531             : 
     532             : /* static */ void
     533           0 : EventDispatcher::Shutdown()
     534             : {
     535           0 :   delete sCachedMainThreadChain;
     536           0 :   sCachedMainThreadChain = nullptr;
     537           0 : }
     538             : 
     539             : EventTargetChainItem*
     540           0 : EventTargetChainItemForChromeTarget(nsTArray<EventTargetChainItem>& aChain,
     541             :                                     nsINode* aNode,
     542             :                                     EventTargetChainItem* aChild = nullptr)
     543             : {
     544           0 :   if (!aNode->IsInComposedDoc()) {
     545           0 :     return nullptr;
     546             :   }
     547           0 :   nsPIDOMWindowInner* win = aNode->OwnerDoc()->GetInnerWindow();
     548           0 :   EventTarget* piTarget = win ? win->GetParentTarget() : nullptr;
     549           0 :   NS_ENSURE_TRUE(piTarget, nullptr);
     550             : 
     551             :   EventTargetChainItem* etci =
     552           0 :     EventTargetChainItem::Create(aChain,
     553           0 :                                  piTarget->GetTargetForEventTargetChain(),
     554           0 :                                  aChild);
     555           0 :   if (!etci->IsValid()) {
     556           0 :     EventTargetChainItem::DestroyLast(aChain, etci);
     557           0 :     return nullptr;
     558             :   }
     559           0 :   return etci;
     560             : }
     561             : 
     562             : /* static */ EventTargetChainItem*
     563           0 : MayRetargetToChromeIfCanNotHandleEvent(
     564             :   nsTArray<EventTargetChainItem>& aChain, EventChainPreVisitor& aPreVisitor,
     565             :   EventTargetChainItem* aTargetEtci, EventTargetChainItem* aChildEtci,
     566             :   nsINode* aContent)
     567             : {
     568           0 :   if (!aPreVisitor.mWantsPreHandleEvent) {
     569             :     // Keep EventTargetChainItem if we need to call PreHandleEvent on it.
     570           0 :     EventTargetChainItem::DestroyLast(aChain, aTargetEtci);
     571             :   }
     572           0 :   if (aPreVisitor.mAutomaticChromeDispatch && aContent) {
     573             :     // Event target couldn't handle the event. Try to propagate to chrome.
     574             :     EventTargetChainItem* chromeTargetEtci =
     575           0 :       EventTargetChainItemForChromeTarget(aChain, aContent, aChildEtci);
     576           0 :     if (chromeTargetEtci) {
     577           0 :       chromeTargetEtci->GetEventTargetParent(aPreVisitor);
     578           0 :       return chromeTargetEtci;
     579             :     }
     580             :   }
     581           0 :   return nullptr;
     582             : }
     583             : 
     584             : /* static */ nsresult
     585         499 : EventDispatcher::Dispatch(nsISupports* aTarget,
     586             :                           nsPresContext* aPresContext,
     587             :                           WidgetEvent* aEvent,
     588             :                           nsIDOMEvent* aDOMEvent,
     589             :                           nsEventStatus* aEventStatus,
     590             :                           EventDispatchingCallback* aCallback,
     591             :                           nsTArray<EventTarget*>* aTargets)
     592             : {
     593         998 :   AUTO_PROFILER_LABEL("EventDispatcher::Dispatch", EVENTS);
     594             : 
     595         499 :   NS_ASSERTION(aEvent, "Trying to dispatch without WidgetEvent!");
     596         499 :   NS_ENSURE_TRUE(!aEvent->mFlags.mIsBeingDispatched,
     597             :                  NS_ERROR_DOM_INVALID_STATE_ERR);
     598         499 :   NS_ASSERTION(!aTargets || !aEvent->mMessage, "Wrong parameters!");
     599             : 
     600             :   // If we're dispatching an already created DOMEvent object, make
     601             :   // sure it is initialized!
     602             :   // If aTargets is non-null, the event isn't going to be dispatched.
     603         499 :   NS_ENSURE_TRUE(aEvent->mMessage || !aDOMEvent || aTargets,
     604             :                  NS_ERROR_DOM_INVALID_STATE_ERR);
     605             : 
     606             : #ifdef MOZ_TASK_TRACER
     607             :   if (MOZ_UNLIKELY(mozilla::tasktracer::IsStartLogging())) {
     608             :     nsAutoCString eventType;
     609             :     nsAutoString eventTypeU16;
     610             :     if (aDOMEvent) {
     611             :       aDOMEvent->GetType(eventTypeU16);
     612             :     } else {
     613             :       Event::GetWidgetEventType(aEvent, eventTypeU16);
     614             :     }
     615             :     eventType = NS_ConvertUTF16toUTF8(eventTypeU16);
     616             : 
     617             :     nsCOMPtr<Element> element = do_QueryInterface(aTarget);
     618             :     nsAutoString elementId;
     619             :     nsAutoString elementTagName;
     620             :     if (element) {
     621             :       element->GetId(elementId);
     622             :       element->GetTagName(elementTagName);
     623             :     }
     624             :     AddLabel("Event [%s] dispatched at target [id:%s tag:%s]",
     625             :              eventType.get(),
     626             :              NS_ConvertUTF16toUTF8(elementId).get(),
     627             :              NS_ConvertUTF16toUTF8(elementTagName).get());
     628             :   }
     629             : #endif
     630             : 
     631         998 :   nsCOMPtr<EventTarget> target = do_QueryInterface(aTarget);
     632             : 
     633         499 :   bool retargeted = false;
     634             : 
     635         499 :   if (aEvent->mFlags.mRetargetToNonNativeAnonymous) {
     636           0 :     nsCOMPtr<nsIContent> content = do_QueryInterface(target);
     637           0 :     if (content && content->IsInNativeAnonymousSubtree()) {
     638             :       nsCOMPtr<EventTarget> newTarget =
     639           0 :         do_QueryInterface(content->FindFirstNonChromeOnlyAccessContent());
     640           0 :       NS_ENSURE_STATE(newTarget);
     641             : 
     642           0 :       aEvent->mOriginalTarget = target;
     643           0 :       target = newTarget;
     644           0 :       retargeted = true;
     645             :     }
     646             :   }
     647             : 
     648         499 :   if (aEvent->mFlags.mOnlyChromeDispatch) {
     649          16 :     nsCOMPtr<nsIDocument> doc;
     650           8 :     if (!IsEventTargetChrome(target, getter_AddRefs(doc)) && doc) {
     651           5 :       nsPIDOMWindowInner* win = doc->GetInnerWindow();
     652             :       // If we can't dispatch the event to chrome, do nothing.
     653           5 :       EventTarget* piTarget = win ? win->GetParentTarget() : nullptr;
     654           5 :       if (!piTarget) {
     655           0 :         return NS_OK;
     656             :       }
     657             : 
     658             :       // Set the target to be the original dispatch target,
     659           5 :       aEvent->mTarget = target;
     660             :       // but use chrome event handler or TabChildGlobal for event target chain.
     661           5 :       target = piTarget;
     662           3 :     } else if (NS_WARN_IF(!doc)) {
     663           0 :       return NS_ERROR_UNEXPECTED;
     664             :     }
     665             :   }
     666             : 
     667             : #ifdef DEBUG
     668         947 :   if (aEvent->mMessage != eVoidEvent &&
     669         448 :       !nsContentUtils::IsSafeToRunScript()) {
     670           2 :     nsresult rv = NS_ERROR_FAILURE;
     671           4 :     if (target->GetContextForEventHandlers(&rv) ||
     672           2 :         NS_FAILED(rv)) {
     673           0 :       nsCOMPtr<nsINode> node = do_QueryInterface(target);
     674           0 :       if (node && nsContentUtils::IsChromeDoc(node->OwnerDoc())) {
     675           0 :         NS_WARNING("Fix the caller!");
     676             :       } else {
     677           0 :         NS_ERROR("This is unsafe! Fix the caller!");
     678             :       }
     679             :     }
     680             :   }
     681             : 
     682         499 :   if (aDOMEvent) {
     683         291 :     WidgetEvent* innerEvent = aDOMEvent->WidgetEventPtr();
     684         291 :     NS_ASSERTION(innerEvent == aEvent,
     685             :                   "The inner event of aDOMEvent is not the same as aEvent!");
     686             :   }
     687             : #endif
     688             : 
     689         499 :   nsresult rv = NS_OK;
     690         499 :   bool externalDOMEvent = !!(aDOMEvent);
     691             : 
     692             :   // If we have a PresContext, make sure it doesn't die before
     693             :   // event dispatching is finished.
     694         998 :   RefPtr<nsPresContext> kungFuDeathGrip(aPresContext);
     695             : 
     696         499 :   ELMCreationDetector cd;
     697         998 :   nsTArray<EventTargetChainItem> chain;
     698         499 :   if (cd.IsMainThread()) {
     699         482 :     if (!sCachedMainThreadChain) {
     700           2 :       sCachedMainThreadChain = new nsTArray<EventTargetChainItem>();
     701             :     }
     702         482 :     chain.SwapElements(*sCachedMainThreadChain);
     703         482 :     chain.SetCapacity(128);
     704             :   }
     705             : 
     706             :   // Create the event target chain item for the event target.
     707             :   EventTargetChainItem* targetEtci =
     708         499 :     EventTargetChainItem::Create(chain, target->GetTargetForEventTargetChain());
     709         499 :   MOZ_ASSERT(&chain[0] == targetEtci);
     710         499 :   if (!targetEtci->IsValid()) {
     711           0 :     EventTargetChainItem::DestroyLast(chain, targetEtci);
     712           0 :     return NS_ERROR_FAILURE;
     713             :   }
     714             : 
     715             :   // Make sure that nsIDOMEvent::target and nsIDOMEvent::originalTarget
     716             :   // point to the last item in the chain.
     717         499 :   if (!aEvent->mTarget) {
     718             :     // Note, CurrentTarget() points always to the object returned by
     719             :     // GetTargetForEventTargetChain().
     720         366 :     aEvent->mTarget = targetEtci->CurrentTarget();
     721             :   } else {
     722             :     // XXX But if the target is already set, use that. This is a hack
     723             :     //     for the 'load', 'beforeunload' and 'unload' events,
     724             :     //     which are dispatched to |window| but have document as their target.
     725             :     //
     726             :     // Make sure that the event target points to the right object.
     727         133 :     aEvent->mTarget = aEvent->mTarget->GetTargetForEventTargetChain();
     728         133 :     NS_ENSURE_STATE(aEvent->mTarget);
     729             :   }
     730             : 
     731         499 :   if (retargeted) {
     732             :     aEvent->mOriginalTarget =
     733           0 :       aEvent->mOriginalTarget->GetTargetForEventTargetChain();
     734           0 :     NS_ENSURE_STATE(aEvent->mOriginalTarget);
     735             :   }
     736             :   else {
     737         499 :     aEvent->mOriginalTarget = aEvent->mTarget;
     738             :   }
     739             : 
     740         998 :   nsCOMPtr<nsIContent> content = do_QueryInterface(aEvent->mOriginalTarget);
     741         594 :   bool isInAnon = (content && (content->IsInAnonymousSubtree() ||
     742        1093 :                                content->IsInShadowTree()));
     743             : 
     744         499 :   aEvent->mFlags.mIsBeingDispatched = true;
     745             : 
     746             :   // Create visitor object and start event dispatching.
     747             :   // GetEventTargetParent for the original target.
     748         499 :   nsEventStatus status = aEventStatus ? *aEventStatus : nsEventStatus_eIgnore;
     749             :   EventChainPreVisitor preVisitor(aPresContext, aEvent, aDOMEvent, status,
     750         998 :                                   isInAnon);
     751         499 :   targetEtci->GetEventTargetParent(preVisitor);
     752             : 
     753         499 :   if (!preVisitor.mCanHandle) {
     754             :     targetEtci = MayRetargetToChromeIfCanNotHandleEvent(chain, preVisitor,
     755             :                                                         targetEtci, nullptr,
     756           0 :                                                         content);
     757             :   }
     758         499 :   if (!preVisitor.mCanHandle) {
     759             :     // The original target and chrome target (mAutomaticChromeDispatch=true)
     760             :     // can not handle the event but we still have to call their PreHandleEvent.
     761           0 :     for (uint32_t i = 0; i < chain.Length(); ++i) {
     762           0 :       chain[i].PreHandleEvent(preVisitor);
     763             :     }
     764             :   } else {
     765             :     // At least the original target can handle the event.
     766             :     // Setting the retarget to the |target| simplifies retargeting code.
     767         998 :     nsCOMPtr<EventTarget> t = do_QueryInterface(aEvent->mTarget);
     768         499 :     targetEtci->SetNewTarget(t);
     769         499 :     EventTargetChainItem* topEtci = targetEtci;
     770         499 :     targetEtci = nullptr;
     771        4147 :     while (preVisitor.mParentTarget) {
     772        1824 :       EventTarget* parentTarget = preVisitor.mParentTarget;
     773             :       EventTargetChainItem* parentEtci =
     774        1824 :         EventTargetChainItem::Create(chain, preVisitor.mParentTarget, topEtci);
     775        1824 :       if (!parentEtci->IsValid()) {
     776           0 :         EventTargetChainItem::DestroyLast(chain, parentEtci);
     777           0 :         rv = NS_ERROR_FAILURE;
     778           0 :         break;
     779             :       }
     780             : 
     781             :       // Item needs event retargetting.
     782        1824 :       if (preVisitor.mEventTargetAtParent) {
     783             :         // Need to set the target of the event
     784             :         // so that also the next retargeting works.
     785          91 :         preVisitor.mEvent->mTarget = preVisitor.mEventTargetAtParent;
     786          91 :         parentEtci->SetNewTarget(preVisitor.mEventTargetAtParent);
     787             :       }
     788             : 
     789        1824 :       parentEtci->GetEventTargetParent(preVisitor);
     790        1824 :       if (preVisitor.mCanHandle) {
     791        1824 :         topEtci = parentEtci;
     792             :       } else {
     793           0 :         nsCOMPtr<nsINode> disabledTarget = do_QueryInterface(parentTarget);
     794           0 :         parentEtci = MayRetargetToChromeIfCanNotHandleEvent(chain,
     795             :                                                             preVisitor,
     796             :                                                             parentEtci,
     797             :                                                             topEtci,
     798           0 :                                                             disabledTarget);
     799           0 :         if (parentEtci && preVisitor.mCanHandle) {
     800             :           EventTargetChainItem* item =
     801           0 :             EventTargetChainItem::GetFirstCanHandleEventTarget(chain);
     802           0 :           item->SetNewTarget(parentTarget);
     803           0 :           topEtci = parentEtci;
     804           0 :           continue;
     805             :         }
     806           0 :         break;
     807             :       }
     808             :     }
     809         499 :     if (NS_SUCCEEDED(rv)) {
     810         499 :       if (aTargets) {
     811          50 :         aTargets->Clear();
     812          50 :         uint32_t numTargets = chain.Length();
     813          50 :         EventTarget** targets = aTargets->AppendElements(numTargets);
     814         202 :         for (uint32_t i = 0; i < numTargets; ++i) {
     815         152 :           targets[i] = chain[i].CurrentTarget()->GetTargetForDOMEvent();
     816             :         }
     817             :       } else {
     818             :         // Event target chain is created. PreHandle the chain.
     819        2620 :         for (uint32_t i = 0; i < chain.Length(); ++i) {
     820        2171 :           chain[i].PreHandleEvent(preVisitor);
     821             :         }
     822             :         // Handle the chain.
     823         898 :         EventChainPostVisitor postVisitor(preVisitor);
     824             :         EventTargetChainItem::HandleEventTargetChain(chain, postVisitor,
     825         449 :                                                      aCallback, cd);
     826             : 
     827         449 :         preVisitor.mEventStatus = postVisitor.mEventStatus;
     828             :         // If the DOM event was created during event flow.
     829         449 :         if (!preVisitor.mDOMEvent && postVisitor.mDOMEvent) {
     830          31 :           preVisitor.mDOMEvent = postVisitor.mDOMEvent;
     831             :         }
     832             :       }
     833             :     }
     834             :   }
     835             : 
     836             :   // Note, EventTargetChainItem objects are deleted when the chain goes out of
     837             :   // the scope.
     838             : 
     839         499 :   aEvent->mFlags.mIsBeingDispatched = false;
     840         499 :   aEvent->mFlags.mDispatchedAtLeastOnce = true;
     841             : 
     842         499 :   if (!externalDOMEvent && preVisitor.mDOMEvent) {
     843             :     // An dom::Event was created while dispatching the event.
     844             :     // Duplicate private data if someone holds a pointer to it.
     845          31 :     nsrefcnt rc = 0;
     846          31 :     NS_RELEASE2(preVisitor.mDOMEvent, rc);
     847          31 :     if (preVisitor.mDOMEvent) {
     848          25 :       preVisitor.mDOMEvent->DuplicatePrivateData();
     849             :     }
     850             :   }
     851             : 
     852         499 :   if (aEventStatus) {
     853         303 :     *aEventStatus = preVisitor.mEventStatus;
     854             :   }
     855             : 
     856         499 :   if (cd.IsMainThread() && chain.Capacity() == 128 && sCachedMainThreadChain) {
     857         482 :     chain.ClearAndRetainStorage();
     858         482 :     chain.SwapElements(*sCachedMainThreadChain);
     859             :   }
     860             : 
     861         499 :   return rv;
     862             : }
     863             : 
     864             : /* static */ nsresult
     865         294 : EventDispatcher::DispatchDOMEvent(nsISupports* aTarget,
     866             :                                   WidgetEvent* aEvent,
     867             :                                   nsIDOMEvent* aDOMEvent,
     868             :                                   nsPresContext* aPresContext,
     869             :                                   nsEventStatus* aEventStatus)
     870             : {
     871         294 :   if (aDOMEvent) {
     872         290 :     WidgetEvent* innerEvent = aDOMEvent->WidgetEventPtr();
     873         290 :     NS_ENSURE_TRUE(innerEvent, NS_ERROR_ILLEGAL_VALUE);
     874             : 
     875         290 :     bool dontResetTrusted = false;
     876         290 :     if (innerEvent->mFlags.mDispatchedAtLeastOnce) {
     877           0 :       innerEvent->mTarget = nullptr;
     878           0 :       innerEvent->mOriginalTarget = nullptr;
     879             :     } else {
     880         290 :       aDOMEvent->GetIsTrusted(&dontResetTrusted);
     881             :     }
     882             : 
     883         290 :     if (!dontResetTrusted) {
     884             :       //Check security state to determine if dispatcher is trusted
     885           6 :       bool trusted = NS_IsMainThread() ? nsContentUtils::LegacyIsCallerChromeOrNativeCode()
     886           6 :                                        : mozilla::dom::workers::IsCurrentThreadRunningChromeWorker();
     887           6 :       aDOMEvent->SetTrusted(trusted);
     888             :     }
     889             : 
     890             :     return EventDispatcher::Dispatch(aTarget, aPresContext, innerEvent,
     891         290 :                                      aDOMEvent, aEventStatus);
     892           4 :   } else if (aEvent) {
     893             :     return EventDispatcher::Dispatch(aTarget, aPresContext, aEvent,
     894           4 :                                      aDOMEvent, aEventStatus);
     895             :   }
     896           0 :   return NS_ERROR_ILLEGAL_VALUE;
     897             : }
     898             : 
     899             : /* static */ already_AddRefed<dom::Event>
     900         158 : EventDispatcher::CreateEvent(EventTarget* aOwner,
     901             :                              nsPresContext* aPresContext,
     902             :                              WidgetEvent* aEvent,
     903             :                              const nsAString& aEventType,
     904             :                              CallerType aCallerType)
     905             : {
     906         158 :   if (aEvent) {
     907          31 :     switch(aEvent->mClass) {
     908             :     case eMutationEventClass:
     909           0 :       return NS_NewDOMMutationEvent(aOwner, aPresContext,
     910           0 :                                     aEvent->AsMutationEvent());
     911             :     case eGUIEventClass:
     912             :     case eScrollPortEventClass:
     913             :     case eUIEventClass:
     914           8 :       return NS_NewDOMUIEvent(aOwner, aPresContext, aEvent->AsGUIEvent());
     915             :     case eScrollAreaEventClass:
     916           0 :       return NS_NewDOMScrollAreaEvent(aOwner, aPresContext,
     917           0 :                                       aEvent->AsScrollAreaEvent());
     918             :     case eKeyboardEventClass:
     919           0 :       return NS_NewDOMKeyboardEvent(aOwner, aPresContext,
     920           0 :                                     aEvent->AsKeyboardEvent());
     921             :     case eCompositionEventClass:
     922           0 :       return NS_NewDOMCompositionEvent(aOwner, aPresContext,
     923           0 :                                        aEvent->AsCompositionEvent());
     924             :     case eMouseEventClass:
     925           5 :       return NS_NewDOMMouseEvent(aOwner, aPresContext, aEvent->AsMouseEvent());
     926             :     case eFocusEventClass:
     927           5 :       return NS_NewDOMFocusEvent(aOwner, aPresContext, aEvent->AsFocusEvent());
     928             :     case eMouseScrollEventClass:
     929           0 :       return NS_NewDOMMouseScrollEvent(aOwner, aPresContext,
     930           0 :                                        aEvent->AsMouseScrollEvent());
     931             :     case eWheelEventClass:
     932           0 :       return NS_NewDOMWheelEvent(aOwner, aPresContext, aEvent->AsWheelEvent());
     933             :     case eEditorInputEventClass:
     934           0 :       return NS_NewDOMInputEvent(aOwner, aPresContext,
     935           0 :                                  aEvent->AsEditorInputEvent());
     936             :     case eDragEventClass:
     937           0 :       return NS_NewDOMDragEvent(aOwner, aPresContext, aEvent->AsDragEvent());
     938             :     case eClipboardEventClass:
     939           0 :       return NS_NewDOMClipboardEvent(aOwner, aPresContext,
     940           0 :                                      aEvent->AsClipboardEvent());
     941             :     case eSMILTimeEventClass:
     942           0 :       return NS_NewDOMTimeEvent(aOwner, aPresContext,
     943           0 :                                 aEvent->AsSMILTimeEvent());
     944             :     case eCommandEventClass:
     945           0 :       return NS_NewDOMCommandEvent(aOwner, aPresContext,
     946           0 :                                    aEvent->AsCommandEvent());
     947             :     case eSimpleGestureEventClass:
     948           0 :       return NS_NewDOMSimpleGestureEvent(aOwner, aPresContext,
     949           0 :                                          aEvent->AsSimpleGestureEvent());
     950             :     case ePointerEventClass:
     951           0 :       return NS_NewDOMPointerEvent(aOwner, aPresContext,
     952           0 :                                    aEvent->AsPointerEvent());
     953             :     case eTouchEventClass:
     954           0 :       return NS_NewDOMTouchEvent(aOwner, aPresContext, aEvent->AsTouchEvent());
     955             :     case eTransitionEventClass:
     956           4 :       return NS_NewDOMTransitionEvent(aOwner, aPresContext,
     957           4 :                                       aEvent->AsTransitionEvent());
     958             :     case eAnimationEventClass:
     959           0 :       return NS_NewDOMAnimationEvent(aOwner, aPresContext,
     960           0 :                                      aEvent->AsAnimationEvent());
     961             :     default:
     962             :       // For all other types of events, create a vanilla event object.
     963          11 :       return NS_NewDOMEvent(aOwner, aPresContext, aEvent);
     964             :     }
     965             :   }
     966             : 
     967             :   // And if we didn't get an event, check the type argument.
     968             : 
     969             : #define LOG_EVENT_CREATION(name) mozilla::Telemetry::Accumulate( \
     970             :     mozilla::Telemetry::CREATE_EVENT_##name, true);
     971             : 
     972         127 :   if (aEventType.LowerCaseEqualsLiteral("mouseevent")) {
     973           0 :     LOG_EVENT_CREATION(MOUSEEVENT);
     974           0 :     return NS_NewDOMMouseEvent(aOwner, aPresContext, nullptr);
     975             :   }
     976         127 :   if (aEventType.LowerCaseEqualsLiteral("mouseevents")) {
     977           0 :     LOG_EVENT_CREATION(MOUSEEVENTS);
     978           0 :     return NS_NewDOMMouseEvent(aOwner, aPresContext, nullptr);
     979             :   }
     980         127 :   if (aEventType.LowerCaseEqualsLiteral("mousescrollevents")) {
     981           0 :     LOG_EVENT_CREATION(MOUSESCROLLEVENTS);
     982           0 :     return NS_NewDOMMouseScrollEvent(aOwner, aPresContext, nullptr);
     983             :   }
     984         127 :   if (aEventType.LowerCaseEqualsLiteral("dragevent")) {
     985           0 :     LOG_EVENT_CREATION(DRAGEVENT);
     986           0 :     return NS_NewDOMDragEvent(aOwner, aPresContext, nullptr);
     987             :   }
     988         127 :   if (aEventType.LowerCaseEqualsLiteral("keyboardevent")) {
     989           0 :     LOG_EVENT_CREATION(KEYBOARDEVENT);
     990           0 :     return NS_NewDOMKeyboardEvent(aOwner, aPresContext, nullptr);
     991             :   }
     992         127 :   if (aEventType.LowerCaseEqualsLiteral("keyevents")) {
     993           0 :     LOG_EVENT_CREATION(KEYEVENTS);
     994           0 :     return NS_NewDOMKeyboardEvent(aOwner, aPresContext, nullptr);
     995             :   }
     996         127 :   if (aEventType.LowerCaseEqualsLiteral("compositionevent")) {
     997           0 :     LOG_EVENT_CREATION(COMPOSITIONEVENT);
     998           0 :     return NS_NewDOMCompositionEvent(aOwner, aPresContext, nullptr);
     999             :   }
    1000         127 :   if (aEventType.LowerCaseEqualsLiteral("textevent")) {
    1001           0 :     LOG_EVENT_CREATION(TEXTEVENT);
    1002           0 :     return NS_NewDOMCompositionEvent(aOwner, aPresContext, nullptr);
    1003             :   }
    1004         127 :   if (aEventType.LowerCaseEqualsLiteral("mutationevent")) {
    1005           0 :     LOG_EVENT_CREATION(MUTATIONEVENT);
    1006           0 :     return NS_NewDOMMutationEvent(aOwner, aPresContext, nullptr);
    1007             :   }
    1008         127 :   if (aEventType.LowerCaseEqualsLiteral("mutationevents")) {
    1009           0 :     LOG_EVENT_CREATION(MUTATIONEVENTS);
    1010           0 :     return NS_NewDOMMutationEvent(aOwner, aPresContext, nullptr);
    1011             :   }
    1012         127 :   if (aEventType.LowerCaseEqualsLiteral("deviceorientationevent")) {
    1013           0 :     LOG_EVENT_CREATION(DEVICEORIENTATIONEVENT);
    1014           0 :     DeviceOrientationEventInit init;
    1015             :     RefPtr<Event> event =
    1016           0 :       DeviceOrientationEvent::Constructor(aOwner, EmptyString(), init);
    1017           0 :     event->MarkUninitialized();
    1018           0 :     return event.forget();
    1019             :   }
    1020         127 :   if (aEventType.LowerCaseEqualsLiteral("devicemotionevent")) {
    1021           0 :     LOG_EVENT_CREATION(DEVICEMOTIONEVENT);
    1022           0 :     return NS_NewDOMDeviceMotionEvent(aOwner, aPresContext, nullptr);
    1023             :   }
    1024         127 :   if (aEventType.LowerCaseEqualsLiteral("uievent")) {
    1025           0 :     LOG_EVENT_CREATION(UIEVENT);
    1026           0 :     return NS_NewDOMUIEvent(aOwner, aPresContext, nullptr);
    1027             :   }
    1028         127 :   if (aEventType.LowerCaseEqualsLiteral("uievents")) {
    1029           0 :     LOG_EVENT_CREATION(UIEVENTS);
    1030           0 :     return NS_NewDOMUIEvent(aOwner, aPresContext, nullptr);
    1031             :   }
    1032         127 :   if (aEventType.LowerCaseEqualsLiteral("event")) {
    1033           0 :     LOG_EVENT_CREATION(EVENT);
    1034           0 :     return NS_NewDOMEvent(aOwner, aPresContext, nullptr);
    1035             :   }
    1036         127 :   if (aEventType.LowerCaseEqualsLiteral("events")) {
    1037         127 :     LOG_EVENT_CREATION(EVENTS);
    1038         127 :     return NS_NewDOMEvent(aOwner, aPresContext, nullptr);
    1039             :   }
    1040           0 :   if (aEventType.LowerCaseEqualsLiteral("htmlevents")) {
    1041           0 :     LOG_EVENT_CREATION(HTMLEVENTS);
    1042           0 :     return NS_NewDOMEvent(aOwner, aPresContext, nullptr);
    1043             :   }
    1044           0 :   if (aEventType.LowerCaseEqualsLiteral("svgevents")) {
    1045           0 :     LOG_EVENT_CREATION(SVGEVENTS);
    1046           0 :     return NS_NewDOMEvent(aOwner, aPresContext, nullptr);
    1047             :   }
    1048           0 :   if (aEventType.LowerCaseEqualsLiteral("timeevent")) {
    1049           0 :     LOG_EVENT_CREATION(TIMEEVENT);
    1050           0 :     return NS_NewDOMTimeEvent(aOwner, aPresContext, nullptr);
    1051             :   }
    1052           0 :   if (aEventType.LowerCaseEqualsLiteral("messageevent")) {
    1053           0 :     LOG_EVENT_CREATION(MESSAGEEVENT);
    1054           0 :     RefPtr<Event> event = new MessageEvent(aOwner, aPresContext, nullptr);
    1055           0 :     return event.forget();
    1056             :   }
    1057           0 :   if (aEventType.LowerCaseEqualsLiteral("beforeunloadevent")) {
    1058           0 :     LOG_EVENT_CREATION(BEFOREUNLOADEVENT);
    1059           0 :     return NS_NewDOMBeforeUnloadEvent(aOwner, aPresContext, nullptr);
    1060             :   }
    1061           0 :   if (aEventType.LowerCaseEqualsLiteral("scrollareaevent")) {
    1062           0 :     LOG_EVENT_CREATION(SCROLLAREAEVENT);
    1063           0 :     return NS_NewDOMScrollAreaEvent(aOwner, aPresContext, nullptr);
    1064             :   }
    1065             :   // XXXkhuey Chrome supports popstateevent here, even though it provides no
    1066             :   // initPopStateEvent method.  This is nuts ... but copying it is unlikely to
    1067             :   // break the web.
    1068           0 :   if (aEventType.LowerCaseEqualsLiteral("popstateevent")) {
    1069           0 :     LOG_EVENT_CREATION(POPSTATEEVENT);
    1070           0 :     AutoJSContext cx;
    1071           0 :     RootedDictionary<PopStateEventInit> init(cx);
    1072             :     RefPtr<Event> event =
    1073           0 :       PopStateEvent::Constructor(aOwner, EmptyString(), init);
    1074           0 :     event->MarkUninitialized();
    1075           0 :     return event.forget();
    1076             :   }
    1077           0 :   if (aEventType.LowerCaseEqualsLiteral("touchevent") &&
    1078           0 :       TouchEvent::PrefEnabled(nsContentUtils::GetDocShellForEventTarget(aOwner))) {
    1079           0 :     LOG_EVENT_CREATION(TOUCHEVENT);
    1080           0 :     return NS_NewDOMTouchEvent(aOwner, aPresContext, nullptr);
    1081             :   }
    1082           0 :   if (aEventType.LowerCaseEqualsLiteral("hashchangeevent")) {
    1083           0 :     LOG_EVENT_CREATION(HASHCHANGEEVENT);
    1084           0 :     HashChangeEventInit init;
    1085             :     RefPtr<Event> event =
    1086           0 :       HashChangeEvent::Constructor(aOwner, EmptyString(), init);
    1087           0 :     event->MarkUninitialized();
    1088           0 :     return event.forget();
    1089             :   }
    1090           0 :   if (aEventType.LowerCaseEqualsLiteral("customevent")) {
    1091           0 :     LOG_EVENT_CREATION(CUSTOMEVENT);
    1092           0 :     return NS_NewDOMCustomEvent(aOwner, aPresContext, nullptr);
    1093             :   }
    1094           0 :   if (aEventType.LowerCaseEqualsLiteral("storageevent")) {
    1095           0 :     LOG_EVENT_CREATION(STORAGEEVENT);
    1096             :     RefPtr<Event> event =
    1097           0 :       StorageEvent::Constructor(aOwner, EmptyString(), StorageEventInit());
    1098           0 :     event->MarkUninitialized();
    1099           0 :     return event.forget();
    1100             :   }
    1101           0 :   if (aEventType.LowerCaseEqualsLiteral("errorevent")) {
    1102           0 :     LOG_EVENT_CREATION(ERROREVENT);
    1103           0 :     RootedDictionary<ErrorEventInit> init(RootingCx());
    1104             :     RefPtr<Event> event =
    1105           0 :       ErrorEvent::Constructor(aOwner, EmptyString(), init);
    1106           0 :     event->MarkUninitialized();
    1107           0 :     return event.forget();
    1108             :   }
    1109             : 
    1110             :   // Only allow these events for chrome
    1111           0 :   if (aCallerType == CallerType::System) {
    1112           0 :     if (aEventType.LowerCaseEqualsLiteral("simplegestureevent")) {
    1113           0 :       return NS_NewDOMSimpleGestureEvent(aOwner, aPresContext, nullptr);
    1114             :     }
    1115           0 :     if (aEventType.LowerCaseEqualsLiteral("xulcommandevent")) {
    1116           0 :       LOG_EVENT_CREATION(XULCOMMANDEVENT);
    1117           0 :       return NS_NewDOMXULCommandEvent(aOwner, aPresContext, nullptr);
    1118             :     }
    1119           0 :     if (aEventType.LowerCaseEqualsLiteral("xulcommandevents")) {
    1120           0 :       LOG_EVENT_CREATION(XULCOMMANDEVENTS);
    1121           0 :       return NS_NewDOMXULCommandEvent(aOwner, aPresContext, nullptr);
    1122             :     }
    1123             :   }
    1124             : 
    1125             : #undef LOG_EVENT_CREATION
    1126             : 
    1127             :   // NEW EVENT TYPES SHOULD NOT BE ADDED HERE; THEY SHOULD USE ONLY EVENT
    1128             :   // CONSTRUCTORS
    1129             : 
    1130           0 :   return nullptr;
    1131             : }
    1132             : 
    1133             : } // namespace mozilla

Generated by: LCOV version 1.13