LCOV - code coverage report
Current view: directory - content/events/src - nsDOMEventTargetHelper.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 154 113 73.4 %
Date: 2012-04-21 Functions: 37 31 83.8 %

       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
       6                 :  * Version 1.1 (the "License"); you may not use this file except in
       7                 :  * compliance with 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                 :  * Mozilla Corporation
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2009
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *  Olli Pettay <Olli.Pettay@helsinki.fi>
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #include "nsDOMEventTargetHelper.h"
      40                 : #include "nsContentUtils.h"
      41                 : #include "nsEventDispatcher.h"
      42                 : #include "nsGUIEvent.h"
      43                 : #include "nsIDocument.h"
      44                 : #include "nsIJSContextStack.h"
      45                 : #include "nsDOMJSUtils.h"
      46                 : #include "prprf.h"
      47                 : #include "nsGlobalWindow.h"
      48                 : 
      49            1396 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMEventListenerWrapper)
      50           35470 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMEventListenerWrapper)
      51            3865 :   NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
      52            3865 : NS_INTERFACE_MAP_END_AGGREGATED(mListener)
      53                 : 
      54           15560 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMEventListenerWrapper)
      55           19425 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMEventListenerWrapper)
      56                 : 
      57             353 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMEventListenerWrapper)
      58             353 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mListener)
      59             353 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
      60                 : 
      61            1040 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMEventListenerWrapper)
      62            1040 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mListener)
      63            1040 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
      64                 : 
      65                 : NS_IMETHODIMP
      66            3612 : nsDOMEventListenerWrapper::HandleEvent(nsIDOMEvent* aEvent)
      67                 : {
      68            3612 :   return mListener->HandleEvent(aEvent);
      69                 : }
      70                 : 
      71            1396 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMEventTargetHelper)
      72                 : 
      73            7341 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDOMEventTargetHelper)
      74            7341 :   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
      75            7341 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
      76                 : 
      77            1319 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDOMEventTargetHelper)
      78            1319 :   if (NS_UNLIKELY(cb.WantDebugInfo())) {
      79                 :     char name[512];
      80               0 :     nsAutoString uri;
      81               0 :     if (tmp->mOwner && tmp->mOwner->GetExtantDocument()) {
      82               0 :       tmp->mOwner->GetExtantDocument()->GetDocumentURI(uri);
      83                 :     }
      84                 :     PR_snprintf(name, sizeof(name), "nsDOMEventTargetHelper %s",
      85               0 :                 NS_ConvertUTF16toUTF8(uri).get());
      86                 :     cb.DescribeRefCountedNode(tmp->mRefCnt.get(), sizeof(nsDOMEventTargetHelper),
      87               0 :                               name);
      88                 :   } else {
      89            1319 :     NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsDOMEventTargetHelper, tmp->mRefCnt.get())
      90                 :   }
      91                 : 
      92            1319 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
      93            1319 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mListenerManager,
      94                 :                                                   nsEventListenerManager)
      95            1319 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
      96                 : 
      97             803 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMEventTargetHelper)
      98             803 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
      99             803 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mListenerManager)
     100             803 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     101                 : 
     102          161712 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMEventTargetHelper)
     103          124402 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
     104          107703 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
     105          103623 :   NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
     106           30447 : NS_INTERFACE_MAP_END
     107                 : 
     108          253893 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMEventTargetHelper)
     109          253893 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMEventTargetHelper)
     110                 : 
     111           36000 : NS_IMPL_DOMTARGET_DEFAULTS(nsDOMEventTargetHelper);
     112                 : 
     113            8070 : nsDOMEventTargetHelper::~nsDOMEventTargetHelper()
     114                 : {
     115            4035 :   if (mOwner) {
     116               0 :     static_cast<nsGlobalWindow*>(mOwner)->RemoveEventTargetObject(this);
     117                 :   }
     118            4035 :   if (mListenerManager) {
     119            3018 :     mListenerManager->Disconnect();
     120                 :   }
     121            4035 :   nsContentUtils::ReleaseWrapper(this, this);
     122            8070 : }
     123                 : 
     124                 : void
     125              76 : nsDOMEventTargetHelper::BindToOwner(nsPIDOMWindow* aOwner)
     126                 : {
     127              76 :   if (mOwner) {
     128               0 :     static_cast<nsGlobalWindow*>(mOwner)->RemoveEventTargetObject(this);
     129               0 :     mOwner = nsnull;
     130               0 :     mHasOrHasHadOwner = false;
     131                 :   }
     132              76 :   if (aOwner) {
     133               0 :     mOwner = aOwner;
     134               0 :     mHasOrHasHadOwner = true;
     135               0 :     static_cast<nsGlobalWindow*>(mOwner)->AddEventTargetObject(this);
     136                 :   }
     137              76 : }
     138                 : 
     139                 : void
     140            3362 : nsDOMEventTargetHelper::BindToOwner(nsDOMEventTargetHelper* aOther)
     141                 : {
     142            3362 :   if (mOwner) {
     143               0 :     static_cast<nsGlobalWindow*>(mOwner)->RemoveEventTargetObject(this);
     144               0 :     mOwner = nsnull;
     145               0 :     mHasOrHasHadOwner = false;
     146                 :   }
     147            3362 :   if (aOther) {
     148            3362 :     mHasOrHasHadOwner = aOther->HasOrHasHadOwner();
     149            3362 :     if (aOther->GetOwner()) {
     150               0 :       mOwner = aOther->GetOwner();
     151               0 :       mHasOrHasHadOwner = true;
     152               0 :       static_cast<nsGlobalWindow*>(mOwner)->AddEventTargetObject(this);
     153                 :     }
     154                 :   }
     155            3362 : }
     156                 : 
     157                 : void
     158               0 : nsDOMEventTargetHelper::DisconnectFromOwner()
     159                 : {
     160               0 :   mOwner = nsnull;
     161                 :   // Event listeners can't be handled anymore, so we can release them here.
     162               0 :   if (mListenerManager) {
     163               0 :     mListenerManager->Disconnect();
     164               0 :     mListenerManager = nsnull;
     165                 :   }
     166               0 : }
     167                 : 
     168                 : NS_IMETHODIMP
     169              29 : nsDOMEventTargetHelper::RemoveEventListener(const nsAString& aType,
     170                 :                                             nsIDOMEventListener* aListener,
     171                 :                                             bool aUseCapture)
     172                 : {
     173              29 :   nsEventListenerManager* elm = GetListenerManager(false);
     174              29 :   if (elm) {
     175              29 :     elm->RemoveEventListener(aType, aListener, aUseCapture);
     176                 :   }
     177                 : 
     178              29 :   return NS_OK;
     179                 : }
     180                 : 
     181               0 : NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(nsDOMEventTargetHelper)
     182                 : 
     183                 : NS_IMETHODIMP
     184            4940 : nsDOMEventTargetHelper::AddEventListener(const nsAString& aType,
     185                 :                                          nsIDOMEventListener *aListener,
     186                 :                                          bool aUseCapture,
     187                 :                                          bool aWantsUntrusted,
     188                 :                                          PRUint8 aOptionalArgc)
     189                 : {
     190            4940 :   NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
     191                 :                "Won't check if this is chrome, you want to set "
     192                 :                "aWantsUntrusted to false or make the aWantsUntrusted "
     193                 :                "explicit by making aOptionalArgc non-zero.");
     194                 : 
     195            4940 :   if (aOptionalArgc < 2) {
     196                 :     nsresult rv;
     197            4940 :     nsIScriptContext* context = GetContextForEventHandlers(&rv);
     198            4940 :     NS_ENSURE_SUCCESS(rv, rv);
     199                 :     nsCOMPtr<nsIDocument> doc =
     200            9880 :       nsContentUtils::GetDocumentFromScriptContext(context);
     201            4940 :     aWantsUntrusted = doc && !nsContentUtils::IsChromeDoc(doc);
     202                 :   }
     203                 : 
     204            4940 :   nsEventListenerManager* elm = GetListenerManager(true);
     205            4940 :   NS_ENSURE_STATE(elm);
     206            4940 :   elm->AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted);
     207            4940 :   return NS_OK;
     208                 : }
     209                 : 
     210                 : NS_IMETHODIMP
     211               0 : nsDOMEventTargetHelper::AddSystemEventListener(const nsAString& aType,
     212                 :                                                nsIDOMEventListener *aListener,
     213                 :                                                bool aUseCapture,
     214                 :                                                bool aWantsUntrusted,
     215                 :                                                PRUint8 aOptionalArgc)
     216                 : {
     217               0 :   NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
     218                 :                "Won't check if this is chrome, you want to set "
     219                 :                "aWantsUntrusted to false or make the aWantsUntrusted "
     220                 :                "explicit by making aOptionalArgc non-zero.");
     221                 : 
     222               0 :   if (aOptionalArgc < 2) {
     223                 :     nsresult rv;
     224               0 :     nsIScriptContext* context = GetContextForEventHandlers(&rv);
     225               0 :     NS_ENSURE_SUCCESS(rv, rv);
     226                 :     nsCOMPtr<nsIDocument> doc =
     227               0 :       nsContentUtils::GetDocumentFromScriptContext(context);
     228               0 :     aWantsUntrusted = doc && !nsContentUtils::IsChromeDoc(doc);
     229                 :   }
     230                 : 
     231                 :   return NS_AddSystemEventListener(this, aType, aListener, aUseCapture,
     232               0 :                                    aWantsUntrusted);
     233                 : }
     234                 : 
     235                 : NS_IMETHODIMP
     236            5217 : nsDOMEventTargetHelper::DispatchEvent(nsIDOMEvent* aEvent, bool* aRetVal)
     237                 : {
     238            5217 :   nsEventStatus status = nsEventStatus_eIgnore;
     239                 :   nsresult rv =
     240            5217 :     nsEventDispatcher::DispatchDOMEvent(this, nsnull, aEvent, nsnull, &status);
     241                 : 
     242            5217 :   *aRetVal = (status != nsEventStatus_eConsumeNoDefault);
     243            5217 :   return rv;
     244                 : }
     245                 : 
     246                 : nsresult
     247            3866 : nsDOMEventTargetHelper::RemoveAddEventListener(const nsAString& aType,
     248                 :                                                nsRefPtr<nsDOMEventListenerWrapper>& aCurrent,
     249                 :                                                nsIDOMEventListener* aNew)
     250                 : {
     251            3866 :   if (aCurrent) {
     252              27 :     RemoveEventListener(aType, aCurrent, false);
     253              27 :     aCurrent = nsnull;
     254                 :   }
     255            3866 :   if (aNew) {
     256            3865 :     aCurrent = new nsDOMEventListenerWrapper(aNew);
     257            3865 :     NS_ENSURE_TRUE(aCurrent, NS_ERROR_OUT_OF_MEMORY);
     258            3865 :     nsIDOMEventTarget::AddEventListener(aType, aCurrent, false);
     259                 :   }
     260            3866 :   return NS_OK;
     261                 : }
     262                 : 
     263                 : nsresult
     264               3 : nsDOMEventTargetHelper::GetInnerEventListener(nsRefPtr<nsDOMEventListenerWrapper>& aWrapper,
     265                 :                                               nsIDOMEventListener** aListener)
     266                 : {
     267               3 :   NS_ENSURE_ARG_POINTER(aListener);
     268               3 :   if (aWrapper) {
     269               0 :     NS_IF_ADDREF(*aListener = aWrapper->GetInner());
     270                 :   } else {
     271               3 :     *aListener = nsnull;
     272                 :   }
     273               3 :   return NS_OK;
     274                 : }
     275                 : 
     276                 : 
     277                 : nsresult
     278           10214 : nsDOMEventTargetHelper::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
     279                 : {
     280           10214 :   aVisitor.mCanHandle = true;
     281           10214 :   aVisitor.mParentTarget = nsnull;
     282           10214 :   return NS_OK;
     283                 : }
     284                 : 
     285                 : nsresult
     286           10317 : nsDOMEventTargetHelper::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
     287                 : {
     288           10317 :   return NS_OK;
     289                 : }
     290                 : 
     291                 : nsresult
     292            5074 : nsDOMEventTargetHelper::DispatchDOMEvent(nsEvent* aEvent,
     293                 :                                          nsIDOMEvent* aDOMEvent,
     294                 :                                          nsPresContext* aPresContext,
     295                 :                                          nsEventStatus* aEventStatus)
     296                 : {
     297                 :   return
     298                 :     nsEventDispatcher::DispatchDOMEvent(this, aEvent, aDOMEvent, aPresContext,
     299            5074 :                                         aEventStatus);
     300                 : }
     301                 : 
     302                 : nsEventListenerManager*
     303           34702 : nsDOMEventTargetHelper::GetListenerManager(bool aCreateIfNotFound)
     304                 : {
     305           34702 :   if (!mListenerManager && aCreateIfNotFound) {
     306            3347 :     mListenerManager = new nsEventListenerManager(this);
     307                 :   }
     308                 : 
     309           34702 :   return mListenerManager;
     310                 : }
     311                 : 
     312                 : nsIScriptContext*
     313           10664 : nsDOMEventTargetHelper::GetContextForEventHandlers(nsresult* aRv)
     314                 : {
     315           10664 :   *aRv = CheckInnerWindowCorrectness();
     316           10664 :   if (NS_FAILED(*aRv)) {
     317               0 :     return nsnull;
     318                 :   }
     319               0 :   return mOwner ? static_cast<nsGlobalWindow*>(mOwner)->GetContextInternal()
     320           10664 :                 : nsnull;
     321                 : }
     322                 : 
     323                 : void
     324               2 : nsDOMEventTargetHelper::Init(JSContext* aCx)
     325                 : {
     326               2 :   JSContext* cx = aCx;
     327               2 :   if (!cx) {
     328               2 :     nsIJSContextStack* stack = nsContentUtils::ThreadJSContextStack();
     329                 : 
     330               2 :     if (!stack)
     331               0 :       return;
     332                 : 
     333               2 :     if (NS_FAILED(stack->Peek(&cx)) || !cx)
     334               0 :       return;
     335                 :   }
     336                 : 
     337               2 :   NS_ASSERTION(cx, "Should have returned earlier ...");
     338               2 :   nsIScriptContext* context = GetScriptContextFromJSContext(cx);
     339               2 :   if (context) {
     340                 :     nsCOMPtr<nsPIDOMWindow> window =
     341               0 :       do_QueryInterface(context->GetGlobalObject());
     342               0 :     if (window) {
     343               0 :       BindToOwner(window->GetCurrentInnerWindow());
     344                 :     }
     345                 :   }
     346            4188 : }

Generated by: LCOV version 1.7