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/. */
6 #ifndef nsXBLPrototypeBinding_h__
7 #define nsXBLPrototypeBinding_h__
9 #include "nsClassHashtable.h"
10 #include "nsCOMArray.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"
24 class nsXBLAttributeEntry
;
26 class nsXBLProtoImplField
;
30 } // namespace mozilla
32 // *********************************************************************/
33 // The XBLPrototypeBinding class
35 // Instances of this class are owned by the nsXBLDocumentInfo object returned
36 // by XBLDocumentInfo(). Consumers who want to refcount things should refcount
38 class nsXBLPrototypeBinding MOZ_FINAL
41 nsIContent
* GetBindingElement() const { return mBinding
; }
42 void SetBindingElement(nsIContent
* aElement
);
44 nsIURI
* BindingURI() const { return mBindingURI
; }
45 nsIURI
* AlternateBindingURI() const { return mAlternateBindingURI
; }
46 nsIURI
* DocURI() const { return mXBLDocInfoWeak
->DocumentURI(); }
47 nsIURI
* GetBaseBindingURI() const { return mBaseBindingURI
; }
49 // Checks if aURI refers to this binding by comparing to both possible
51 bool CompareBindingURI(nsIURI
* aURI
) const;
53 bool GetAllowScripts() const;
55 nsresult
BindingAttached(nsIContent
* aBoundElement
);
56 nsresult
BindingDetached(nsIContent
* aBoundElement
);
59 nsresult
AddResource(nsIAtom
* aResourceType
, const nsAString
& aSrc
);
61 bool InheritsStyle() const { return mInheritStyle
; }
62 void SetInheritsStyle(bool aInheritStyle
) { mInheritStyle
= aInheritStyle
; }
64 nsXBLPrototypeHandler
* GetPrototypeHandlers() { return mPrototypeHandler
; }
65 void SetPrototypeHandlers(nsXBLPrototypeHandler
* aHandler
) { mPrototypeHandler
= aHandler
; }
67 nsXBLProtoImplAnonymousMethod
* GetConstructor();
68 nsresult
SetConstructor(nsXBLProtoImplAnonymousMethod
* aConstructor
);
69 nsXBLProtoImplAnonymousMethod
* GetDestructor();
70 nsresult
SetDestructor(nsXBLProtoImplAnonymousMethod
* aDestructor
);
72 nsXBLProtoImplField
* FindField(const nsString
& aFieldName
) const
74 return mImplementation
? mImplementation
->FindField(aFieldName
) : nullptr;
77 // Resolve all the fields for this binding on the object |obj|.
78 // False return means a JS exception was set.
79 bool ResolveAllFields(JSContext
* cx
, JS::Handle
<JSObject
*> obj
) const
81 return !mImplementation
|| mImplementation
->ResolveAllFields(cx
, obj
);
84 // Undefine all our fields from object |obj| (which should be a
85 // JSObject for a bound element).
86 void UndefineFields(JSContext
* cx
, JS::Handle
<JSObject
*> obj
) const {
87 if (mImplementation
) {
88 mImplementation
->UndefineFields(cx
, obj
);
92 const nsCString
& ClassName() const {
93 return mImplementation
? mImplementation
->mClassName
: EmptyCString();
96 nsresult
InitClass(const nsCString
& aClassName
, JSContext
* aContext
,
97 JS::Handle
<JSObject
*> aScriptObject
,
98 JS::MutableHandle
<JSObject
*> aClassObject
,
101 nsresult
ConstructInterfaceTable(const nsAString
& aImpls
);
103 void SetImplementation(nsXBLProtoImpl
* aImpl
) { mImplementation
= aImpl
; }
104 nsXBLProtoImpl
* GetImplementation() { return mImplementation
; }
105 nsresult
InstallImplementation(nsXBLBinding
* aBinding
);
106 bool HasImplementation() const { return mImplementation
!= nullptr; }
108 void AttributeChanged(nsIAtom
* aAttribute
, int32_t aNameSpaceID
,
109 bool aRemoveFlag
, nsIContent
* aChangedElement
,
110 nsIContent
* aAnonymousContent
, bool aNotify
);
112 void SetBasePrototype(nsXBLPrototypeBinding
* aBinding
);
113 nsXBLPrototypeBinding
* GetBasePrototype() { return mBaseBinding
; }
115 nsXBLDocumentInfo
* XBLDocumentInfo() const { return mXBLDocInfoWeak
; }
116 bool IsChrome() { return mXBLDocInfoWeak
->IsChrome(); }
118 void SetInitialAttributes(nsIContent
* aBoundElement
, nsIContent
* aAnonymousContent
);
120 void AppendStyleSheet(mozilla::CSSStyleSheet
* aSheet
);
121 void RemoveStyleSheet(mozilla::CSSStyleSheet
* aSheet
);
122 void InsertStyleSheetAt(size_t aIndex
, mozilla::CSSStyleSheet
* aSheet
);
123 mozilla::CSSStyleSheet
* StyleSheetAt(size_t aIndex
) const;
124 size_t SheetCount() const;
125 bool HasStyleSheets() const;
126 void AppendStyleSheetsTo(nsTArray
<mozilla::CSSStyleSheet
*>& aResult
) const;
128 nsIStyleRuleProcessor
* GetRuleProcessor();
130 nsresult
FlushSkinSheets();
132 nsIAtom
* GetBaseTag(int32_t* aNamespaceID
);
133 void SetBaseTag(int32_t aNamespaceID
, nsIAtom
* aTag
);
135 bool ImplementsInterface(REFNSIID aIID
) const;
137 nsresult
AddResourceListener(nsIContent
* aBoundElement
);
141 nsresult
ResolveBaseBinding();
143 const nsCOMArray
<nsXBLKeyEventHandler
>* GetKeyEventHandlers()
145 if (!mKeyHandlersRegistered
) {
147 mKeyHandlersRegistered
= true;
150 return &mKeyHandlers
;
154 nsresult
Read(nsIObjectInputStream
* aStream
,
155 nsXBLDocumentInfo
* aDocInfo
,
156 nsIDocument
* aDocument
,
160 * Read a new binding from the stream aStream into the xbl document aDocument.
161 * aDocInfo should be the xbl document info for the binding document.
162 * aFlags can contain XBLBinding_Serialize_InheritStyle to indicate that
163 * mInheritStyle flag should be set, and XBLBinding_Serialize_IsFirstBinding
164 * to indicate the first binding in a document.
165 * XBLBinding_Serialize_ChromeOnlyContent indicates that
166 * nsXBLPrototypeBinding::mChromeOnlyContent should be true.
167 * XBLBinding_Serialize_BindToUntrustedContent indicates that
168 * nsXBLPrototypeBinding::mBindToUntrustedContent should be true.
171 static nsresult
ReadNewBinding(nsIObjectInputStream
* aStream
,
172 nsXBLDocumentInfo
* aDocInfo
,
173 nsIDocument
* aDocument
,
177 * Write this binding to the stream.
179 nsresult
Write(nsIObjectOutputStream
* aStream
);
182 * Read a content node from aStream and return it in aChild.
183 * aDocument and aNim are the document and node info manager for the document
184 * the child will be inserted into.
186 nsresult
ReadContentNode(nsIObjectInputStream
* aStream
,
187 nsIDocument
* aDocument
,
188 nsNodeInfoManager
* aNim
,
189 nsIContent
** aChild
);
192 * Write the content node aNode to aStream.
194 * This method is called recursively for each child descendant. For the topmost
195 * call, aNode must be an element.
197 * Text, CDATA and comment nodes are serialized as:
198 * the constant XBLBinding_Serialize_TextNode, XBLBinding_Serialize_CDATANode
199 * or XBLBinding_Serialize_CommentNode
200 * the text for the node
201 * Elements are serialized in the following format:
202 * node's namespace, written with WriteNamespace
203 * node's namespace prefix
205 * 32-bit attribute count
206 * table of attributes:
207 * attribute's namespace, written with WriteNamespace
208 * attribute's namespace prefix
211 * attribute forwarding table:
214 * destination namespace
215 * destination attribute
216 * the constant XBLBinding_Serialize_NoMoreAttributes
217 * 32-bit count of the number of child nodes
218 * each child node is serialized in the same manner in sequence
219 * the constant XBLBinding_Serialize_NoContent
221 nsresult
WriteContentNode(nsIObjectOutputStream
* aStream
, nsIContent
* aNode
);
224 * Read or write a namespace id from or to aStream. If the namespace matches
225 * one of the built-in ones defined in nsNameSpaceManager.h, it will be written as
226 * a single byte with that value. Otherwise, XBLBinding_Serialize_CustomNamespace is
227 * written out, followed by a string written with writeWStringZ.
229 nsresult
ReadNamespace(nsIObjectInputStream
* aStream
, int32_t& aNameSpaceID
);
230 nsresult
WriteNamespace(nsIObjectOutputStream
* aStream
, int32_t aNameSpaceID
);
233 nsXBLPrototypeBinding();
234 ~nsXBLPrototypeBinding();
236 // Init must be called after construction to initialize the prototype
237 // binding. It may well throw errors (eg on out-of-memory). Do not confuse
238 // this with the Initialize() method, which must be called after the
239 // binding's handlers, properties, etc are all set.
240 nsresult
Init(const nsACString
& aRef
,
241 nsXBLDocumentInfo
* aInfo
,
242 nsIContent
* aElement
,
243 bool aFirstBinding
= false);
245 void Traverse(nsCycleCollectionTraversalCallback
&cb
) const;
247 void Trace(const TraceCallbacks
& aCallbacks
, void *aClosure
) const;
249 // Internal member functions.
252 * GetImmediateChild locates the immediate child of our binding element which
253 * has the localname given by aTag and is in the XBL namespace.
255 nsIContent
* GetImmediateChild(nsIAtom
* aTag
);
256 nsIContent
* LocateInstance(nsIContent
* aBoundElt
,
257 nsIContent
* aTemplRoot
,
258 nsIContent
* aCopyRoot
,
259 nsIContent
* aTemplChild
);
261 bool ChromeOnlyContent() { return mChromeOnlyContent
; }
262 bool BindToUntrustedContent() { return mBindToUntrustedContent
; }
264 typedef nsClassHashtable
<nsISupportsHashKey
, nsXBLAttributeEntry
> InnerAttributeTable
;
267 // Ensure that mAttributeTable has been created.
268 void EnsureAttributeTable();
269 // Ad an entry to the attribute table
270 void AddToAttributeTable(int32_t aSourceNamespaceID
, nsIAtom
* aSourceTag
,
271 int32_t aDestNamespaceID
, nsIAtom
* aDestTag
,
272 nsIContent
* aContent
);
273 void ConstructAttributeTable(nsIContent
* aElement
);
274 void CreateKeyHandlers();
277 void EnsureResources();
281 nsCOMPtr
<nsIURI
> mBindingURI
;
282 nsCOMPtr
<nsIURI
> mAlternateBindingURI
; // Alternate id-less URI that is only non-null on the first binding.
283 nsCOMPtr
<nsIContent
> mBinding
; // Strong. We own a ref to our content element in the binding doc.
284 nsAutoPtr
<nsXBLPrototypeHandler
> mPrototypeHandler
; // Strong. DocInfo owns us, and we own the handlers.
286 // the url of the base binding
287 nsCOMPtr
<nsIURI
> mBaseBindingURI
;
289 nsXBLProtoImpl
* mImplementation
; // Our prototype implementation (includes methods, properties, fields,
290 // the constructor, and the destructor).
292 nsXBLPrototypeBinding
* mBaseBinding
; // Weak. The docinfo will own our base binding.
294 bool mCheckedBaseProto
;
295 bool mKeyHandlersRegistered
;
296 bool mChromeOnlyContent
;
297 bool mBindToUntrustedContent
;
299 nsAutoPtr
<nsXBLPrototypeResources
> mResources
; // If we have any resources, this will be non-null.
301 nsXBLDocumentInfo
* mXBLDocInfoWeak
; // A pointer back to our doc info. Weak, since it owns us.
303 // A table for attribute containers. Namespace IDs are used as
304 // keys in the table. Containers are InnerAttributeTables.
305 // This table is used to efficiently handle attribute changes.
306 nsAutoPtr
<nsClassHashtable
<nsUint32HashKey
, InnerAttributeTable
>> mAttributeTable
;
308 class IIDHashKey
: public PLDHashEntryHdr
311 typedef const nsIID
& KeyType
;
312 typedef const nsIID
* KeyTypePointer
;
314 explicit IIDHashKey(const nsIID
* aKey
)
317 IIDHashKey(const IIDHashKey
& aOther
)
318 : mKey(aOther
.GetKey())
323 KeyType
GetKey() const
327 bool KeyEquals(const KeyTypePointer aKey
) const
329 return mKey
.Equals(*aKey
);
332 static KeyTypePointer
KeyToPointer(KeyType aKey
)
336 static PLDHashNumber
HashKey(const KeyTypePointer aKey
)
338 // Just use the 32-bit m0 field.
342 enum { ALLOW_MEMMOVE
= true };
347 nsInterfaceHashtable
<IIDHashKey
, nsIContent
> mInterfaceTable
; // A table of cached interfaces that we support.
349 int32_t mBaseNameSpaceID
; // If we extend a tagname/namespace, then that information will
350 nsCOMPtr
<nsIAtom
> mBaseTag
; // be stored in here.
352 nsCOMArray
<nsXBLKeyEventHandler
> mKeyHandlers
;