LCOV - code coverage report
Current view: top level - dom/xul - nsXULPrototypeDocument.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 104 254 40.9 %
Date: 2017-07-14 16:53:18 Functions: 18 33 54.5 %
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           6 : nsXULPrototypeDocument::nsXULPrototypeDocument()
      43             :     : mRoot(nullptr),
      44             :       mLoaded(false),
      45             :       mCCGeneration(0),
      46           6 :       mGCNumber(0)
      47             : {
      48           6 :     ++gRefCnt;
      49           6 : }
      50             : 
      51             : 
      52             : nsresult
      53           6 : nsXULPrototypeDocument::Init()
      54             : {
      55           6 :     mNodeInfoManager = new nsNodeInfoManager();
      56           6 :     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           0 :         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           6 : 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          25 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULPrototypeDocument)
      85          11 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULPrototypeDocument)
      86             : 
      87             : NS_IMETHODIMP
      88           6 : NS_NewXULPrototypeDocument(nsXULPrototypeDocument** aResult)
      89             : {
      90           6 :     *aResult = nullptr;
      91             :     RefPtr<nsXULPrototypeDocument> doc =
      92          12 :       new nsXULPrototypeDocument();
      93             : 
      94           6 :     nsresult rv = doc->Init();
      95           6 :     if (NS_FAILED(rv)) {
      96           0 :         return rv;
      97             :     }
      98             : 
      99           6 :     doc.forget(aResult);
     100           6 :     return rv;
     101             : }
     102             : 
     103             : //----------------------------------------------------------------------
     104             : //
     105             : // nsISerializable methods
     106             : //
     107             : 
     108             : NS_IMETHODIMP
     109           6 : nsXULPrototypeDocument::Read(nsIObjectInputStream* aStream)
     110             : {
     111             :     nsresult rv;
     112             : 
     113          12 :     nsCOMPtr<nsISupports> supports;
     114           6 :     rv = aStream->ReadObject(true, getter_AddRefs(supports));
     115           6 :     mURI = do_QueryInterface(supports);
     116             : 
     117             :     uint32_t count, i;
     118          12 :     nsCOMPtr<nsIURI> styleOverlayURI;
     119             : 
     120           6 :     nsresult tmp = aStream->Read32(&count);
     121           6 :     if (NS_FAILED(tmp)) {
     122           0 :       return tmp;
     123             :     }
     124           6 :     if (NS_FAILED(rv)) {
     125           0 :       return rv;
     126             :     }
     127             : 
     128           6 :     for (i = 0; i < count; ++i) {
     129           0 :         tmp = aStream->ReadObject(true, getter_AddRefs(supports));
     130           0 :         if (NS_FAILED(tmp)) {
     131           0 :           rv = tmp;
     132             :         }
     133           0 :         styleOverlayURI = do_QueryInterface(supports);
     134           0 :         mStyleSheetReferences.AppendObject(styleOverlayURI);
     135             :     }
     136             : 
     137             : 
     138             :     // nsIPrincipal mNodeInfoManager->mPrincipal
     139          12 :     nsCOMPtr<nsIPrincipal> principal;
     140           6 :     tmp = aStream->ReadObject(true, getter_AddRefs(supports));
     141           6 :     principal = do_QueryInterface(supports);
     142           6 :     if (NS_FAILED(tmp)) {
     143           0 :       rv = tmp;
     144             :     }
     145             :     // Better safe than sorry....
     146           6 :     mNodeInfoManager->SetDocumentPrincipal(principal);
     147             : 
     148           6 :     mRoot = new nsXULPrototypeElement();
     149             : 
     150             :     // mozilla::dom::NodeInfo table
     151          12 :     nsTArray<RefPtr<mozilla::dom::NodeInfo>> nodeInfos;
     152             : 
     153           6 :     tmp = aStream->Read32(&count);
     154           6 :     if (NS_FAILED(tmp)) {
     155           0 :       rv = tmp;
     156             :     }
     157          12 :     nsAutoString namespaceURI, prefixStr, localName;
     158             :     bool prefixIsNull;
     159          12 :     nsCOMPtr<nsIAtom> prefix;
     160         401 :     for (i = 0; i < count; ++i) {
     161         395 :         tmp = aStream->ReadString(namespaceURI);
     162         395 :         if (NS_FAILED(tmp)) {
     163           0 :           rv = tmp;
     164             :         }
     165         395 :         tmp = aStream->ReadBoolean(&prefixIsNull);
     166         395 :         if (NS_FAILED(tmp)) {
     167           0 :           rv = tmp;
     168             :         }
     169         395 :         if (prefixIsNull) {
     170         379 :             prefix = nullptr;
     171             :         } else {
     172          16 :             tmp = aStream->ReadString(prefixStr);
     173          16 :             if (NS_FAILED(tmp)) {
     174           0 :               rv = tmp;
     175             :             }
     176          16 :             prefix = NS_Atomize(prefixStr);
     177             :         }
     178         395 :         tmp = aStream->ReadString(localName);
     179         395 :         if (NS_FAILED(tmp)) {
     180           0 :           rv = tmp;
     181             :         }
     182             : 
     183         790 :         RefPtr<mozilla::dom::NodeInfo> nodeInfo;
     184             :         // Using UINT16_MAX here as we don't know which nodeinfos will be
     185             :         // used for attributes and which for elements. And that doesn't really
     186             :         // matter.
     187         395 :         tmp = mNodeInfoManager->GetNodeInfo(localName, prefix, namespaceURI,
     188             :                                             UINT16_MAX,
     189         790 :                                             getter_AddRefs(nodeInfo));
     190         395 :         if (NS_FAILED(tmp)) {
     191           0 :           rv = tmp;
     192             :         }
     193         395 :         nodeInfos.AppendElement(nodeInfo);
     194             :     }
     195             : 
     196             :     // Document contents
     197             :     uint32_t type;
     198          24 :     while (NS_SUCCEEDED(rv)) {
     199          15 :         tmp = aStream->Read32(&type);
     200          15 :         if (NS_FAILED(tmp)) {
     201           0 :           rv = tmp;
     202             :         }
     203             : 
     204          15 :         if ((nsXULPrototypeNode::Type)type == nsXULPrototypeNode::eType_PI) {
     205          18 :             RefPtr<nsXULPrototypePI> pi = new nsXULPrototypePI();
     206             : 
     207           9 :             tmp = pi->Deserialize(aStream, this, mURI, &nodeInfos);
     208           9 :             if (NS_FAILED(tmp)) {
     209           0 :               rv = tmp;
     210             :             }
     211           9 :             tmp = AddProcessingInstruction(pi);
     212           9 :             if (NS_FAILED(tmp)) {
     213           0 :               rv = tmp;
     214             :             }
     215           6 :         } else if ((nsXULPrototypeNode::Type)type == nsXULPrototypeNode::eType_Element) {
     216           6 :             tmp = mRoot->Deserialize(aStream, this, mURI, &nodeInfos);
     217           6 :             if (NS_FAILED(tmp)) {
     218           0 :               rv = tmp;
     219             :             }
     220           6 :             break;
     221             :         } else {
     222           0 :             NS_NOTREACHED("Unexpected prototype node type");
     223           0 :             rv = NS_ERROR_FAILURE;
     224           0 :             break;
     225             :         }
     226             :     }
     227           6 :     tmp = NotifyLoadDone();
     228           6 :     if (NS_FAILED(tmp)) {
     229           0 :       rv = tmp;
     230             :     }
     231             : 
     232           6 :     return rv;
     233             : }
     234             : 
     235             : static nsresult
     236           0 : GetNodeInfos(nsXULPrototypeElement* aPrototype,
     237             :              nsTArray<RefPtr<mozilla::dom::NodeInfo>>& aArray)
     238             : {
     239           0 :     if (aArray.IndexOf(aPrototype->mNodeInfo) == aArray.NoIndex) {
     240           0 :         aArray.AppendElement(aPrototype->mNodeInfo);
     241             :     }
     242             : 
     243             :     // Search attributes
     244             :     uint32_t i;
     245           0 :     for (i = 0; i < aPrototype->mNumAttributes; ++i) {
     246           0 :         RefPtr<mozilla::dom::NodeInfo> ni;
     247           0 :         nsAttrName* name = &aPrototype->mAttributes[i].mName;
     248           0 :         if (name->IsAtom()) {
     249             :             ni = aPrototype->mNodeInfo->NodeInfoManager()->
     250           0 :                 GetNodeInfo(name->Atom(), nullptr, kNameSpaceID_None,
     251           0 :                             nsIDOMNode::ATTRIBUTE_NODE);
     252             :         }
     253             :         else {
     254           0 :             ni = name->NodeInfo();
     255             :         }
     256             : 
     257           0 :         if (aArray.IndexOf(ni) == aArray.NoIndex) {
     258           0 :             aArray.AppendElement(ni);
     259             :         }
     260             :     }
     261             : 
     262             :     // Search children
     263           0 :     for (i = 0; i < aPrototype->mChildren.Length(); ++i) {
     264           0 :         nsXULPrototypeNode* child = aPrototype->mChildren[i];
     265           0 :         if (child->mType == nsXULPrototypeNode::eType_Element) {
     266             :             nsresult rv =
     267           0 :               GetNodeInfos(static_cast<nsXULPrototypeElement*>(child), aArray);
     268           0 :             NS_ENSURE_SUCCESS(rv, rv);
     269             :         }
     270             :     }
     271             : 
     272           0 :     return NS_OK;
     273             : }
     274             : 
     275             : NS_IMETHODIMP
     276           0 : nsXULPrototypeDocument::Write(nsIObjectOutputStream* aStream)
     277             : {
     278             :     nsresult rv;
     279             : 
     280           0 :     rv = aStream->WriteCompoundObject(mURI, NS_GET_IID(nsIURI), true);
     281             : 
     282             :     uint32_t count;
     283             : 
     284           0 :     count = mStyleSheetReferences.Count();
     285           0 :     nsresult tmp = aStream->Write32(count);
     286           0 :     if (NS_FAILED(tmp)) {
     287           0 :       rv = tmp;
     288             :     }
     289             : 
     290             :     uint32_t i;
     291           0 :     for (i = 0; i < count; ++i) {
     292           0 :         tmp = aStream->WriteCompoundObject(mStyleSheetReferences[i],
     293           0 :                                            NS_GET_IID(nsIURI), true);
     294           0 :         if (NS_FAILED(tmp)) {
     295           0 :           rv = tmp;
     296             :         }
     297             :     }
     298             : 
     299             :     // nsIPrincipal mNodeInfoManager->mPrincipal
     300           0 :     tmp = aStream->WriteObject(mNodeInfoManager->DocumentPrincipal(),
     301           0 :                                true);
     302           0 :     if (NS_FAILED(tmp)) {
     303           0 :       rv = tmp;
     304             :     }
     305             : 
     306             : #ifdef DEBUG
     307             :     // XXX Worrisome if we're caching things without system principal.
     308           0 :     if (!nsContentUtils::IsSystemPrincipal(mNodeInfoManager->DocumentPrincipal())) {
     309           0 :         NS_WARNING("Serializing document without system principal");
     310             :     }
     311             : #endif
     312             : 
     313             :     // mozilla::dom::NodeInfo table
     314           0 :     nsTArray<RefPtr<mozilla::dom::NodeInfo>> nodeInfos;
     315           0 :     if (mRoot) {
     316           0 :       tmp = GetNodeInfos(mRoot, nodeInfos);
     317           0 :       if (NS_FAILED(tmp)) {
     318           0 :         rv = tmp;
     319             :       }
     320             :     }
     321             : 
     322           0 :     uint32_t nodeInfoCount = nodeInfos.Length();
     323           0 :     tmp = aStream->Write32(nodeInfoCount);
     324           0 :     if (NS_FAILED(tmp)) {
     325           0 :       rv = tmp;
     326             :     }
     327           0 :     for (i = 0; i < nodeInfoCount; ++i) {
     328           0 :         mozilla::dom::NodeInfo *nodeInfo = nodeInfos[i];
     329           0 :         NS_ENSURE_TRUE(nodeInfo, NS_ERROR_FAILURE);
     330             : 
     331           0 :         nsAutoString namespaceURI;
     332           0 :         nodeInfo->GetNamespaceURI(namespaceURI);
     333           0 :         tmp = aStream->WriteWStringZ(namespaceURI.get());
     334           0 :         if (NS_FAILED(tmp)) {
     335           0 :           rv = tmp;
     336             :         }
     337             : 
     338           0 :         nsAutoString prefix;
     339           0 :         nodeInfo->GetPrefix(prefix);
     340           0 :         bool nullPrefix = DOMStringIsNull(prefix);
     341           0 :         tmp = aStream->WriteBoolean(nullPrefix);
     342           0 :         if (NS_FAILED(tmp)) {
     343           0 :           rv = tmp;
     344             :         }
     345           0 :         if (!nullPrefix) {
     346           0 :             tmp = aStream->WriteWStringZ(prefix.get());
     347           0 :             if (NS_FAILED(tmp)) {
     348           0 :               rv = tmp;
     349             :             }
     350             :         }
     351             : 
     352           0 :         nsAutoString localName;
     353           0 :         nodeInfo->GetName(localName);
     354           0 :         tmp = aStream->WriteWStringZ(localName.get());
     355           0 :         if (NS_FAILED(tmp)) {
     356           0 :           rv = tmp;
     357             :         }
     358             :     }
     359             : 
     360             :     // Now serialize the document contents
     361           0 :     count = mProcessingInstructions.Length();
     362           0 :     for (i = 0; i < count; ++i) {
     363           0 :         nsXULPrototypePI* pi = mProcessingInstructions[i];
     364           0 :         tmp = pi->Serialize(aStream, this, &nodeInfos);
     365           0 :         if (NS_FAILED(tmp)) {
     366           0 :           rv = tmp;
     367             :         }
     368             :     }
     369             : 
     370           0 :     if (mRoot) {
     371           0 :       tmp = mRoot->Serialize(aStream, this, &nodeInfos);
     372           0 :       if (NS_FAILED(tmp)) {
     373           0 :         rv = tmp;
     374             :       }
     375             :     }
     376             : 
     377           0 :     return rv;
     378             : }
     379             : 
     380             : 
     381             : //----------------------------------------------------------------------
     382             : //
     383             : 
     384             : nsresult
     385           0 : nsXULPrototypeDocument::InitPrincipal(nsIURI* aURI, nsIPrincipal* aPrincipal)
     386             : {
     387           0 :     NS_ENSURE_ARG_POINTER(aURI);
     388             : 
     389           0 :     mURI = aURI;
     390           0 :     mNodeInfoManager->SetDocumentPrincipal(aPrincipal);
     391           0 :     return NS_OK;
     392             : }
     393             : 
     394             : 
     395             : nsIURI*
     396          67 : nsXULPrototypeDocument::GetURI()
     397             : {
     398          67 :     NS_ASSERTION(mURI, "null URI");
     399          67 :     return mURI;
     400             : }
     401             : 
     402             : 
     403             : nsXULPrototypeElement*
     404           6 : nsXULPrototypeDocument::GetRootElement()
     405             : {
     406           6 :     return mRoot;
     407             : }
     408             : 
     409             : 
     410             : void
     411           0 : nsXULPrototypeDocument::SetRootElement(nsXULPrototypeElement* aElement)
     412             : {
     413           0 :     mRoot = aElement;
     414           0 : }
     415             : 
     416             : nsresult
     417           9 : nsXULPrototypeDocument::AddProcessingInstruction(nsXULPrototypePI* aPI)
     418             : {
     419           9 :     NS_PRECONDITION(aPI, "null ptr");
     420           9 :     if (!mProcessingInstructions.AppendElement(aPI)) {
     421           0 :         return NS_ERROR_OUT_OF_MEMORY;
     422             :     }
     423           9 :     return NS_OK;
     424             : }
     425             : 
     426             : const nsTArray<RefPtr<nsXULPrototypePI> >&
     427           6 : nsXULPrototypeDocument::GetProcessingInstructions() const
     428             : {
     429           6 :     return mProcessingInstructions;
     430             : }
     431             : 
     432             : void
     433           0 : nsXULPrototypeDocument::AddStyleSheetReference(nsIURI* aURI)
     434             : {
     435           0 :     NS_PRECONDITION(aURI, "null ptr");
     436           0 :     if (!mStyleSheetReferences.AppendObject(aURI)) {
     437             :         NS_WARNING("mStyleSheetReferences->AppendElement() failed."
     438           0 :                    "Stylesheet overlay dropped.");
     439             :     }
     440           0 : }
     441             : 
     442             : const nsCOMArray<nsIURI>&
     443           6 : nsXULPrototypeDocument::GetStyleSheetReferences() const
     444             : {
     445           6 :     return mStyleSheetReferences;
     446             : }
     447             : 
     448             : NS_IMETHODIMP
     449           0 : nsXULPrototypeDocument::GetHeaderData(nsIAtom* aField, nsAString& aData) const
     450             : {
     451             :     // XXX Not implemented
     452           0 :     aData.Truncate();
     453           0 :     return NS_OK;
     454             : }
     455             : 
     456             : 
     457             : NS_IMETHODIMP
     458           0 : nsXULPrototypeDocument::SetHeaderData(nsIAtom* aField, const nsAString& aData)
     459             : {
     460             :     // XXX Not implemented
     461           0 :     return NS_OK;
     462             : }
     463             : 
     464             : 
     465             : 
     466             : nsIPrincipal*
     467           1 : nsXULPrototypeDocument::DocumentPrincipal()
     468             : {
     469           1 :     NS_PRECONDITION(mNodeInfoManager, "missing nodeInfoManager");
     470           1 :     return mNodeInfoManager->DocumentPrincipal();
     471             : }
     472             : 
     473             : void
     474           0 : nsXULPrototypeDocument::SetDocumentPrincipal(nsIPrincipal* aPrincipal)
     475             : {
     476           0 :     mNodeInfoManager->SetDocumentPrincipal(aPrincipal);
     477           0 : }
     478             : 
     479             : void
     480           0 : nsXULPrototypeDocument::MarkInCCGeneration(uint32_t aCCGeneration)
     481             : {
     482           0 :     mCCGeneration = aCCGeneration;
     483           0 : }
     484             : 
     485             : nsNodeInfoManager*
     486           0 : nsXULPrototypeDocument::GetNodeInfoManager()
     487             : {
     488           0 :     return mNodeInfoManager;
     489             : }
     490             : 
     491             : 
     492             : nsresult
     493           6 : nsXULPrototypeDocument::AwaitLoadDone(XULDocument* aDocument, bool* aResult)
     494             : {
     495           6 :     nsresult rv = NS_OK;
     496             : 
     497           6 :     *aResult = mLoaded;
     498             : 
     499           6 :     if (!mLoaded) {
     500           0 :         rv = mPrototypeWaiters.AppendElement(aDocument)
     501           0 :               ? NS_OK : NS_ERROR_OUT_OF_MEMORY; // addrefs
     502             :     }
     503             : 
     504           6 :     return rv;
     505             : }
     506             : 
     507             : 
     508             : nsresult
     509           6 : nsXULPrototypeDocument::NotifyLoadDone()
     510             : {
     511             :     // Call back to each XUL document that raced to start the same
     512             :     // prototype document load, lost the race, but hit the XUL
     513             :     // prototype cache because the winner filled the cache with
     514             :     // the not-yet-loaded prototype object.
     515             : 
     516           6 :     nsresult rv = NS_OK;
     517             : 
     518           6 :     mLoaded = true;
     519             : 
     520           6 :     for (uint32_t i = mPrototypeWaiters.Length(); i > 0; ) {
     521           0 :         --i;
     522             :         // true means that OnPrototypeLoadDone will also
     523             :         // call ResumeWalk().
     524           0 :         rv = mPrototypeWaiters[i]->OnPrototypeLoadDone(true);
     525           0 :         if (NS_FAILED(rv)) break;
     526             :     }
     527           6 :     mPrototypeWaiters.Clear();
     528             : 
     529           6 :     return rv;
     530             : }
     531             : 
     532             : void
     533           7 : nsXULPrototypeDocument::TraceProtos(JSTracer* aTrc, uint32_t aGCNumber)
     534             : {
     535             :   // Only trace the protos once per GC.
     536           7 :   if (mGCNumber == aGCNumber) {
     537           1 :     return;
     538             :   }
     539             : 
     540           6 :   mGCNumber = aGCNumber;
     541           6 :   if (mRoot) {
     542           6 :     mRoot->TraceAllScripts(aTrc);
     543             :   }
     544           9 : }

Generated by: LCOV version 1.13