1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is Mozilla Communicator client code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
23 * Original Author: David W. Hyatt (hyatt@netscape.com)
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 #ifndef nsXBLPrototypeBinding_h__
40 #define nsXBLPrototypeBinding_h__
43 #include "nsXBLPrototypeResources.h"
44 #include "nsXBLPrototypeHandler.h"
45 #include "nsXBLProtoImplMethod.h"
46 #include "nsICSSStyleSheet.h"
47 #include "nsICSSLoaderObserver.h"
48 #include "nsWeakReference.h"
49 #include "nsIContent.h"
50 #include "nsHashtable.h"
51 #include "nsIXBLDocumentInfo.h"
52 #include "nsCOMArray.h"
53 #include "nsXBLProtoImpl.h"
57 class nsIScriptContext
;
58 class nsSupportsHashtable
;
60 class nsFixedSizeAllocator
;
61 class nsXBLProtoImplField
;
64 // *********************************************************************/
65 // The XBLPrototypeBinding class
67 // Instances of this class are owned by the nsXBLDocumentInfo object returned
68 // by XBLDocumentInfo(). Consumers who want to refcount things should refcount
70 class nsXBLPrototypeBinding
73 already_AddRefed
<nsIContent
> GetBindingElement();
74 void SetBindingElement(nsIContent
* aElement
);
76 nsIURI
* BindingURI() const { return mBindingURI
; }
77 nsIURI
* DocURI() const { return mXBLDocInfoWeak
->DocumentURI(); }
79 nsresult
GetAllowScripts(PRBool
* aResult
);
81 nsresult
BindingAttached(nsIContent
* aBoundElement
);
82 nsresult
BindingDetached(nsIContent
* aBoundElement
);
84 PRBool
LoadResources();
85 nsresult
AddResource(nsIAtom
* aResourceType
, const nsAString
& aSrc
);
87 PRBool
InheritsStyle() const { return mInheritStyle
; }
89 nsXBLPrototypeHandler
* GetPrototypeHandlers() { return mPrototypeHandler
; }
90 void SetPrototypeHandlers(nsXBLPrototypeHandler
* aHandler
) { mPrototypeHandler
= aHandler
; }
92 nsXBLProtoImplAnonymousMethod
* GetConstructor();
93 nsresult
SetConstructor(nsXBLProtoImplAnonymousMethod
* aConstructor
);
94 nsXBLProtoImplAnonymousMethod
* GetDestructor();
95 nsresult
SetDestructor(nsXBLProtoImplAnonymousMethod
* aDestructor
);
97 nsXBLProtoImplField
* FindField(const nsString
& aFieldName
) const
99 return mImplementation
? mImplementation
->FindField(aFieldName
) : nsnull
;
102 // Resolve all the fields for this binding on the object |obj|.
103 // False return means a JS exception was set.
104 PRBool
ResolveAllFields(JSContext
* cx
, JSObject
* obj
) const
106 return !mImplementation
|| mImplementation
->ResolveAllFields(cx
, obj
);
109 // Undefine all our fields from object |obj| (which should be a
110 // JSObject for a bound element).
111 void UndefineFields(JSContext
* cx
, JSObject
* obj
) const {
112 if (mImplementation
) {
113 mImplementation
->UndefineFields(cx
, obj
);
117 const nsCString
& ClassName() const {
118 return mImplementation
? mImplementation
->mClassName
: EmptyCString();
121 nsresult
InitClass(const nsCString
& aClassName
, JSContext
* aContext
,
122 JSObject
* aGlobal
, JSObject
* aScriptObject
,
123 void ** aClassObject
);
125 nsresult
ConstructInterfaceTable(const nsAString
& aImpls
);
127 void SetImplementation(nsXBLProtoImpl
* aImpl
) { mImplementation
= aImpl
; }
128 nsresult
InstallImplementation(nsIContent
* aBoundElement
);
129 PRBool
HasImplementation() const { return mImplementation
!= nsnull
; }
131 void AttributeChanged(nsIAtom
* aAttribute
, PRInt32 aNameSpaceID
,
132 PRBool aRemoveFlag
, nsIContent
* aChangedElement
,
133 nsIContent
* aAnonymousContent
, PRBool aNotify
);
135 void SetBasePrototype(nsXBLPrototypeBinding
* aBinding
);
136 nsXBLPrototypeBinding
* GetBasePrototype() { return mBaseBinding
; }
138 nsIXBLDocumentInfo
* XBLDocumentInfo() const { return mXBLDocInfoWeak
; }
140 PRBool
HasBasePrototype() { return mHasBaseProto
; }
141 void SetHasBasePrototype(PRBool aHasBase
) { mHasBaseProto
= aHasBase
; }
143 void SetInitialAttributes(nsIContent
* aBoundElement
, nsIContent
* aAnonymousContent
);
145 nsIStyleRuleProcessor
* GetRuleProcessor();
146 nsCOMArray
<nsICSSStyleSheet
>* GetStyleSheets();
148 PRBool
HasInsertionPoints() { return mInsertionPointTable
!= nsnull
; }
150 PRBool
HasStyleSheets() {
151 return mResources
&& mResources
->mStyleSheetList
.Count() > 0;
154 nsresult
FlushSkinSheets();
156 void InstantiateInsertionPoints(nsXBLBinding
* aBinding
);
158 nsIContent
* GetInsertionPoint(nsIContent
* aBoundElement
,
159 nsIContent
* aCopyRoot
, nsIContent
*aChild
,
162 nsIContent
* GetSingleInsertionPoint(nsIContent
* aBoundElement
,
163 nsIContent
* aCopyRoot
,
164 PRUint32
* aIndex
, PRBool
* aMultiple
);
166 nsIAtom
* GetBaseTag(PRInt32
* aNamespaceID
);
167 void SetBaseTag(PRInt32 aNamespaceID
, nsIAtom
* aTag
);
169 PRBool
ImplementsInterface(REFNSIID aIID
) const;
171 PRBool
ShouldBuildChildFrames() const;
173 nsresult
AddResourceListener(nsIContent
* aBoundElement
);
177 const nsCOMArray
<nsXBLKeyEventHandler
>* GetKeyEventHandlers()
179 if (!mKeyHandlersRegistered
) {
181 mKeyHandlersRegistered
= PR_TRUE
;
184 return &mKeyHandlers
;
188 nsXBLPrototypeBinding();
189 ~nsXBLPrototypeBinding();
191 // Init must be called after construction to initialize the prototype
192 // binding. It may well throw errors (eg on out-of-memory). Do not confuse
193 // this with the Initialize() method, which must be called after the
194 // binding's handlers, properties, etc are all set.
195 nsresult
Init(const nsACString
& aRef
,
196 nsIXBLDocumentInfo
* aInfo
,
197 nsIContent
* aElement
);
199 void Traverse(nsCycleCollectionTraversalCallback
&cb
) const;
200 void UnlinkJSObjects();
201 void Trace(TraceCallback aCallback
, void *aClosure
) const;
204 static PRUint32 gRefCnt
;
206 static nsFixedSizeAllocator
* kAttrPool
;
208 // Internal member functions.
209 // XXXbz GetImmediateChild needs to be public to be called by SetAttrs,
210 // InstantiateInsertionPoints, etc; those should probably be a class static
211 // method instead of a global (non-static!) ones.
214 * GetImmediateChild locates the immediate child of our binding element which
215 * has the localname given by aTag and is in the XBL namespace.
217 nsIContent
* GetImmediateChild(nsIAtom
* aTag
);
218 nsIContent
* LocateInstance(nsIContent
* aBoundElt
,
219 nsIContent
* aTemplRoot
,
220 nsIContent
* aCopyRoot
,
221 nsIContent
* aTemplChild
);
224 void ConstructAttributeTable(nsIContent
* aElement
);
225 void ConstructInsertionTable(nsIContent
* aElement
);
226 void GetNestedChildren(nsIAtom
* aTag
, PRInt32 aNamespace
,
227 nsIContent
* aContent
,
228 nsCOMArray
<nsIContent
> & aList
);
229 void CreateKeyHandlers();
232 // Internal helper class for managing our IID table.
233 class nsIIDKey
: public nsHashKey
{
238 nsIIDKey(REFNSIID key
) : mKey(key
) {}
241 PRUint32
HashCode(void) const {
242 // Just use the 32-bit m0 field.
246 PRBool
Equals(const nsHashKey
*aKey
) const {
247 return mKey
.Equals( ((nsIIDKey
*) aKey
)->mKey
);
250 nsHashKey
*Clone(void) const {
251 return new nsIIDKey(mKey
);
257 nsCOMPtr
<nsIURI
> mBindingURI
;
258 nsCOMPtr
<nsIContent
> mBinding
; // Strong. We own a ref to our content element in the binding doc.
259 nsAutoPtr
<nsXBLPrototypeHandler
> mPrototypeHandler
; // Strong. DocInfo owns us, and we own the handlers.
261 nsXBLProtoImpl
* mImplementation
; // Our prototype implementation (includes methods, properties, fields,
262 // the constructor, and the destructor).
264 nsXBLPrototypeBinding
* mBaseBinding
; // Weak. The docinfo will own our base binding.
265 PRPackedBool mInheritStyle
;
266 PRPackedBool mHasBaseProto
;
267 PRPackedBool mKeyHandlersRegistered
;
269 nsXBLPrototypeResources
* mResources
; // If we have any resources, this will be non-null.
271 nsIXBLDocumentInfo
* mXBLDocInfoWeak
; // A pointer back to our doc info. Weak, since it owns us.
273 nsObjectHashtable
* mAttributeTable
; // A table for attribute containers. Namespace IDs are used as
274 // keys in the table. Containers are nsObjectHashtables.
275 // This table is used to efficiently handle attribute changes.
277 nsObjectHashtable
* mInsertionPointTable
; // A table of insertion points for placing explicit content
278 // underneath anonymous content.
280 nsSupportsHashtable
* mInterfaceTable
; // A table of cached interfaces that we support.
282 PRInt32 mBaseNameSpaceID
; // If we extend a tagname/namespace, then that information will
283 nsCOMPtr
<nsIAtom
> mBaseTag
; // be stored in here.
285 nsCOMArray
<nsXBLKeyEventHandler
> mKeyHandlers
;