|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
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 nsXULContentSink_h__ |
|
7 #define nsXULContentSink_h__ |
|
8 |
|
9 #include "mozilla/Attributes.h" |
|
10 #include "nsIExpatSink.h" |
|
11 #include "nsIXMLContentSink.h" |
|
12 #include "nsAutoPtr.h" |
|
13 #include "nsNodeInfoManager.h" |
|
14 #include "nsWeakPtr.h" |
|
15 #include "nsXULElement.h" |
|
16 #include "nsIDTD.h" |
|
17 |
|
18 class nsIDocument; |
|
19 class nsIScriptSecurityManager; |
|
20 class nsAttrName; |
|
21 class nsXULPrototypeDocument; |
|
22 class nsXULPrototypeElement; |
|
23 class nsXULPrototypeNode; |
|
24 |
|
25 class XULContentSinkImpl : public nsIXMLContentSink, |
|
26 public nsIExpatSink |
|
27 { |
|
28 public: |
|
29 XULContentSinkImpl(); |
|
30 virtual ~XULContentSinkImpl(); |
|
31 |
|
32 // nsISupports |
|
33 NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
|
34 NS_DECL_NSIEXPATSINK |
|
35 |
|
36 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(XULContentSinkImpl, nsIXMLContentSink) |
|
37 |
|
38 // nsIContentSink |
|
39 NS_IMETHOD WillParse(void) MOZ_OVERRIDE { return NS_OK; } |
|
40 NS_IMETHOD WillBuildModel(nsDTDMode aDTDMode) MOZ_OVERRIDE; |
|
41 NS_IMETHOD DidBuildModel(bool aTerminated) MOZ_OVERRIDE; |
|
42 NS_IMETHOD WillInterrupt(void) MOZ_OVERRIDE; |
|
43 NS_IMETHOD WillResume(void) MOZ_OVERRIDE; |
|
44 NS_IMETHOD SetParser(nsParserBase* aParser) MOZ_OVERRIDE; |
|
45 virtual void FlushPendingNotifications(mozFlushType aType) MOZ_OVERRIDE { } |
|
46 NS_IMETHOD SetDocumentCharset(nsACString& aCharset) MOZ_OVERRIDE; |
|
47 virtual nsISupports *GetTarget() MOZ_OVERRIDE; |
|
48 |
|
49 /** |
|
50 * Initialize the content sink, giving it an nsIDocument object |
|
51 * with which to communicate with the outside world, and an |
|
52 * nsXULPrototypeDocument to build. |
|
53 */ |
|
54 nsresult Init(nsIDocument* aDocument, nsXULPrototypeDocument* aPrototype); |
|
55 |
|
56 protected: |
|
57 // pseudo-constants |
|
58 char16_t* mText; |
|
59 int32_t mTextLength; |
|
60 int32_t mTextSize; |
|
61 bool mConstrainSize; |
|
62 |
|
63 nsresult AddAttributes(const char16_t** aAttributes, |
|
64 const uint32_t aAttrLen, |
|
65 nsXULPrototypeElement* aElement); |
|
66 |
|
67 nsresult OpenRoot(const char16_t** aAttributes, |
|
68 const uint32_t aAttrLen, |
|
69 nsINodeInfo *aNodeInfo); |
|
70 |
|
71 nsresult OpenTag(const char16_t** aAttributes, |
|
72 const uint32_t aAttrLen, |
|
73 const uint32_t aLineNumber, |
|
74 nsINodeInfo *aNodeInfo); |
|
75 |
|
76 // If OpenScript returns NS_OK and after it returns our state is eInScript, |
|
77 // that means that we created a prototype script and stuck it on |
|
78 // mContextStack. If NS_OK is returned but the state is still |
|
79 // eInDocumentElement then we didn't create a prototype script (e.g. the |
|
80 // script had an unknown type), and the caller should create a prototype |
|
81 // element. |
|
82 nsresult OpenScript(const char16_t** aAttributes, |
|
83 const uint32_t aLineNumber); |
|
84 |
|
85 static bool IsDataInBuffer(char16_t* aBuffer, int32_t aLength); |
|
86 |
|
87 // Text management |
|
88 nsresult FlushText(bool aCreateTextNode = true); |
|
89 nsresult AddText(const char16_t* aText, int32_t aLength); |
|
90 |
|
91 |
|
92 nsRefPtr<nsNodeInfoManager> mNodeInfoManager; |
|
93 |
|
94 nsresult NormalizeAttributeString(const char16_t *aExpatName, |
|
95 nsAttrName &aName); |
|
96 nsresult CreateElement(nsINodeInfo *aNodeInfo, |
|
97 nsXULPrototypeElement** aResult); |
|
98 |
|
99 |
|
100 public: |
|
101 enum State { eInProlog, eInDocumentElement, eInScript, eInEpilog }; |
|
102 protected: |
|
103 |
|
104 State mState; |
|
105 |
|
106 // content stack management |
|
107 class ContextStack { |
|
108 protected: |
|
109 struct Entry { |
|
110 nsRefPtr<nsXULPrototypeNode> mNode; |
|
111 // a LOT of nodes have children; preallocate for 8 |
|
112 nsPrototypeArray mChildren; |
|
113 State mState; |
|
114 Entry* mNext; |
|
115 Entry() : mChildren(8) {} |
|
116 }; |
|
117 |
|
118 Entry* mTop; |
|
119 int32_t mDepth; |
|
120 |
|
121 public: |
|
122 ContextStack(); |
|
123 ~ContextStack(); |
|
124 |
|
125 int32_t Depth() { return mDepth; } |
|
126 |
|
127 nsresult Push(nsXULPrototypeNode* aNode, State aState); |
|
128 nsresult Pop(State* aState); |
|
129 |
|
130 nsresult GetTopNode(nsRefPtr<nsXULPrototypeNode>& aNode); |
|
131 nsresult GetTopChildren(nsPrototypeArray** aChildren); |
|
132 |
|
133 void Clear(); |
|
134 |
|
135 void Traverse(nsCycleCollectionTraversalCallback& aCallback); |
|
136 }; |
|
137 |
|
138 friend class ContextStack; |
|
139 ContextStack mContextStack; |
|
140 |
|
141 nsWeakPtr mDocument; // [OWNER] |
|
142 nsCOMPtr<nsIURI> mDocumentURL; // [OWNER] |
|
143 |
|
144 nsRefPtr<nsXULPrototypeDocument> mPrototype; // [OWNER] |
|
145 |
|
146 // We use regular pointer b/c of funky exports on nsIParser: |
|
147 nsParserBase* mParser; // [OWNER] |
|
148 nsCOMPtr<nsIScriptSecurityManager> mSecMan; |
|
149 }; |
|
150 |
|
151 #endif /* nsXULContentSink_h__ */ |