1 /* -*- Mode: C++; tab-width: 4; 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 #ifndef nsXULPrototypeDocument_h__
7 #define nsXULPrototypeDocument_h__
8 
9 #include "js/TracingAPI.h"
10 #include "mozilla/Attributes.h"
11 #include "nsCOMArray.h"
12 #include "nsCOMPtr.h"
13 #include "nsTArray.h"
14 #include "nsISerializable.h"
15 #include "nsCycleCollectionParticipant.h"
16 #include <functional>
17 
18 class nsAtom;
19 class nsIPrincipal;
20 class nsIURI;
21 class nsNodeInfoManager;
22 class nsXULPrototypeElement;
23 class nsXULPrototypePI;
24 
25 namespace mozilla::dom {
26 class Element;
27 }
28 
29 /**
30  * A "prototype" document that stores shared document information
31  * for the XUL cache.
32  * Among other things, stores the tree of nsXULPrototype*
33  * objects, from which the real DOM tree is built later in
34  * PrototypeDocumentContentSink::ResumeWalk.
35  */
36 class nsXULPrototypeDocument final : public nsISerializable {
37  public:
38   typedef std::function<void()> Callback;
39 
40   // nsISupports interface
41   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
42 
43   // nsISerializable interface
44   NS_DECL_NSISERIALIZABLE
45 
46   nsresult InitPrincipal(nsIURI* aURI, nsIPrincipal* aPrincipal);
47   nsIURI* GetURI();
48 
49   /**
50    * Get/set the root nsXULPrototypeElement of the document.
51    */
52   nsXULPrototypeElement* GetRootElement();
53   void SetRootElement(nsXULPrototypeElement* aElement);
54 
55   /**
56    * Add a processing instruction to the prolog. Note that only
57    * PI nodes are currently stored in a XUL prototype document's
58    * prolog and that they're handled separately from the rest of
59    * prototype node tree.
60    *
61    * @param aPI an already adrefed PI proto to add. This method takes
62    *            ownership of the passed PI.
63    */
64   nsresult AddProcessingInstruction(nsXULPrototypePI* aPI);
65   /**
66    * @note GetProcessingInstructions retains the ownership (the PI
67    *       protos only get deleted when the proto document is deleted)
68    */
69   const nsTArray<RefPtr<nsXULPrototypePI> >& GetProcessingInstructions() const;
70 
71   nsIPrincipal* DocumentPrincipal();
72   void SetDocumentPrincipal(nsIPrincipal* aPrincipal);
73 
74   /**
75    * If current prototype document has not yet finished loading,
76    * appends aDocument to the list of documents to notify (via
77    * PrototypeDocumentContentSink::OnPrototypeLoadDone()) and
78    * sets aLoaded to false. Otherwise sets aLoaded to true.
79    */
80   nsresult AwaitLoadDone(Callback&& aCallback, bool* aResult);
81 
82   /**
83    * Notifies each document registered via AwaitLoadDone on this
84    * prototype document that the prototype has finished loading.
85    * The notification is performed by calling
86    * PrototypeDocumentContentSink::OnPrototypeLoadDone on the
87    * registered documents.
88    */
89   nsresult NotifyLoadDone();
90 
91   nsNodeInfoManager* GetNodeInfoManager();
92 
93   void MarkInCCGeneration(uint32_t aCCGeneration);
94 
95   NS_DECL_CYCLE_COLLECTION_CLASS(nsXULPrototypeDocument)
96 
97   void TraceProtos(JSTracer* aTrc);
98 
WasL10nCached()99   bool WasL10nCached() { return mWasL10nCached; };
100 
101   void SetIsL10nCached(bool aIsCached);
102   void RebuildPrototypeFromElement(nsXULPrototypeElement* aPrototype,
103                                    mozilla::dom::Element* aElement, bool aDeep);
104   void RebuildL10nPrototype(mozilla::dom::Element* aElement, bool aDeep);
105 
106  protected:
107   nsCOMPtr<nsIURI> mURI;
108   RefPtr<nsXULPrototypeElement> mRoot;
109   nsTArray<RefPtr<nsXULPrototypePI> > mProcessingInstructions;
110 
111   bool mLoaded;
112   nsTArray<Callback> mPrototypeWaiters;
113 
114   RefPtr<nsNodeInfoManager> mNodeInfoManager;
115 
116   uint32_t mCCGeneration;
117   uint32_t mGCNumber;
118 
119   nsXULPrototypeDocument();
120   virtual ~nsXULPrototypeDocument();
121   nsresult Init();
122 
123   friend NS_IMETHODIMP NS_NewXULPrototypeDocument(
124       nsXULPrototypeDocument** aResult);
125 
126   static uint32_t gRefCnt;
127   bool mWasL10nCached;
128 };
129 
130 #endif  // nsXULPrototypeDocument_h__
131