dom/xbl/nsXBLPrototypeBinding.h

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:978496fc4cb0
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 #ifndef nsXBLPrototypeBinding_h__
7 #define nsXBLPrototypeBinding_h__
8
9 #include "nsClassHashtable.h"
10 #include "nsCOMArray.h"
11 #include "nsCOMPtr.h"
12 #include "nsICSSLoaderObserver.h"
13 #include "nsInterfaceHashtable.h"
14 #include "nsWeakReference.h"
15 #include "nsXBLDocumentInfo.h"
16 #include "nsXBLProtoImpl.h"
17 #include "nsXBLProtoImplMethod.h"
18 #include "nsXBLPrototypeHandler.h"
19 #include "nsXBLPrototypeResources.h"
20
21 class nsIAtom;
22 class nsIContent;
23 class nsIDocument;
24 class nsXBLAttributeEntry;
25 class nsXBLBinding;
26 class nsXBLProtoImplField;
27
28 // *********************************************************************/
29 // The XBLPrototypeBinding class
30
31 // Instances of this class are owned by the nsXBLDocumentInfo object returned
32 // by XBLDocumentInfo(). Consumers who want to refcount things should refcount
33 // that.
34 class nsXBLPrototypeBinding MOZ_FINAL
35 {
36 public:
37 nsIContent* GetBindingElement() const { return mBinding; }
38 void SetBindingElement(nsIContent* aElement);
39
40 nsIURI* BindingURI() const { return mBindingURI; }
41 nsIURI* AlternateBindingURI() const { return mAlternateBindingURI; }
42 nsIURI* DocURI() const { return mXBLDocInfoWeak->DocumentURI(); }
43 nsIURI* GetBaseBindingURI() const { return mBaseBindingURI; }
44
45 // Checks if aURI refers to this binding by comparing to both possible
46 // binding URIs.
47 bool CompareBindingURI(nsIURI* aURI) const;
48
49 bool GetAllowScripts() const;
50
51 nsresult BindingAttached(nsIContent* aBoundElement);
52 nsresult BindingDetached(nsIContent* aBoundElement);
53
54 bool LoadResources();
55 nsresult AddResource(nsIAtom* aResourceType, const nsAString& aSrc);
56
57 bool InheritsStyle() const { return mInheritStyle; }
58 void SetInheritsStyle(bool aInheritStyle) { mInheritStyle = aInheritStyle; }
59
60 nsXBLPrototypeHandler* GetPrototypeHandlers() { return mPrototypeHandler; }
61 void SetPrototypeHandlers(nsXBLPrototypeHandler* aHandler) { mPrototypeHandler = aHandler; }
62
63 nsXBLProtoImplAnonymousMethod* GetConstructor();
64 nsresult SetConstructor(nsXBLProtoImplAnonymousMethod* aConstructor);
65 nsXBLProtoImplAnonymousMethod* GetDestructor();
66 nsresult SetDestructor(nsXBLProtoImplAnonymousMethod* aDestructor);
67
68 nsXBLProtoImplField* FindField(const nsString& aFieldName) const
69 {
70 return mImplementation ? mImplementation->FindField(aFieldName) : nullptr;
71 }
72
73 // Resolve all the fields for this binding on the object |obj|.
74 // False return means a JS exception was set.
75 bool ResolveAllFields(JSContext* cx, JS::Handle<JSObject*> obj) const
76 {
77 return !mImplementation || mImplementation->ResolveAllFields(cx, obj);
78 }
79
80 // Undefine all our fields from object |obj| (which should be a
81 // JSObject for a bound element).
82 void UndefineFields(JSContext* cx, JS::Handle<JSObject*> obj) const {
83 if (mImplementation) {
84 mImplementation->UndefineFields(cx, obj);
85 }
86 }
87
88 const nsCString& ClassName() const {
89 return mImplementation ? mImplementation->mClassName : EmptyCString();
90 }
91
92 nsresult InitClass(const nsCString& aClassName, JSContext * aContext,
93 JS::Handle<JSObject*> aScriptObject,
94 JS::MutableHandle<JSObject*> aClassObject,
95 bool* aNew);
96
97 nsresult ConstructInterfaceTable(const nsAString& aImpls);
98
99 void SetImplementation(nsXBLProtoImpl* aImpl) { mImplementation = aImpl; }
100 nsXBLProtoImpl* GetImplementation() { return mImplementation; }
101 nsresult InstallImplementation(nsXBLBinding* aBinding);
102 bool HasImplementation() const { return mImplementation != nullptr; }
103
104 void AttributeChanged(nsIAtom* aAttribute, int32_t aNameSpaceID,
105 bool aRemoveFlag, nsIContent* aChangedElement,
106 nsIContent* aAnonymousContent, bool aNotify);
107
108 void SetBasePrototype(nsXBLPrototypeBinding* aBinding);
109 nsXBLPrototypeBinding* GetBasePrototype() { return mBaseBinding; }
110
111 nsXBLDocumentInfo* XBLDocumentInfo() const { return mXBLDocInfoWeak; }
112 bool IsChrome() { return mXBLDocInfoWeak->IsChrome(); }
113
114 void SetInitialAttributes(nsIContent* aBoundElement, nsIContent* aAnonymousContent);
115
116 nsIStyleRuleProcessor* GetRuleProcessor();
117 nsXBLPrototypeResources::sheet_array_type* GetOrCreateStyleSheets();
118 nsXBLPrototypeResources::sheet_array_type* GetStyleSheets();
119
120 bool HasStyleSheets() {
121 return mResources && mResources->mStyleSheetList.Length() > 0;
122 }
123
124 nsresult FlushSkinSheets();
125
126 nsIAtom* GetBaseTag(int32_t* aNamespaceID);
127 void SetBaseTag(int32_t aNamespaceID, nsIAtom* aTag);
128
129 bool ImplementsInterface(REFNSIID aIID) const;
130
131 nsresult AddResourceListener(nsIContent* aBoundElement);
132
133 void Initialize();
134
135 nsresult ResolveBaseBinding();
136
137 const nsCOMArray<nsXBLKeyEventHandler>* GetKeyEventHandlers()
138 {
139 if (!mKeyHandlersRegistered) {
140 CreateKeyHandlers();
141 mKeyHandlersRegistered = true;
142 }
143
144 return &mKeyHandlers;
145 }
146
147 private:
148 nsresult Read(nsIObjectInputStream* aStream,
149 nsXBLDocumentInfo* aDocInfo,
150 nsIDocument* aDocument,
151 uint8_t aFlags);
152
153 /**
154 * Read a new binding from the stream aStream into the xbl document aDocument.
155 * aDocInfo should be the xbl document info for the binding document.
156 * aFlags can contain XBLBinding_Serialize_InheritStyle to indicate that
157 * mInheritStyle flag should be set, and XBLBinding_Serialize_IsFirstBinding
158 * to indicate the first binding in a document.
159 * XBLBinding_Serialize_ChromeOnlyContent indicates that
160 * nsXBLPrototypeBinding::mChromeOnlyContent should be true.
161 */
162 public:
163 static nsresult ReadNewBinding(nsIObjectInputStream* aStream,
164 nsXBLDocumentInfo* aDocInfo,
165 nsIDocument* aDocument,
166 uint8_t aFlags);
167
168 /**
169 * Write this binding to the stream.
170 */
171 nsresult Write(nsIObjectOutputStream* aStream);
172
173 /**
174 * Read a content node from aStream and return it in aChild.
175 * aDocument and aNim are the document and node info manager for the document
176 * the child will be inserted into.
177 */
178 nsresult ReadContentNode(nsIObjectInputStream* aStream,
179 nsIDocument* aDocument,
180 nsNodeInfoManager* aNim,
181 nsIContent** aChild);
182
183 /**
184 * Write the content node aNode to aStream.
185 *
186 * This method is called recursively for each child descendant. For the topmost
187 * call, aNode must be an element.
188 *
189 * Text, CDATA and comment nodes are serialized as:
190 * the constant XBLBinding_Serialize_TextNode, XBLBinding_Serialize_CDATANode
191 * or XBLBinding_Serialize_CommentNode
192 * the text for the node
193 * Elements are serialized in the following format:
194 * node's namespace, written with WriteNamespace
195 * node's namespace prefix
196 * node's tag
197 * 32-bit attribute count
198 * table of attributes:
199 * attribute's namespace, written with WriteNamespace
200 * attribute's namespace prefix
201 * attribute's tag
202 * attribute's value
203 * attribute forwarding table:
204 * source namespace
205 * source attribute
206 * destination namespace
207 * destination attribute
208 * the constant XBLBinding_Serialize_NoMoreAttributes
209 * 32-bit count of the number of child nodes
210 * each child node is serialized in the same manner in sequence
211 * the constant XBLBinding_Serialize_NoContent
212 */
213 nsresult WriteContentNode(nsIObjectOutputStream* aStream, nsIContent* aNode);
214
215 /**
216 * Read or write a namespace id from or to aStream. If the namespace matches
217 * one of the built-in ones defined in nsNameSpaceManager.h, it will be written as
218 * a single byte with that value. Otherwise, XBLBinding_Serialize_CustomNamespace is
219 * written out, followed by a string written with writeWStringZ.
220 */
221 nsresult ReadNamespace(nsIObjectInputStream* aStream, int32_t& aNameSpaceID);
222 nsresult WriteNamespace(nsIObjectOutputStream* aStream, int32_t aNameSpaceID);
223
224 public:
225 nsXBLPrototypeBinding();
226 ~nsXBLPrototypeBinding();
227
228 // Init must be called after construction to initialize the prototype
229 // binding. It may well throw errors (eg on out-of-memory). Do not confuse
230 // this with the Initialize() method, which must be called after the
231 // binding's handlers, properties, etc are all set.
232 nsresult Init(const nsACString& aRef,
233 nsXBLDocumentInfo* aInfo,
234 nsIContent* aElement,
235 bool aFirstBinding = false);
236
237 void Traverse(nsCycleCollectionTraversalCallback &cb) const;
238 void UnlinkJSObjects();
239 void Trace(const TraceCallbacks& aCallbacks, void *aClosure) const;
240
241 // Internal member functions.
242 public:
243 /**
244 * GetImmediateChild locates the immediate child of our binding element which
245 * has the localname given by aTag and is in the XBL namespace.
246 */
247 nsIContent* GetImmediateChild(nsIAtom* aTag);
248 nsIContent* LocateInstance(nsIContent* aBoundElt,
249 nsIContent* aTemplRoot,
250 nsIContent* aCopyRoot,
251 nsIContent* aTemplChild);
252
253 bool ChromeOnlyContent() { return mChromeOnlyContent; }
254
255 typedef nsClassHashtable<nsISupportsHashKey, nsXBLAttributeEntry> InnerAttributeTable;
256
257 protected:
258 // Ensure that mAttributeTable has been created.
259 void EnsureAttributeTable();
260 // Ad an entry to the attribute table
261 void AddToAttributeTable(int32_t aSourceNamespaceID, nsIAtom* aSourceTag,
262 int32_t aDestNamespaceID, nsIAtom* aDestTag,
263 nsIContent* aContent);
264 void ConstructAttributeTable(nsIContent* aElement);
265 void CreateKeyHandlers();
266
267 // MEMBER VARIABLES
268 protected:
269 nsCOMPtr<nsIURI> mBindingURI;
270 nsCOMPtr<nsIURI> mAlternateBindingURI; // Alternate id-less URI that is only non-null on the first binding.
271 nsCOMPtr<nsIContent> mBinding; // Strong. We own a ref to our content element in the binding doc.
272 nsAutoPtr<nsXBLPrototypeHandler> mPrototypeHandler; // Strong. DocInfo owns us, and we own the handlers.
273
274 // the url of the base binding
275 nsCOMPtr<nsIURI> mBaseBindingURI;
276
277 nsXBLProtoImpl* mImplementation; // Our prototype implementation (includes methods, properties, fields,
278 // the constructor, and the destructor).
279
280 nsXBLPrototypeBinding* mBaseBinding; // Weak. The docinfo will own our base binding.
281 bool mInheritStyle;
282 bool mCheckedBaseProto;
283 bool mKeyHandlersRegistered;
284 bool mChromeOnlyContent;
285
286 nsAutoPtr<nsXBLPrototypeResources> mResources; // If we have any resources, this will be non-null.
287
288 nsXBLDocumentInfo* mXBLDocInfoWeak; // A pointer back to our doc info. Weak, since it owns us.
289
290 // A table for attribute containers. Namespace IDs are used as
291 // keys in the table. Containers are InnerAttributeTables.
292 // This table is used to efficiently handle attribute changes.
293 nsAutoPtr<nsClassHashtable<nsUint32HashKey, InnerAttributeTable>> mAttributeTable;
294
295 class IIDHashKey : public PLDHashEntryHdr
296 {
297 public:
298 typedef const nsIID& KeyType;
299 typedef const nsIID* KeyTypePointer;
300
301 IIDHashKey(const nsIID* aKey)
302 : mKey(*aKey)
303 {}
304 IIDHashKey(const IIDHashKey& aOther)
305 : mKey(aOther.GetKey())
306 {}
307 ~IIDHashKey()
308 {}
309
310 KeyType GetKey() const
311 {
312 return mKey;
313 }
314 bool KeyEquals(const KeyTypePointer aKey) const
315 {
316 return mKey.Equals(*aKey);
317 }
318
319 static KeyTypePointer KeyToPointer(KeyType aKey)
320 {
321 return &aKey;
322 }
323 static PLDHashNumber HashKey(const KeyTypePointer aKey)
324 {
325 // Just use the 32-bit m0 field.
326 return aKey->m0;
327 }
328
329 enum { ALLOW_MEMMOVE = true };
330
331 private:
332 nsIID mKey;
333 };
334 nsInterfaceHashtable<IIDHashKey, nsIContent> mInterfaceTable; // A table of cached interfaces that we support.
335
336 int32_t mBaseNameSpaceID; // If we extend a tagname/namespace, then that information will
337 nsCOMPtr<nsIAtom> mBaseTag; // be stored in here.
338
339 nsCOMArray<nsXBLKeyEventHandler> mKeyHandlers;
340 };
341
342 #endif

mercurial