LCOV - code coverage report
Current view: top level - dom/xul - nsXULPrototypeDocument.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 52 203 25.6 %
Date: 2018-08-07 16:42:27 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : 
       7             : #include "nsXULPrototypeDocument.h"
       8             : #include "XULDocument.h"
       9             : 
      10             : #include "nsAString.h"
      11             : #include "nsIObjectInputStream.h"
      12             : #include "nsIObjectOutputStream.h"
      13             : #include "nsIPrincipal.h"
      14             : #include "nsJSPrincipals.h"
      15             : #include "nsIScriptObjectPrincipal.h"
      16             : #include "nsIScriptSecurityManager.h"
      17             : #include "nsIServiceManager.h"
      18             : #include "nsIArray.h"
      19             : #include "nsIURI.h"
      20             : #include "jsapi.h"
      21             : #include "jsfriendapi.h"
      22             : #include "nsString.h"
      23             : #include "nsIConsoleService.h"
      24             : #include "nsIScriptError.h"
      25             : #include "nsDOMCID.h"
      26             : #include "nsNodeInfoManager.h"
      27             : #include "nsContentUtils.h"
      28             : #include "nsCCUncollectableMarker.h"
      29             : #include "xpcpublic.h"
      30             : #include "mozilla/dom/BindingUtils.h"
      31             : 
      32             : using mozilla::dom::DestroyProtoAndIfaceCache;
      33             : using mozilla::dom::XULDocument;
      34             : 
      35             : uint32_t nsXULPrototypeDocument::gRefCnt;
      36             : 
      37             : //----------------------------------------------------------------------
      38             : //
      39             : // ctors, dtors, n' stuff
      40             : //
      41             : 
      42           0 : nsXULPrototypeDocument::nsXULPrototypeDocument()
      43             :     : mRoot(nullptr),
      44             :       mLoaded(false),
      45             :       mCCGeneration(0),
      46           0 :       mGCNumber(0)
      47             : {
      48           0 :     ++gRefCnt;
      49           0 : }
      50             : 
      51             : 
      52             : nsresult
      53           0 : nsXULPrototypeDocument::Init()
      54             : {
      55           0 :     mNodeInfoManager = new nsNodeInfoManager();
      56           0 :     return mNodeInfoManager->Init(nullptr);
      57             : }
      58             : 
      59           0 : nsXULPrototypeDocument::~nsXULPrototypeDocument()
      60             : {
      61           0 :     if (mRoot)
      62           0 :         mRoot->ReleaseSubtree();
      63           0 : }
      64             : 
      65             : NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULPrototypeDocument)
      66             : 
      67           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULPrototypeDocument)
      68           0 :     NS_IMPL_CYCLE_COLLECTION_UNLINK(mPrototypeWaiters)
      69           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
      70           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULPrototypeDocument)
      71           0 :     if (nsCCUncollectableMarker::InGeneration(cb, tmp->mCCGeneration)) {
      72             :         return NS_SUCCESS_INTERRUPTED_TRAVERSE;
      73             :     }
      74           0 :     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRoot)
      75           0 :     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNodeInfoManager)
      76           0 :     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPrototypeWaiters)
      77           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
      78             : 
      79           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULPrototypeDocument)
      80           0 :     NS_INTERFACE_MAP_ENTRY(nsISerializable)
      81           0 :     NS_INTERFACE_MAP_ENTRY(nsISupports)
      82           0 : NS_INTERFACE_MAP_END
      83             : 
      84           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULPrototypeDocument)
      85           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULPrototypeDocument)
      86             : 
      87             : NS_IMETHODIMP
      88           0 : NS_NewXULPrototypeDocument(nsXULPrototypeDocument** aResult)
      89             : {
      90           0 :     *aResult = nullptr;
      91             :     RefPtr<nsXULPrototypeDocument> doc =
      92           0 :       new nsXULPrototypeDocument();
      93             : 
      94           0 :     nsresult rv = doc->Init();
      95           0 :     if (NS_FAILED(rv)) {
      96             :         return rv;
      97             :     }
      98             : 
      99           0 :     doc.forget(aResult);
     100           0 :     return rv;
     101             : }
     102             : 
     103             : //----------------------------------------------------------------------
     104             : //
     105             : // nsISerializable methods
     106             : //
     107             : 
     108             : NS_IMETHODIMP
     109           0 : nsXULPrototypeDocument::Read(nsIObjectInputStream* aStream)
     110             : {
     111           0 :     nsCOMPtr<nsISupports> supports;
     112           0 :     nsresult rv = aStream->ReadObject(true, getter_AddRefs(supports));
     113           0 :     if (NS_FAILED(rv)) {
     114             :       return rv;
     115             :     }
     116           0 :     mURI = do_QueryInterface(supports);
     117             : 
     118             :     // nsIPrincipal mNodeInfoManager->mPrincipal
     119           0 :     rv = aStream->ReadObject(true, getter_AddRefs(supports));
     120           0 :     if (NS_FAILED(rv)) {
     121             :       return rv;
     122             :     }
     123           0 :     nsCOMPtr<nsIPrincipal> principal = do_QueryInterface(supports);
     124             :     // Better safe than sorry....
     125           0 :     mNodeInfoManager->SetDocumentPrincipal(principal);
     126             : 
     127           0 :     mRoot = new nsXULPrototypeElement();
     128             : 
     129             :     // mozilla::dom::NodeInfo table
     130           0 :     nsTArray<RefPtr<mozilla::dom::NodeInfo>> nodeInfos;
     131             : 
     132             :     uint32_t count, i;
     133           0 :     rv = aStream->Read32(&count);
     134           0 :     if (NS_FAILED(rv)) {
     135             :       return rv;
     136             :     }
     137           0 :     nsAutoString namespaceURI, prefixStr, localName;
     138             :     bool prefixIsNull;
     139           0 :     RefPtr<nsAtom> prefix;
     140           0 :     for (i = 0; i < count; ++i) {
     141           0 :         rv = aStream->ReadString(namespaceURI);
     142           0 :         if (NS_FAILED(rv)) {
     143           0 :           return rv;
     144             :         }
     145           0 :         rv = aStream->ReadBoolean(&prefixIsNull);
     146           0 :         if (NS_FAILED(rv)) {
     147             :           return rv;
     148             :         }
     149           0 :         if (prefixIsNull) {
     150           0 :             prefix = nullptr;
     151             :         } else {
     152           0 :             rv = aStream->ReadString(prefixStr);
     153           0 :             if (NS_FAILED(rv)) {
     154             :               return rv;
     155             :             }
     156           0 :             prefix = NS_Atomize(prefixStr);
     157             :         }
     158           0 :         rv = aStream->ReadString(localName);
     159           0 :         if (NS_FAILED(rv)) {
     160             :           return rv;
     161             :         }
     162             : 
     163           0 :         RefPtr<mozilla::dom::NodeInfo> nodeInfo;
     164             :         // Using UINT16_MAX here as we don't know which nodeinfos will be
     165             :         // used for attributes and which for elements. And that doesn't really
     166             :         // matter.
     167           0 :         rv = mNodeInfoManager->GetNodeInfo(localName, prefix, namespaceURI,
     168             :                                            UINT16_MAX,
     169           0 :                                            getter_AddRefs(nodeInfo));
     170           0 :         if (NS_FAILED(rv)) {
     171           0 :           return rv;
     172             :         }
     173           0 :         nodeInfos.AppendElement(nodeInfo);
     174             :     }
     175             : 
     176             :     // Document contents
     177             :     uint32_t type;
     178           0 :     while (NS_SUCCEEDED(rv)) {
     179           0 :         rv = aStream->Read32(&type);
     180           0 :         if (NS_FAILED(rv)) {
     181             :           return rv;
     182             :           break;
     183             :         }
     184             : 
     185           0 :         if ((nsXULPrototypeNode::Type)type == nsXULPrototypeNode::eType_PI) {
     186           0 :             RefPtr<nsXULPrototypePI> pi = new nsXULPrototypePI();
     187             : 
     188           0 :             rv = pi->Deserialize(aStream, this, mURI, &nodeInfos);
     189           0 :             if (NS_FAILED(rv)) {
     190           0 :               return rv;
     191             :             }
     192           0 :             rv = AddProcessingInstruction(pi);
     193           0 :             if (NS_FAILED(rv)) {
     194             :               return rv;
     195             :             }
     196           0 :         } else if ((nsXULPrototypeNode::Type)type == nsXULPrototypeNode::eType_Element) {
     197           0 :             rv = mRoot->Deserialize(aStream, this, mURI, &nodeInfos);
     198           0 :             if (NS_FAILED(rv)) {
     199             :               return rv;
     200             :             }
     201             :             break;
     202             :         } else {
     203           0 :             NS_NOTREACHED("Unexpected prototype node type");
     204           0 :             return NS_ERROR_FAILURE;
     205             :         }
     206             :     }
     207             : 
     208           0 :     return NotifyLoadDone();
     209             : }
     210             : 
     211             : static nsresult
     212        1300 : GetNodeInfos(nsXULPrototypeElement* aPrototype,
     213             :              nsTArray<RefPtr<mozilla::dom::NodeInfo>>& aArray)
     214             : {
     215           0 :     if (aArray.IndexOf(aPrototype->mNodeInfo) == aArray.NoIndex) {
     216          70 :         aArray.AppendElement(aPrototype->mNodeInfo);
     217             :     }
     218             : 
     219             :     // Search attributes
     220             :     uint32_t i;
     221           1 :     for (i = 0; i < aPrototype->mNumAttributes; ++i) {
     222        8064 :         RefPtr<mozilla::dom::NodeInfo> ni;
     223        4032 :         nsAttrName* name = &aPrototype->mAttributes[i].mName;
     224        4032 :         if (name->IsAtom()) {
     225             :             ni = aPrototype->mNodeInfo->NodeInfoManager()->
     226       12081 :                 GetNodeInfo(name->Atom(), nullptr, kNameSpaceID_None,
     227        4027 :                             nsINode::ATTRIBUTE_NODE);
     228             :         }
     229             :         else {
     230           5 :             ni = name->NodeInfo();
     231             :         }
     232             : 
     233           0 :         if (aArray.IndexOf(ni) == aArray.NoIndex) {
     234         254 :             aArray.AppendElement(ni);
     235             :         }
     236             :     }
     237             : 
     238             :     // Search children
     239           0 :     for (i = 0; i < aPrototype->mChildren.Length(); ++i) {
     240           0 :         nsXULPrototypeNode* child = aPrototype->mChildren[i];
     241           0 :         if (child->mType == nsXULPrototypeNode::eType_Element) {
     242             :             nsresult rv =
     243           0 :               GetNodeInfos(static_cast<nsXULPrototypeElement*>(child), aArray);
     244           0 :             NS_ENSURE_SUCCESS(rv, rv);
     245             :         }
     246             :     }
     247             : 
     248             :     return NS_OK;
     249             : }
     250             : 
     251             : NS_IMETHODIMP
     252           2 : nsXULPrototypeDocument::Write(nsIObjectOutputStream* aStream)
     253             : {
     254             :     nsresult rv;
     255             : 
     256           0 :     rv = aStream->WriteCompoundObject(mURI, NS_GET_IID(nsIURI), true);
     257             : 
     258             : 
     259             :     // nsIPrincipal mNodeInfoManager->mPrincipal
     260           0 :     nsresult tmp = aStream->WriteObject(mNodeInfoManager->DocumentPrincipal(),
     261           0 :                                true);
     262           2 :     if (NS_FAILED(tmp)) {
     263           0 :       rv = tmp;
     264             :     }
     265             : 
     266             : #ifdef DEBUG
     267             :     // XXX Worrisome if we're caching things without system principal.
     268           2 :     if (!nsContentUtils::IsSystemPrincipal(mNodeInfoManager->DocumentPrincipal())) {
     269           0 :         NS_WARNING("Serializing document without system principal");
     270             :     }
     271             : #endif
     272             : 
     273             :     // mozilla::dom::NodeInfo table
     274           4 :     nsTArray<RefPtr<mozilla::dom::NodeInfo>> nodeInfos;
     275           4 :     if (mRoot) {
     276           4 :       tmp = GetNodeInfos(mRoot, nodeInfos);
     277           0 :       if (NS_FAILED(tmp)) {
     278           0 :         rv = tmp;
     279             :       }
     280             :     }
     281             : 
     282           2 :     uint32_t nodeInfoCount = nodeInfos.Length();
     283           2 :     tmp = aStream->Write32(nodeInfoCount);
     284           0 :     if (NS_FAILED(tmp)) {
     285           0 :       rv = tmp;
     286             :     }
     287             :     uint32_t i;
     288           1 :     for (i = 0; i < nodeInfoCount; ++i) {
     289         972 :         mozilla::dom::NodeInfo *nodeInfo = nodeInfos[i];
     290         324 :         NS_ENSURE_TRUE(nodeInfo, NS_ERROR_FAILURE);
     291             : 
     292         648 :         nsAutoString namespaceURI;
     293           0 :         nodeInfo->GetNamespaceURI(namespaceURI);
     294           0 :         tmp = aStream->WriteWStringZ(namespaceURI.get());
     295           0 :         if (NS_FAILED(tmp)) {
     296           0 :           rv = tmp;
     297             :         }
     298             : 
     299         648 :         nsAutoString prefix;
     300         324 :         nodeInfo->GetPrefix(prefix);
     301           0 :         bool nullPrefix = DOMStringIsNull(prefix);
     302           1 :         tmp = aStream->WriteBoolean(nullPrefix);
     303         324 :         if (NS_FAILED(tmp)) {
     304           0 :           rv = tmp;
     305             :         }
     306         324 :         if (!nullPrefix) {
     307           0 :             tmp = aStream->WriteWStringZ(prefix.get());
     308           0 :             if (NS_FAILED(tmp)) {
     309           0 :               rv = tmp;
     310             :             }
     311             :         }
     312             : 
     313         648 :         nsAutoString localName;
     314         324 :         nodeInfo->GetName(localName);
     315           0 :         tmp = aStream->WriteWStringZ(localName.get());
     316           0 :         if (NS_FAILED(tmp)) {
     317           0 :           rv = tmp;
     318             :         }
     319             :     }
     320             : 
     321             :     // Now serialize the document contents
     322           0 :     uint32_t count = mProcessingInstructions.Length();
     323          15 :     for (i = 0; i < count; ++i) {
     324           0 :         nsXULPrototypePI* pi = mProcessingInstructions[i];
     325           0 :         tmp = pi->Serialize(aStream, this, &nodeInfos);
     326           0 :         if (NS_FAILED(tmp)) {
     327           0 :           rv = tmp;
     328             :         }
     329             :     }
     330             : 
     331           0 :     if (mRoot) {
     332           0 :       tmp = mRoot->Serialize(aStream, this, &nodeInfos);
     333           0 :       if (NS_FAILED(tmp)) {
     334           0 :         rv = tmp;
     335             :       }
     336             :     }
     337             : 
     338             :     return rv;
     339             : }
     340             : 
     341             : 
     342             : //----------------------------------------------------------------------
     343             : //
     344             : 
     345             : nsresult
     346           0 : nsXULPrototypeDocument::InitPrincipal(nsIURI* aURI, nsIPrincipal* aPrincipal)
     347             : {
     348           0 :     NS_ENSURE_ARG_POINTER(aURI);
     349             : 
     350           2 :     mURI = aURI;
     351           2 :     mNodeInfoManager->SetDocumentPrincipal(aPrincipal);
     352           2 :     return NS_OK;
     353             : }
     354             : 
     355             : 
     356             : nsIURI*
     357           0 : nsXULPrototypeDocument::GetURI()
     358             : {
     359           1 :     NS_ASSERTION(mURI, "null URI");
     360          60 :     return mURI;
     361             : }
     362             : 
     363             : 
     364             : nsXULPrototypeElement*
     365           0 : nsXULPrototypeDocument::GetRootElement()
     366             : {
     367           6 :     return mRoot;
     368             : }
     369             : 
     370             : 
     371             : void
     372           0 : nsXULPrototypeDocument::SetRootElement(nsXULPrototypeElement* aElement)
     373             : {
     374           4 :     mRoot = aElement;
     375           0 : }
     376             : 
     377             : nsresult
     378           0 : nsXULPrototypeDocument::AddProcessingInstruction(nsXULPrototypePI* aPI)
     379             : {
     380           0 :     MOZ_ASSERT(aPI, "null ptr");
     381          13 :     if (!mProcessingInstructions.AppendElement(aPI)) {
     382             :         return NS_ERROR_OUT_OF_MEMORY;
     383             :     }
     384           0 :     return NS_OK;
     385             : }
     386             : 
     387             : const nsTArray<RefPtr<nsXULPrototypePI> >&
     388           0 : nsXULPrototypeDocument::GetProcessingInstructions() const
     389             : {
     390           0 :     return mProcessingInstructions;
     391             : }
     392             : 
     393             : nsIPrincipal*
     394           1 : nsXULPrototypeDocument::DocumentPrincipal()
     395             : {
     396           2 :     MOZ_ASSERT(mNodeInfoManager, "missing nodeInfoManager");
     397           1 :     return mNodeInfoManager->DocumentPrincipal();
     398             : }
     399             : 
     400             : void
     401           0 : nsXULPrototypeDocument::SetDocumentPrincipal(nsIPrincipal* aPrincipal)
     402             : {
     403           0 :     mNodeInfoManager->SetDocumentPrincipal(aPrincipal);
     404           0 : }
     405             : 
     406             : void
     407           0 : nsXULPrototypeDocument::MarkInCCGeneration(uint32_t aCCGeneration)
     408             : {
     409           0 :     mCCGeneration = aCCGeneration;
     410           0 : }
     411             : 
     412             : nsNodeInfoManager*
     413           0 : nsXULPrototypeDocument::GetNodeInfoManager()
     414             : {
     415           4 :     return mNodeInfoManager;
     416             : }
     417             : 
     418             : 
     419             : nsresult
     420           1 : nsXULPrototypeDocument::AwaitLoadDone(XULDocument* aDocument, bool* aResult)
     421             : {
     422           1 :     nsresult rv = NS_OK;
     423             : 
     424           1 :     *aResult = mLoaded;
     425             : 
     426           1 :     if (!mLoaded) {
     427           0 :         rv = mPrototypeWaiters.AppendElement(aDocument)
     428           0 :               ? NS_OK : NS_ERROR_OUT_OF_MEMORY; // addrefs
     429             :     }
     430             : 
     431           1 :     return rv;
     432             : }
     433             : 
     434             : 
     435             : nsresult
     436           1 : nsXULPrototypeDocument::NotifyLoadDone()
     437             : {
     438             :     // Call back to each XUL document that raced to start the same
     439             :     // prototype document load, lost the race, but hit the XUL
     440             :     // prototype cache because the winner filled the cache with
     441             :     // the not-yet-loaded prototype object.
     442             : 
     443           2 :     nsresult rv = NS_OK;
     444             : 
     445           0 :     mLoaded = true;
     446             : 
     447           4 :     for (uint32_t i = mPrototypeWaiters.Length(); i > 0; ) {
     448           0 :         --i;
     449             :         // true means that OnPrototypeLoadDone will also
     450             :         // call ResumeWalk().
     451           0 :         rv = mPrototypeWaiters[i]->OnPrototypeLoadDone(true);
     452           0 :         if (NS_FAILED(rv)) break;
     453             :     }
     454           2 :     mPrototypeWaiters.Clear();
     455             : 
     456           2 :     return rv;
     457             : }
     458             : 
     459             : void
     460           0 : nsXULPrototypeDocument::TraceProtos(JSTracer* aTrc)
     461             : {
     462             :   // Only trace the protos once per GC if we are marking.
     463           0 :   if (aTrc->isMarkingTracer()) {
     464           0 :     uint32_t currentGCNumber = aTrc->gcNumberForMarking();
     465           0 :     if (mGCNumber == currentGCNumber) {
     466             :       return;
     467             :     }
     468           0 :     mGCNumber = currentGCNumber;
     469             :   }
     470             : 
     471           0 :   if (mRoot) {
     472           0 :     mRoot->TraceAllScripts(aTrc);
     473             :   }
     474             : }

Generated by: LCOV version 1.13-14-ga5dd952