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

LCOV - code coverage report
| Current view: | directory - content/events/src - nsXMLEventsManager.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 191 | 0 | 0.0 %
| Date: | 2012-04-21 | Functions: | 29 | 0 | 0.0 %

           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.
          19                 :  * Portions created by the Initial Developer are Copyright (C) 2004
          20                 :  * the Initial Developer. All Rights Reserved.
          21                 :  *
          22                 :  * Contributor(s):
          23                 :  *   Olli Pettay <Olli.Pettay@helsinki.fi> (original author)
          24                 :  *
          25                 :  * Alternatively, the contents of this file may be used under the terms of
          26                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
          27                 :  * or 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 "nsIDOMMutationEvent.h"
          40                 : #include "nsXMLEventsManager.h"
          41                 : #include "nsGkAtoms.h"
          42                 : #include "nsIDOMElement.h"
          43                 : #include "nsIDOMDocument.h"
          44                 : #include "nsIDOMEventTarget.h"
          45                 : #include "nsNetUtil.h"
          46                 : #include "nsIURL.h"
          47                 : #include "nsIDOMEventListener.h"
          48                 : #include "nsINameSpaceManager.h"
          49                 : #include "nsINodeInfo.h"
          50                 : #include "mozilla/dom/Element.h"
          51                 :
          52                 : using namespace mozilla::dom;
          53                 :
          54               0 : bool nsXMLEventsListener::InitXMLEventsListener(nsIDocument * aDocument,
          55                 :                                                   nsXMLEventsManager * aManager,
          56                 :                                                   nsIContent * aContent)
          57                 : {
          58                 :   nsresult rv;
          59                 :   PRInt32 nameSpaceID;
          60               0 :   if (aContent->GetDocument() != aDocument)
          61               0 :     return false;
          62               0 :   if (aContent->NodeInfo()->Equals(nsGkAtoms::listener,
          63               0 :                                    kNameSpaceID_XMLEvents))
          64               0 :     nameSpaceID = kNameSpaceID_None;
          65                 :   else
          66               0 :     nameSpaceID = kNameSpaceID_XMLEvents;
          67               0 :   nsAutoString eventType;
          68               0 :   aContent->GetAttr(nameSpaceID, nsGkAtoms::event, eventType);
          69               0 :   if (eventType.IsEmpty())
          70               0 :     return false;
          71               0 :   nsAutoString handlerURIStr;
          72               0 :   bool hasHandlerURI = false;
          73               0 :   nsIContent *handler = nsnull;
          74               0 :   nsAutoString observerID;
          75               0 :   nsAutoString targetIdref;
          76                 :
          77               0 :   if (aContent->GetAttr(nameSpaceID, nsGkAtoms::handler, handlerURIStr)) {
          78               0 :     hasHandlerURI = true;
          79               0 :     nsCAutoString handlerRef;
          80               0 :     nsCOMPtr<nsIURI> handlerURI;
          81               0 :     bool equals = false;
          82               0 :     nsIURI *docURI = aDocument->GetDocumentURI();
          83               0 :     nsIURI *baseURI = aDocument->GetDocBaseURI();
          84               0 :     rv = NS_NewURI( getter_AddRefs(handlerURI), handlerURIStr, nsnull, baseURI);
          85               0 :     if (NS_SUCCEEDED(rv)) {
          86               0 :       handlerURI->GetRef(handlerRef);
          87                 :       // We support only XML Events Basic.
          88               0 :       rv = docURI->EqualsExceptRef(handlerURI, &equals);
          89               0 :       if (NS_SUCCEEDED(rv) && equals) {
          90               0 :         handler = aDocument->GetElementById(NS_ConvertUTF8toUTF16(handlerRef));
          91                 :       }
          92                 :     }
          93                 :   }
          94                 :   else
          95               0 :     handler = aContent;
          96               0 :   if (!handler)
          97               0 :     return false;
          98                 :
          99               0 :   aContent->GetAttr(nameSpaceID, nsGkAtoms::target, targetIdref);
         100                 :
         101                 :   bool hasObserver =
         102               0 :     aContent->GetAttr(nameSpaceID, nsGkAtoms::observer, observerID);
         103                 :
         104                 :   bool capture =
         105                 :     aContent->AttrValueIs(nameSpaceID, nsGkAtoms::phase,
         106               0 :                           nsGkAtoms::capture, eCaseMatters);
         107                 :
         108                 :   bool stopPropagation =
         109                 :     aContent->AttrValueIs(nameSpaceID, nsGkAtoms::propagate,
         110               0 :                           nsGkAtoms::stop, eCaseMatters);
         111                 :
         112                 :   bool cancelDefault =
         113                 :     aContent->AttrValueIs(nameSpaceID, nsGkAtoms::defaultAction,
         114               0 :                           nsGkAtoms::cancel, eCaseMatters);
         115                 :
         116               0 :   nsIContent *observer = nsnull;
         117               0 :   if (!hasObserver) {
         118               0 :     if (!hasHandlerURI) //Parent should be the observer
         119               0 :       observer = aContent->GetParent();
         120                 :     else //We have the handler, so this is the observer
         121               0 :       observer = aContent;
         122                 :   }
         123               0 :   else if (!observerID.IsEmpty()) {
         124               0 :     observer = aDocument->GetElementById(observerID);
         125                 :   }
         126               0 :   nsCOMPtr<nsIDOMEventTarget> eventObserver(do_QueryInterface(observer));
         127               0 :   if (eventObserver) {
         128                 :     nsXMLEventsListener * eli = new nsXMLEventsListener(aManager,
         129                 :                                                         aContent,
         130                 :                                                         observer,
         131                 :                                                         handler,
         132                 :                                                         eventType,
         133                 :                                                         capture,
         134                 :                                                         stopPropagation,
         135                 :                                                         cancelDefault,
         136               0 :                                                         targetIdref);
         137               0 :     if (eli) {
         138               0 :       nsresult rv = eventObserver->AddEventListener(eventType, eli, capture);
         139               0 :       if (NS_SUCCEEDED(rv)) {
         140               0 :         aManager->RemoveXMLEventsContent(aContent);
         141               0 :         aManager->RemoveListener(aContent);
         142               0 :         aManager->AddListener(aContent, eli);
         143               0 :         return true;
         144                 :       }
         145                 :       else
         146               0 :         delete eli;
         147                 :     }
         148                 :   }
         149               0 :   return false;
         150                 : }
         151                 :
         152               0 : nsXMLEventsListener::nsXMLEventsListener(nsXMLEventsManager * aManager,
         153                 :                                          nsIContent * aElement,
         154                 :                                          nsIContent * aObserver,
         155                 :                                          nsIContent * aHandler,
         156                 :                                          const nsAString& aEvent,
         157                 :                                          bool aPhase,
         158                 :                                          bool aStopPropagation,
         159                 :                                          bool aCancelDefault,
         160                 :                                          const nsAString& aTarget)
         161                 :  : mManager(aManager),
         162                 :    mElement(aElement),
         163                 :    mObserver(aObserver),
         164                 :    mHandler(aHandler),
         165                 :    mEvent(aEvent),
         166                 :    mPhase(aPhase),
         167                 :    mStopPropagation(aStopPropagation),
         168               0 :    mCancelDefault(aCancelDefault)
         169                 : {
         170               0 :   if (!aTarget.IsEmpty())
         171               0 :     mTarget = do_GetAtom(aTarget);
         172               0 : }
         173                 :
         174               0 : nsXMLEventsListener::~nsXMLEventsListener()
         175                 : {
         176               0 : }
         177                 :
         178               0 : void nsXMLEventsListener::Unregister()
         179                 : {
         180               0 :   nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mObserver);
         181               0 :   if (target) {
         182               0 :     target->RemoveEventListener(mEvent, this, mPhase);
         183                 :   }
         184               0 :   mObserver = nsnull;
         185               0 :   mHandler = nsnull;
         186               0 : }
         187                 :
         188               0 : void nsXMLEventsListener::SetIncomplete()
         189                 : {
         190               0 :   Unregister();
         191               0 :   mManager->AddXMLEventsContent(mElement);
         192               0 :   mElement = nsnull;
         193               0 : }
         194                 :
         195               0 : bool nsXMLEventsListener::ObserverEquals(nsIContent * aTarget)
         196                 : {
         197               0 :   return aTarget == mObserver;
         198                 : }
         199                 :
         200               0 : bool nsXMLEventsListener::HandlerEquals(nsIContent * aTarget)
         201                 : {
         202               0 :   return aTarget == mHandler;
         203                 : }
         204                 :
         205               0 : NS_IMPL_ISUPPORTS1(nsXMLEventsListener, nsIDOMEventListener)
         206                 : NS_IMETHODIMP
         207               0 : nsXMLEventsListener::HandleEvent(nsIDOMEvent* aEvent)
         208                 : {
         209               0 :   if (!aEvent)
         210               0 :     return NS_ERROR_INVALID_ARG;
         211               0 :   bool targetMatched = true;
         212               0 :   nsCOMPtr<nsIDOMEvent> event(aEvent);
         213               0 :   if (mTarget) {
         214               0 :     targetMatched = false;
         215               0 :     nsCOMPtr<nsIDOMEventTarget> target;
         216               0 :     aEvent->GetTarget(getter_AddRefs(target));
         217               0 :     nsCOMPtr<nsIContent> targetEl(do_QueryInterface(target));
         218               0 :     if (targetEl && targetEl->GetID() == mTarget)
         219               0 :         targetMatched = true;
         220                 :   }
         221               0 :   if (!targetMatched)
         222               0 :     return NS_OK;
         223               0 :   nsCOMPtr<nsIDOMEventListener> handler(do_QueryInterface(mHandler));
         224               0 :   if (handler) {
         225               0 :     nsresult rv = handler->HandleEvent(event);
         226               0 :     if (NS_SUCCEEDED(rv)) {
         227               0 :       if (mStopPropagation)
         228               0 :         event->StopPropagation();
         229               0 :       if (mCancelDefault)
         230               0 :         event->PreventDefault();
         231                 :     }
         232               0 :     return rv;
         233                 :   }
         234               0 :   return NS_OK;
         235                 : }
         236                 :
         237                 :
         238                 : //XMLEventsManager / DocumentObserver
         239                 :
         240               0 : static PLDHashOperator EnumAndUnregisterListener(nsISupports * aContent,
         241                 :                                                  nsCOMPtr<nsXMLEventsListener> & aListener,
         242                 :                                                  void * aData)
         243                 : {
         244               0 :   if (aListener)
         245               0 :     aListener->Unregister();
         246               0 :   return PL_DHASH_NEXT;
         247                 : }
         248                 :
         249               0 : static PLDHashOperator EnumAndSetIncomplete(nsISupports * aContent,
         250                 :                                             nsCOMPtr<nsXMLEventsListener> & aListener,
         251                 :                                             void * aData)
         252                 : {
         253               0 :   if (aListener && aData) {
         254               0 :     nsCOMPtr<nsIContent> content = static_cast<nsIContent *>(aData);
         255               0 :     if (content) {
         256               0 :       if (aListener->ObserverEquals(content) || aListener->HandlerEquals(content)) {
         257               0 :         aListener->SetIncomplete();
         258               0 :         return PL_DHASH_REMOVE;
         259                 :       }
         260                 :     }
         261                 :   }
         262               0 :   return PL_DHASH_NEXT;
         263                 : }
         264                 :
         265               0 : nsXMLEventsManager::nsXMLEventsManager()
         266                 : {
         267               0 :   mListeners.Init();
         268               0 : }
         269               0 : nsXMLEventsManager::~nsXMLEventsManager()
         270                 : {
         271               0 : }
         272                 :
         273               0 : NS_IMPL_ISUPPORTS2(nsXMLEventsManager, nsIDocumentObserver, nsIMutationObserver)
         274                 :
         275               0 : void nsXMLEventsManager::AddXMLEventsContent(nsIContent * aContent)
         276                 : {
         277               0 :   mIncomplete.RemoveObject(aContent);
         278               0 :   mIncomplete.AppendObject(aContent);
         279               0 : }
         280                 :
         281               0 : void nsXMLEventsManager::RemoveXMLEventsContent(nsIContent * aContent)
         282                 : {
         283               0 :   mIncomplete.RemoveObject(aContent);
         284               0 : }
         285                 :
         286               0 : void nsXMLEventsManager::AddListener(nsIContent * aContent,
         287                 :                                      nsXMLEventsListener * aListener)
         288                 : {
         289               0 :   mListeners.Put(aContent, aListener);
         290               0 : }
         291                 :
         292               0 : bool nsXMLEventsManager::RemoveListener(nsIContent * aContent)
         293                 : {
         294               0 :   nsCOMPtr<nsXMLEventsListener> listener;
         295               0 :   mListeners.Get(aContent, getter_AddRefs(listener));
         296               0 :   if (listener) {
         297               0 :     listener->Unregister();
         298               0 :     mListeners.Remove(aContent);
         299               0 :     return true;
         300                 :   }
         301               0 :   return false;
         302                 : }
         303                 :
         304               0 : void nsXMLEventsManager::AddListeners(nsIDocument* aDocument)
         305                 : {
         306               0 :   nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
         307                 :
         308                 :   nsIContent *cur;
         309               0 :   for (int i = 0; i < mIncomplete.Count(); ++i) {
         310               0 :     cur = mIncomplete[i];
         311                 :     //If this succeeds, the object will be removed from mIncomplete
         312               0 :     if (nsXMLEventsListener::InitXMLEventsListener(aDocument, this, cur))
         313               0 :       --i;
         314                 :   }
         315               0 : }
         316                 :
         317                 : void
         318               0 : nsXMLEventsManager::NodeWillBeDestroyed(const nsINode* aNode)
         319                 : {
         320               0 :   nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
         321               0 :   mIncomplete.Clear();
         322               0 :   mListeners.Enumerate(EnumAndUnregisterListener, this);
         323               0 :   mListeners.Clear();
         324               0 : }
         325                 :
         326                 : void
         327               0 : nsXMLEventsManager::EndLoad(nsIDocument* aDocument)
         328                 : {
         329               0 :   AddListeners(aDocument);
         330               0 : }
         331                 :
         332                 : void
         333               0 : nsXMLEventsManager::AttributeChanged(nsIDocument* aDocument,
         334                 :                                      Element* aElement,
         335                 :                                      PRInt32 aNameSpaceID,
         336                 :                                      nsIAtom* aAttribute,
         337                 :                                      PRInt32 aModType)
         338                 : {
         339               0 :   nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
         340                 :
         341               0 :   if (aNameSpaceID == kNameSpaceID_XMLEvents &&
         342                 :       (aAttribute == nsGkAtoms::event ||
         343                 :        aAttribute == nsGkAtoms::handler ||
         344                 :        aAttribute == nsGkAtoms::target ||
         345                 :        aAttribute == nsGkAtoms::observer ||
         346                 :        aAttribute == nsGkAtoms::phase ||
         347                 :        aAttribute == nsGkAtoms::propagate)) {
         348               0 :     RemoveListener(aElement);
         349               0 :     AddXMLEventsContent(aElement);
         350               0 :     nsXMLEventsListener::InitXMLEventsListener(aDocument, this, aElement);
         351                 :   }
         352                 :   else {
         353               0 :     if (aElement->NodeInfo()->Equals(nsGkAtoms::listener,
         354               0 :                                      kNameSpaceID_XMLEvents)) {
         355               0 :       RemoveListener(aElement);
         356               0 :       AddXMLEventsContent(aElement);
         357               0 :       nsXMLEventsListener::InitXMLEventsListener(aDocument, this, aElement);
         358                 :     }
         359               0 :     else if (aElement->GetIDAttributeName() == aAttribute) {
         360               0 :       if (aModType == nsIDOMMutationEvent::REMOVAL)
         361               0 :         mListeners.Enumerate(EnumAndSetIncomplete, aElement);
         362               0 :       else if (aModType == nsIDOMMutationEvent::MODIFICATION) {
         363                 :         //Remove possible listener
         364               0 :         mListeners.Enumerate(EnumAndSetIncomplete, aElement);
         365                 :         //Add new listeners
         366               0 :         AddListeners(aDocument);
         367                 :       }
         368                 :       else {
         369                 :         //If we are adding the ID attribute, we must check whether we can
         370                 :         //add new listeners
         371               0 :         AddListeners(aDocument);
         372                 :       }
         373                 :     }
         374                 :   }
         375               0 : }
         376                 :
         377                 : void
         378               0 : nsXMLEventsManager::ContentAppended(nsIDocument* aDocument,
         379                 :                                     nsIContent* aContainer,
         380                 :                                     nsIContent* aFirstNewContent,
         381                 :                                     PRInt32 aNewIndexInContainer)
         382                 : {
         383               0 :   AddListeners(aDocument);
         384               0 : }
         385                 :
         386                 : void
         387               0 : nsXMLEventsManager::ContentInserted(nsIDocument* aDocument,
         388                 :                                     nsIContent* aContainer,
         389                 :                                     nsIContent* aChild,
         390                 :                                     PRInt32 aIndexInContainer)
         391                 : {
         392               0 :   AddListeners(aDocument);
         393               0 : }
         394                 :
         395                 : void
         396               0 : nsXMLEventsManager::ContentRemoved(nsIDocument* aDocument,
         397                 :                                    nsIContent* aContainer,
         398                 :                                    nsIContent* aChild,
         399                 :                                    PRInt32 aIndexInContainer,
         400                 :                                    nsIContent* aPreviousSibling)
         401                 : {
         402               0 :   if (!aChild || !aChild->IsElement())
         403               0 :     return;
         404                 :   //Note, we can't use IDs here, the observer may not always have an ID.
         405                 :   //And to remember: the same observer can be referenced by many
         406                 :   //XMLEventsListeners
         407                 :
         408               0 :   nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
         409                 :
         410                 :   //If the content was an XML Events observer or handler
         411               0 :   mListeners.Enumerate(EnumAndSetIncomplete, aChild);
         412                 :
         413                 :   //If the content was an XML Events attributes container
         414               0 :   if (RemoveListener(aChild)) {
         415                 :     //for aContainer.appendChild(aContainer.removeChild(aChild));
         416               0 :     AddXMLEventsContent(aChild);
         417                 :   }
         418                 :
         419               0 :   PRUint32 count = aChild->GetChildCount();
         420               0 :   for (PRUint32 i = 0; i < count; ++i) {
         421               0 :     ContentRemoved(aDocument, aChild, aChild->GetChildAt(i), i, aChild->GetPreviousSibling());
         422                 :   }
         423                 : }

Generated by: LCOV version 1.7