LCOV - code coverage report
Current view: directory - content/events/src - nsEventListenerManager.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 450 162 36.0 %
Date: 2012-06-02 Functions: 39 25 64.1 %

       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                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      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 "nsISupports.h"
      39                 : #include "nsGUIEvent.h"
      40                 : #include "nsDOMEvent.h"
      41                 : #include "nsEventListenerManager.h"
      42                 : #include "nsCaret.h"
      43                 : #include "nsIDOMNSEvent.h"
      44                 : #include "nsIDOMEventListener.h"
      45                 : #include "nsITextControlFrame.h"
      46                 : #include "nsGkAtoms.h"
      47                 : #include "nsPIDOMWindow.h"
      48                 : #include "nsIPrivateDOMEvent.h"
      49                 : #include "nsIJSEventListener.h"
      50                 : #include "prmem.h"
      51                 : #include "nsIScriptGlobalObject.h"
      52                 : #include "nsIScriptRuntime.h"
      53                 : #include "nsLayoutUtils.h"
      54                 : #include "nsINameSpaceManager.h"
      55                 : #include "nsIContent.h"
      56                 : #include "mozilla/dom/Element.h"
      57                 : #include "nsIFrame.h"
      58                 : #include "nsIView.h"
      59                 : #include "nsIViewManager.h"
      60                 : #include "nsCOMPtr.h"
      61                 : #include "nsIServiceManager.h"
      62                 : #include "nsIScriptSecurityManager.h"
      63                 : #include "nsDOMError.h"
      64                 : #include "nsIJSContextStack.h"
      65                 : #include "nsIDocument.h"
      66                 : #include "nsIPresShell.h"
      67                 : #include "nsMutationEvent.h"
      68                 : #include "nsIXPConnect.h"
      69                 : #include "nsDOMCID.h"
      70                 : #include "nsIScriptObjectOwner.h" // for nsIScriptEventHandlerOwner
      71                 : #include "nsFocusManager.h"
      72                 : #include "nsIDOMElement.h"
      73                 : #include "nsContentUtils.h"
      74                 : #include "nsJSUtils.h"
      75                 : #include "nsContentCID.h"
      76                 : #include "nsEventDispatcher.h"
      77                 : #include "nsDOMJSUtils.h"
      78                 : #include "nsDOMScriptObjectHolder.h"
      79                 : #include "nsDataHashtable.h"
      80                 : #include "nsCOMArray.h"
      81                 : #include "nsEventListenerService.h"
      82                 : #include "nsDOMEvent.h"
      83                 : #include "nsIContentSecurityPolicy.h"
      84                 : #include "nsJSEnvironment.h"
      85                 : #include "xpcpublic.h"
      86                 : #include "sampler.h"
      87                 : 
      88                 : using namespace mozilla::dom;
      89                 : 
      90                 : #define EVENT_TYPE_EQUALS( ls, type, userType ) \
      91                 :   (ls->mEventType == type && \
      92                 :   (ls->mEventType != NS_USER_DEFINED_EVENT || ls->mTypeAtom == userType))
      93                 : 
      94                 : static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
      95                 :                      NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
      96                 : 
      97                 : static const PRUint32 kAllMutationBits =
      98                 :   NS_EVENT_BITS_MUTATION_SUBTREEMODIFIED |
      99                 :   NS_EVENT_BITS_MUTATION_NODEINSERTED |
     100                 :   NS_EVENT_BITS_MUTATION_NODEREMOVED |
     101                 :   NS_EVENT_BITS_MUTATION_NODEREMOVEDFROMDOCUMENT |
     102                 :   NS_EVENT_BITS_MUTATION_NODEINSERTEDINTODOCUMENT |
     103                 :   NS_EVENT_BITS_MUTATION_ATTRMODIFIED |
     104                 :   NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED;
     105                 : 
     106                 : static PRUint32
     107               0 : MutationBitForEventType(PRUint32 aEventType)
     108                 : {
     109               0 :   switch (aEventType) {
     110                 :     case NS_MUTATION_SUBTREEMODIFIED:
     111               0 :       return NS_EVENT_BITS_MUTATION_SUBTREEMODIFIED;
     112                 :     case NS_MUTATION_NODEINSERTED:
     113               0 :       return NS_EVENT_BITS_MUTATION_NODEINSERTED;
     114                 :     case NS_MUTATION_NODEREMOVED:
     115               0 :       return NS_EVENT_BITS_MUTATION_NODEREMOVED;
     116                 :     case NS_MUTATION_NODEREMOVEDFROMDOCUMENT:
     117               0 :       return NS_EVENT_BITS_MUTATION_NODEREMOVEDFROMDOCUMENT;
     118                 :     case NS_MUTATION_NODEINSERTEDINTODOCUMENT:
     119               0 :       return NS_EVENT_BITS_MUTATION_NODEINSERTEDINTODOCUMENT;
     120                 :     case NS_MUTATION_ATTRMODIFIED:
     121               0 :       return NS_EVENT_BITS_MUTATION_ATTRMODIFIED;
     122                 :     case NS_MUTATION_CHARACTERDATAMODIFIED:
     123               0 :       return NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED;
     124                 :     default:
     125                 :       break;
     126                 :   }
     127               0 :   return 0;
     128                 : }
     129                 : 
     130                 : PRUint32 nsEventListenerManager::sCreatedCount = 0;
     131                 : 
     132            3170 : nsEventListenerManager::nsEventListenerManager(nsISupports* aTarget) :
     133                 :   mMayHavePaintEventListener(false),
     134                 :   mMayHaveMutationListeners(false),
     135                 :   mMayHaveCapturingListeners(false),
     136                 :   mMayHaveSystemGroupListeners(false),
     137                 :   mMayHaveAudioAvailableEventListener(false),
     138                 :   mMayHaveTouchEventListener(false),
     139                 :   mMayHaveMouseEnterLeaveEventListener(false),
     140                 :   mNoListenerForEvent(0),
     141            3170 :   mTarget(aTarget)
     142                 : {
     143            3170 :   NS_ASSERTION(aTarget, "unexpected null pointer");
     144                 : 
     145            3170 :   ++sCreatedCount;
     146            3170 : }
     147                 : 
     148            9504 : nsEventListenerManager::~nsEventListenerManager() 
     149                 : {
     150                 :   // If your code fails this assertion, a possible reason is that
     151                 :   // a class did not call our Disconnect() manually. Note that
     152                 :   // this class can have Disconnect called in one of two ways:
     153                 :   // if it is part of a cycle, then in Unlink() (such a cycle
     154                 :   // would be with one of the listeners, not mTarget which is weak).
     155                 :   // If not part of a cycle, then Disconnect must be called manually,
     156                 :   // typically from the destructor of the owner class (mTarget).
     157                 :   // XXX azakai: Is there any reason to not just call Disconnect
     158                 :   //             from right here, if not previously called?
     159            3168 :   NS_ASSERTION(!mTarget, "didn't call Disconnect");
     160            3168 :   RemoveAllListeners();
     161                 : 
     162           12672 : }
     163                 : 
     164                 : void
     165            6336 : nsEventListenerManager::RemoveAllListeners()
     166                 : {
     167            6336 :   mListeners.Clear();
     168            6336 : }
     169                 : 
     170                 : void
     171            1403 : nsEventListenerManager::Shutdown()
     172                 : {
     173            1403 :   nsDOMEvent::Shutdown();
     174            1403 : }
     175                 : 
     176            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsEventListenerManager)
     177                 : 
     178             329 : NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsEventListenerManager, AddRef)
     179             329 : NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsEventListenerManager, Release)
     180                 : 
     181             337 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsEventListenerManager)
     182             337 :   PRUint32 count = tmp->mListeners.Length();
     183             721 :   for (PRUint32 i = 0; i < count; i++) {
     184             384 :     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mListeners[i] mListener");
     185             384 :     cb.NoteXPCOMChild(tmp->mListeners.ElementAt(i).mListener.get());
     186                 :   }  
     187             337 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     188                 : 
     189             329 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsEventListenerManager)
     190             329 :   tmp->Disconnect();
     191             329 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     192                 : 
     193                 : 
     194                 : nsPIDOMWindow*
     195               2 : nsEventListenerManager::GetInnerWindowForTarget()
     196                 : {
     197               4 :   nsCOMPtr<nsINode> node = do_QueryInterface(mTarget);
     198               2 :   if (node) {
     199                 :     // XXX sXBL/XBL2 issue -- do we really want the owner here?  What
     200                 :     // if that's the XBL document?
     201               2 :     return node->OwnerDoc()->GetInnerWindow();
     202                 :   }
     203                 : 
     204               0 :   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mTarget);
     205               0 :   if (window) {
     206               0 :     NS_ASSERTION(window->IsInnerWindow(), "Target should not be an outer window");
     207               0 :     return window;
     208                 :   }
     209                 : 
     210               0 :   return nsnull;
     211                 : }
     212                 : 
     213                 : void
     214            4584 : nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener,
     215                 :                                          PRUint32 aType,
     216                 :                                          nsIAtom* aTypeAtom,
     217                 :                                          PRInt32 aFlags)
     218                 : {
     219            4584 :   NS_ABORT_IF_FALSE(aType && aTypeAtom, "Missing type");
     220                 : 
     221            4584 :   if (!aListener) {
     222               0 :     return;
     223                 :   }
     224                 : 
     225            9168 :   nsRefPtr<nsIDOMEventListener> kungFuDeathGrip = aListener;
     226                 : 
     227                 :   nsListenerStruct* ls;
     228            4584 :   PRUint32 count = mListeners.Length();
     229            6056 :   for (PRUint32 i = 0; i < count; i++) {
     230            1472 :     ls = &mListeners.ElementAt(i);
     231            1472 :     if (ls->mListener == aListener && ls->mFlags == aFlags &&
     232               0 :         EVENT_TYPE_EQUALS(ls, aType, aTypeAtom)) {
     233                 :       return;
     234                 :     }
     235                 :   }
     236                 : 
     237            4584 :   mNoListenerForEvent = NS_EVENT_TYPE_NULL;
     238            4584 :   mNoListenerForEventAtom = nsnull;
     239                 : 
     240            4584 :   ls = mListeners.AppendElement();
     241            4584 :   ls->mListener = aListener;
     242            4584 :   ls->mEventType = aType;
     243            4584 :   ls->mTypeAtom = aTypeAtom;
     244            4584 :   ls->mWrappedJS = false;
     245            4584 :   ls->mFlags = aFlags;
     246            4584 :   ls->mHandlerIsString = false;
     247                 : 
     248            9168 :   nsCOMPtr<nsIXPConnectWrappedJS> wjs = do_QueryInterface(aListener);
     249            4584 :   if (wjs) {
     250            4584 :     ls->mWrappedJS = true;
     251                 :   }
     252            4584 :   if (aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) {
     253               0 :     mMayHaveSystemGroupListeners = true;
     254                 :   }
     255            4584 :   if (aFlags & NS_EVENT_FLAG_CAPTURE) {
     256               2 :     mMayHaveCapturingListeners = true;
     257                 :   }
     258                 : 
     259            4584 :   if (aType == NS_AFTERPAINT) {
     260               0 :     mMayHavePaintEventListener = true;
     261               0 :     nsPIDOMWindow* window = GetInnerWindowForTarget();
     262               0 :     if (window) {
     263               0 :       window->SetHasPaintEventListeners();
     264                 :     }
     265                 : #ifdef MOZ_MEDIA
     266            4584 :   } else if (aType == NS_MOZAUDIOAVAILABLE) {
     267               0 :     mMayHaveAudioAvailableEventListener = true;
     268               0 :     nsPIDOMWindow* window = GetInnerWindowForTarget();
     269               0 :     if (window) {
     270               0 :       window->SetHasAudioAvailableEventListeners();
     271                 :     }
     272                 : #endif // MOZ_MEDIA
     273            4584 :   } else if (aType >= NS_MUTATION_START && aType <= NS_MUTATION_END) {
     274                 :     // For mutation listeners, we need to update the global bit on the DOM window.
     275                 :     // Otherwise we won't actually fire the mutation event.
     276               2 :     mMayHaveMutationListeners = true;
     277                 :     // Go from our target to the nearest enclosing DOM window.
     278               2 :     nsPIDOMWindow* window = GetInnerWindowForTarget();
     279               2 :     if (window) {
     280                 :       // If aType is NS_MUTATION_SUBTREEMODIFIED, we need to listen all
     281                 :       // mutations. nsContentUtils::HasMutationListeners relies on this.
     282                 :       window->SetMutationListeners((aType == NS_MUTATION_SUBTREEMODIFIED) ?
     283                 :                                    kAllMutationBits :
     284               0 :                                    MutationBitForEventType(aType));
     285               2 :     }
     286            4582 :   } else if (aTypeAtom == nsGkAtoms::ondeviceorientation ||
     287                 :              aTypeAtom == nsGkAtoms::ondevicemotion) {
     288               0 :     nsPIDOMWindow* window = GetInnerWindowForTarget();
     289               0 :     if (window)
     290               0 :       window->SetHasOrientationEventListener();
     291            4582 :   } else if ((aType >= NS_MOZTOUCH_DOWN && aType <= NS_MOZTOUCH_UP) ||
     292                 :              (aTypeAtom == nsGkAtoms::ontouchstart ||
     293                 :               aTypeAtom == nsGkAtoms::ontouchend ||
     294                 :               aTypeAtom == nsGkAtoms::ontouchmove ||
     295                 :               aTypeAtom == nsGkAtoms::ontouchenter ||
     296                 :               aTypeAtom == nsGkAtoms::ontouchleave ||
     297                 :               aTypeAtom == nsGkAtoms::ontouchcancel)) {
     298               0 :     mMayHaveTouchEventListener = true;
     299               0 :     nsPIDOMWindow* window = GetInnerWindowForTarget();
     300               0 :     if (window)
     301               0 :       window->SetHasTouchEventListeners();
     302            4582 :   } else if (aTypeAtom == nsGkAtoms::onmouseenter ||
     303                 :              aTypeAtom == nsGkAtoms::onmouseleave) {
     304               0 :     mMayHaveMouseEnterLeaveEventListener = true;
     305               0 :     nsPIDOMWindow* window = GetInnerWindowForTarget();
     306               0 :     if (window) {
     307                 : #ifdef DEBUG
     308               0 :       nsCOMPtr<nsIDocument> d = do_QueryInterface(window->GetExtantDocument());
     309               0 :       NS_WARN_IF_FALSE(!nsContentUtils::IsChromeDoc(d),
     310                 :                        "Please do not use mouseenter/leave events in chrome. "
     311                 :                        "They are slower than mouseover/out!");
     312                 : #endif
     313               0 :       window->SetHasMouseEnterLeaveEventListeners();
     314                 :     }
     315                 :   }
     316                 : }
     317                 : 
     318                 : void
     319              29 : nsEventListenerManager::RemoveEventListener(nsIDOMEventListener *aListener, 
     320                 :                                             PRUint32 aType,
     321                 :                                             nsIAtom* aUserType,
     322                 :                                             PRInt32 aFlags)
     323                 : {
     324              29 :   if (!aListener || !aType) {
     325               0 :     return;
     326                 :   }
     327                 : 
     328                 :   nsListenerStruct* ls;
     329              29 :   aFlags &= ~NS_PRIV_EVENT_UNTRUSTED_PERMITTED;
     330                 : 
     331              29 :   PRUint32 count = mListeners.Length();
     332              52 :   for (PRUint32 i = 0; i < count; ++i) {
     333              52 :     ls = &mListeners.ElementAt(i);
     334              80 :     if (ls->mListener == aListener &&
     335                 :         ((ls->mFlags & ~NS_PRIV_EVENT_UNTRUSTED_PERMITTED) == aFlags) &&
     336              28 :         EVENT_TYPE_EQUALS(ls, aType, aUserType)) {
     337              58 :       nsRefPtr<nsEventListenerManager> kungFuDeathGrip = this;
     338              29 :       mListeners.RemoveElementAt(i);
     339              29 :       mNoListenerForEvent = NS_EVENT_TYPE_NULL;
     340              29 :       mNoListenerForEventAtom = nsnull;
     341              29 :       if (aType == NS_DEVICE_ORIENTATION) {
     342               0 :         nsPIDOMWindow* window = GetInnerWindowForTarget();
     343               0 :         if (window)
     344               0 :           window->RemoveOrientationEventListener();
     345                 :       }
     346                 :       break;
     347                 :     }
     348                 :   }
     349                 : }
     350                 : 
     351                 : static inline bool
     352           14072 : ListenerCanHandle(nsListenerStruct* aLs, nsEvent* aEvent)
     353                 : {
     354                 :   // This is slightly different from EVENT_TYPE_EQUALS in that it returns
     355                 :   // true even when aEvent->message == NS_USER_DEFINED_EVENT and
     356                 :   // aLs=>mEventType != NS_USER_DEFINED_EVENT as long as the atoms are the same
     357                 :   return aEvent->message == NS_USER_DEFINED_EVENT ?
     358           12906 :     (aLs->mTypeAtom == aEvent->userType) :
     359           26978 :     (aLs->mEventType == aEvent->message);
     360                 : }
     361                 : 
     362                 : void
     363            4584 : nsEventListenerManager::AddEventListenerByType(nsIDOMEventListener *aListener, 
     364                 :                                                const nsAString& aType,
     365                 :                                                PRInt32 aFlags)
     366                 : {
     367            9168 :   nsCOMPtr<nsIAtom> atom = do_GetAtom(NS_LITERAL_STRING("on") + aType);
     368            4584 :   PRUint32 type = nsContentUtils::GetEventId(atom);
     369            4584 :   AddEventListener(aListener, type, atom, aFlags);
     370            4584 : }
     371                 : 
     372                 : void
     373              29 : nsEventListenerManager::RemoveEventListenerByType(nsIDOMEventListener *aListener, 
     374                 :                                                   const nsAString& aType,
     375                 :                                                   PRInt32 aFlags)
     376                 : {
     377              58 :   nsCOMPtr<nsIAtom> atom = do_GetAtom(NS_LITERAL_STRING("on") + aType);
     378              29 :   PRUint32 type = nsContentUtils::GetEventId(atom);
     379              29 :   RemoveEventListener(aListener, type, atom, aFlags);
     380              29 : }
     381                 : 
     382                 : nsListenerStruct*
     383               0 : nsEventListenerManager::FindJSEventListener(PRUint32 aEventType,
     384                 :                                             nsIAtom* aTypeAtom)
     385                 : {
     386                 :   // Run through the listeners for this type and see if a script
     387                 :   // listener is registered
     388                 :   nsListenerStruct *ls;
     389               0 :   PRUint32 count = mListeners.Length();
     390               0 :   for (PRUint32 i = 0; i < count; ++i) {
     391               0 :     ls = &mListeners.ElementAt(i);
     392               0 :     if (EVENT_TYPE_EQUALS(ls, aEventType, aTypeAtom) &&
     393                 :         ls->mFlags & NS_PRIV_EVENT_FLAG_SCRIPT) {
     394               0 :       return ls;
     395                 :     }
     396                 :   }
     397               0 :   return nsnull;
     398                 : }
     399                 : 
     400                 : nsresult
     401               0 : nsEventListenerManager::SetJSEventListener(nsIScriptContext *aContext,
     402                 :                                            JSObject* aScopeObject,
     403                 :                                            nsIAtom* aName,
     404                 :                                            JSObject *aHandler,
     405                 :                                            bool aPermitUntrustedEvents,
     406                 :                                            nsListenerStruct **aListenerStruct)
     407                 : {
     408               0 :   nsresult rv = NS_OK;
     409               0 :   PRUint32 eventType = nsContentUtils::GetEventId(aName);
     410               0 :   nsListenerStruct* ls = FindJSEventListener(eventType, aName);
     411                 : 
     412               0 :   if (!ls) {
     413                 :     // If we didn't find a script listener or no listeners existed
     414                 :     // create and add a new one.
     415               0 :     nsCOMPtr<nsIJSEventListener> scriptListener;
     416                 :     rv = NS_NewJSEventListener(aContext, aScopeObject, mTarget, aName,
     417               0 :                                aHandler, getter_AddRefs(scriptListener));
     418               0 :     if (NS_SUCCEEDED(rv)) {
     419                 :       AddEventListener(scriptListener, eventType, aName,
     420               0 :                        NS_EVENT_FLAG_BUBBLE | NS_PRIV_EVENT_FLAG_SCRIPT);
     421                 : 
     422               0 :       ls = FindJSEventListener(eventType, aName);
     423                 :     }
     424                 :   } else {
     425               0 :     ls->GetJSListener()->SetHandler(aHandler);
     426                 :   }
     427                 : 
     428               0 :   if (NS_SUCCEEDED(rv) && ls) {
     429                 :     // Set flag to indicate possible need for compilation later
     430               0 :     ls->mHandlerIsString = !aHandler;
     431               0 :     if (aPermitUntrustedEvents) {
     432               0 :       ls->mFlags |= NS_PRIV_EVENT_UNTRUSTED_PERMITTED;
     433                 :     }
     434                 : 
     435               0 :     *aListenerStruct = ls;
     436                 :   } else {
     437               0 :     *aListenerStruct = nsnull;
     438                 :   }
     439                 : 
     440               0 :   return rv;
     441                 : }
     442                 : 
     443                 : nsresult
     444               0 : nsEventListenerManager::AddScriptEventListener(nsIAtom *aName,
     445                 :                                                const nsAString& aBody,
     446                 :                                                PRUint32 aLanguage,
     447                 :                                                bool aDeferCompilation,
     448                 :                                                bool aPermitUntrustedEvents)
     449                 : {
     450               0 :   NS_PRECONDITION(aLanguage != nsIProgrammingLanguage::UNKNOWN,
     451                 :                   "Must know the language for the script event listener");
     452                 : 
     453                 :   // |aPermitUntrustedEvents| is set to False for chrome - events
     454                 :   // *generated* from an unknown source are not allowed.
     455                 :   // However, for script languages with no 'sandbox', we want to reject
     456                 :   // such scripts based on the source of their code, not just the source
     457                 :   // of the event.
     458               0 :   if (aPermitUntrustedEvents && 
     459                 :       aLanguage != nsIProgrammingLanguage::JAVASCRIPT) {
     460               0 :     NS_WARNING("Discarding non-JS event listener from untrusted source");
     461               0 :     return NS_ERROR_FAILURE;
     462                 :   }
     463                 : 
     464               0 :   nsCOMPtr<nsINode> node(do_QueryInterface(mTarget));
     465                 : 
     466               0 :   nsCOMPtr<nsIDocument> doc;
     467                 : 
     468               0 :   nsCOMPtr<nsIScriptGlobalObject> global;
     469                 : 
     470               0 :   if (node) {
     471                 :     // Try to get context from doc
     472                 :     // XXX sXBL/XBL2 issue -- do we really want the owner here?  What
     473                 :     // if that's the XBL document?
     474               0 :     doc = node->OwnerDoc();
     475               0 :     global = doc->GetScriptGlobalObject();
     476                 :   } else {
     477               0 :     nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(mTarget));
     478               0 :     if (win) {
     479               0 :       NS_ASSERTION(win->IsInnerWindow(),
     480                 :                    "Event listener added to outer window!");
     481                 : 
     482               0 :       nsCOMPtr<nsIDOMDocument> domdoc;
     483               0 :       win->GetDocument(getter_AddRefs(domdoc));
     484               0 :       doc = do_QueryInterface(domdoc);
     485               0 :       global = do_QueryInterface(win);
     486                 :     } else {
     487               0 :       global = do_QueryInterface(mTarget);
     488                 :     }
     489                 :   }
     490                 : 
     491               0 :   if (!global) {
     492                 :     // This can happen; for example this document might have been
     493                 :     // loaded as data.
     494               0 :     return NS_OK;
     495                 :   }
     496                 : 
     497               0 :   nsresult rv = NS_OK;
     498                 :   // return early preventing the event listener from being added
     499                 :   // 'doc' is fetched above
     500               0 :   if (doc) {
     501               0 :     nsCOMPtr<nsIContentSecurityPolicy> csp;
     502               0 :     rv = doc->NodePrincipal()->GetCsp(getter_AddRefs(csp));
     503               0 :     NS_ENSURE_SUCCESS(rv, rv);
     504                 : 
     505               0 :     if (csp) {
     506                 :       bool inlineOK;
     507               0 :       rv = csp->GetAllowsInlineScript(&inlineOK);
     508               0 :       NS_ENSURE_SUCCESS(rv, rv);
     509                 : 
     510               0 :       if ( !inlineOK ) {
     511                 :         // gather information to log with violation report
     512               0 :         nsIURI* uri = doc->GetDocumentURI();
     513               0 :         nsCAutoString asciiSpec;
     514               0 :         if (uri)
     515               0 :           uri->GetAsciiSpec(asciiSpec);
     516               0 :         nsAutoString scriptSample, attr, tagName(NS_LITERAL_STRING("UNKNOWN"));
     517               0 :         aName->ToString(attr);
     518               0 :         nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(mTarget));
     519               0 :         if (domNode)
     520               0 :           domNode->GetNodeName(tagName);
     521                 :         // build a "script sample" based on what we know about this element
     522               0 :         scriptSample.Assign(attr);
     523               0 :         scriptSample.AppendLiteral(" attribute on ");
     524               0 :         scriptSample.Append(tagName);
     525               0 :         scriptSample.AppendLiteral(" element");
     526               0 :         csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_INLINE_SCRIPT,
     527               0 :                                  NS_ConvertUTF8toUTF16(asciiSpec),
     528                 :                                  scriptSample,
     529               0 :                                  nsnull);
     530               0 :         return NS_OK;
     531                 :       }
     532                 :     }
     533                 :   }
     534                 : 
     535                 :   // This might be the first reference to this language in the global
     536                 :   // We must init the language before we attempt to fetch its context.
     537               0 :   if (NS_FAILED(global->EnsureScriptEnvironment(aLanguage))) {
     538               0 :     NS_WARNING("Failed to setup script environment for this language");
     539                 :     // but fall through and let the inevitable failure below handle it.
     540                 :   }
     541                 : 
     542               0 :   nsIScriptContext* context = global->GetScriptContext(aLanguage);
     543               0 :   NS_ENSURE_TRUE(context, NS_ERROR_FAILURE);
     544                 : 
     545               0 :   JSObject* scope = global->GetGlobalJSObject();
     546                 : 
     547                 :   nsListenerStruct *ls;
     548                 :   rv = SetJSEventListener(context, scope, aName, nsnull,
     549               0 :                           aPermitUntrustedEvents, &ls);
     550               0 :   NS_ENSURE_SUCCESS(rv, rv);
     551                 : 
     552               0 :   if (!aDeferCompilation) {
     553               0 :     return CompileEventHandlerInternal(ls, true, &aBody);
     554                 :   }
     555                 : 
     556               0 :   return NS_OK;
     557                 : }
     558                 : 
     559                 : void
     560               0 : nsEventListenerManager::RemoveScriptEventListener(nsIAtom* aName)
     561                 : {
     562               0 :   PRUint32 eventType = nsContentUtils::GetEventId(aName);
     563               0 :   nsListenerStruct* ls = FindJSEventListener(eventType, aName);
     564                 : 
     565               0 :   if (ls) {
     566               0 :     mListeners.RemoveElementAt(PRUint32(ls - &mListeners.ElementAt(0)));
     567               0 :     mNoListenerForEvent = NS_EVENT_TYPE_NULL;
     568               0 :     mNoListenerForEventAtom = nsnull;
     569                 :   }
     570               0 : }
     571                 : 
     572                 : nsresult
     573               0 : nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerStruct,
     574                 :                                                     bool aNeedsCxPush,
     575                 :                                                     const nsAString* aBody)
     576                 : {
     577               0 :   NS_PRECONDITION(aListenerStruct->GetJSListener(),
     578                 :                   "Why do we not have a JS listener?");
     579               0 :   NS_PRECONDITION(aListenerStruct->mHandlerIsString,
     580                 :                   "Why are we compiling a non-string JS listener?");
     581                 : 
     582               0 :   nsresult result = NS_OK;
     583                 : 
     584               0 :   nsIJSEventListener *listener = aListenerStruct->GetJSListener();
     585               0 :   NS_ASSERTION(!listener->GetHandler(), "What is there to compile?");
     586                 : 
     587               0 :   nsIScriptContext *context = listener->GetEventContext();
     588                 :   nsCOMPtr<nsIScriptEventHandlerOwner> handlerOwner =
     589               0 :     do_QueryInterface(mTarget);
     590               0 :   nsScriptObjectHolder<JSObject> handler(context);
     591                 : 
     592               0 :   if (handlerOwner) {
     593               0 :     result = handlerOwner->GetCompiledEventHandler(aListenerStruct->mTypeAtom,
     594               0 :                                                    handler);
     595               0 :     if (NS_SUCCEEDED(result) && handler) {
     596               0 :       aListenerStruct->mHandlerIsString = false;
     597                 :     } else {
     598                 :       // Make sure there's nothing in the holder in the failure case
     599               0 :       handler.set(nsnull);
     600                 :     }
     601                 :   }
     602                 : 
     603               0 :   if (aListenerStruct->mHandlerIsString) {
     604                 :     // OK, we didn't find an existing compiled event handler.  Flag us
     605                 :     // as not a string so we don't keep trying to compile strings
     606                 :     // which can't be compiled
     607               0 :     aListenerStruct->mHandlerIsString = false;
     608                 : 
     609                 :     // mTarget may not be an nsIContent if it's a window and we're
     610                 :     // getting an inline event listener forwarded from <html:body> or
     611                 :     // <html:frameset> or <xul:window> or the like.
     612                 :     // XXX I don't like that we have to reference content from
     613                 :     // here. The alternative is to store the event handler string on
     614                 :     // the nsIJSEventListener itself, and that still doesn't address
     615                 :     // the arg names issue.
     616               0 :     nsCOMPtr<nsIContent> content = do_QueryInterface(mTarget);
     617               0 :     nsAutoString handlerBody;
     618               0 :     const nsAString* body = aBody;
     619               0 :     if (content && !aBody) {
     620               0 :       nsIAtom* attrName = aListenerStruct->mTypeAtom;
     621               0 :       if (aListenerStruct->mTypeAtom == nsGkAtoms::onSVGLoad)
     622               0 :         attrName = nsGkAtoms::onload;
     623               0 :       else if (aListenerStruct->mTypeAtom == nsGkAtoms::onSVGUnload)
     624               0 :         attrName = nsGkAtoms::onunload;
     625               0 :       else if (aListenerStruct->mTypeAtom == nsGkAtoms::onSVGAbort)
     626               0 :         attrName = nsGkAtoms::onabort;
     627               0 :       else if (aListenerStruct->mTypeAtom == nsGkAtoms::onSVGError)
     628               0 :         attrName = nsGkAtoms::onerror;
     629               0 :       else if (aListenerStruct->mTypeAtom == nsGkAtoms::onSVGResize)
     630               0 :         attrName = nsGkAtoms::onresize;
     631               0 :       else if (aListenerStruct->mTypeAtom == nsGkAtoms::onSVGScroll)
     632               0 :         attrName = nsGkAtoms::onscroll;
     633               0 :       else if (aListenerStruct->mTypeAtom == nsGkAtoms::onSVGZoom)
     634               0 :         attrName = nsGkAtoms::onzoom;
     635               0 :       else if (aListenerStruct->mTypeAtom == nsGkAtoms::onbeginEvent)
     636               0 :         attrName = nsGkAtoms::onbegin;
     637               0 :       else if (aListenerStruct->mTypeAtom == nsGkAtoms::onrepeatEvent)
     638               0 :         attrName = nsGkAtoms::onrepeat;
     639               0 :       else if (aListenerStruct->mTypeAtom == nsGkAtoms::onendEvent)
     640               0 :         attrName = nsGkAtoms::onend;
     641                 : 
     642               0 :       content->GetAttr(kNameSpaceID_None, attrName, handlerBody);
     643               0 :       body = &handlerBody;
     644                 :     }
     645                 : 
     646               0 :     PRUint32 lineNo = 0;
     647               0 :     nsCAutoString url (NS_LITERAL_CSTRING("-moz-evil:lying-event-listener"));
     648               0 :     nsCOMPtr<nsIDocument> doc;
     649               0 :     if (content) {
     650               0 :       doc = content->OwnerDoc();
     651                 :     } else {
     652               0 :       nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mTarget);
     653               0 :       if (win) {
     654               0 :         doc = do_QueryInterface(win->GetExtantDocument());
     655                 :       }
     656                 :     }
     657                 : 
     658               0 :     if (doc) {
     659               0 :       nsIURI *uri = doc->GetDocumentURI();
     660               0 :       if (uri) {
     661               0 :         uri->GetSpec(url);
     662               0 :         lineNo = 1;
     663                 :       }
     664                 :     }
     665                 : 
     666               0 :     nsCxPusher pusher;
     667               0 :     if (aNeedsCxPush && !pusher.Push(context->GetNativeContext())) {
     668               0 :       return NS_ERROR_FAILURE;
     669                 :     }
     670                 : 
     671                 : 
     672               0 :     if (handlerOwner) {
     673                 :       // Always let the handler owner compile the event
     674                 :       // handler, as it may want to use a special
     675                 :       // context or scope object.
     676               0 :       result = handlerOwner->CompileEventHandler(context,
     677                 :                                                  aListenerStruct->mTypeAtom,
     678                 :                                                  *body,
     679                 :                                                  url.get(), lineNo,
     680               0 :                                                  handler);
     681                 :     } else {
     682                 :       PRUint32 argCount;
     683                 :       const char **argNames;
     684                 :       // If no content, then just use kNameSpaceID_None for the
     685                 :       // namespace ID.  In practice, it doesn't matter since SVG is
     686                 :       // the only thing with weird arg names and SVG doesn't map event
     687                 :       // listeners to the window.
     688                 :       nsContentUtils::GetEventArgNames(content ?
     689               0 :                                          content->GetNameSpaceID() :
     690               0 :                                          kNameSpaceID_None,
     691                 :                                        aListenerStruct->mTypeAtom,
     692               0 :                                        &argCount, &argNames);
     693                 : 
     694                 :       result = context->CompileEventHandler(aListenerStruct->mTypeAtom,
     695                 :                                             argCount, argNames,
     696                 :                                             *body,
     697                 :                                             url.get(), lineNo,
     698                 :                                             SCRIPTVERSION_DEFAULT, // for now?
     699               0 :                                             handler);
     700               0 :       if (result == NS_ERROR_ILLEGAL_VALUE) {
     701               0 :         NS_WARNING("Probably a syntax error in the event handler!");
     702               0 :         return NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA;
     703                 :       }
     704               0 :       NS_ENSURE_SUCCESS(result, result);
     705                 :     }
     706                 :   }
     707                 : 
     708               0 :   if (handler) {
     709                 :     // Bind it
     710               0 :     nsScriptObjectHolder<JSObject> boundHandler(context);
     711                 :     context->BindCompiledEventHandler(mTarget, listener->GetEventScope(),
     712               0 :                                       handler.get(), boundHandler);
     713               0 :     listener->SetHandler(boundHandler.get());
     714                 :   }
     715                 : 
     716               0 :   return result;
     717                 : }
     718                 : 
     719                 : nsresult
     720            3972 : nsEventListenerManager::HandleEventSubType(nsListenerStruct* aListenerStruct,
     721                 :                                            nsIDOMEventListener* aListener,
     722                 :                                            nsIDOMEvent* aDOMEvent,
     723                 :                                            nsIDOMEventTarget* aCurrentTarget,
     724                 :                                            PRUint32 aPhaseFlags,
     725                 :                                            nsCxPusher* aPusher)
     726                 : {
     727            3972 :   nsresult result = NS_OK;
     728                 : 
     729                 :   // If this is a script handler and we haven't yet
     730                 :   // compiled the event handler itself
     731            3972 :   if ((aListenerStruct->mFlags & NS_PRIV_EVENT_FLAG_SCRIPT) &&
     732                 :       aListenerStruct->mHandlerIsString) {
     733               0 :     nsIJSEventListener *jslistener = aListenerStruct->GetJSListener();
     734                 :     result = CompileEventHandlerInternal(aListenerStruct,
     735               0 :                                          jslistener->GetEventContext() !=
     736               0 :                                            aPusher->GetCurrentScriptContext(),
     737               0 :                                          nsnull);
     738                 :   }
     739                 : 
     740            3972 :   if (NS_SUCCEEDED(result)) {
     741                 :     // nsIDOMEvent::currentTarget is set in nsEventDispatcher.
     742            3972 :     result = aListener->HandleEvent(aDOMEvent);
     743                 :   }
     744                 : 
     745            3972 :   return result;
     746                 : }
     747                 : 
     748                 : /**
     749                 : * Causes a check for event listeners and processing by them if they exist.
     750                 : * @param an event listener
     751                 : */
     752                 : 
     753                 : void
     754            8232 : nsEventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
     755                 :                                             nsEvent* aEvent,
     756                 :                                             nsIDOMEvent** aDOMEvent,
     757                 :                                             nsIDOMEventTarget* aCurrentTarget,
     758                 :                                             PRUint32 aFlags,
     759                 :                                             nsEventStatus* aEventStatus,
     760                 :                                             nsCxPusher* aPusher)
     761                 : {
     762           16464 :   SAMPLE_LABEL("nsEventListenerManager", "HandleEventInternal");
     763                 :   //Set the value of the internal PreventDefault flag properly based on aEventStatus
     764            8232 :   if (*aEventStatus == nsEventStatus_eConsumeNoDefault) {
     765               7 :     aEvent->flags |= NS_EVENT_FLAG_NO_DEFAULT;
     766                 :   }
     767                 : 
     768           16464 :   nsAutoTObserverArray<nsListenerStruct, 2>::EndLimitedIterator iter(mListeners);
     769           16464 :   nsAutoPopupStatePusher popupStatePusher(nsDOMEvent::GetEventPopupControlState(aEvent));
     770            8232 :   bool hasListener = false;
     771           30536 :   while (iter.HasMore()) {
     772           14072 :     if (aEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH_IMMEDIATELY) {
     773               0 :       break;
     774                 :     }
     775           14072 :     nsListenerStruct* ls = &iter.GetNext();
     776                 :     // Check that the phase is same in event and event listener.
     777                 :     // Handle only trusted events, except when listener permits untrusted events.
     778           14072 :     if (ListenerCanHandle(ls, aEvent)) {
     779            3974 :       hasListener = true;
     780                 :       // XXX The (mFlags & aFlags) test here seems fragile. Shouldn't we
     781                 :       // specifically only test the capture/bubble flags.
     782            3974 :       if ((ls->mFlags & aFlags & ~NS_EVENT_FLAG_SYSTEM_EVENT) &&
     783                 :           (ls->mFlags & NS_EVENT_FLAG_SYSTEM_EVENT) ==
     784                 :           (aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) &&
     785                 :           (NS_IS_TRUSTED_EVENT(aEvent) ||
     786                 :            ls->mFlags & NS_PRIV_EVENT_UNTRUSTED_PERMITTED)) {
     787            3972 :         if (!*aDOMEvent) {
     788                 :           nsEventDispatcher::CreateEvent(aPresContext, aEvent,
     789               0 :                                          EmptyString(), aDOMEvent);
     790                 :         }
     791            3972 :         if (*aDOMEvent) {
     792            3972 :           if (!aEvent->currentTarget) {
     793            3972 :             aEvent->currentTarget = aCurrentTarget->GetTargetForDOMEvent();
     794            3972 :             if (!aEvent->currentTarget) {
     795               0 :               break;
     796                 :             }
     797                 :           }
     798            7944 :           nsRefPtr<nsIDOMEventListener> kungFuDeathGrip = ls->mListener;
     799            3972 :           if (aPusher->RePush(aCurrentTarget)) {
     800            3972 :             if (NS_FAILED(HandleEventSubType(ls, ls->mListener, *aDOMEvent,
     801                 :                                              aCurrentTarget, aFlags,
     802                 :                                              aPusher))) {
     803               9 :               aEvent->flags |= NS_EVENT_FLAG_EXCEPTION_THROWN;
     804                 :             }
     805                 :           }
     806                 :         }
     807                 :       }
     808                 :     }
     809                 :   }
     810                 : 
     811            8232 :   aEvent->currentTarget = nsnull;
     812                 : 
     813            8232 :   if (!hasListener) {
     814            4258 :     mNoListenerForEvent = aEvent->message;
     815            4258 :     mNoListenerForEventAtom = aEvent->userType;
     816                 :   }
     817                 : 
     818            8232 :   if (aEvent->flags & NS_EVENT_FLAG_NO_DEFAULT) {
     819              38 :     *aEventStatus = nsEventStatus_eConsumeNoDefault;
     820                 :   }
     821            8232 : }
     822                 : 
     823                 : void
     824            3168 : nsEventListenerManager::Disconnect()
     825                 : {
     826            3168 :   mTarget = nsnull;
     827            3168 :   RemoveAllListeners();
     828            3168 : }
     829                 : 
     830                 : void
     831            4584 : nsEventListenerManager::AddEventListener(const nsAString& aType,
     832                 :                                          nsIDOMEventListener* aListener,
     833                 :                                          bool aUseCapture,
     834                 :                                          bool aWantsUntrusted)
     835                 : {
     836            4584 :   PRInt32 flags = aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE;
     837                 : 
     838            4584 :   if (aWantsUntrusted) {
     839               2 :     flags |= NS_PRIV_EVENT_UNTRUSTED_PERMITTED;
     840                 :   }
     841                 : 
     842            4584 :   return AddEventListenerByType(aListener, aType, flags);
     843                 : }
     844                 : 
     845                 : void
     846              29 : nsEventListenerManager::RemoveEventListener(const nsAString& aType, 
     847                 :                                             nsIDOMEventListener* aListener, 
     848                 :                                             bool aUseCapture)
     849                 : {
     850              29 :   PRInt32 flags = aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE;
     851                 :   
     852              29 :   RemoveEventListenerByType(aListener, aType, flags);
     853              29 : }
     854                 : 
     855                 : bool
     856               2 : nsEventListenerManager::HasMutationListeners()
     857                 : {
     858               2 :   if (mMayHaveMutationListeners) {
     859               2 :     PRUint32 count = mListeners.Length();
     860               2 :     for (PRUint32 i = 0; i < count; ++i) {
     861               2 :       nsListenerStruct* ls = &mListeners.ElementAt(i);
     862               2 :       if (ls->mEventType >= NS_MUTATION_START &&
     863                 :           ls->mEventType <= NS_MUTATION_END) {
     864               2 :         return true;
     865                 :       }
     866                 :     }
     867                 :   }
     868                 : 
     869               0 :   return false;
     870                 : }
     871                 : 
     872                 : PRUint32
     873               0 : nsEventListenerManager::MutationListenerBits()
     874                 : {
     875               0 :   PRUint32 bits = 0;
     876               0 :   if (mMayHaveMutationListeners) {
     877               0 :     PRUint32 count = mListeners.Length();
     878               0 :     for (PRUint32 i = 0; i < count; ++i) {
     879               0 :       nsListenerStruct* ls = &mListeners.ElementAt(i);
     880               0 :       if (ls->mEventType >= NS_MUTATION_START &&
     881                 :           ls->mEventType <= NS_MUTATION_END) {
     882               0 :         if (ls->mEventType == NS_MUTATION_SUBTREEMODIFIED) {
     883               0 :           return kAllMutationBits;
     884                 :         }
     885               0 :         bits |= MutationBitForEventType(ls->mEventType);
     886                 :       }
     887                 :     }
     888                 :   }
     889               0 :   return bits;
     890                 : }
     891                 : 
     892                 : bool
     893            1609 : nsEventListenerManager::HasListenersFor(const nsAString& aEventName)
     894                 : {
     895            3218 :   nsCOMPtr<nsIAtom> atom = do_GetAtom(NS_LITERAL_STRING("on") + aEventName);
     896                 : 
     897            1609 :   PRUint32 count = mListeners.Length();
     898            4803 :   for (PRUint32 i = 0; i < count; ++i) {
     899            3194 :     nsListenerStruct* ls = &mListeners.ElementAt(i);
     900            3194 :     if (ls->mTypeAtom == atom) {
     901               0 :       return true;
     902                 :     }
     903                 :   }
     904            1609 :   return false;
     905                 : }
     906                 : 
     907                 : bool
     908               0 : nsEventListenerManager::HasListeners()
     909                 : {
     910               0 :   return !mListeners.IsEmpty();
     911                 : }
     912                 : 
     913                 : nsresult
     914               0 : nsEventListenerManager::GetListenerInfo(nsCOMArray<nsIEventListenerInfo>* aList)
     915                 : {
     916               0 :   nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mTarget);
     917               0 :   NS_ENSURE_STATE(target);
     918               0 :   aList->Clear();
     919               0 :   PRUint32 count = mListeners.Length();
     920               0 :   for (PRUint32 i = 0; i < count; ++i) {
     921               0 :     const nsListenerStruct& ls = mListeners.ElementAt(i);
     922               0 :     bool capturing = !!(ls.mFlags & NS_EVENT_FLAG_CAPTURE);
     923               0 :     bool systemGroup = !!(ls.mFlags & NS_EVENT_FLAG_SYSTEM_EVENT);
     924               0 :     bool allowsUntrusted = !!(ls.mFlags & NS_PRIV_EVENT_UNTRUSTED_PERMITTED);
     925                 :     // If this is a script handler and we haven't yet
     926                 :     // compiled the event handler itself go ahead and compile it
     927               0 :     if ((ls.mFlags & NS_PRIV_EVENT_FLAG_SCRIPT) && ls.mHandlerIsString) {
     928                 :       CompileEventHandlerInternal(const_cast<nsListenerStruct*>(&ls),
     929               0 :                                   true, nsnull);
     930                 :     }
     931                 :     const nsDependentSubstring& eventType =
     932               0 :       Substring(nsDependentAtomString(ls.mTypeAtom), 2);
     933                 :     nsRefPtr<nsEventListenerInfo> info =
     934                 :       new nsEventListenerInfo(eventType, ls.mListener, capturing,
     935               0 :                               allowsUntrusted, systemGroup);
     936               0 :     NS_ENSURE_TRUE(info, NS_ERROR_OUT_OF_MEMORY);
     937               0 :     aList->AppendObject(info);
     938                 :   }
     939               0 :   return NS_OK;
     940                 : }
     941                 : 
     942                 : bool
     943               0 : nsEventListenerManager::HasUnloadListeners()
     944                 : {
     945               0 :   PRUint32 count = mListeners.Length();
     946               0 :   for (PRUint32 i = 0; i < count; ++i) {
     947               0 :     nsListenerStruct* ls = &mListeners.ElementAt(i);
     948               0 :     if (ls->mEventType == NS_PAGE_UNLOAD ||
     949                 :         ls->mEventType == NS_BEFORE_PAGE_UNLOAD) {
     950               0 :       return true;
     951                 :     }
     952                 :   }
     953               0 :   return false;
     954                 : }
     955                 : 
     956                 : nsresult
     957               0 : nsEventListenerManager::SetJSEventListenerToJsval(nsIAtom *aEventName,
     958                 :                                                   JSContext *cx,
     959                 :                                                   JSObject* aScope,
     960                 :                                                   const jsval & v)
     961                 : {
     962                 :   JSObject *handler;
     963               0 :   if (JSVAL_IS_PRIMITIVE(v) ||
     964               0 :       !JS_ObjectIsCallable(cx, handler = JSVAL_TO_OBJECT(v))) {
     965               0 :     RemoveScriptEventListener(aEventName);
     966               0 :     return NS_OK;
     967                 :   }
     968                 : 
     969                 :   // We might not have a script context, e.g. if we're setting a listener
     970                 :   // on a dead Window.
     971               0 :   nsIScriptContext *context = nsJSUtils::GetStaticScriptContext(cx, aScope);
     972               0 :   NS_ENSURE_TRUE(context, NS_ERROR_FAILURE);
     973                 : 
     974               0 :   JSObject *scope = ::JS_GetGlobalForObject(cx, aScope);
     975                 :   // Untrusted events are always permitted for non-chrome script
     976                 :   // handlers.
     977                 :   nsListenerStruct *ignored;
     978                 :   return SetJSEventListener(context, scope, aEventName, handler,
     979               0 :                             !nsContentUtils::IsCallerChrome(), &ignored);
     980                 : }
     981                 : 
     982                 : void
     983               0 : nsEventListenerManager::GetJSEventListener(nsIAtom *aEventName, jsval *vp)
     984                 : {
     985               0 :   PRUint32 eventType = nsContentUtils::GetEventId(aEventName);
     986               0 :   nsListenerStruct* ls = FindJSEventListener(eventType, aEventName);
     987                 : 
     988               0 :   *vp = JSVAL_NULL;
     989                 : 
     990               0 :   if (!ls) {
     991               0 :     return;
     992                 :   }
     993                 : 
     994               0 :   nsIJSEventListener *listener = ls->GetJSListener();
     995               0 :   if (listener->GetEventContext()->GetScriptTypeID() !=
     996                 :         nsIProgrammingLanguage::JAVASCRIPT) {
     997                 :     // Not JS, so no point doing anything with it.
     998               0 :     return;
     999                 :   }
    1000                 :     
    1001               0 :   if (ls->mHandlerIsString) {
    1002               0 :     CompileEventHandlerInternal(ls, true, nsnull);
    1003                 :   }
    1004                 : 
    1005               0 :   *vp = OBJECT_TO_JSVAL(listener->GetHandler());
    1006                 : }
    1007                 : 
    1008                 : size_t
    1009               0 : nsEventListenerManager::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf)
    1010                 :   const
    1011                 : {
    1012               0 :   size_t n = aMallocSizeOf(this);
    1013               0 :   n += mListeners.SizeOfExcludingThis(aMallocSizeOf);
    1014               0 :   PRUint32 count = mListeners.Length();
    1015               0 :   for (PRUint32 i = 0; i < count; ++i) {
    1016               0 :     nsIJSEventListener* jsl = mListeners.ElementAt(i).GetJSListener();
    1017               0 :     if (jsl) {
    1018               0 :       n += jsl->SizeOfIncludingThis(aMallocSizeOf);
    1019                 :     }
    1020                 :   }
    1021               0 :   return n;
    1022                 : }
    1023                 : 
    1024                 : void
    1025             187 : nsEventListenerManager::UnmarkGrayJSListeners()
    1026                 : {
    1027             187 :   PRUint32 count = mListeners.Length();
    1028             561 :   for (PRUint32 i = 0; i < count; ++i) {
    1029             374 :     const nsListenerStruct& ls = mListeners.ElementAt(i);
    1030             374 :     nsIJSEventListener* jsl = ls.GetJSListener();
    1031             374 :     if (jsl) {
    1032               0 :       xpc_UnmarkGrayObject(jsl->GetHandler());
    1033               0 :       xpc_UnmarkGrayObject(jsl->GetEventScope());
    1034             374 :     } else if (ls.mWrappedJS) {
    1035             748 :       nsCOMPtr<nsIXPConnectWrappedJS> wjs = do_QueryInterface(ls.mListener);
    1036             374 :       xpc_UnmarkGrayObject(wjs);
    1037                 :     }
    1038                 :   }
    1039            4579 : }

Generated by: LCOV version 1.7