content/base/src/nsNodeInfoManager.cpp

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 /*
     8  * A class for handing out nodeinfos and ensuring sharing of them as needed.
     9  */
    11 #include "nsNodeInfoManager.h"
    13 #include "mozilla/DebugOnly.h"
    14 #include "nsNodeInfo.h"
    15 #include "nsCOMPtr.h"
    16 #include "nsString.h"
    17 #include "nsIAtom.h"
    18 #include "nsIDocument.h"
    19 #include "nsIPrincipal.h"
    20 #include "nsIURI.h"
    21 #include "nsContentUtils.h"
    22 #include "nsReadableUtils.h"
    23 #include "nsGkAtoms.h"
    24 #include "nsComponentManagerUtils.h"
    25 #include "nsLayoutStatics.h"
    26 #include "nsBindingManager.h"
    27 #include "nsHashKeys.h"
    28 #include "nsCCUncollectableMarker.h"
    30 using namespace mozilla;
    32 #ifdef MOZ_LOGGING
    33 // so we can get logging even in release builds
    34 #define FORCE_PR_LOG 1
    35 #endif
    36 #include "prlog.h"
    38 #ifdef PR_LOGGING
    39 static PRLogModuleInfo* gNodeInfoManagerLeakPRLog;
    40 #endif
    42 PLHashNumber
    43 nsNodeInfoManager::GetNodeInfoInnerHashValue(const void *key)
    44 {
    45   NS_ASSERTION(key, "Null key passed to nsNodeInfo::GetHashValue!");
    47   const nsINodeInfo::nsNodeInfoInner *node =
    48     reinterpret_cast<const nsINodeInfo::nsNodeInfoInner *>(key);
    50   return node->mName ? node->mName->hash() : HashString(*(node->mNameString));
    51 }
    54 int
    55 nsNodeInfoManager::NodeInfoInnerKeyCompare(const void *key1, const void *key2)
    56 {
    57   NS_ASSERTION(key1 && key2, "Null key passed to NodeInfoInnerKeyCompare!");
    59   const nsINodeInfo::nsNodeInfoInner *node1 =
    60     reinterpret_cast<const nsINodeInfo::nsNodeInfoInner *>(key1);
    61   const nsINodeInfo::nsNodeInfoInner *node2 =
    62     reinterpret_cast<const nsINodeInfo::nsNodeInfoInner *>(key2);
    64   if (node1->mPrefix != node2->mPrefix ||
    65       node1->mNamespaceID != node2->mNamespaceID ||
    66       node1->mNodeType != node2->mNodeType ||
    67       node1->mExtraName != node2->mExtraName) {
    68     return 0;
    69   }
    71   if (node1->mName) {
    72     if (node2->mName) {
    73       return (node1->mName == node2->mName);
    74     }
    75     return (node1->mName->Equals(*(node2->mNameString)));
    76   }
    77   if (node2->mName) {
    78     return (node2->mName->Equals(*(node1->mNameString)));
    79   }
    80   return (node1->mNameString->Equals(*(node2->mNameString)));
    81 }
    84 static void* PR_CALLBACK
    85 AllocTable(void* pool, size_t size)
    86 {
    87   return malloc(size);
    88 }
    90 static void PR_CALLBACK
    91 FreeTable(void* pool, void* item)
    92 {
    93   free(item);
    94 }
    96 static PLHashEntry* PR_CALLBACK
    97 AllocEntry(void* pool, const void* key)
    98 {
    99   return (PLHashEntry*)malloc(sizeof(PLHashEntry));
   100 }
   102 static void PR_CALLBACK
   103 FreeEntry(void* pool, PLHashEntry* he, unsigned flag)
   104 {
   105   if (flag == HT_FREE_ENTRY) {
   106     free(he);
   107   }
   108 }
   110 static PLHashAllocOps allocOps =
   111   { AllocTable, FreeTable, AllocEntry, FreeEntry };
   113 nsNodeInfoManager::nsNodeInfoManager()
   114   : mDocument(nullptr),
   115     mNonDocumentNodeInfos(0),
   116     mTextNodeInfo(nullptr),
   117     mCommentNodeInfo(nullptr),
   118     mDocumentNodeInfo(nullptr)
   119 {
   120   nsLayoutStatics::AddRef();
   122 #ifdef PR_LOGGING
   123   if (!gNodeInfoManagerLeakPRLog)
   124     gNodeInfoManagerLeakPRLog = PR_NewLogModule("NodeInfoManagerLeak");
   126   if (gNodeInfoManagerLeakPRLog)
   127     PR_LOG(gNodeInfoManagerLeakPRLog, PR_LOG_DEBUG,
   128            ("NODEINFOMANAGER %p created", this));
   129 #endif
   131   mNodeInfoHash = PL_NewHashTable(32, GetNodeInfoInnerHashValue,
   132                                   NodeInfoInnerKeyCompare,
   133                                   PL_CompareValues, &allocOps, nullptr);
   134 }
   137 nsNodeInfoManager::~nsNodeInfoManager()
   138 {
   139   if (mNodeInfoHash)
   140     PL_HashTableDestroy(mNodeInfoHash);
   142   // Note: mPrincipal may be null here if we never got inited correctly
   143   mPrincipal = nullptr;
   145   mBindingManager = nullptr;
   147 #ifdef PR_LOGGING
   148   if (gNodeInfoManagerLeakPRLog)
   149     PR_LOG(gNodeInfoManagerLeakPRLog, PR_LOG_DEBUG,
   150            ("NODEINFOMANAGER %p destroyed", this));
   151 #endif
   153   nsLayoutStatics::Release();
   154 }
   156 NS_IMPL_CYCLE_COLLECTION_CLASS(nsNodeInfoManager)
   158 NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsNodeInfoManager)
   159 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsNodeInfoManager)
   160   if (tmp->mDocument &&
   161       nsCCUncollectableMarker::InGeneration(cb,
   162                                             tmp->mDocument->GetMarkedCCGeneration())) {
   163     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
   164   }
   165   if (tmp->mNonDocumentNodeInfos) {
   166     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mDocument)
   167   }
   168   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBindingManager)
   169 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
   171 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsNodeInfoManager, AddRef)
   172 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsNodeInfoManager, Release)
   174 nsresult
   175 nsNodeInfoManager::Init(nsIDocument *aDocument)
   176 {
   177   NS_ENSURE_TRUE(mNodeInfoHash, NS_ERROR_OUT_OF_MEMORY);
   179   NS_PRECONDITION(!mPrincipal,
   180                   "Being inited when we already have a principal?");
   181   nsresult rv;
   182   mPrincipal = do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
   183   NS_ENSURE_TRUE(mPrincipal, rv);
   185   if (aDocument) {
   186     mBindingManager = new nsBindingManager(aDocument);
   187   }
   189   mDefaultPrincipal = mPrincipal;
   191   mDocument = aDocument;
   193 #ifdef PR_LOGGING
   194   if (gNodeInfoManagerLeakPRLog)
   195     PR_LOG(gNodeInfoManagerLeakPRLog, PR_LOG_DEBUG,
   196            ("NODEINFOMANAGER %p Init document=%p", this, aDocument));
   197 #endif
   199   return NS_OK;
   200 }
   202 // static
   203 int
   204 nsNodeInfoManager::DropNodeInfoDocument(PLHashEntry *he, int hashIndex, void *arg)
   205 {
   206   static_cast<nsINodeInfo*>(he->value)->mDocument = nullptr;
   207   return HT_ENUMERATE_NEXT;
   208 }
   210 void
   211 nsNodeInfoManager::DropDocumentReference()
   212 {
   213   if (mBindingManager) {
   214     mBindingManager->DropDocumentReference();
   215   }
   217   // This is probably not needed anymore.
   218   PL_HashTableEnumerateEntries(mNodeInfoHash, DropNodeInfoDocument, nullptr);
   220   NS_ASSERTION(!mNonDocumentNodeInfos, "Shouldn't have non-document nodeinfos!");
   221   mDocument = nullptr;
   222 }
   225 already_AddRefed<nsINodeInfo>
   226 nsNodeInfoManager::GetNodeInfo(nsIAtom *aName, nsIAtom *aPrefix,
   227                                int32_t aNamespaceID, uint16_t aNodeType,
   228                                nsIAtom* aExtraName /* = nullptr */)
   229 {
   230   CheckValidNodeInfo(aNodeType, aName, aNamespaceID, aExtraName);
   232   nsINodeInfo::nsNodeInfoInner tmpKey(aName, aPrefix, aNamespaceID, aNodeType,
   233                                       aExtraName);
   235   void *node = PL_HashTableLookup(mNodeInfoHash, &tmpKey);
   237   if (node) {
   238     nsCOMPtr<nsINodeInfo> nodeInfo = static_cast<nsINodeInfo*>(node);
   240     return nodeInfo.forget();
   241   }
   243   nsRefPtr<nsNodeInfo> newNodeInfo =
   244     new nsNodeInfo(aName, aPrefix, aNamespaceID, aNodeType, aExtraName, this);
   246   DebugOnly<PLHashEntry*> he =
   247     PL_HashTableAdd(mNodeInfoHash, &newNodeInfo->mInner, newNodeInfo);
   248   MOZ_ASSERT(he, "PL_HashTableAdd() failed");
   250   // Have to do the swap thing, because already_AddRefed<nsNodeInfo>
   251   // doesn't cast to already_AddRefed<nsINodeInfo>
   252   ++mNonDocumentNodeInfos;
   253   if (mNonDocumentNodeInfos == 1) {
   254     NS_IF_ADDREF(mDocument);
   255   }
   257   return newNodeInfo.forget();
   258 }
   261 nsresult
   262 nsNodeInfoManager::GetNodeInfo(const nsAString& aName, nsIAtom *aPrefix,
   263                                int32_t aNamespaceID, uint16_t aNodeType,
   264                                nsINodeInfo** aNodeInfo)
   265 {
   266 #ifdef DEBUG
   267   {
   268     nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aName);
   269     CheckValidNodeInfo(aNodeType, nameAtom, aNamespaceID, nullptr);
   270   }
   271 #endif
   273   nsINodeInfo::nsNodeInfoInner tmpKey(aName, aPrefix, aNamespaceID, aNodeType);
   275   void *node = PL_HashTableLookup(mNodeInfoHash, &tmpKey);
   277   if (node) {
   278     nsINodeInfo* nodeInfo = static_cast<nsINodeInfo *>(node);
   280     NS_ADDREF(*aNodeInfo = nodeInfo);
   282     return NS_OK;
   283   }
   285   nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aName);
   286   NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
   288   nsRefPtr<nsNodeInfo> newNodeInfo =
   289     new nsNodeInfo(nameAtom, aPrefix, aNamespaceID, aNodeType, nullptr, this);
   290   NS_ENSURE_TRUE(newNodeInfo, NS_ERROR_OUT_OF_MEMORY);
   292   PLHashEntry *he;
   293   he = PL_HashTableAdd(mNodeInfoHash, &newNodeInfo->mInner, newNodeInfo);
   294   NS_ENSURE_TRUE(he, NS_ERROR_FAILURE);
   296   ++mNonDocumentNodeInfos;
   297   if (mNonDocumentNodeInfos == 1) {
   298     NS_IF_ADDREF(mDocument);
   299   }
   301   newNodeInfo.forget(aNodeInfo);
   303   return NS_OK;
   304 }
   307 nsresult
   308 nsNodeInfoManager::GetNodeInfo(const nsAString& aName, nsIAtom *aPrefix,
   309                                const nsAString& aNamespaceURI,
   310                                uint16_t aNodeType,
   311                                nsINodeInfo** aNodeInfo)
   312 {
   313   int32_t nsid = kNameSpaceID_None;
   315   if (!aNamespaceURI.IsEmpty()) {
   316     nsresult rv = nsContentUtils::NameSpaceManager()->
   317       RegisterNameSpace(aNamespaceURI, nsid);
   318     NS_ENSURE_SUCCESS(rv, rv);
   319   }
   321   return GetNodeInfo(aName, aPrefix, nsid, aNodeType, aNodeInfo);
   322 }
   324 already_AddRefed<nsINodeInfo>
   325 nsNodeInfoManager::GetTextNodeInfo()
   326 {
   327   nsCOMPtr<nsINodeInfo> nodeInfo;
   329   if (!mTextNodeInfo) {
   330     nodeInfo = GetNodeInfo(nsGkAtoms::textTagName, nullptr, kNameSpaceID_None,
   331                            nsIDOMNode::TEXT_NODE, nullptr);
   332     // Hold a weak ref; the nodeinfo will let us know when it goes away
   333     mTextNodeInfo = nodeInfo;
   334   } else {
   335     nodeInfo = mTextNodeInfo;
   336   }
   338   return nodeInfo.forget();
   339 }
   341 already_AddRefed<nsINodeInfo>
   342 nsNodeInfoManager::GetCommentNodeInfo()
   343 {
   344   nsCOMPtr<nsINodeInfo> nodeInfo;
   346   if (!mCommentNodeInfo) {
   347     nodeInfo = GetNodeInfo(nsGkAtoms::commentTagName, nullptr,
   348                            kNameSpaceID_None, nsIDOMNode::COMMENT_NODE,
   349                            nullptr);
   350     // Hold a weak ref; the nodeinfo will let us know when it goes away
   351     mCommentNodeInfo = nodeInfo;
   352   }
   353   else {
   354     nodeInfo = mCommentNodeInfo;
   355   }
   357   return nodeInfo.forget();
   358 }
   360 already_AddRefed<nsINodeInfo>
   361 nsNodeInfoManager::GetDocumentNodeInfo()
   362 {
   363   nsCOMPtr<nsINodeInfo> nodeInfo;
   365   if (!mDocumentNodeInfo) {
   366     NS_ASSERTION(mDocument, "Should have mDocument!");
   367     nodeInfo = GetNodeInfo(nsGkAtoms::documentNodeName, nullptr,
   368                            kNameSpaceID_None, nsIDOMNode::DOCUMENT_NODE,
   369                            nullptr);
   370     // Hold a weak ref; the nodeinfo will let us know when it goes away
   371     mDocumentNodeInfo = nodeInfo;
   373     --mNonDocumentNodeInfos;
   374     if (!mNonDocumentNodeInfos) {
   375       mDocument->Release(); // Don't set mDocument to null!
   376     }
   377   }
   378   else {
   379     nodeInfo = mDocumentNodeInfo;
   380   }
   382   return nodeInfo.forget();
   383 }
   385 void
   386 nsNodeInfoManager::SetDocumentPrincipal(nsIPrincipal *aPrincipal)
   387 {
   388   mPrincipal = nullptr;
   389   if (!aPrincipal) {
   390     aPrincipal = mDefaultPrincipal;
   391   }
   393   NS_ASSERTION(aPrincipal, "Must have principal by this point!");
   395   mPrincipal = aPrincipal;
   396 }
   398 void
   399 nsNodeInfoManager::RemoveNodeInfo(nsNodeInfo *aNodeInfo)
   400 {
   401   NS_PRECONDITION(aNodeInfo, "Trying to remove null nodeinfo from manager!");
   403   if (aNodeInfo == mDocumentNodeInfo) {
   404     mDocumentNodeInfo = nullptr;
   405     mDocument = nullptr;
   406   } else {
   407     if (--mNonDocumentNodeInfos == 0) {
   408       if (mDocument) {
   409         // Note, whoever calls this method should keep NodeInfoManager alive,
   410         // even if mDocument gets deleted.
   411         mDocument->Release();
   412       }
   413     }
   414     // Drop weak reference if needed
   415     if (aNodeInfo == mTextNodeInfo) {
   416       mTextNodeInfo = nullptr;
   417     }
   418     else if (aNodeInfo == mCommentNodeInfo) {
   419       mCommentNodeInfo = nullptr;
   420     }
   421   }
   423 #ifdef DEBUG
   424   bool ret =
   425 #endif
   426   PL_HashTableRemove(mNodeInfoHash, &aNodeInfo->mInner);
   428   NS_POSTCONDITION(ret, "Can't find nsINodeInfo to remove!!!");
   429 }

mercurial