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-06-02 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           25419 : {
      67                 : private:
      68                 :   nsEventTargetChainItem(nsIDOMEventTarget* aTarget,
      69                 :                          nsEventTargetChainItem* aChild = nsnull);
      70                 : 
      71                 : public:
      72           25419 :   static nsEventTargetChainItem* Create(nsFixedSizeAllocator* aAllocator, 
      73                 :                                         nsIDOMEventTarget* aTarget,
      74                 :                                         nsEventTargetChainItem* aChild = nsnull)
      75                 :   {
      76           25419 :     void* place = nsnull;
      77           25419 :     if (gCachedETCI) {
      78           24956 :       place = gCachedETCI;
      79           24956 :       gCachedETCI = gCachedETCI->mNext;
      80                 :     } else {
      81             463 :       place = aAllocator->Alloc(sizeof(nsEventTargetChainItem));
      82                 :     }
      83                 :     return place
      84           25419 :       ? ::new (place) nsEventTargetChainItem(aTarget, aChild)
      85           50838 :       : nsnull;
      86                 :   }
      87                 : 
      88           16381 :   static void Destroy(nsFixedSizeAllocator* aAllocator,
      89                 :                       nsEventTargetChainItem* aItem)
      90                 :   {
      91                 :     // ::Destroy deletes ancestor chain.
      92           16381 :     nsEventTargetChainItem* item = aItem;
      93           16381 :     if (item->mChild) {
      94               0 :       item->mChild->mParent = nsnull;
      95               0 :       item->mChild = nsnull;
      96                 :     }
      97           58181 :     while (item) {
      98           25419 :       nsEventTargetChainItem* parent = item->mParent;
      99           25419 :       item->~nsEventTargetChainItem();
     100           25419 :       item->mNext = gCachedETCI;
     101           25419 :       gCachedETCI = item;
     102           25419 :       --sCurrentEtciCount;
     103           25419 :       item = parent;
     104                 :     }
     105           16381 :   }
     106                 : 
     107           25419 :   bool IsValid()
     108                 :   {
     109           25419 :     NS_WARN_IF_FALSE(!!(mTarget), "Event target is not valid!");
     110           25419 :     return !!(mTarget);
     111                 :   }
     112                 : 
     113           36152 :   nsIDOMEventTarget* GetNewTarget()
     114                 :   {
     115           36152 :     return mNewTarget;
     116                 :   }
     117                 : 
     118           16381 :   void SetNewTarget(nsIDOMEventTarget* aNewTarget)
     119                 :   {
     120           16381 :     mNewTarget = aNewTarget;
     121           16381 :   }
     122                 : 
     123           25419 :   void SetForceContentDispatch(bool aForce)
     124                 :   {
     125           25419 :     if (aForce) {
     126            6409 :       mFlags |= NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH;
     127                 :     } else {
     128           19010 :       mFlags &= ~NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH;
     129                 :     }
     130           25419 :   }
     131                 : 
     132               0 :   bool ForceContentDispatch()
     133                 :   {
     134               0 :     return !!(mFlags & NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH);
     135                 :   }
     136                 : 
     137           25419 :   void SetWantsWillHandleEvent(bool aWants)
     138                 :   {
     139           25419 :     if (aWants) {
     140               0 :       mFlags |= NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT;
     141                 :     } else {
     142           25419 :       mFlags &= ~NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT;
     143                 :     }
     144           25419 :   }
     145                 : 
     146           51006 :   bool WantsWillHandleEvent()
     147                 :   {
     148           51006 :     return !!(mFlags & NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT);
     149                 :   }
     150                 : 
     151           25419 :   void SetMayHaveListenerManager(bool aMayHave)
     152                 :   {
     153           25419 :     if (aMayHave) {
     154           25363 :       mFlags |= NS_TARGET_CHAIN_MAY_HAVE_MANAGER;
     155                 :     } else {
     156              56 :       mFlags &= ~NS_TARGET_CHAIN_MAY_HAVE_MANAGER;
     157                 :     }
     158           25419 :   }
     159                 : 
     160           41103 :   bool MayHaveListenerManager()
     161                 :   {
     162           41103 :     return !!(mFlags & NS_TARGET_CHAIN_MAY_HAVE_MANAGER);
     163                 :   }
     164                 :   
     165           31028 :   nsIDOMEventTarget* CurrentTarget()
     166                 :   {
     167           31028 :     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           51006 :   nsresult HandleEvent(nsEventChainPostVisitor& aVisitor, PRUint32 aFlags,
     193                 :                        bool aMayHaveNewListenerManagers,
     194                 :                        nsCxPusher* aPusher)
     195                 :   {
     196           51006 :     if (WantsWillHandleEvent()) {
     197               0 :       mTarget->WillHandleEvent(aVisitor);
     198                 :     }
     199           51006 :     if (aVisitor.mEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH) {
     200               0 :       return NS_OK;
     201                 :     }
     202           51006 :     if (!mManager) {
     203           41103 :       if (!MayHaveListenerManager() && !aMayHaveNewListenerManagers) {
     204             140 :         return NS_OK;
     205                 :       }
     206                 :       mManager =
     207           40963 :         static_cast<nsEventListenerManager*>(mTarget->GetListenerManager(false));
     208                 :     }
     209           50866 :     if (mManager) {
     210           20010 :       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           20010 :                             aPusher);
     217           20010 :       NS_ASSERTION(aVisitor.mEvent->currentTarget == nsnull,
     218                 :                    "CurrentTarget should be null!");
     219                 :     }
     220           50866 :     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           15691 :   static PRUint32 MaxEtciCount() { return sMaxEtciCount; }
     230                 : 
     231            1403 :   static void ResetMaxEtciCount()
     232                 :   {
     233            1403 :     NS_ASSERTION(!sCurrentEtciCount, "Wrong time to call ResetMaxEtciCount()!");
     234            1403 :     sMaxEtciCount = 0;
     235            1403 :   }
     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           25419 : nsEventTargetChainItem::nsEventTargetChainItem(nsIDOMEventTarget* aTarget,
     260                 :                                                nsEventTargetChainItem* aChild)
     261           25419 : : mChild(aChild), mParent(nsnull), mFlags(0), mItemFlags(0)
     262                 : {
     263           25419 :   mTarget = aTarget->GetTargetForEventTargetChain();
     264           25419 :   if (mChild) {
     265            9038 :     mChild->mParent = this;
     266                 :   }
     267                 : 
     268           25419 :   if (++sCurrentEtciCount > sMaxEtciCount) {
     269             463 :     sMaxEtciCount = sCurrentEtciCount;
     270                 :   }
     271           25419 : }
     272                 : 
     273                 : nsresult
     274           25419 : nsEventTargetChainItem::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
     275                 : {
     276           25419 :   aVisitor.Reset();
     277           25419 :   nsresult rv = mTarget->PreHandleEvent(aVisitor);
     278           25419 :   SetForceContentDispatch(aVisitor.mForceContentDispatch);
     279           25419 :   SetWantsWillHandleEvent(aVisitor.mWantsWillHandleEvent);
     280           25419 :   SetMayHaveListenerManager(aVisitor.mMayHaveListenerManager);
     281           25419 :   mItemFlags = aVisitor.mItemFlags;
     282           25419 :   mItemData = aVisitor.mItemData;
     283           25419 :   return rv;
     284                 : }
     285                 : 
     286                 : nsresult
     287           16475 : nsEventTargetChainItem::PostHandleEvent(nsEventChainPostVisitor& aVisitor,
     288                 :                                         nsCxPusher* aPusher)
     289                 : {
     290           16475 :   aPusher->Pop();
     291           16475 :   aVisitor.mItemFlags = mItemFlags;
     292           16475 :   aVisitor.mItemData = mItemData;
     293           16475 :   mTarget->PostHandleEvent(aVisitor);
     294           16475 :   return NS_OK;
     295                 : }
     296                 : 
     297                 : nsresult
     298           32762 : nsEventTargetChainItem::HandleEventTargetChain(nsEventChainPostVisitor& aVisitor, PRUint32 aFlags,
     299                 :                                                nsDispatchingCallback* aCallback,
     300                 :                                                bool aMayHaveNewListenerManagers,
     301                 :                                                nsCxPusher* aPusher)
     302                 : {
     303           32762 :   PRUint32 createdELMs = nsEventListenerManager::sCreatedCount;
     304                 :   // Save the target so that it can be restored later.
     305           65524 :   nsCOMPtr<nsIDOMEventTarget> firstTarget = aVisitor.mEvent->target;
     306                 : 
     307                 :   // Capture
     308           32762 :   nsEventTargetChainItem* item = this;
     309           32762 :   aVisitor.mEvent->flags |= NS_EVENT_FLAG_CAPTURE;
     310           32762 :   aVisitor.mEvent->flags &= ~NS_EVENT_FLAG_BUBBLE;
     311           83600 :   while (item->mChild) {
     312           36152 :     if ((!(aVisitor.mEvent->flags & NS_EVENT_FLAG_NO_CONTENT_DISPATCH) ||
     313               0 :          item->ForceContentDispatch()) &&
     314           18076 :         !(aVisitor.mEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH)) {
     315                 :       item->HandleEvent(aVisitor, aFlags & NS_EVENT_CAPTURE_MASK,
     316                 :                         aMayHaveNewListenerManagers ||
     317                 :                         createdELMs != nsEventListenerManager::sCreatedCount,
     318           18076 :                         aPusher);
     319                 :     }
     320                 : 
     321           18076 :     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           18076 :     item = item->mChild;
     335                 :   }
     336                 : 
     337                 :   // Target
     338           32762 :   aVisitor.mEvent->flags |= NS_EVENT_FLAG_BUBBLE;
     339           65524 :   if (!(aVisitor.mEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH) &&
     340           32762 :       (!(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           32762 :                       aPusher);
     349                 :   }
     350           32762 :   if (aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) {
     351           16381 :     item->PostHandleEvent(aVisitor, aPusher);
     352                 :   }
     353                 : 
     354                 :   // Bubble
     355           32762 :   aVisitor.mEvent->flags &= ~NS_EVENT_FLAG_CAPTURE;
     356           32762 :   item = item->mParent;
     357           83600 :   while (item) {
     358           18076 :     nsIDOMEventTarget* newTarget = item->GetNewTarget();
     359           18076 :     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           18076 :     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           18076 :     item = item->mParent;
     378                 :   }
     379           32762 :   aVisitor.mEvent->flags &= ~NS_EVENT_FLAG_BUBBLE;
     380                 : 
     381           32762 :   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           16381 :       ~(NS_EVENT_FLAG_STOP_DISPATCH | NS_EVENT_FLAG_STOP_DISPATCH_IMMEDIATELY);
     386                 : 
     387                 :     // Setting back the original target of the event.
     388           16381 :     aVisitor.mEvent->target = aVisitor.mEvent->originalTarget;
     389                 : 
     390                 :     // Special handling if PresShell (or some other caller)
     391                 :     // used a callback object.
     392           16381 :     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           16381 :     aVisitor.mEvent->target = firstTarget;
     400                 :     HandleEventTargetChain(aVisitor, aFlags | NS_EVENT_FLAG_SYSTEM_EVENT,
     401                 :                            aCallback,
     402                 :                            createdELMs != nsEventListenerManager::sCreatedCount,
     403           16381 :                            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           16381 :       ~(NS_EVENT_FLAG_STOP_DISPATCH | NS_EVENT_FLAG_STOP_DISPATCH_IMMEDIATELY);
     409                 :   }
     410                 : 
     411           32762 :   return NS_OK;
     412                 : }
     413                 : 
     414                 : #define NS_CHAIN_POOL_SIZE 128
     415                 : 
     416                 : class ChainItemPool {
     417                 : public:
     418           16381 :   ChainItemPool() {
     419           16381 :     if (!sEtciPool) {
     420             304 :       sEtciPool = new nsFixedSizeAllocator();
     421             304 :       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             304 :                                       kNumBuckets, kInitialPoolSize);
     428             304 :         if (NS_FAILED(rv)) {
     429               0 :           delete sEtciPool;
     430               0 :           sEtciPool = nsnull;
     431                 :         }
     432                 :       }
     433                 :     }
     434           16381 :     if (sEtciPool) {
     435           16381 :       ++sEtciPoolUsers;
     436                 :     }
     437           16381 :   }
     438                 : 
     439           16381 :   ~ChainItemPool() {
     440           16381 :     if (sEtciPool) {
     441           16381 :       --sEtciPoolUsers;
     442                 :     }
     443           16381 :     if (!sEtciPoolUsers) {
     444           15691 :       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           16381 :   }
     452                 : 
     453            1403 :   static void Shutdown()
     454                 :   {
     455            1403 :     if (!sEtciPoolUsers) {
     456            1403 :       gCachedETCI = nsnull;
     457            1403 :       delete sEtciPool;
     458            1403 :       sEtciPool = nsnull;
     459            1403 :       nsEventTargetChainItem::ResetMaxEtciCount();
     460                 :     }
     461            1403 :   }
     462                 : 
     463           58181 :   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            1403 : void NS_ShutdownChainItemPool() { ChainItemPool::Shutdown(); }
     473                 : 
     474                 : /* static */ nsresult
     475           16381 : 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           16381 :   NS_ASSERTION(aEvent, "Trying to dispatch without nsEvent!");
     484           16381 :   NS_ENSURE_TRUE(!NS_IS_EVENT_IN_DISPATCH(aEvent),
     485                 :                  NS_ERROR_ILLEGAL_VALUE);
     486           16381 :   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           16381 :   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           32762 :   nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(aTarget);
     501                 : 
     502           16381 :   bool retargeted = false;
     503                 : 
     504           16381 :   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           16381 :   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           16381 :   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           16381 :   if (aDOMEvent) {
     565           30686 :     nsCOMPtr<nsIPrivateDOMEvent> privEvt(do_QueryInterface(aDOMEvent));
     566           15343 :     if (privEvt) {
     567           15343 :       nsEvent* innerEvent = privEvt->GetInternalNSEvent();
     568           15343 :       NS_ASSERTION(innerEvent == aEvent,
     569                 :                     "The inner event of aDOMEvent is not the same as aEvent!");
     570                 :     }
     571                 :   }
     572                 : #endif
     573                 : 
     574           16381 :   nsresult rv = NS_OK;
     575           16381 :   bool externalDOMEvent = !!(aDOMEvent);
     576                 : 
     577                 :   // If we have a PresContext, make sure it doesn't die before
     578                 :   // event dispatching is finished.
     579           32762 :   nsRefPtr<nsPresContext> kungFuDeathGrip(aPresContext);
     580           32762 :   ChainItemPool pool;
     581           16381 :   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           16381 :     nsEventTargetChainItem::Create(pool.GetPool(), target);
     586           16381 :   NS_ENSURE_TRUE(targetEtci, NS_ERROR_OUT_OF_MEMORY);
     587           16381 :   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           16381 :   if (!aEvent->target) {
     595                 :     // Note, CurrentTarget() points always to the object returned by
     596                 :     // GetTargetForEventTargetChain().
     597           11018 :     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            5363 :     aEvent->target = aEvent->target->GetTargetForEventTargetChain();
     605            5363 :     NS_ENSURE_STATE(aEvent->target);
     606                 :   }
     607                 : 
     608           16381 :   if (retargeted) {
     609                 :     aEvent->originalTarget =
     610               0 :       aEvent->originalTarget->GetTargetForEventTargetChain();
     611               0 :     NS_ENSURE_STATE(aEvent->originalTarget);
     612                 :   }
     613                 :   else {
     614           16381 :     aEvent->originalTarget = aEvent->target;
     615                 :   }
     616                 : 
     617           32762 :   nsCOMPtr<nsIContent> content = do_QueryInterface(aEvent->originalTarget);
     618           16381 :   bool isInAnon = (content && content->IsInAnonymousSubtree());
     619                 : 
     620           16381 :   NS_MARK_EVENT_DISPATCH_STARTED(aEvent);
     621                 : 
     622                 :   // Create visitor object and start event dispatching.
     623                 :   // PreHandleEvent for the original target.
     624           16381 :   nsEventStatus status = aEventStatus ? *aEventStatus : nsEventStatus_eIgnore;
     625                 :   nsEventChainPreVisitor preVisitor(aPresContext, aEvent, aDOMEvent, status,
     626           32762 :                                     isInAnon);
     627           16381 :   targetEtci->PreHandleEvent(preVisitor);
     628                 : 
     629           16381 :   if (preVisitor.mCanHandle) {
     630                 :     // At least the original target can handle the event.
     631                 :     // Setting the retarget to the |target| simplifies retargeting code.
     632           32762 :     nsCOMPtr<nsIDOMEventTarget> t = aEvent->target;
     633           16381 :     targetEtci->SetNewTarget(t);
     634           16381 :     nsEventTargetChainItem* topEtci = targetEtci;
     635           41800 :     while (preVisitor.mParentTarget) {
     636                 :       nsEventTargetChainItem* parentEtci =
     637                 :         nsEventTargetChainItem::Create(pool.GetPool(), preVisitor.mParentTarget,
     638            9038 :                                        topEtci);
     639            9038 :       if (!parentEtci) {
     640               0 :         rv = NS_ERROR_OUT_OF_MEMORY;
     641               0 :         break;
     642                 :       }
     643            9038 :       if (!parentEtci->IsValid()) {
     644               0 :         rv = NS_ERROR_FAILURE;
     645               0 :         break;
     646                 :       }
     647                 : 
     648                 :       // Item needs event retargetting.
     649            9038 :       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            9038 :       parentEtci->PreHandleEvent(preVisitor);
     657            9038 :       if (preVisitor.mCanHandle) {
     658            9038 :         topEtci = parentEtci;
     659                 :       } else {
     660               0 :         nsEventTargetChainItem::Destroy(pool.GetPool(), parentEtci);
     661               0 :         parentEtci = nsnull;
     662               0 :         break;
     663                 :       }
     664                 :     }
     665           16381 :     if (NS_SUCCEEDED(rv)) {
     666           16381 :       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           32762 :         nsEventChainPostVisitor postVisitor(preVisitor);
     676           32762 :         nsCxPusher pusher;
     677                 :         rv = topEtci->HandleEventTargetChain(postVisitor,
     678                 :                                              NS_EVENT_FLAG_BUBBLE |
     679                 :                                              NS_EVENT_FLAG_CAPTURE,
     680                 :                                              aCallback,
     681                 :                                              false,
     682           16381 :                                              &pusher);
     683                 :   
     684           16381 :         preVisitor.mEventStatus = postVisitor.mEventStatus;
     685                 :         // If the DOM event was created during event flow.
     686           16381 :         if (!preVisitor.mDOMEvent && postVisitor.mDOMEvent) {
     687               0 :           preVisitor.mDOMEvent = postVisitor.mDOMEvent;
     688                 :         }
     689                 :       }
     690                 :     }
     691                 :   }
     692                 : 
     693           16381 :   nsEventTargetChainItem::Destroy(pool.GetPool(), targetEtci);
     694           16381 :   targetEtci = nsnull;
     695                 : 
     696           16381 :   NS_MARK_EVENT_DISPATCH_DONE(aEvent);
     697                 : 
     698           16381 :   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           16381 :   if (aEventStatus) {
     711           10265 :     *aEventStatus = preVisitor.mEventStatus;
     712                 :   }
     713           16381 :   return rv;
     714                 : }
     715                 : 
     716                 : /* static */ nsresult
     717           15343 : nsEventDispatcher::DispatchDOMEvent(nsISupports* aTarget,
     718                 :                                     nsEvent* aEvent,
     719                 :                                     nsIDOMEvent* aDOMEvent,
     720                 :                                     nsPresContext* aPresContext,
     721                 :                                     nsEventStatus* aEventStatus)
     722                 : {
     723           15343 :   if (aDOMEvent) {
     724           30686 :     nsCOMPtr<nsIPrivateDOMEvent> privEvt(do_QueryInterface(aDOMEvent));
     725           15343 :     if (privEvt) {
     726           15343 :       nsEvent* innerEvent = privEvt->GetInternalNSEvent();
     727           15343 :       NS_ENSURE_TRUE(innerEvent, NS_ERROR_ILLEGAL_VALUE);
     728                 : 
     729           15343 :       bool dontResetTrusted = false;
     730           15343 :       if (innerEvent->flags & NS_EVENT_DISPATCHED) {
     731               0 :         innerEvent->target = nsnull;
     732               0 :         innerEvent->originalTarget = nsnull;
     733                 :       }
     734                 :       else {
     735           30686 :         nsCOMPtr<nsIDOMNSEvent> nsevent(do_QueryInterface(privEvt));
     736           15343 :         nsevent->GetIsTrusted(&dontResetTrusted);
     737                 :       }
     738                 : 
     739           15343 :       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           15343 :                                          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           11525 : nsEventDispatcher::CreateEvent(nsPresContext* aPresContext,
     756                 :                                nsEvent* aEvent,
     757                 :                                const nsAString& aEventType,
     758                 :                                nsIDOMEvent** aDOMEvent)
     759                 : {
     760           11525 :   *aDOMEvent = nsnull;
     761                 : 
     762           11525 :   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           34439 :   if (aEventType.LowerCaseEqualsLiteral("mouseevent") ||
     830           11479 :       aEventType.LowerCaseEqualsLiteral("mouseevents") ||
     831           11479 :       aEventType.LowerCaseEqualsLiteral("popupevents"))
     832               2 :     return NS_NewDOMMouseEvent(aDOMEvent, aPresContext, nsnull);
     833           11479 :   if (aEventType.LowerCaseEqualsLiteral("mousescrollevents"))
     834               0 :     return NS_NewDOMMouseScrollEvent(aDOMEvent, aPresContext, nsnull);
     835           22958 :   if (aEventType.LowerCaseEqualsLiteral("dragevent") ||
     836           11479 :       aEventType.LowerCaseEqualsLiteral("dragevents"))
     837               0 :     return NS_NewDOMDragEvent(aDOMEvent, aPresContext, nsnull);
     838           22958 :   if (aEventType.LowerCaseEqualsLiteral("keyboardevent") ||
     839           11479 :       aEventType.LowerCaseEqualsLiteral("keyevents"))
     840               0 :     return NS_NewDOMKeyboardEvent(aDOMEvent, aPresContext, nsnull);
     841           11479 :   if (aEventType.LowerCaseEqualsLiteral("compositionevent"))
     842               0 :     return NS_NewDOMCompositionEvent(aDOMEvent, aPresContext, nsnull);
     843           22958 :   if (aEventType.LowerCaseEqualsLiteral("mutationevent") ||
     844           11479 :         aEventType.LowerCaseEqualsLiteral("mutationevents"))
     845               0 :     return NS_NewDOMMutationEvent(aDOMEvent, aPresContext, nsnull);
     846           22958 :   if (aEventType.LowerCaseEqualsLiteral("textevent") ||
     847           11479 :       aEventType.LowerCaseEqualsLiteral("textevents"))
     848               0 :     return NS_NewDOMTextEvent(aDOMEvent, aPresContext, nsnull);
     849           11479 :   if (aEventType.LowerCaseEqualsLiteral("popupblockedevents"))
     850               0 :     return NS_NewDOMPopupBlockedEvent(aDOMEvent, aPresContext, nsnull);
     851           11479 :   if (aEventType.LowerCaseEqualsLiteral("deviceorientationevent"))
     852               0 :     return NS_NewDOMDeviceOrientationEvent(aDOMEvent, aPresContext, nsnull);
     853           11479 :   if (aEventType.LowerCaseEqualsLiteral("devicemotionevent"))
     854               0 :     return NS_NewDOMDeviceMotionEvent(aDOMEvent, aPresContext, nsnull);
     855           22958 :   if (aEventType.LowerCaseEqualsLiteral("uievent") ||
     856           11479 :       aEventType.LowerCaseEqualsLiteral("uievents"))
     857               0 :     return NS_NewDOMUIEvent(aDOMEvent, aPresContext, nsnull);
     858           25221 :   if (aEventType.LowerCaseEqualsLiteral("event") ||
     859           11479 :       aEventType.LowerCaseEqualsLiteral("events") ||
     860            2263 :       aEventType.LowerCaseEqualsLiteral("htmlevents"))
     861            9216 :     return NS_NewDOMEvent(aDOMEvent, aPresContext, nsnull);
     862            4526 :   if (aEventType.LowerCaseEqualsLiteral("svgevent") ||
     863            2263 :       aEventType.LowerCaseEqualsLiteral("svgevents"))
     864               0 :     return NS_NewDOMSVGEvent(aDOMEvent, aPresContext, nsnull);
     865            4526 :   if (aEventType.LowerCaseEqualsLiteral("svgzoomevent") ||
     866            2263 :       aEventType.LowerCaseEqualsLiteral("svgzoomevents"))
     867               0 :     return NS_NewDOMSVGZoomEvent(aDOMEvent, aPresContext, nsnull);
     868            4526 :   if (aEventType.LowerCaseEqualsLiteral("timeevent") ||
     869            2263 :       aEventType.LowerCaseEqualsLiteral("timeevents"))
     870               0 :     return NS_NewDOMTimeEvent(aDOMEvent, aPresContext, nsnull);
     871            4526 :   if (aEventType.LowerCaseEqualsLiteral("xulcommandevent") ||
     872            2263 :       aEventType.LowerCaseEqualsLiteral("xulcommandevents"))
     873               0 :     return NS_NewDOMXULCommandEvent(aDOMEvent, aPresContext, nsnull);
     874            4526 :   if (aEventType.LowerCaseEqualsLiteral("commandevent") ||
     875            2263 :       aEventType.LowerCaseEqualsLiteral("commandevents"))
     876               0 :     return NS_NewDOMCommandEvent(aDOMEvent, aPresContext, nsnull);
     877            4526 :   if (aEventType.LowerCaseEqualsLiteral("datacontainerevent") ||
     878            2263 :       aEventType.LowerCaseEqualsLiteral("datacontainerevents"))
     879               0 :     return NS_NewDOMDataContainerEvent(aDOMEvent, aPresContext, nsnull);
     880            2263 :   if (aEventType.LowerCaseEqualsLiteral("messageevent"))
     881               0 :     return NS_NewDOMMessageEvent(aDOMEvent, aPresContext, nsnull);
     882            2263 :   if (aEventType.LowerCaseEqualsLiteral("progressevent"))
     883            2263 :     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