LCOV - app.info - content/base/src/nsNodeUtils.cpp

LCOV - code coverage report
| Current view: | directory - content/base/src - nsNodeUtils.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 264 | 126 | 47.7 %
| Date: | 2012-04-21 | Functions: | 19 | 14 | 73.7 %

           1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
           2                 : /* vim: set ts=2 sw=2 et tw=99: */
           3                 : /* ***** BEGIN LICENSE BLOCK *****
           4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           5                 :  *
           6                 :  * The contents of this file are subject to the Mozilla Public License Version
           7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           8                 :  * the License. You may obtain a copy of the License at
           9                 :  * http://www.mozilla.org/MPL/
          10                 :  *
          11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          13                 :  * for the specific language governing rights and limitations under the
          14                 :  * License.
          15                 :  *
          16                 :  * The Original Code is Mozilla.org code.
          17                 :  *
          18                 :  * The Initial Developer of the Original Code is Mozilla Foundation.
          19                 :  * Portions created by the Initial Developer are Copyright (C) 2006
          20                 :  * the Initial Developer. All Rights Reserved.
          21                 :  *
          22                 :  * Contributor(s):
          23                 :  *         Jonas Sicking <jonas@sicking.cc> (Original Author)
          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 "nsNodeUtils.h"
          40                 : #include "nsContentUtils.h"
          41                 : #include "nsINode.h"
          42                 : #include "nsIContent.h"
          43                 : #include "mozilla/dom/Element.h"
          44                 : #include "nsIMutationObserver.h"
          45                 : #include "nsIMutationObserver2.h"
          46                 : #include "nsIDocument.h"
          47                 : #include "nsIDOMUserDataHandler.h"
          48                 : #include "nsEventListenerManager.h"
          49                 : #include "nsIAttribute.h"
          50                 : #include "nsIXPConnect.h"
          51                 : #include "nsGenericElement.h"
          52                 : #include "pldhash.h"
          53                 : #include "nsIDOMAttr.h"
          54                 : #include "nsCOMArray.h"
          55                 : #include "nsPIDOMWindow.h"
          56                 : #include "nsDocument.h"
          57                 : #ifdef MOZ_XUL
          58                 : #include "nsXULElement.h"
          59                 : #endif
          60                 : #include "nsBindingManager.h"
          61                 : #include "nsGenericHTMLElement.h"
          62                 : #ifdef MOZ_MEDIA
          63                 : #include "nsHTMLMediaElement.h"
          64                 : #endif // MOZ_MEDIA
          65                 : #include "nsImageLoadingContent.h"
          66                 : #include "jsgc.h"
          67                 : #include "nsWrapperCacheInlines.h"
          68                 : #include "nsObjectLoadingContent.h"
          69                 :
          70                 : using namespace mozilla::dom;
          71                 :
          72                 : // This macro expects the ownerDocument of content_ to be in scope as
          73                 : // |nsIDocument* doc|
          74                 : // NOTE: AttributeChildRemoved doesn't use this macro but has a very similar use.
          75                 : // If you change how this macro behave please update AttributeChildRemoved.
          76                 : #define IMPL_MUTATION_NOTIFICATION(func_, content_, params_)      \
          77                 :   PR_BEGIN_MACRO                                                  \
          78                 :   nsINode* node = content_;                                       \
          79                 :   NS_ASSERTION(node->OwnerDoc() == doc, "Bogus document");     \
          80                 :   if (doc) {                                                      \
          81                 :     static_cast<nsIMutationObserver*>(doc->BindingManager())->    \
          82                 :       func_ params_;                                              \
          83                 :   }                                                               \
          84                 :   do {                                                            \
          85                 :     nsINode::nsSlots* slots = node->GetExistingSlots();           \
          86                 :     if (slots && !slots->mMutationObservers.IsEmpty()) {          \
          87                 :       /* No need to explicitly notify the first observer first    \
          88                 :          since that'll happen anyway. */                          \
          89                 :       NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(                         \
          90                 :         slots->mMutationObservers, nsIMutationObserver,           \
          91                 :         func_, params_);                                          \
          92                 :     }                                                             \
          93                 :     node = node->GetNodeParent();                                 \
          94                 :   } while (node);                                                 \
          95                 :   PR_END_MACRO
          96                 :
          97                 : void
          98              36 : nsNodeUtils::CharacterDataWillChange(nsIContent* aContent,
          99                 :                                      CharacterDataChangeInfo* aInfo)
         100                 : {
         101              36 :   nsIDocument* doc = aContent->OwnerDoc();
         102              36 :   IMPL_MUTATION_NOTIFICATION(CharacterDataWillChange, aContent,
         103                 :                              (doc, aContent, aInfo));
         104              36 : }
         105                 :
         106                 : void
         107              36 : nsNodeUtils::CharacterDataChanged(nsIContent* aContent,
         108                 :                                   CharacterDataChangeInfo* aInfo)
         109                 : {
         110              36 :   nsIDocument* doc = aContent->OwnerDoc();
         111              36 :   IMPL_MUTATION_NOTIFICATION(CharacterDataChanged, aContent,
         112                 :                              (doc, aContent, aInfo));
         113              36 : }
         114                 :
         115                 : void
         116            1769 : nsNodeUtils::AttributeWillChange(Element* aElement,
         117                 :                                  PRInt32 aNameSpaceID,
         118                 :                                  nsIAtom* aAttribute,
         119                 :                                  PRInt32 aModType)
         120                 : {
         121            1769 :   nsIDocument* doc = aElement->OwnerDoc();
         122            1769 :   IMPL_MUTATION_NOTIFICATION(AttributeWillChange, aElement,
         123                 :                              (doc, aElement, aNameSpaceID, aAttribute,
         124                 :                               aModType));
         125            1769 : }
         126                 :
         127                 : void
         128            1769 : nsNodeUtils::AttributeChanged(Element* aElement,
         129                 :                               PRInt32 aNameSpaceID,
         130                 :                               nsIAtom* aAttribute,
         131                 :                               PRInt32 aModType)
         132                 : {
         133            1769 :   nsIDocument* doc = aElement->OwnerDoc();
         134            1769 :   IMPL_MUTATION_NOTIFICATION(AttributeChanged, aElement,
         135                 :                              (doc, aElement, aNameSpaceID, aAttribute,
         136                 :                               aModType));
         137            1769 : }
         138                 :
         139                 : void
         140            2421 : nsNodeUtils::ContentAppended(nsIContent* aContainer,
         141                 :                              nsIContent* aFirstNewContent,
         142                 :                              PRInt32 aNewIndexInContainer)
         143                 : {
         144            2421 :   nsIDocument* doc = aContainer->OwnerDoc();
         145                 :
         146            2421 :   IMPL_MUTATION_NOTIFICATION(ContentAppended, aContainer,
         147                 :                              (doc, aContainer, aFirstNewContent,
         148                 :                               aNewIndexInContainer));
         149            2421 : }
         150                 :
         151                 : void
         152            1273 : nsNodeUtils::ContentInserted(nsINode* aContainer,
         153                 :                              nsIContent* aChild,
         154                 :                              PRInt32 aIndexInContainer)
         155                 : {
         156            1273 :   NS_PRECONDITION(aContainer->IsNodeOfType(nsINode::eCONTENT) ||
         157                 :                   aContainer->IsNodeOfType(nsINode::eDOCUMENT),
         158                 :                   "container must be an nsIContent or an nsIDocument");
         159                 :   nsIContent* container;
         160            1273 :   nsIDocument* doc = aContainer->OwnerDoc();
         161                 :   nsIDocument* document;
         162            1273 :   if (aContainer->IsNodeOfType(nsINode::eCONTENT)) {
         163              12 :     container = static_cast<nsIContent*>(aContainer);
         164              12 :     document = doc;
         165                 :   }
         166                 :   else {
         167            1261 :     container = nsnull;
         168            1261 :     document = static_cast<nsIDocument*>(aContainer);
         169                 :   }
         170                 :
         171            1273 :   IMPL_MUTATION_NOTIFICATION(ContentInserted, aContainer,
         172                 :                              (document, container, aChild, aIndexInContainer));
         173            1273 : }
         174                 :
         175                 : void
         176             236 : nsNodeUtils::ContentRemoved(nsINode* aContainer,
         177                 :                             nsIContent* aChild,
         178                 :                             PRInt32 aIndexInContainer,
         179                 :                             nsIContent* aPreviousSibling)
         180                 : {
         181             236 :   NS_PRECONDITION(aContainer->IsNodeOfType(nsINode::eCONTENT) ||
         182                 :                   aContainer->IsNodeOfType(nsINode::eDOCUMENT),
         183                 :                   "container must be an nsIContent or an nsIDocument");
         184                 :   nsIContent* container;
         185             236 :   nsIDocument* doc = aContainer->OwnerDoc();
         186                 :   nsIDocument* document;
         187             236 :   if (aContainer->IsNodeOfType(nsINode::eCONTENT)) {
         188             226 :     container = static_cast<nsIContent*>(aContainer);
         189             226 :     document = doc;
         190                 :   }
         191                 :   else {
         192              10 :     container = nsnull;
         193              10 :     document = static_cast<nsIDocument*>(aContainer);
         194                 :   }
         195                 :
         196             236 :   IMPL_MUTATION_NOTIFICATION(ContentRemoved, aContainer,
         197                 :                              (document, container, aChild, aIndexInContainer,
         198                 :                               aPreviousSibling));
         199             236 : }
         200                 :
         201                 : void
         202               0 : nsNodeUtils::AttributeChildRemoved(nsINode* aAttribute,
         203                 :                                    nsIContent* aChild)
         204                 : {
         205               0 :   NS_PRECONDITION(aAttribute->IsNodeOfType(nsINode::eATTRIBUTE),
         206                 :                   "container must be a nsIAttribute");
         207                 :
         208                 :   // This is a variant of IMPL_MUTATION_NOTIFICATION.
         209               0 :   do {
         210               0 :     nsINode::nsSlots* slots = aAttribute->GetExistingSlots();
         211               0 :     if (slots && !slots->mMutationObservers.IsEmpty()) {
         212                 :       // This is a variant of NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS.
         213                 :       nsTObserverArray<nsIMutationObserver*>::ForwardIterator iter_ =
         214               0 :         slots->mMutationObservers;
         215               0 :       nsCOMPtr<nsIMutationObserver2> obs_;
         216               0 :       while (iter_.HasMore()) {
         217               0 :         obs_ = do_QueryInterface(iter_.GetNext());
         218               0 :         if (obs_) {
         219               0 :           obs_->AttributeChildRemoved(aAttribute, aChild);
         220                 :         }
         221                 :       }
         222                 :     }
         223               0 :     aAttribute = aAttribute->GetNodeParent();
         224                 :   } while (aAttribute);
         225               0 : }
         226                 :
         227                 : void
         228          422027 : nsNodeUtils::ParentChainChanged(nsIContent *aContent)
         229                 : {
         230                 :   // No need to notify observers on the parents since their parent
         231                 :   // chain must have been changed too and so their observers were
         232                 :   // notified at that time.
         233                 :
         234          422027 :   nsINode::nsSlots* slots = aContent->GetExistingSlots();
         235          422027 :   if (slots && !slots->mMutationObservers.IsEmpty()) {
         236             474 :     NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(
         237                 :         slots->mMutationObservers,
         238                 :         nsIMutationObserver,
         239                 :         ParentChainChanged,
         240                 :         (aContent));
         241                 :   }
         242          422027 : }
         243                 :
         244                 : void
         245          115160 : nsNodeUtils::LastRelease(nsINode* aNode)
         246                 : {
         247          115160 :   nsINode::nsSlots* slots = aNode->GetExistingSlots();
         248          115160 :   if (slots) {
         249            4587 :     if (!slots->mMutationObservers.IsEmpty()) {
         250            1278 :       NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(slots->mMutationObservers,
         251                 :                                          nsIMutationObserver,
         252                 :                                          NodeWillBeDestroyed, (aNode));
         253                 :     }
         254                 :
         255            4587 :     delete slots;
         256            4587 :     aNode->mSlots = nsnull;
         257                 :   }
         258                 :
         259                 :   // Kill properties first since that may run external code, so we want to
         260                 :   // be in as complete state as possible at that time.
         261          115160 :   if (aNode->IsNodeOfType(nsINode::eDOCUMENT)) {
         262                 :     // Delete all properties before tearing down the document. Some of the
         263                 :     // properties are bound to nsINode objects and the destructor functions of
         264                 :     // the properties may want to use the owner document of the nsINode.
         265            1249 :     static_cast<nsIDocument*>(aNode)->DeleteAllProperties();
         266                 :   }
         267                 :   else {
         268          113911 :     if (aNode->HasProperties()) {
         269                 :       // Strong reference to the document so that deleting properties can't
         270                 :       // delete the document.
         271               0 :       nsCOMPtr<nsIDocument> document = aNode->OwnerDoc();
         272               0 :       document->DeleteAllPropertiesFor(aNode);
         273                 :     }
         274                 :
         275                 :     // I wonder whether it's faster to do the HasFlag check first....
         276          113912 :     if (aNode->IsNodeOfType(nsINode::eHTML_FORM_CONTROL) &&
         277               1 :         aNode->HasFlag(ADDED_TO_FORM)) {
         278                 :       // Tell the form (if any) this node is going away.  Don't
         279                 :       // notify, since we're being destroyed in any case.
         280               0 :       static_cast<nsGenericHTMLFormElement*>(aNode)->ClearForm(true);
         281                 :     }
         282                 :   }
         283          115160 :   aNode->UnsetFlags(NODE_HAS_PROPERTIES);
         284                 :
         285          229071 :   if (aNode->NodeType() != nsIDOMNode::DOCUMENT_NODE &&
         286          113911 :       aNode->HasFlag(NODE_HAS_LISTENERMANAGER)) {
         287                 : #ifdef DEBUG
         288               0 :     if (nsContentUtils::IsInitialized()) {
         289                 :       nsEventListenerManager* manager =
         290               0 :         nsContentUtils::GetListenerManager(aNode, false);
         291               0 :       if (!manager) {
         292                 :         NS_ERROR("Huh, our bit says we have a listener manager list, "
         293               0 :                  "but there's nothing in the hash!?!!");
         294                 :       }
         295                 :     }
         296                 : #endif
         297                 :
         298               0 :     nsContentUtils::RemoveListenerManager(aNode);
         299               0 :     aNode->UnsetFlags(NODE_HAS_LISTENERMANAGER);
         300                 :   }
         301                 :
         302          115160 :   if (aNode->IsElement()) {
         303           37889 :     nsIDocument* ownerDoc = aNode->OwnerDoc();
         304           37889 :     Element* elem = aNode->AsElement();
         305           37889 :     ownerDoc->ClearBoxObjectFor(elem);
         306                 :
         307           37889 :     NS_ASSERTION(aNode->HasFlag(NODE_FORCE_XBL_BINDINGS) ||
         308                 :                  !ownerDoc->BindingManager() ||
         309                 :                  !ownerDoc->BindingManager()->GetBinding(elem),
         310                 :                  "Non-forced node has binding on destruction");
         311                 :
         312                 :     // if NODE_FORCE_XBL_BINDINGS is set, the node might still have a binding
         313                 :     // attached
         314           37889 :     if (aNode->HasFlag(NODE_FORCE_XBL_BINDINGS) &&
         315               0 :         ownerDoc->BindingManager()) {
         316               0 :       ownerDoc->BindingManager()->RemovedFromDocument(elem, ownerDoc);
         317                 :     }
         318                 :   }
         319                 :
         320          115160 :   nsContentUtils::ReleaseWrapper(aNode, aNode);
         321                 :
         322          115160 :   delete aNode;
         323          115160 : }
         324                 :
         325                 : struct NS_STACK_CLASS nsHandlerData
         326             524 : {
         327                 :   PRUint16 mOperation;
         328                 :   nsCOMPtr<nsIDOMNode> mSource;
         329                 :   nsCOMPtr<nsIDOMNode> mDest;
         330                 :   nsCxPusher mPusher;
         331                 : };
         332                 :
         333                 : static void
         334               0 : CallHandler(void *aObject, nsIAtom *aKey, void *aHandler, void *aData)
         335                 : {
         336               0 :   nsHandlerData *handlerData = static_cast<nsHandlerData*>(aData);
         337                 :   nsCOMPtr<nsIDOMUserDataHandler> handler =
         338               0 :     static_cast<nsIDOMUserDataHandler*>(aHandler);
         339               0 :   nsINode *node = static_cast<nsINode*>(aObject);
         340                 :   nsCOMPtr<nsIVariant> data =
         341               0 :     static_cast<nsIVariant*>(node->GetProperty(DOM_USER_DATA, aKey));
         342               0 :   NS_ASSERTION(data, "Handler without data?");
         343                 :
         344               0 :   if (!handlerData->mPusher.RePush(node)) {
         345                 :     return;
         346                 :   }
         347               0 :   nsAutoString key;
         348               0 :   aKey->ToString(key);
         349               0 :   handler->Handle(handlerData->mOperation, key, data, handlerData->mSource,
         350               0 :                   handlerData->mDest);
         351                 : }
         352                 :
         353                 : /* static */
         354                 : nsresult
         355             262 : nsNodeUtils::CallUserDataHandlers(nsCOMArray<nsINode> &aNodesWithProperties,
         356                 :                                   nsIDocument *aOwnerDocument,
         357                 :                                   PRUint16 aOperation, bool aCloned)
         358                 : {
         359             262 :   NS_PRECONDITION(!aCloned || (aNodesWithProperties.Count() % 2 == 0),
         360                 :                   "Expected aNodesWithProperties to contain original and "
         361                 :                   "cloned nodes.");
         362                 :
         363             262 :   if (!nsContentUtils::IsSafeToRunScript()) {
         364               0 :     if (nsContentUtils::IsChromeDoc(aOwnerDocument)) {
         365               0 :       NS_WARNING("Fix the caller! Userdata callback disabled.");
         366                 :     } else {
         367               0 :       NS_ERROR("This is unsafe! Fix the caller! Userdata callback disabled.");
         368                 :     }
         369                 :
         370               0 :     return NS_OK;
         371                 :   }
         372                 :
         373             262 :   nsPropertyTable *table = aOwnerDocument->PropertyTable(DOM_USER_DATA_HANDLER);
         374                 :
         375                 :   // Keep the document alive, just in case one of the handlers causes it to go
         376                 :   // away.
         377             524 :   nsCOMPtr<nsIDocument> ownerDoc = aOwnerDocument;
         378                 :
         379             524 :   nsHandlerData handlerData;
         380             262 :   handlerData.mOperation = aOperation;
         381                 :
         382             262 :   PRUint32 i, count = aNodesWithProperties.Count();
         383             262 :   for (i = 0; i < count; ++i) {
         384               0 :     nsINode *nodeWithProperties = aNodesWithProperties[i];
         385                 :
         386                 :     nsresult rv;
         387               0 :     handlerData.mSource = do_QueryInterface(nodeWithProperties, &rv);
         388               0 :     NS_ENSURE_SUCCESS(rv, rv);
         389                 :
         390               0 :     if (aCloned) {
         391               0 :       handlerData.mDest = do_QueryInterface(aNodesWithProperties[++i], &rv);
         392               0 :       NS_ENSURE_SUCCESS(rv, rv);
         393                 :     }
         394                 :
         395               0 :     table->Enumerate(nodeWithProperties, CallHandler, &handlerData);
         396                 :   }
         397                 :
         398             262 :   return NS_OK;
         399                 : }
         400                 :
         401                 : static void
         402               0 : NoteUserData(void *aObject, nsIAtom *aKey, void *aXPCOMChild, void *aData)
         403                 : {
         404                 :   nsCycleCollectionTraversalCallback* cb =
         405               0 :     static_cast<nsCycleCollectionTraversalCallback*>(aData);
         406               0 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "[user data (or handler)]");
         407               0 :   cb->NoteXPCOMChild(static_cast<nsISupports*>(aXPCOMChild));
         408               0 : }
         409                 :
         410                 : /* static */
         411                 : void
         412               0 : nsNodeUtils::TraverseUserData(nsINode* aNode,
         413                 :                               nsCycleCollectionTraversalCallback &aCb)
         414                 : {
         415               0 :   nsIDocument* ownerDoc = aNode->OwnerDoc();
         416               0 :   ownerDoc->PropertyTable(DOM_USER_DATA)->Enumerate(aNode, NoteUserData, &aCb);
         417               0 :   ownerDoc->PropertyTable(DOM_USER_DATA_HANDLER)->Enumerate(aNode, NoteUserData, &aCb);
         418               0 : }
         419                 :
         420                 : /* static */
         421                 : nsresult
         422             262 : nsNodeUtils::CloneNodeImpl(nsINode *aNode, bool aDeep,
         423                 :                            bool aCallUserDataHandlers,
         424                 :                            nsIDOMNode **aResult)
         425                 : {
         426             262 :   *aResult = nsnull;
         427                 :
         428             524 :   nsCOMPtr<nsIDOMNode> newNode;
         429             524 :   nsCOMArray<nsINode> nodesWithProperties;
         430                 :   nsresult rv = Clone(aNode, aDeep, nsnull, nodesWithProperties,
         431             262 :                       getter_AddRefs(newNode));
         432             262 :   NS_ENSURE_SUCCESS(rv, rv);
         433                 :
         434             262 :   if (aCallUserDataHandlers) {
         435                 :     rv = CallUserDataHandlers(nodesWithProperties, aNode->OwnerDoc(),
         436             262 :                               nsIDOMUserDataHandler::NODE_CLONED, true);
         437             262 :     NS_ENSURE_SUCCESS(rv, rv);
         438                 :   }
         439                 :
         440             262 :   newNode.swap(*aResult);
         441                 :
         442             262 :   return NS_OK;
         443                 : }
         444                 :
         445                 : /* static */
         446                 : nsresult
         447             823 : nsNodeUtils::CloneAndAdopt(nsINode *aNode, bool aClone, bool aDeep,
         448                 :                            nsNodeInfoManager *aNewNodeInfoManager,
         449                 :                            JSContext *aCx, JSObject *aNewScope,
         450                 :                            nsCOMArray<nsINode> &aNodesWithProperties,
         451                 :                            nsINode *aParent, nsINode **aResult)
         452                 : {
         453             823 :   NS_PRECONDITION((!aClone && aNewNodeInfoManager) || !aCx,
         454                 :                   "If cloning or not getting a new nodeinfo we shouldn't "
         455                 :                   "rewrap");
         456             823 :   NS_PRECONDITION(!aCx || aNewScope, "Must have new scope");
         457             823 :   NS_PRECONDITION(!aParent || aNode->IsNodeOfType(nsINode::eCONTENT),
         458                 :                   "Can't insert document or attribute nodes into a parent");
         459                 :
         460             823 :   *aResult = nsnull;
         461                 :
         462                 :   // First deal with aNode and walk its attributes (and their children). Then,
         463                 :   // if aDeep is true, deal with aNode's children (and recurse into their
         464                 :   // attributes and children).
         465                 :
         466                 :   nsresult rv;
         467                 :   JSObject *wrapper;
         468             823 :   if (aCx && (wrapper = aNode->GetWrapper())) {
         469               0 :       rv = xpc_MorphSlimWrapper(aCx, aNode);
         470               0 :       NS_ENSURE_SUCCESS(rv, rv);
         471                 :   }
         472                 :
         473             823 :   nsNodeInfoManager *nodeInfoManager = aNewNodeInfoManager;
         474                 :
         475                 :   // aNode.
         476             823 :   nsINodeInfo *nodeInfo = aNode->mNodeInfo;
         477            1646 :   nsCOMPtr<nsINodeInfo> newNodeInfo;
         478             823 :   if (nodeInfoManager) {
         479                 :
         480                 :     // Don't allow importing/adopting nodes from non-privileged "scriptable"
         481                 :     // documents to "non-scriptable" documents.
         482               0 :     nsIDocument* newDoc = nodeInfoManager->GetDocument();
         483               0 :     NS_ENSURE_STATE(newDoc);
         484               0 :     bool hasHadScriptHandlingObject = false;
         485               0 :     if (!newDoc->GetScriptHandlingObject(hasHadScriptHandlingObject) &&
         486               0 :         !hasHadScriptHandlingObject) {
         487               0 :       nsIDocument* currentDoc = aNode->OwnerDoc();
         488               0 :       NS_ENSURE_STATE((nsContentUtils::IsChromeDoc(currentDoc) ||
         489                 :                        (!currentDoc->GetScriptHandlingObject(hasHadScriptHandlingObject) &&
         490                 :                         !hasHadScriptHandlingObject)));
         491                 :     }
         492                 :
         493                 :     newNodeInfo = nodeInfoManager->GetNodeInfo(nodeInfo->NameAtom(),
         494                 :                                                nodeInfo->GetPrefixAtom(),
         495                 :                                                nodeInfo->NamespaceID(),
         496               0 :                                                nodeInfo->NodeType(),
         497               0 :                                                nodeInfo->GetExtraName());
         498               0 :     NS_ENSURE_TRUE(newNodeInfo, NS_ERROR_OUT_OF_MEMORY);
         499                 :
         500               0 :     nodeInfo = newNodeInfo;
         501                 :   }
         502                 :
         503             823 :   nsGenericElement *elem = aNode->IsElement() ?
         504                 :                            static_cast<nsGenericElement*>(aNode) :
         505             823 :                            nsnull;
         506                 :
         507            1646 :   nsCOMPtr<nsINode> clone;
         508             823 :   if (aClone) {
         509             823 :     rv = aNode->Clone(nodeInfo, getter_AddRefs(clone));
         510             823 :     NS_ENSURE_SUCCESS(rv, rv);
         511                 :
         512             823 :     if (aParent) {
         513                 :       // If we're cloning we need to insert the cloned children into the cloned
         514                 :       // parent.
         515             561 :       rv = aParent->AppendChildTo(static_cast<nsIContent*>(clone.get()),
         516             561 :                                   false);
         517             561 :       NS_ENSURE_SUCCESS(rv, rv);
         518                 :     }
         519             262 :     else if (aDeep && clone->IsNodeOfType(nsINode::eDOCUMENT)) {
         520                 :       // After cloning the document itself, we want to clone the children into
         521                 :       // the cloned document (somewhat like cloning and importing them into the
         522                 :       // cloned document).
         523               0 :       nodeInfoManager = clone->mNodeInfo->NodeInfoManager();
         524                 :     }
         525                 :   }
         526               0 :   else if (nodeInfoManager) {
         527               0 :     nsIDocument* oldDoc = aNode->OwnerDoc();
         528               0 :     bool wasRegistered = false;
         529               0 :     if (aNode->IsElement()) {
         530               0 :       Element* element = aNode->AsElement();
         531               0 :       oldDoc->ClearBoxObjectFor(element);
         532               0 :       wasRegistered = oldDoc->UnregisterFreezableElement(element);
         533                 :     }
         534                 :
         535               0 :     aNode->mNodeInfo.swap(newNodeInfo);
         536               0 :     if (elem) {
         537               0 :       elem->NodeInfoChanged(newNodeInfo);
         538                 :     }
         539                 :
         540               0 :     nsIDocument* newDoc = aNode->OwnerDoc();
         541               0 :     if (newDoc) {
         542                 :       // XXX what if oldDoc is null, we don't know if this should be
         543                 :       // registered or not! Can that really happen?
         544               0 :       if (wasRegistered) {
         545               0 :         newDoc->RegisterFreezableElement(aNode->AsElement());
         546                 :       }
         547                 :
         548               0 :       nsPIDOMWindow* window = newDoc->GetInnerWindow();
         549               0 :       if (window) {
         550               0 :         nsEventListenerManager* elm = aNode->GetListenerManager(false);
         551               0 :         if (elm) {
         552               0 :           window->SetMutationListeners(elm->MutationListenerBits());
         553               0 :           if (elm->MayHavePaintEventListener()) {
         554               0 :             window->SetHasPaintEventListeners();
         555                 :           }
         556                 : #ifdef MOZ_MEDIA
         557               0 :           if (elm->MayHaveAudioAvailableEventListener()) {
         558               0 :             window->SetHasAudioAvailableEventListeners();
         559                 :           }
         560                 : #endif
         561               0 :           if (elm->MayHaveTouchEventListener()) {
         562               0 :             window->SetHasTouchEventListeners();
         563                 :           }
         564               0 :           if (elm->MayHaveMouseEnterLeaveEventListener()) {
         565               0 :             window->SetHasMouseEnterLeaveEventListeners();
         566                 :           }
         567                 :         }
         568                 :       }
         569                 :     }
         570                 :
         571               0 :     if (wasRegistered && oldDoc != newDoc) {
         572                 : #ifdef MOZ_MEDIA
         573               0 :       nsCOMPtr<nsIDOMHTMLMediaElement> domMediaElem(do_QueryInterface(aNode));
         574               0 :       if (domMediaElem) {
         575               0 :         nsHTMLMediaElement* mediaElem = static_cast<nsHTMLMediaElement*>(aNode);
         576               0 :         mediaElem->NotifyOwnerDocumentActivityChanged();
         577                 :       }
         578                 : #endif
         579               0 :       nsCOMPtr<nsIObjectLoadingContent> objectLoadingContent(do_QueryInterface(aNode));
         580               0 :       if (objectLoadingContent) {
         581               0 :         nsObjectLoadingContent* olc = static_cast<nsObjectLoadingContent*>(objectLoadingContent.get());
         582               0 :         olc->NotifyOwnerDocumentActivityChanged();
         583                 :       }
         584                 :     }
         585                 :
         586                 :     // nsImageLoadingContent needs to know when its document changes
         587               0 :     if (oldDoc != newDoc) {
         588               0 :       nsCOMPtr<nsIImageLoadingContent> imageContent(do_QueryInterface(aNode));
         589               0 :       if (imageContent)
         590               0 :         imageContent->NotifyOwnerDocumentChanged(oldDoc);
         591                 :     }
         592                 :
         593               0 :     if (elem) {
         594               0 :       elem->RecompileScriptEventListeners();
         595                 :     }
         596                 :
         597               0 :     if (aCx && wrapper) {
         598               0 :       nsIXPConnect *xpc = nsContentUtils::XPConnect();
         599               0 :       if (xpc) {
         600               0 :         nsCOMPtr<nsIXPConnectJSObjectHolder> oldWrapper;
         601                 :         rv = xpc->ReparentWrappedNativeIfFound(aCx, wrapper, aNewScope, aNode,
         602               0 :                                                getter_AddRefs(oldWrapper));
         603                 :
         604               0 :         if (NS_FAILED(rv)) {
         605               0 :           aNode->mNodeInfo.swap(nodeInfo);
         606                 :
         607               0 :           return rv;
         608                 :         }
         609                 :       }
         610                 :     }
         611                 :   }
         612                 :
         613                 :   // XXX If there are any attribute nodes on this element with UserDataHandlers
         614                 :   // we should technically adopt/clone/import such attribute nodes and notify
         615                 :   // those handlers. However we currently don't have code to do so without
         616                 :   // also notifying when it's not safe so we're not doing that at this time.
         617                 :
         618                 :   // The DOM spec says to always adopt/clone/import the children of attribute
         619                 :   // nodes.
         620                 :   // XXX The following block is here because our implementation of attribute
         621                 :   //     nodes is broken when it comes to inserting children. Instead of cloning
         622                 :   //     their children we force creation of the only child by calling
         623                 :   //     GetChildAt(0). We can remove this when
         624                 :   //     https://bugzilla.mozilla.org/show_bug.cgi?id=56758 is fixed.
         625             823 :   if (aClone && aNode->IsNodeOfType(nsINode::eATTRIBUTE)) {
         626              96 :     nsCOMPtr<nsINode> attrChildNode = aNode->GetChildAt(0);
         627                 :     // We only need to do this if the child node has properties (because we
         628                 :     // might need to call a userdata handler).
         629              48 :     if (attrChildNode && attrChildNode->HasProperties()) {
         630               0 :       nsCOMPtr<nsINode> clonedAttrChildNode = clone->GetChildAt(0);
         631               0 :       if (clonedAttrChildNode) {
         632               0 :         bool ok = aNodesWithProperties.AppendObject(attrChildNode) &&
         633               0 :                     aNodesWithProperties.AppendObject(clonedAttrChildNode);
         634               0 :         NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
         635                 :       }
         636                 :     }
         637                 :   }
         638                 :   // XXX End of workaround for broken attribute nodes.
         639             775 :   else if (aDeep || aNode->IsNodeOfType(nsINode::eATTRIBUTE)) {
         640                 :     // aNode's children.
         641            1327 :     for (nsIContent* cloneChild = aNode->GetFirstChild();
         642                 :          cloneChild;
         643             561 :        cloneChild = cloneChild->GetNextSibling()) {
         644            1122 :       nsCOMPtr<nsINode> child;
         645                 :       rv = CloneAndAdopt(cloneChild, aClone, true, nodeInfoManager,
         646                 :                          aCx, aNewScope, aNodesWithProperties, clone,
         647             561 :                          getter_AddRefs(child));
         648             561 :       NS_ENSURE_SUCCESS(rv, rv);
         649                 :     }
         650                 :   }
         651                 :
         652                 :   // XXX setting document on some nodes not in a document so XBL will bind
         653                 :   // and chrome won't break. Make XBL bind to document-less nodes!
         654                 :   // XXXbz Once this is fixed, fix up the asserts in all implementations of
         655                 :   // BindToTree to assert what they would like to assert, and fix the
         656                 :   // ChangeDocumentFor() call in nsXULElement::BindToTree as well.  Also,
         657                 :   // remove the UnbindFromTree call in ~nsXULElement, and add back in the
         658                 :   // precondition in nsXULElement::UnbindFromTree and remove the line in
         659                 :   // nsXULElement.h that makes nsNodeUtils a friend of nsXULElement.
         660                 :   // Note: Make sure to do this witchery _after_ we've done any deep
         661                 :   // cloning, so kids of the new node aren't confused about whether they're
         662                 :   // in a document.
         663                 : #ifdef MOZ_XUL
         664             939 :   if (aClone && !aParent && aNode->IsElement() &&
         665             116 :       aNode->AsElement()->IsXUL()) {
         666               0 :     nsXULElement *xulElem = static_cast<nsXULElement*>(elem);
         667               0 :     if (!xulElem->mPrototype || xulElem->IsInDoc()) {
         668               0 :       clone->SetFlags(NODE_FORCE_XBL_BINDINGS);
         669                 :     }
         670                 :   }
         671                 : #endif
         672                 :
         673             823 :   if (aNode->HasProperties()) {
         674               0 :     bool ok = aNodesWithProperties.AppendObject(aNode);
         675               0 :     if (aClone) {
         676               0 :       ok = ok && aNodesWithProperties.AppendObject(clone);
         677                 :     }
         678                 :
         679               0 :     NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
         680                 :   }
         681                 :
         682             823 :   clone.forget(aResult);
         683                 :
         684             823 :   return NS_OK;
         685                 : }
         686                 :
         687                 :
         688                 : /* static */
         689                 : void
         690               0 : nsNodeUtils::UnlinkUserData(nsINode *aNode)
         691                 : {
         692               0 :   NS_ASSERTION(aNode->HasProperties(), "Call to UnlinkUserData not needed.");
         693                 :
         694                 :   // Strong reference to the document so that deleting properties can't
         695                 :   // delete the document.
         696               0 :   nsCOMPtr<nsIDocument> document = aNode->OwnerDoc();
         697               0 :   document->PropertyTable(DOM_USER_DATA)->DeleteAllPropertiesFor(aNode);
         698               0 :   document->PropertyTable(DOM_USER_DATA_HANDLER)->DeleteAllPropertiesFor(aNode);
         699               0 : }

Generated by: LCOV version 1.7