LCOV - app.info - content/events/src/nsEventDispatcher.cpp

LCOV - code coverage report
| Current view: | directory - content/events/src - nsEventDispatcher.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 426 | 267 | 62.7 %
| Date: | 2012-04-21 | Functions: | 28 | 27 | 96.4 %

           1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
           2                 : /* ***** BEGIN LICENSE BLOCK *****
           3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           4                 :  *
           5                 :  * The contents of this file are subject to the Mozilla Public License Version
           6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           7                 :  * the License. You may obtain a copy of the License at
           8                 :  * http://www.mozilla.org/MPL/
           9                 :  *
          10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          12                 :  * for the specific language governing rights and limitations under the
          13                 :  * License.
          14                 :  *
          15                 :  * The Original Code is mozilla.org code.
          16                 :  *
          17                 :  * The Initial Developer of the Original Code is
          18                 :  * Olli Pettay (Olli.Pettay@helsinki.fi)
          19                 :  * Portions created by the Initial Developer are Copyright (C) 2006
          20                 :  * the Initial Developer. All Rights Reserved.
          21                 :  *
          22                 :  * Contributor(s):
          23                 :  *
          24                 :  * Alternatively, the contents of this file may be used under the terms of
          25                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
          26                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          28                 :  * of those above. If you wish to allow use of your version of this file only
          29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          30                 :  * use your version of this file under the terms of the MPL, indicate your
          31                 :  * decision by deleting the provisions above and replace them with the notice
          32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          33                 :  * the provisions above, a recipient may use your version of this file under
          34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          35                 :  *
          36                 :  * ***** END LICENSE BLOCK ***** */
          37                 :
          38                 : #include "nsEventDispatcher.h"
          39                 : #include "nsDOMEvent.h"
          40                 : #include "nsIDOMEventTarget.h"
          41                 : #include "nsPresContext.h"
          42                 : #include "nsIPrivateDOMEvent.h"
          43                 : #include "nsEventListenerManager.h"
          44                 : #include "nsContentUtils.h"
          45                 : #include "nsDOMError.h"
          46                 : #include "mozilla/FunctionTimer.h"
          47                 : #include "nsMutationEvent.h"
          48                 : #include NEW_H
          49                 : #include "nsFixedSizeAllocator.h"
          50                 : #include "nsINode.h"
          51                 : #include "nsPIDOMWindow.h"
          52                 : #include "nsDOMPopStateEvent.h"
          53                 : #include "nsDOMHashChangeEvent.h"
          54                 : #include "nsFrameLoader.h"
          55                 : #include "nsDOMTouchEvent.h"
          56                 : #include "nsDOMStorage.h"
          57                 :
          58                 : #define NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH  (1 << 0)
          59                 : #define NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT (1 << 1)
          60                 : #define NS_TARGET_CHAIN_MAY_HAVE_MANAGER        (1 << 2)
          61                 :
          62                 : static nsEventTargetChainItem* gCachedETCI = nsnull;
          63                 :
          64                 : // nsEventTargetChainItem represents a single item in the event target chain.
          65                 : class nsEventTargetChainItem
          66           26270 : {
          67                 : private:
          68                 :   nsEventTargetChainItem(nsIDOMEventTarget* aTarget,
          69                 :                          nsEventTargetChainItem* aChild = nsnull);
          70                 :
          71                 : public:
          72           26270 :   static nsEventTargetChainItem* Create(nsFixedSizeAllocator* aAllocator,
          73                 :                                         nsIDOMEventTarget* aTarget,
          74                 :                                         nsEventTargetChainItem* aChild = nsnull)
          75                 :   {
          76           26270 :     void* place = nsnull;
          77           26270 :     if (gCachedETCI) {
          78           25810 :       place = gCachedETCI;
          79           25810 :       gCachedETCI = gCachedETCI->mNext;
          80                 :     } else {
          81             460 :       place = aAllocator->Alloc(sizeof(nsEventTargetChainItem));
          82                 :     }
          83                 :     return place
          84           26270 :       ? ::new (place) nsEventTargetChainItem(aTarget, aChild)
          85           52540 :       : nsnull;
          86                 :   }
          87                 :
          88           16694 :   static void Destroy(nsFixedSizeAllocator* aAllocator,
          89                 :                       nsEventTargetChainItem* aItem)
          90                 :   {
          91                 :     // ::Destroy deletes ancestor chain.
          92           16694 :     nsEventTargetChainItem* item = aItem;
          93           16694 :     if (item->mChild) {
          94               0 :       item->mChild->mParent = nsnull;
          95               0 :       item->mChild = nsnull;
          96                 :     }
          97           59658 :     while (item) {
          98           26270 :       nsEventTargetChainItem* parent = item->mParent;
          99           26270 :       item->~nsEventTargetChainItem();
         100           26270 :       item->mNext = gCachedETCI;
         101           26270 :       gCachedETCI = item;
         102           26270 :       --sCurrentEtciCount;
         103           26270 :       item = parent;
         104                 :     }
         105           16694 :   }
         106                 :
         107           26270 :   bool IsValid()
         108                 :   {
         109           26270 :     NS_WARN_IF_FALSE(!!(mTarget), "Event target is not valid!");
         110           26270 :     return !!(mTarget);
         111                 :   }
         112                 :
         113           38304 :   nsIDOMEventTarget* GetNewTarget()
         114                 :   {
         115           38304 :     return mNewTarget;
         116                 :   }
         117                 :
         118           16694 :   void SetNewTarget(nsIDOMEventTarget* aNewTarget)
         119                 :   {
         120           16694 :     mNewTarget = aNewTarget;
         121           16694 :   }
         122                 :
         123           26270 :   void SetForceContentDispatch(bool aForce)
         124                 :   {
         125           26270 :     if (aForce) {
         126            6367 :       mFlags |= NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH;
         127                 :     } else {
         128           19903 :       mFlags &= ~NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH;
         129                 :     }
         130           26270 :   }
         131                 :
         132               0 :   bool ForceContentDispatch()
         133                 :   {
         134               0 :     return !!(mFlags & NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH);
         135                 :   }
         136                 :
         137           26270 :   void SetWantsWillHandleEvent(bool aWants)
         138                 :   {
         139           26270 :     if (aWants) {
         140               0 :       mFlags |= NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT;
         141                 :     } else {
         142           26270 :       mFlags &= ~NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT;
         143                 :     }
         144           26270 :   }
         145                 :
         146           52708 :   bool WantsWillHandleEvent()
         147                 :   {
         148           52708 :     return !!(mFlags & NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT);
         149                 :   }
         150                 :
         151           26270 :   void SetMayHaveListenerManager(bool aMayHave)
         152                 :   {
         153           26270 :     if (aMayHave) {
         154           26214 :       mFlags |= NS_TARGET_CHAIN_MAY_HAVE_MANAGER;
         155                 :     } else {
         156              56 :       mFlags &= ~NS_TARGET_CHAIN_MAY_HAVE_MANAGER;
         157                 :     }
         158           26270 :   }
         159                 :
         160           42627 :   bool MayHaveListenerManager()
         161                 :   {
         162           42627 :     return !!(mFlags & NS_TARGET_CHAIN_MAY_HAVE_MANAGER);
         163                 :   }
         164                 :
         165           31735 :   nsIDOMEventTarget* CurrentTarget()
         166                 :   {
         167           31735 :     return mTarget;
         168                 :   }
         169                 :
         170                 :   /**
         171                 :    * Dispatches event through the event target chain.
         172                 :    * Handles capture, target and bubble phases both in default
         173                 :    * and system event group and calls also PostHandleEvent for each
         174                 :    * item in the chain.
         175                 :    */
         176                 :   nsresult HandleEventTargetChain(nsEventChainPostVisitor& aVisitor,
         177                 :                                   PRUint32 aFlags,
         178                 :                                   nsDispatchingCallback* aCallback,
         179                 :                                   bool aMayHaveNewListenerManagers,
         180                 :                                   nsCxPusher* aPusher);
         181                 :
         182                 :   /**
         183                 :    * Resets aVisitor object and calls PreHandleEvent.
         184                 :    * Copies mItemFlags and mItemData to the current nsEventTargetChainItem.
         185                 :    */
         186                 :   nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
         187                 :
         188                 :   /**
         189                 :    * If the current item in the event target chain has an event listener
         190                 :    * manager, this method calls nsEventListenerManager::HandleEvent().
         191                 :    */
         192           52708 :   nsresult HandleEvent(nsEventChainPostVisitor& aVisitor, PRUint32 aFlags,
         193                 :                        bool aMayHaveNewListenerManagers,
         194                 :                        nsCxPusher* aPusher)
         195                 :   {
         196           52708 :     if (WantsWillHandleEvent()) {
         197               0 :       mTarget->WillHandleEvent(aVisitor);
         198                 :     }
         199           52708 :     if (aVisitor.mEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH) {
         200               0 :       return NS_OK;
         201                 :     }
         202           52708 :     if (!mManager) {
         203           42627 :       if (!MayHaveListenerManager() && !aMayHaveNewListenerManagers) {
         204             140 :         return NS_OK;
         205                 :       }
         206                 :       mManager =
         207           42487 :         static_cast<nsEventListenerManager*>(mTarget->GetListenerManager(false));
         208                 :     }
         209           52568 :     if (mManager) {
         210           20366 :       NS_ASSERTION(aVisitor.mEvent->currentTarget == nsnull,
         211                 :                    "CurrentTarget should be null!");
         212                 :       mManager->HandleEvent(aVisitor.mPresContext, aVisitor.mEvent,
         213                 :                             &aVisitor.mDOMEvent,
         214                 :                             CurrentTarget(), aFlags,
         215                 :                             &aVisitor.mEventStatus,
         216           20366 :                             aPusher);
         217           20366 :       NS_ASSERTION(aVisitor.mEvent->currentTarget == nsnull,
         218                 :                    "CurrentTarget should be null!");
         219                 :     }
         220           52568 :     return NS_OK;
         221                 :   }
         222                 :
         223                 :   /**
         224                 :    * Copies mItemFlags and mItemData to aVisitor and calls PostHandleEvent.
         225                 :    */
         226                 :   nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor,
         227                 :                            nsCxPusher* aPusher);
         228                 :
         229           16004 :   static PRUint32 MaxEtciCount() { return sMaxEtciCount; }
         230                 :
         231            1364 :   static void ResetMaxEtciCount()
         232                 :   {
         233            1364 :     NS_ASSERTION(!sCurrentEtciCount, "Wrong time to call ResetMaxEtciCount()!");
         234            1364 :     sMaxEtciCount = 0;
         235            1364 :   }
         236                 :
         237                 :   nsCOMPtr<nsIDOMEventTarget>       mTarget;
         238                 :   nsEventTargetChainItem*           mChild;
         239                 :   union {
         240                 :     nsEventTargetChainItem*         mParent;
         241                 :      // This is used only when caching ETCI objects.
         242                 :     nsEventTargetChainItem*         mNext;
         243                 :   };
         244                 :   PRUint16                          mFlags;
         245                 :   PRUint16                          mItemFlags;
         246                 :   nsCOMPtr<nsISupports>             mItemData;
         247                 :   // Event retargeting must happen whenever mNewTarget is non-null.
         248                 :   nsCOMPtr<nsIDOMEventTarget>       mNewTarget;
         249                 :   // Cache mTarget's event listener manager.
         250                 :   nsRefPtr<nsEventListenerManager>  mManager;
         251                 :
         252                 :   static PRUint32                   sMaxEtciCount;
         253                 :   static PRUint32                   sCurrentEtciCount;
         254                 : };
         255                 :
         256                 : PRUint32 nsEventTargetChainItem::sMaxEtciCount = 0;
         257                 : PRUint32 nsEventTargetChainItem::sCurrentEtciCount = 0;
         258                 :
         259           26270 : nsEventTargetChainItem::nsEventTargetChainItem(nsIDOMEventTarget* aTarget,
         260                 :                                                nsEventTargetChainItem* aChild)
         261           26270 : : mChild(aChild), mParent(nsnull), mFlags(0), mItemFlags(0)
         262                 : {
         263           26270 :   mTarget = aTarget->GetTargetForEventTargetChain();
         264           26270 :   if (mChild) {
         265            9576 :     mChild->mParent = this;
         266                 :   }
         267                 :
         268           26270 :   if (++sCurrentEtciCount > sMaxEtciCount) {
         269             460 :     sMaxEtciCount = sCurrentEtciCount;
         270                 :   }
         271           26270 : }
         272                 :
         273                 : nsresult
         274           26270 : nsEventTargetChainItem::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
         275                 : {
         276           26270 :   aVisitor.Reset();
         277           26270 :   nsresult rv = mTarget->PreHandleEvent(aVisitor);
         278           26270 :   SetForceContentDispatch(aVisitor.mForceContentDispatch);
         279           26270 :   SetWantsWillHandleEvent(aVisitor.mWantsWillHandleEvent);
         280           26270 :   SetMayHaveListenerManager(aVisitor.mMayHaveListenerManager);
         281           26270 :   mItemFlags = aVisitor.mItemFlags;
         282           26270 :   mItemData = aVisitor.mItemData;
         283           26270 :   return rv;
         284                 : }
         285                 :
         286                 : nsresult
         287           16788 : nsEventTargetChainItem::PostHandleEvent(nsEventChainPostVisitor& aVisitor,
         288                 :                                         nsCxPusher* aPusher)
         289                 : {
         290           16788 :   aPusher->Pop();
         291           16788 :   aVisitor.mItemFlags = mItemFlags;
         292           16788 :   aVisitor.mItemData = mItemData;
         293           16788 :   mTarget->PostHandleEvent(aVisitor);
         294           16788 :   return NS_OK;
         295                 : }
         296                 :
         297                 : nsresult
         298           33388 : nsEventTargetChainItem::HandleEventTargetChain(nsEventChainPostVisitor& aVisitor, PRUint32 aFlags,
         299                 :                                                nsDispatchingCallback* aCallback,
         300                 :                                                bool aMayHaveNewListenerManagers,
         301                 :                                                nsCxPusher* aPusher)
         302                 : {
         303           33388 :   PRUint32 createdELMs = nsEventListenerManager::sCreatedCount;
         304                 :   // Save the target so that it can be restored later.
         305           66776 :   nsCOMPtr<nsIDOMEventTarget> firstTarget = aVisitor.mEvent->target;
         306                 :
         307                 :   // Capture
         308           33388 :   nsEventTargetChainItem* item = this;
         309           33388 :   aVisitor.mEvent->flags |= NS_EVENT_FLAG_CAPTURE;
         310           33388 :   aVisitor.mEvent->flags &= ~NS_EVENT_FLAG_BUBBLE;
         311           85928 :   while (item->mChild) {
         312           38304 :     if ((!(aVisitor.mEvent->flags & NS_EVENT_FLAG_NO_CONTENT_DISPATCH) ||
         313               0 :          item->ForceContentDispatch()) &&
         314           19152 :         !(aVisitor.mEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH)) {
         315                 :       item->HandleEvent(aVisitor, aFlags & NS_EVENT_CAPTURE_MASK,
         316                 :                         aMayHaveNewListenerManagers ||
         317                 :                         createdELMs != nsEventListenerManager::sCreatedCount,
         318           19152 :                         aPusher);
         319                 :     }
         320                 :
         321           19152 :     if (item->GetNewTarget()) {
         322                 :       // item is at anonymous boundary. Need to retarget for the child items.
         323               0 :       nsEventTargetChainItem* nextTarget = item->mChild;
         324               0 :       while (nextTarget) {
         325               0 :         nsIDOMEventTarget* newTarget = nextTarget->GetNewTarget();
         326               0 :         if (newTarget) {
         327               0 :           aVisitor.mEvent->target = newTarget;
         328               0 :           break;
         329                 :         }
         330               0 :         nextTarget = nextTarget->mChild;
         331                 :       }
         332                 :     }
         333                 :
         334           19152 :     item = item->mChild;
         335                 :   }
         336                 :
         337                 :   // Target
         338           33388 :   aVisitor.mEvent->flags |= NS_EVENT_FLAG_BUBBLE;
         339           66776 :   if (!(aVisitor.mEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH) &&
         340           33388 :       (!(aVisitor.mEvent->flags & NS_EVENT_FLAG_NO_CONTENT_DISPATCH) ||
         341               0 :        item->ForceContentDispatch())) {
         342                 :     // FIXME Should use aFlags & NS_EVENT_BUBBLE_MASK because capture phase
         343                 :     //       event listeners should not be fired. But it breaks at least
         344                 :     //       <xul:dialog>'s buttons. Bug 235441.
         345                 :     item->HandleEvent(aVisitor, aFlags,
         346                 :                       aMayHaveNewListenerManagers ||
         347                 :                       createdELMs != nsEventListenerManager::sCreatedCount,
         348           33388 :                       aPusher);
         349                 :   }
         350           33388 :   if (aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) {
         351           16694 :     item->PostHandleEvent(aVisitor, aPusher);
         352                 :   }
         353                 :
         354                 :   // Bubble
         355           33388 :   aVisitor.mEvent->flags &= ~NS_EVENT_FLAG_CAPTURE;
         356           33388 :   item = item->mParent;
         357           85928 :   while (item) {
         358           19152 :     nsIDOMEventTarget* newTarget = item->GetNewTarget();
         359           19152 :     if (newTarget) {
         360                 :       // Item is at anonymous boundary. Need to retarget for the current item
         361                 :       // and for parent items.
         362               0 :       aVisitor.mEvent->target = newTarget;
         363                 :     }
         364                 :
         365           19152 :     if (!(aVisitor.mEvent->flags & NS_EVENT_FLAG_CANT_BUBBLE) || newTarget) {
         366             376 :       if ((!(aVisitor.mEvent->flags & NS_EVENT_FLAG_NO_CONTENT_DISPATCH) ||
         367               0 :            item->ForceContentDispatch()) &&
         368             188 :           !(aVisitor.mEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH)) {
         369                 :         item->HandleEvent(aVisitor, aFlags & NS_EVENT_BUBBLE_MASK,
         370                 :                           createdELMs != nsEventListenerManager::sCreatedCount,
         371             168 :                           aPusher);
         372                 :       }
         373             188 :       if (aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) {
         374              94 :         item->PostHandleEvent(aVisitor, aPusher);
         375                 :       }
         376                 :     }
         377           19152 :     item = item->mParent;
         378                 :   }
         379           33388 :   aVisitor.mEvent->flags &= ~NS_EVENT_FLAG_BUBBLE;
         380                 :
         381           33388 :   if (!(aFlags & NS_EVENT_FLAG_SYSTEM_EVENT)) {
         382                 :     // Dispatch to the system event group.  Make sure to clear the
         383                 :     // STOP_DISPATCH flag since this resets for each event group.
         384                 :     aVisitor.mEvent->flags &=
         385           16694 :       ~(NS_EVENT_FLAG_STOP_DISPATCH | NS_EVENT_FLAG_STOP_DISPATCH_IMMEDIATELY);
         386                 :
         387                 :     // Setting back the original target of the event.
         388           16694 :     aVisitor.mEvent->target = aVisitor.mEvent->originalTarget;
         389                 :
         390                 :     // Special handling if PresShell (or some other caller)
         391                 :     // used a callback object.
         392           16694 :     if (aCallback) {
         393               0 :       aPusher->Pop();
         394               0 :       aCallback->HandleEvent(aVisitor);
         395                 :     }
         396                 :
         397                 :     // Retarget for system event group (which does the default handling too).
         398                 :     // Setting back the target which was used also for default event group.
         399           16694 :     aVisitor.mEvent->target = firstTarget;
         400                 :     HandleEventTargetChain(aVisitor, aFlags | NS_EVENT_FLAG_SYSTEM_EVENT,
         401                 :                            aCallback,
         402                 :                            createdELMs != nsEventListenerManager::sCreatedCount,
         403           16694 :                            aPusher);
         404                 :
         405                 :     // After dispatch, clear all the propagation flags so that
         406                 :     // system group listeners don't affect to the event.
         407                 :     aVisitor.mEvent->flags &=
         408           16694 :       ~(NS_EVENT_FLAG_STOP_DISPATCH | NS_EVENT_FLAG_STOP_DISPATCH_IMMEDIATELY);
         409                 :   }
         410                 :
         411           33388 :   return NS_OK;
         412                 : }
         413                 :
         414                 : #define NS_CHAIN_POOL_SIZE 128
         415                 :
         416                 : class ChainItemPool {
         417                 : public:
         418           16694 :   ChainItemPool() {
         419           16694 :     if (!sEtciPool) {
         420             301 :       sEtciPool = new nsFixedSizeAllocator();
         421             301 :       if (sEtciPool) {
         422                 :         static const size_t kBucketSizes[] = { sizeof(nsEventTargetChainItem) };
         423                 :         static const PRInt32 kNumBuckets = sizeof(kBucketSizes) / sizeof(size_t);
         424                 :         static const PRInt32 kInitialPoolSize =
         425                 :           NS_SIZE_IN_HEAP(sizeof(nsEventTargetChainItem)) * NS_CHAIN_POOL_SIZE;
         426                 :         nsresult rv = sEtciPool->Init("EventTargetChainItem Pool", kBucketSizes,
         427             301 :                                       kNumBuckets, kInitialPoolSize);
         428             301 :         if (NS_FAILED(rv)) {
         429               0 :           delete sEtciPool;
         430               0 :           sEtciPool = nsnull;
         431                 :         }
         432                 :       }
         433                 :     }
         434           16694 :     if (sEtciPool) {
         435           16694 :       ++sEtciPoolUsers;
         436                 :     }
         437           16694 :   }
         438                 :
         439           16694 :   ~ChainItemPool() {
         440           16694 :     if (sEtciPool) {
         441           16694 :       --sEtciPoolUsers;
         442                 :     }
         443           16694 :     if (!sEtciPoolUsers) {
         444           16004 :       if (nsEventTargetChainItem::MaxEtciCount() > NS_CHAIN_POOL_SIZE) {
         445               0 :         gCachedETCI = nsnull;
         446               0 :         delete sEtciPool;
         447               0 :         sEtciPool = nsnull;
         448               0 :         nsEventTargetChainItem::ResetMaxEtciCount();
         449                 :       }
         450                 :     }
         451           16694 :   }
         452                 :
         453            1364 :   static void Shutdown()
         454                 :   {
         455            1364 :     if (!sEtciPoolUsers) {
         456            1364 :       gCachedETCI = nsnull;
         457            1364 :       delete sEtciPool;
         458            1364 :       sEtciPool = nsnull;
         459            1364 :       nsEventTargetChainItem::ResetMaxEtciCount();
         460                 :     }
         461            1364 :   }
         462                 :
         463           59658 :   nsFixedSizeAllocator* GetPool() { return sEtciPool; }
         464                 :
         465                 :   static nsFixedSizeAllocator* sEtciPool;
         466                 :   static PRInt32               sEtciPoolUsers;
         467                 : };
         468                 :
         469                 : nsFixedSizeAllocator* ChainItemPool::sEtciPool = nsnull;
         470                 : PRInt32 ChainItemPool::sEtciPoolUsers = 0;
         471                 :
         472            1364 : void NS_ShutdownChainItemPool() { ChainItemPool::Shutdown(); }
         473                 :
         474                 : /* static */ nsresult
         475           16694 : nsEventDispatcher::Dispatch(nsISupports* aTarget,
         476                 :                             nsPresContext* aPresContext,
         477                 :                             nsEvent* aEvent,
         478                 :                             nsIDOMEvent* aDOMEvent,
         479                 :                             nsEventStatus* aEventStatus,
         480                 :                             nsDispatchingCallback* aCallback,
         481                 :                             nsCOMArray<nsIDOMEventTarget>* aTargets)
         482                 : {
         483           16694 :   NS_ASSERTION(aEvent, "Trying to dispatch without nsEvent!");
         484           16694 :   NS_ENSURE_TRUE(!NS_IS_EVENT_IN_DISPATCH(aEvent),
         485                 :                  NS_ERROR_ILLEGAL_VALUE);
         486           16694 :   NS_ASSERTION(!aTargets || !aEvent->message, "Wrong parameters!");
         487                 :
         488                 :   // If we're dispatching an already created DOMEvent object, make
         489                 :   // sure it is initialized!
         490                 :   // If aTargets is non-null, the event isn't going to be dispatched.
         491           16694 :   NS_ENSURE_TRUE(aEvent->message || !aDOMEvent || aTargets,
         492                 :                  NS_ERROR_DOM_INVALID_STATE_ERR);
         493                 :
         494                 : #ifdef NS_FUNCTION_TIMER
         495                 :   const char* timer_event_name = nsDOMEvent::GetEventName(aEvent->message);
         496                 :   NS_TIME_FUNCTION_MIN_FMT(20, "Dispatching '%s' event",
         497                 :                            timer_event_name ? timer_event_name : "<other>");
         498                 : #endif
         499                 :
         500           33388 :   nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(aTarget);
         501                 :
         502           16694 :   bool retargeted = false;
         503                 :
         504           16694 :   if (aEvent->flags & NS_EVENT_RETARGET_TO_NON_NATIVE_ANONYMOUS) {
         505               0 :     nsCOMPtr<nsIContent> content = do_QueryInterface(target);
         506               0 :     if (content && content->IsInNativeAnonymousSubtree()) {
         507                 :       nsCOMPtr<nsPIDOMEventTarget> newTarget =
         508               0 :         do_QueryInterface(content->FindFirstNonNativeAnonymous());
         509               0 :       NS_ENSURE_STATE(newTarget);
         510                 :
         511               0 :       aEvent->originalTarget = target;
         512               0 :       target = newTarget;
         513               0 :       retargeted = true;
         514                 :     }
         515                 :   }
         516                 :
         517           16694 :   if (aEvent->flags & NS_EVENT_FLAG_ONLY_CHROME_DISPATCH) {
         518               0 :     nsCOMPtr<nsINode> node = do_QueryInterface(aTarget);
         519               0 :     if (!node) {
         520               0 :       nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(aTarget);
         521               0 :       if (win) {
         522               0 :         node = do_QueryInterface(win->GetExtantDocument());
         523                 :       }
         524                 :     }
         525                 :
         526               0 :     NS_ENSURE_STATE(node);
         527               0 :     nsIDocument* doc = node->OwnerDoc();
         528               0 :     if (!nsContentUtils::IsChromeDoc(doc)) {
         529               0 :       nsPIDOMWindow* win = doc ? doc->GetInnerWindow() : nsnull;
         530                 :       // If we can't dispatch the event to chrome, do nothing.
         531               0 :       nsIDOMEventTarget* piTarget = win ? win->GetChromeEventHandler() : nsnull;
         532               0 :       NS_ENSURE_TRUE(piTarget, NS_OK);
         533                 :
         534               0 :       nsCOMPtr<nsIFrameLoaderOwner> flo = do_QueryInterface(piTarget);
         535               0 :       if (flo) {
         536               0 :         nsRefPtr<nsFrameLoader> fl = flo->GetFrameLoader();
         537               0 :         if (fl) {
         538               0 :           nsIDOMEventTarget* t = fl->GetTabChildGlobalAsEventTarget();
         539               0 :           piTarget = t ? t : piTarget;
         540                 :         }
         541                 :       }
         542                 :
         543                 :       // Set the target to be the original dispatch target,
         544               0 :       aEvent->target = target;
         545                 :       // but use chrome event handler or TabChildGlobal for event target chain.
         546               0 :       target = piTarget;
         547                 :     }
         548                 :   }
         549                 :
         550                 : #ifdef DEBUG
         551           16694 :   if (!nsContentUtils::IsSafeToRunScript()) {
         552               0 :     nsresult rv = NS_ERROR_FAILURE;
         553               0 :     if (target->GetContextForEventHandlers(&rv) ||
         554               0 :         NS_FAILED(rv)) {
         555               0 :       nsCOMPtr<nsINode> node = do_QueryInterface(target);
         556               0 :       if (node && nsContentUtils::IsChromeDoc(node->OwnerDoc())) {
         557               0 :         NS_WARNING("Fix the caller!");
         558                 :       } else {
         559               0 :         NS_ERROR("This is unsafe! Fix the caller!");
         560                 :       }
         561                 :     }
         562                 :   }
         563                 :
         564           16694 :   if (aDOMEvent) {
         565           31320 :     nsCOMPtr<nsIPrivateDOMEvent> privEvt(do_QueryInterface(aDOMEvent));
         566           15660 :     if (privEvt) {
         567           15660 :       nsEvent* innerEvent = privEvt->GetInternalNSEvent();
         568           15660 :       NS_ASSERTION(innerEvent == aEvent,
         569                 :                     "The inner event of aDOMEvent is not the same as aEvent!");
         570                 :     }
         571                 :   }
         572                 : #endif
         573                 :
         574           16694 :   nsresult rv = NS_OK;
         575           16694 :   bool externalDOMEvent = !!(aDOMEvent);
         576                 :
         577                 :   // If we have a PresContext, make sure it doesn't die before
         578                 :   // event dispatching is finished.
         579           33388 :   nsRefPtr<nsPresContext> kungFuDeathGrip(aPresContext);
         580           33388 :   ChainItemPool pool;
         581           16694 :   NS_ENSURE_TRUE(pool.GetPool(), NS_ERROR_OUT_OF_MEMORY);
         582                 :
         583                 :   // Create the event target chain item for the event target.
         584                 :   nsEventTargetChainItem* targetEtci =
         585           16694 :     nsEventTargetChainItem::Create(pool.GetPool(), target);
         586           16694 :   NS_ENSURE_TRUE(targetEtci, NS_ERROR_OUT_OF_MEMORY);
         587           16694 :   if (!targetEtci->IsValid()) {
         588               0 :     nsEventTargetChainItem::Destroy(pool.GetPool(), targetEtci);
         589               0 :     return NS_ERROR_FAILURE;
         590                 :   }
         591                 :
         592                 :   // Make sure that nsIDOMEvent::target and nsIDOMNSEvent::originalTarget
         593                 :   // point to the last item in the chain.
         594           16694 :   if (!aEvent->target) {
         595                 :     // Note, CurrentTarget() points always to the object returned by
         596                 :     // GetTargetForEventTargetChain().
         597           11369 :     aEvent->target = targetEtci->CurrentTarget();
         598                 :   } else {
         599                 :     // XXX But if the target is already set, use that. This is a hack
         600                 :     //     for the 'load', 'beforeunload' and 'unload' events,
         601                 :     //     which are dispatched to |window| but have document as their target.
         602                 :     //
         603                 :     // Make sure that the event target points to the right object.
         604            5325 :     aEvent->target = aEvent->target->GetTargetForEventTargetChain();
         605            5325 :     NS_ENSURE_STATE(aEvent->target);
         606                 :   }
         607                 :
         608           16694 :   if (retargeted) {
         609                 :     aEvent->originalTarget =
         610               0 :       aEvent->originalTarget->GetTargetForEventTargetChain();
         611               0 :     NS_ENSURE_STATE(aEvent->originalTarget);
         612                 :   }
         613                 :   else {
         614           16694 :     aEvent->originalTarget = aEvent->target;
         615                 :   }
         616                 :
         617           33388 :   nsCOMPtr<nsIContent> content = do_QueryInterface(aEvent->originalTarget);
         618           16694 :   bool isInAnon = (content && content->IsInAnonymousSubtree());
         619                 :
         620           16694 :   NS_MARK_EVENT_DISPATCH_STARTED(aEvent);
         621                 :
         622                 :   // Create visitor object and start event dispatching.
         623                 :   // PreHandleEvent for the original target.
         624           16694 :   nsEventStatus status = aEventStatus ? *aEventStatus : nsEventStatus_eIgnore;
         625                 :   nsEventChainPreVisitor preVisitor(aPresContext, aEvent, aDOMEvent, status,
         626           33388 :                                     isInAnon);
         627           16694 :   targetEtci->PreHandleEvent(preVisitor);
         628                 :
         629           16694 :   if (preVisitor.mCanHandle) {
         630                 :     // At least the original target can handle the event.
         631                 :     // Setting the retarget to the |target| simplifies retargeting code.
         632           33388 :     nsCOMPtr<nsIDOMEventTarget> t = aEvent->target;
         633           16694 :     targetEtci->SetNewTarget(t);
         634           16694 :     nsEventTargetChainItem* topEtci = targetEtci;
         635           42964 :     while (preVisitor.mParentTarget) {
         636                 :       nsEventTargetChainItem* parentEtci =
         637                 :         nsEventTargetChainItem::Create(pool.GetPool(), preVisitor.mParentTarget,
         638            9576 :                                        topEtci);
         639            9576 :       if (!parentEtci) {
         640               0 :         rv = NS_ERROR_OUT_OF_MEMORY;
         641               0 :         break;
         642                 :       }
         643            9576 :       if (!parentEtci->IsValid()) {
         644               0 :         rv = NS_ERROR_FAILURE;
         645               0 :         break;
         646                 :       }
         647                 :
         648                 :       // Item needs event retargetting.
         649            9576 :       if (preVisitor.mEventTargetAtParent) {
         650                 :         // Need to set the target of the event
         651                 :         // so that also the next retargeting works.
         652               0 :         preVisitor.mEvent->target = preVisitor.mEventTargetAtParent;
         653               0 :         parentEtci->SetNewTarget(preVisitor.mEventTargetAtParent);
         654                 :       }
         655                 :
         656            9576 :       parentEtci->PreHandleEvent(preVisitor);
         657            9576 :       if (preVisitor.mCanHandle) {
         658            9576 :         topEtci = parentEtci;
         659                 :       } else {
         660               0 :         nsEventTargetChainItem::Destroy(pool.GetPool(), parentEtci);
         661               0 :         parentEtci = nsnull;
         662               0 :         break;
         663                 :       }
         664                 :     }
         665           16694 :     if (NS_SUCCEEDED(rv)) {
         666           16694 :       if (aTargets) {
         667               0 :         aTargets->Clear();
         668               0 :         nsEventTargetChainItem* item = targetEtci;
         669               0 :         while(item) {
         670               0 :           aTargets->AppendObject(item->CurrentTarget()->GetTargetForDOMEvent());
         671               0 :           item = item->mParent;
         672                 :         }
         673                 :       } else {
         674                 :         // Event target chain is created. Handle the chain.
         675           33388 :         nsEventChainPostVisitor postVisitor(preVisitor);
         676           33388 :         nsCxPusher pusher;
         677                 :         rv = topEtci->HandleEventTargetChain(postVisitor,
         678                 :                                              NS_EVENT_FLAG_BUBBLE |
         679                 :                                              NS_EVENT_FLAG_CAPTURE,
         680                 :                                              aCallback,
         681                 :                                              false,
         682           16694 :                                              &pusher);
         683                 :
         684           16694 :         preVisitor.mEventStatus = postVisitor.mEventStatus;
         685                 :         // If the DOM event was created during event flow.
         686           16694 :         if (!preVisitor.mDOMEvent && postVisitor.mDOMEvent) {
         687               0 :           preVisitor.mDOMEvent = postVisitor.mDOMEvent;
         688                 :         }
         689                 :       }
         690                 :     }
         691                 :   }
         692                 :
         693           16694 :   nsEventTargetChainItem::Destroy(pool.GetPool(), targetEtci);
         694           16694 :   targetEtci = nsnull;
         695                 :
         696           16694 :   NS_MARK_EVENT_DISPATCH_DONE(aEvent);
         697                 :
         698           16694 :   if (!externalDOMEvent && preVisitor.mDOMEvent) {
         699                 :     // An nsDOMEvent was created while dispatching the event.
         700                 :     // Duplicate private data if someone holds a pointer to it.
         701               0 :     nsrefcnt rc = 0;
         702               0 :     NS_RELEASE2(preVisitor.mDOMEvent, rc);
         703                 :     nsCOMPtr<nsIPrivateDOMEvent> privateEvent =
         704               0 :       do_QueryInterface(preVisitor.mDOMEvent);
         705               0 :     if (privateEvent) {
         706               0 :       privateEvent->DuplicatePrivateData();
         707                 :     }
         708                 :   }
         709                 :
         710           16694 :   if (aEventStatus) {
         711           10586 :     *aEventStatus = preVisitor.mEventStatus;
         712                 :   }
         713           16694 :   return rv;
         714                 : }
         715                 :
         716                 : /* static */ nsresult
         717           15660 : nsEventDispatcher::DispatchDOMEvent(nsISupports* aTarget,
         718                 :                                     nsEvent* aEvent,
         719                 :                                     nsIDOMEvent* aDOMEvent,
         720                 :                                     nsPresContext* aPresContext,
         721                 :                                     nsEventStatus* aEventStatus)
         722                 : {
         723           15660 :   if (aDOMEvent) {
         724           31320 :     nsCOMPtr<nsIPrivateDOMEvent> privEvt(do_QueryInterface(aDOMEvent));
         725           15660 :     if (privEvt) {
         726           15660 :       nsEvent* innerEvent = privEvt->GetInternalNSEvent();
         727           15660 :       NS_ENSURE_TRUE(innerEvent, NS_ERROR_ILLEGAL_VALUE);
         728                 :
         729           15660 :       bool dontResetTrusted = false;
         730           15660 :       if (innerEvent->flags & NS_EVENT_DISPATCHED) {
         731               0 :         innerEvent->target = nsnull;
         732               0 :         innerEvent->originalTarget = nsnull;
         733                 :       }
         734                 :       else {
         735           31320 :         nsCOMPtr<nsIDOMNSEvent> nsevent(do_QueryInterface(privEvt));
         736           15660 :         nsevent->GetIsTrusted(&dontResetTrusted);
         737                 :       }
         738                 :
         739           15660 :       if (!dontResetTrusted) {
         740                 :         //Check security state to determine if dispatcher is trusted
         741               0 :         privEvt->SetTrusted(nsContentUtils::IsCallerTrustedForWrite());
         742                 :       }
         743                 :
         744                 :       return nsEventDispatcher::Dispatch(aTarget, aPresContext, innerEvent,
         745           15660 :                                          aDOMEvent, aEventStatus);
         746                 :     }
         747               0 :   } else if (aEvent) {
         748                 :     return nsEventDispatcher::Dispatch(aTarget, aPresContext, aEvent,
         749               0 :                                        aDOMEvent, aEventStatus);
         750                 :   }
         751               0 :   return NS_ERROR_ILLEGAL_VALUE;
         752                 : }
         753                 :
         754                 : /* static */ nsresult
         755           11475 : nsEventDispatcher::CreateEvent(nsPresContext* aPresContext,
         756                 :                                nsEvent* aEvent,
         757                 :                                const nsAString& aEventType,
         758                 :                                nsIDOMEvent** aDOMEvent)
         759                 : {
         760           11475 :   *aDOMEvent = nsnull;
         761                 :
         762           11475 :   if (aEvent) {
         763              44 :     switch(aEvent->eventStructType) {
         764                 :     case NS_MUTATION_EVENT:
         765                 :       return NS_NewDOMMutationEvent(aDOMEvent, aPresContext,
         766              44 :                                     static_cast<nsMutationEvent*>(aEvent));
         767                 :     case NS_GUI_EVENT:
         768                 :     case NS_SCROLLPORT_EVENT:
         769                 :     case NS_UI_EVENT:
         770                 :       return NS_NewDOMUIEvent(aDOMEvent, aPresContext,
         771               0 :                               static_cast<nsGUIEvent*>(aEvent));
         772                 :     case NS_SCROLLAREA_EVENT:
         773                 :       return NS_NewDOMScrollAreaEvent(aDOMEvent, aPresContext,
         774               0 :                                       static_cast<nsScrollAreaEvent *>(aEvent));
         775                 :     case NS_KEY_EVENT:
         776                 :       return NS_NewDOMKeyboardEvent(aDOMEvent, aPresContext,
         777               0 :                                     static_cast<nsKeyEvent*>(aEvent));
         778                 :     case NS_COMPOSITION_EVENT:
         779                 :       return NS_NewDOMCompositionEvent(
         780               0 :         aDOMEvent, aPresContext, static_cast<nsCompositionEvent*>(aEvent));
         781                 :     case NS_MOUSE_EVENT:
         782                 :     case NS_POPUP_EVENT:
         783                 :       return NS_NewDOMMouseEvent(aDOMEvent, aPresContext,
         784               0 :                                  static_cast<nsInputEvent*>(aEvent));
         785                 :     case NS_MOUSE_SCROLL_EVENT:
         786                 :       return NS_NewDOMMouseScrollEvent(aDOMEvent, aPresContext,
         787               0 :                                  static_cast<nsInputEvent*>(aEvent));
         788                 :     case NS_DRAG_EVENT:
         789                 :       return NS_NewDOMDragEvent(aDOMEvent, aPresContext,
         790               0 :                                  static_cast<nsDragEvent*>(aEvent));
         791                 :     case NS_TEXT_EVENT:
         792                 :       return NS_NewDOMTextEvent(aDOMEvent, aPresContext,
         793               0 :                                 static_cast<nsTextEvent*>(aEvent));
         794                 :     case NS_SVG_EVENT:
         795                 :       return NS_NewDOMSVGEvent(aDOMEvent, aPresContext,
         796               0 :                                aEvent);
         797                 :     case NS_SVGZOOM_EVENT:
         798                 :       return NS_NewDOMSVGZoomEvent(aDOMEvent, aPresContext,
         799               0 :                                    static_cast<nsGUIEvent*>(aEvent));
         800                 :     case NS_SMIL_TIME_EVENT:
         801               0 :       return NS_NewDOMTimeEvent(aDOMEvent, aPresContext, aEvent);
         802                 :
         803                 :     case NS_COMMAND_EVENT:
         804                 :       return NS_NewDOMCommandEvent(aDOMEvent, aPresContext,
         805               0 :                                    static_cast<nsCommandEvent*>(aEvent));
         806                 :     case NS_SIMPLE_GESTURE_EVENT:
         807                 :       return NS_NewDOMSimpleGestureEvent(aDOMEvent, aPresContext,
         808               0 :                                          static_cast<nsSimpleGestureEvent*>(aEvent));
         809                 :     case NS_MOZTOUCH_EVENT:
         810                 :       return NS_NewDOMMozTouchEvent(aDOMEvent, aPresContext,
         811               0 :                                     static_cast<nsMozTouchEvent*>(aEvent));
         812                 :     case NS_TOUCH_EVENT:
         813                 :       return NS_NewDOMTouchEvent(aDOMEvent, aPresContext,
         814               0 :                                  static_cast<nsTouchEvent*>(aEvent));
         815                 :     case NS_TRANSITION_EVENT:
         816                 :       return NS_NewDOMTransitionEvent(aDOMEvent, aPresContext,
         817               0 :                                       static_cast<nsTransitionEvent*>(aEvent));
         818                 :     case NS_ANIMATION_EVENT:
         819                 :       return NS_NewDOMAnimationEvent(aDOMEvent, aPresContext,
         820               0 :                                      static_cast<nsAnimationEvent*>(aEvent));
         821                 :     }
         822                 :
         823                 :     // For all other types of events, create a vanilla event object.
         824               0 :     return NS_NewDOMEvent(aDOMEvent, aPresContext, aEvent);
         825                 :   }
         826                 :
         827                 :   // And if we didn't get an event, check the type argument.
         828                 :
         829           34289 :   if (aEventType.LowerCaseEqualsLiteral("mouseevent") ||
         830           11429 :       aEventType.LowerCaseEqualsLiteral("mouseevents") ||
         831           11429 :       aEventType.LowerCaseEqualsLiteral("popupevents"))
         832               2 :     return NS_NewDOMMouseEvent(aDOMEvent, aPresContext, nsnull);
         833           11429 :   if (aEventType.LowerCaseEqualsLiteral("mousescrollevents"))
         834               0 :     return NS_NewDOMMouseScrollEvent(aDOMEvent, aPresContext, nsnull);
         835           22858 :   if (aEventType.LowerCaseEqualsLiteral("dragevent") ||
         836           11429 :       aEventType.LowerCaseEqualsLiteral("dragevents"))
         837               0 :     return NS_NewDOMDragEvent(aDOMEvent, aPresContext, nsnull);
         838           22858 :   if (aEventType.LowerCaseEqualsLiteral("keyboardevent") ||
         839           11429 :       aEventType.LowerCaseEqualsLiteral("keyevents"))
         840               0 :     return NS_NewDOMKeyboardEvent(aDOMEvent, aPresContext, nsnull);
         841           11429 :   if (aEventType.LowerCaseEqualsLiteral("compositionevent"))
         842               0 :     return NS_NewDOMCompositionEvent(aDOMEvent, aPresContext, nsnull);
         843           22858 :   if (aEventType.LowerCaseEqualsLiteral("mutationevent") ||
         844           11429 :         aEventType.LowerCaseEqualsLiteral("mutationevents"))
         845               0 :     return NS_NewDOMMutationEvent(aDOMEvent, aPresContext, nsnull);
         846           22858 :   if (aEventType.LowerCaseEqualsLiteral("textevent") ||
         847           11429 :       aEventType.LowerCaseEqualsLiteral("textevents"))
         848               0 :     return NS_NewDOMTextEvent(aDOMEvent, aPresContext, nsnull);
         849           11429 :   if (aEventType.LowerCaseEqualsLiteral("popupblockedevents"))
         850               0 :     return NS_NewDOMPopupBlockedEvent(aDOMEvent, aPresContext, nsnull);
         851           11429 :   if (aEventType.LowerCaseEqualsLiteral("deviceorientationevent"))
         852               0 :     return NS_NewDOMDeviceOrientationEvent(aDOMEvent, aPresContext, nsnull);
         853           11429 :   if (aEventType.LowerCaseEqualsLiteral("devicemotionevent"))
         854               0 :     return NS_NewDOMDeviceMotionEvent(aDOMEvent, aPresContext, nsnull);
         855           22858 :   if (aEventType.LowerCaseEqualsLiteral("uievent") ||
         856           11429 :       aEventType.LowerCaseEqualsLiteral("uievents"))
         857               0 :     return NS_NewDOMUIEvent(aDOMEvent, aPresContext, nsnull);
         858           25119 :   if (aEventType.LowerCaseEqualsLiteral("event") ||
         859           11429 :       aEventType.LowerCaseEqualsLiteral("events") ||
         860            2261 :       aEventType.LowerCaseEqualsLiteral("htmlevents"))
         861            9168 :     return NS_NewDOMEvent(aDOMEvent, aPresContext, nsnull);
         862            4522 :   if (aEventType.LowerCaseEqualsLiteral("svgevent") ||
         863            2261 :       aEventType.LowerCaseEqualsLiteral("svgevents"))
         864               0 :     return NS_NewDOMSVGEvent(aDOMEvent, aPresContext, nsnull);
         865            4522 :   if (aEventType.LowerCaseEqualsLiteral("svgzoomevent") ||
         866            2261 :       aEventType.LowerCaseEqualsLiteral("svgzoomevents"))
         867               0 :     return NS_NewDOMSVGZoomEvent(aDOMEvent, aPresContext, nsnull);
         868            4522 :   if (aEventType.LowerCaseEqualsLiteral("timeevent") ||
         869            2261 :       aEventType.LowerCaseEqualsLiteral("timeevents"))
         870               0 :     return NS_NewDOMTimeEvent(aDOMEvent, aPresContext, nsnull);
         871            4522 :   if (aEventType.LowerCaseEqualsLiteral("xulcommandevent") ||
         872            2261 :       aEventType.LowerCaseEqualsLiteral("xulcommandevents"))
         873               0 :     return NS_NewDOMXULCommandEvent(aDOMEvent, aPresContext, nsnull);
         874            4522 :   if (aEventType.LowerCaseEqualsLiteral("commandevent") ||
         875            2261 :       aEventType.LowerCaseEqualsLiteral("commandevents"))
         876               0 :     return NS_NewDOMCommandEvent(aDOMEvent, aPresContext, nsnull);
         877            4522 :   if (aEventType.LowerCaseEqualsLiteral("datacontainerevent") ||
         878            2261 :       aEventType.LowerCaseEqualsLiteral("datacontainerevents"))
         879               0 :     return NS_NewDOMDataContainerEvent(aDOMEvent, aPresContext, nsnull);
         880            2261 :   if (aEventType.LowerCaseEqualsLiteral("messageevent"))
         881               0 :     return NS_NewDOMMessageEvent(aDOMEvent, aPresContext, nsnull);
         882            2261 :   if (aEventType.LowerCaseEqualsLiteral("progressevent"))
         883            2261 :     return NS_NewDOMProgressEvent(aDOMEvent, aPresContext, nsnull);
         884               0 :   if (aEventType.LowerCaseEqualsLiteral("notifypaintevent"))
         885               0 :     return NS_NewDOMNotifyPaintEvent(aDOMEvent, aPresContext, nsnull);
         886               0 :   if (aEventType.LowerCaseEqualsLiteral("simplegestureevent"))
         887               0 :     return NS_NewDOMSimpleGestureEvent(aDOMEvent, aPresContext, nsnull);
         888               0 :   if (aEventType.LowerCaseEqualsLiteral("beforeunloadevent"))
         889               0 :     return NS_NewDOMBeforeUnloadEvent(aDOMEvent, aPresContext, nsnull);
         890               0 :   if (aEventType.LowerCaseEqualsLiteral("pagetransition"))
         891               0 :     return NS_NewDOMPageTransitionEvent(aDOMEvent, aPresContext, nsnull);
         892               0 :   if (aEventType.LowerCaseEqualsLiteral("moztouchevent"))
         893               0 :     return NS_NewDOMMozTouchEvent(aDOMEvent, aPresContext, nsnull);
         894               0 :   if (aEventType.LowerCaseEqualsLiteral("scrollareaevent"))
         895               0 :     return NS_NewDOMScrollAreaEvent(aDOMEvent, aPresContext, nsnull);
         896                 :   // FIXME: Should get spec to say what the right string is here!  This
         897                 :   // is probably wrong!
         898               0 :   if (aEventType.LowerCaseEqualsLiteral("transitionevent"))
         899               0 :     return NS_NewDOMTransitionEvent(aDOMEvent, aPresContext, nsnull);
         900               0 :   if (aEventType.LowerCaseEqualsLiteral("animationevent"))
         901               0 :     return NS_NewDOMAnimationEvent(aDOMEvent, aPresContext, nsnull);
         902               0 :   if (aEventType.LowerCaseEqualsLiteral("popstateevent"))
         903               0 :     return NS_NewDOMPopStateEvent(aDOMEvent, aPresContext, nsnull);
         904               0 :   if (aEventType.LowerCaseEqualsLiteral("mozaudioavailableevent"))
         905               0 :     return NS_NewDOMAudioAvailableEvent(aDOMEvent, aPresContext, nsnull);
         906               0 :   if (aEventType.LowerCaseEqualsLiteral("closeevent"))
         907               0 :     return NS_NewDOMCloseEvent(aDOMEvent, aPresContext, nsnull);
         908               0 :   if (aEventType.LowerCaseEqualsLiteral("touchevent") &&
         909               0 :       nsDOMTouchEvent::PrefEnabled())
         910               0 :     return NS_NewDOMTouchEvent(aDOMEvent, aPresContext, nsnull);
         911               0 :   if (aEventType.LowerCaseEqualsLiteral("hashchangeevent"))
         912               0 :     return NS_NewDOMHashChangeEvent(aDOMEvent, aPresContext, nsnull);
         913               0 :   if (aEventType.LowerCaseEqualsLiteral("customevent"))
         914               0 :     return NS_NewDOMCustomEvent(aDOMEvent, aPresContext, nsnull);
         915               0 :   if (aEventType.LowerCaseEqualsLiteral("mozsmsevent"))
         916               0 :     return NS_NewDOMSmsEvent(aDOMEvent, aPresContext, nsnull);
         917               0 :   if (aEventType.LowerCaseEqualsLiteral("storageevent")) {
         918               0 :     NS_ADDREF(*aDOMEvent = static_cast<nsDOMEvent*>(new nsDOMStorageEvent()));
         919               0 :     return NS_OK;
         920                 :   }
         921                 :
         922                 :
         923               0 :   return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
         924                 : }

Generated by: LCOV version 1.7