1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/xbl/nsXBLPrototypeBinding.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,342 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef nsXBLPrototypeBinding_h__ 1.10 +#define nsXBLPrototypeBinding_h__ 1.11 + 1.12 +#include "nsClassHashtable.h" 1.13 +#include "nsCOMArray.h" 1.14 +#include "nsCOMPtr.h" 1.15 +#include "nsICSSLoaderObserver.h" 1.16 +#include "nsInterfaceHashtable.h" 1.17 +#include "nsWeakReference.h" 1.18 +#include "nsXBLDocumentInfo.h" 1.19 +#include "nsXBLProtoImpl.h" 1.20 +#include "nsXBLProtoImplMethod.h" 1.21 +#include "nsXBLPrototypeHandler.h" 1.22 +#include "nsXBLPrototypeResources.h" 1.23 + 1.24 +class nsIAtom; 1.25 +class nsIContent; 1.26 +class nsIDocument; 1.27 +class nsXBLAttributeEntry; 1.28 +class nsXBLBinding; 1.29 +class nsXBLProtoImplField; 1.30 + 1.31 +// *********************************************************************/ 1.32 +// The XBLPrototypeBinding class 1.33 + 1.34 +// Instances of this class are owned by the nsXBLDocumentInfo object returned 1.35 +// by XBLDocumentInfo(). Consumers who want to refcount things should refcount 1.36 +// that. 1.37 +class nsXBLPrototypeBinding MOZ_FINAL 1.38 +{ 1.39 +public: 1.40 + nsIContent* GetBindingElement() const { return mBinding; } 1.41 + void SetBindingElement(nsIContent* aElement); 1.42 + 1.43 + nsIURI* BindingURI() const { return mBindingURI; } 1.44 + nsIURI* AlternateBindingURI() const { return mAlternateBindingURI; } 1.45 + nsIURI* DocURI() const { return mXBLDocInfoWeak->DocumentURI(); } 1.46 + nsIURI* GetBaseBindingURI() const { return mBaseBindingURI; } 1.47 + 1.48 + // Checks if aURI refers to this binding by comparing to both possible 1.49 + // binding URIs. 1.50 + bool CompareBindingURI(nsIURI* aURI) const; 1.51 + 1.52 + bool GetAllowScripts() const; 1.53 + 1.54 + nsresult BindingAttached(nsIContent* aBoundElement); 1.55 + nsresult BindingDetached(nsIContent* aBoundElement); 1.56 + 1.57 + bool LoadResources(); 1.58 + nsresult AddResource(nsIAtom* aResourceType, const nsAString& aSrc); 1.59 + 1.60 + bool InheritsStyle() const { return mInheritStyle; } 1.61 + void SetInheritsStyle(bool aInheritStyle) { mInheritStyle = aInheritStyle; } 1.62 + 1.63 + nsXBLPrototypeHandler* GetPrototypeHandlers() { return mPrototypeHandler; } 1.64 + void SetPrototypeHandlers(nsXBLPrototypeHandler* aHandler) { mPrototypeHandler = aHandler; } 1.65 + 1.66 + nsXBLProtoImplAnonymousMethod* GetConstructor(); 1.67 + nsresult SetConstructor(nsXBLProtoImplAnonymousMethod* aConstructor); 1.68 + nsXBLProtoImplAnonymousMethod* GetDestructor(); 1.69 + nsresult SetDestructor(nsXBLProtoImplAnonymousMethod* aDestructor); 1.70 + 1.71 + nsXBLProtoImplField* FindField(const nsString& aFieldName) const 1.72 + { 1.73 + return mImplementation ? mImplementation->FindField(aFieldName) : nullptr; 1.74 + } 1.75 + 1.76 + // Resolve all the fields for this binding on the object |obj|. 1.77 + // False return means a JS exception was set. 1.78 + bool ResolveAllFields(JSContext* cx, JS::Handle<JSObject*> obj) const 1.79 + { 1.80 + return !mImplementation || mImplementation->ResolveAllFields(cx, obj); 1.81 + } 1.82 + 1.83 + // Undefine all our fields from object |obj| (which should be a 1.84 + // JSObject for a bound element). 1.85 + void UndefineFields(JSContext* cx, JS::Handle<JSObject*> obj) const { 1.86 + if (mImplementation) { 1.87 + mImplementation->UndefineFields(cx, obj); 1.88 + } 1.89 + } 1.90 + 1.91 + const nsCString& ClassName() const { 1.92 + return mImplementation ? mImplementation->mClassName : EmptyCString(); 1.93 + } 1.94 + 1.95 + nsresult InitClass(const nsCString& aClassName, JSContext * aContext, 1.96 + JS::Handle<JSObject*> aScriptObject, 1.97 + JS::MutableHandle<JSObject*> aClassObject, 1.98 + bool* aNew); 1.99 + 1.100 + nsresult ConstructInterfaceTable(const nsAString& aImpls); 1.101 + 1.102 + void SetImplementation(nsXBLProtoImpl* aImpl) { mImplementation = aImpl; } 1.103 + nsXBLProtoImpl* GetImplementation() { return mImplementation; } 1.104 + nsresult InstallImplementation(nsXBLBinding* aBinding); 1.105 + bool HasImplementation() const { return mImplementation != nullptr; } 1.106 + 1.107 + void AttributeChanged(nsIAtom* aAttribute, int32_t aNameSpaceID, 1.108 + bool aRemoveFlag, nsIContent* aChangedElement, 1.109 + nsIContent* aAnonymousContent, bool aNotify); 1.110 + 1.111 + void SetBasePrototype(nsXBLPrototypeBinding* aBinding); 1.112 + nsXBLPrototypeBinding* GetBasePrototype() { return mBaseBinding; } 1.113 + 1.114 + nsXBLDocumentInfo* XBLDocumentInfo() const { return mXBLDocInfoWeak; } 1.115 + bool IsChrome() { return mXBLDocInfoWeak->IsChrome(); } 1.116 + 1.117 + void SetInitialAttributes(nsIContent* aBoundElement, nsIContent* aAnonymousContent); 1.118 + 1.119 + nsIStyleRuleProcessor* GetRuleProcessor(); 1.120 + nsXBLPrototypeResources::sheet_array_type* GetOrCreateStyleSheets(); 1.121 + nsXBLPrototypeResources::sheet_array_type* GetStyleSheets(); 1.122 + 1.123 + bool HasStyleSheets() { 1.124 + return mResources && mResources->mStyleSheetList.Length() > 0; 1.125 + } 1.126 + 1.127 + nsresult FlushSkinSheets(); 1.128 + 1.129 + nsIAtom* GetBaseTag(int32_t* aNamespaceID); 1.130 + void SetBaseTag(int32_t aNamespaceID, nsIAtom* aTag); 1.131 + 1.132 + bool ImplementsInterface(REFNSIID aIID) const; 1.133 + 1.134 + nsresult AddResourceListener(nsIContent* aBoundElement); 1.135 + 1.136 + void Initialize(); 1.137 + 1.138 + nsresult ResolveBaseBinding(); 1.139 + 1.140 + const nsCOMArray<nsXBLKeyEventHandler>* GetKeyEventHandlers() 1.141 + { 1.142 + if (!mKeyHandlersRegistered) { 1.143 + CreateKeyHandlers(); 1.144 + mKeyHandlersRegistered = true; 1.145 + } 1.146 + 1.147 + return &mKeyHandlers; 1.148 + } 1.149 + 1.150 +private: 1.151 + nsresult Read(nsIObjectInputStream* aStream, 1.152 + nsXBLDocumentInfo* aDocInfo, 1.153 + nsIDocument* aDocument, 1.154 + uint8_t aFlags); 1.155 + 1.156 + /** 1.157 + * Read a new binding from the stream aStream into the xbl document aDocument. 1.158 + * aDocInfo should be the xbl document info for the binding document. 1.159 + * aFlags can contain XBLBinding_Serialize_InheritStyle to indicate that 1.160 + * mInheritStyle flag should be set, and XBLBinding_Serialize_IsFirstBinding 1.161 + * to indicate the first binding in a document. 1.162 + * XBLBinding_Serialize_ChromeOnlyContent indicates that 1.163 + * nsXBLPrototypeBinding::mChromeOnlyContent should be true. 1.164 + */ 1.165 +public: 1.166 + static nsresult ReadNewBinding(nsIObjectInputStream* aStream, 1.167 + nsXBLDocumentInfo* aDocInfo, 1.168 + nsIDocument* aDocument, 1.169 + uint8_t aFlags); 1.170 + 1.171 + /** 1.172 + * Write this binding to the stream. 1.173 + */ 1.174 + nsresult Write(nsIObjectOutputStream* aStream); 1.175 + 1.176 + /** 1.177 + * Read a content node from aStream and return it in aChild. 1.178 + * aDocument and aNim are the document and node info manager for the document 1.179 + * the child will be inserted into. 1.180 + */ 1.181 + nsresult ReadContentNode(nsIObjectInputStream* aStream, 1.182 + nsIDocument* aDocument, 1.183 + nsNodeInfoManager* aNim, 1.184 + nsIContent** aChild); 1.185 + 1.186 + /** 1.187 + * Write the content node aNode to aStream. 1.188 + * 1.189 + * This method is called recursively for each child descendant. For the topmost 1.190 + * call, aNode must be an element. 1.191 + * 1.192 + * Text, CDATA and comment nodes are serialized as: 1.193 + * the constant XBLBinding_Serialize_TextNode, XBLBinding_Serialize_CDATANode 1.194 + * or XBLBinding_Serialize_CommentNode 1.195 + * the text for the node 1.196 + * Elements are serialized in the following format: 1.197 + * node's namespace, written with WriteNamespace 1.198 + * node's namespace prefix 1.199 + * node's tag 1.200 + * 32-bit attribute count 1.201 + * table of attributes: 1.202 + * attribute's namespace, written with WriteNamespace 1.203 + * attribute's namespace prefix 1.204 + * attribute's tag 1.205 + * attribute's value 1.206 + * attribute forwarding table: 1.207 + * source namespace 1.208 + * source attribute 1.209 + * destination namespace 1.210 + * destination attribute 1.211 + * the constant XBLBinding_Serialize_NoMoreAttributes 1.212 + * 32-bit count of the number of child nodes 1.213 + * each child node is serialized in the same manner in sequence 1.214 + * the constant XBLBinding_Serialize_NoContent 1.215 + */ 1.216 + nsresult WriteContentNode(nsIObjectOutputStream* aStream, nsIContent* aNode); 1.217 + 1.218 + /** 1.219 + * Read or write a namespace id from or to aStream. If the namespace matches 1.220 + * one of the built-in ones defined in nsNameSpaceManager.h, it will be written as 1.221 + * a single byte with that value. Otherwise, XBLBinding_Serialize_CustomNamespace is 1.222 + * written out, followed by a string written with writeWStringZ. 1.223 + */ 1.224 + nsresult ReadNamespace(nsIObjectInputStream* aStream, int32_t& aNameSpaceID); 1.225 + nsresult WriteNamespace(nsIObjectOutputStream* aStream, int32_t aNameSpaceID); 1.226 + 1.227 +public: 1.228 + nsXBLPrototypeBinding(); 1.229 + ~nsXBLPrototypeBinding(); 1.230 + 1.231 + // Init must be called after construction to initialize the prototype 1.232 + // binding. It may well throw errors (eg on out-of-memory). Do not confuse 1.233 + // this with the Initialize() method, which must be called after the 1.234 + // binding's handlers, properties, etc are all set. 1.235 + nsresult Init(const nsACString& aRef, 1.236 + nsXBLDocumentInfo* aInfo, 1.237 + nsIContent* aElement, 1.238 + bool aFirstBinding = false); 1.239 + 1.240 + void Traverse(nsCycleCollectionTraversalCallback &cb) const; 1.241 + void UnlinkJSObjects(); 1.242 + void Trace(const TraceCallbacks& aCallbacks, void *aClosure) const; 1.243 + 1.244 +// Internal member functions. 1.245 +public: 1.246 + /** 1.247 + * GetImmediateChild locates the immediate child of our binding element which 1.248 + * has the localname given by aTag and is in the XBL namespace. 1.249 + */ 1.250 + nsIContent* GetImmediateChild(nsIAtom* aTag); 1.251 + nsIContent* LocateInstance(nsIContent* aBoundElt, 1.252 + nsIContent* aTemplRoot, 1.253 + nsIContent* aCopyRoot, 1.254 + nsIContent* aTemplChild); 1.255 + 1.256 + bool ChromeOnlyContent() { return mChromeOnlyContent; } 1.257 + 1.258 + typedef nsClassHashtable<nsISupportsHashKey, nsXBLAttributeEntry> InnerAttributeTable; 1.259 + 1.260 +protected: 1.261 + // Ensure that mAttributeTable has been created. 1.262 + void EnsureAttributeTable(); 1.263 + // Ad an entry to the attribute table 1.264 + void AddToAttributeTable(int32_t aSourceNamespaceID, nsIAtom* aSourceTag, 1.265 + int32_t aDestNamespaceID, nsIAtom* aDestTag, 1.266 + nsIContent* aContent); 1.267 + void ConstructAttributeTable(nsIContent* aElement); 1.268 + void CreateKeyHandlers(); 1.269 + 1.270 +// MEMBER VARIABLES 1.271 +protected: 1.272 + nsCOMPtr<nsIURI> mBindingURI; 1.273 + nsCOMPtr<nsIURI> mAlternateBindingURI; // Alternate id-less URI that is only non-null on the first binding. 1.274 + nsCOMPtr<nsIContent> mBinding; // Strong. We own a ref to our content element in the binding doc. 1.275 + nsAutoPtr<nsXBLPrototypeHandler> mPrototypeHandler; // Strong. DocInfo owns us, and we own the handlers. 1.276 + 1.277 + // the url of the base binding 1.278 + nsCOMPtr<nsIURI> mBaseBindingURI; 1.279 + 1.280 + nsXBLProtoImpl* mImplementation; // Our prototype implementation (includes methods, properties, fields, 1.281 + // the constructor, and the destructor). 1.282 + 1.283 + nsXBLPrototypeBinding* mBaseBinding; // Weak. The docinfo will own our base binding. 1.284 + bool mInheritStyle; 1.285 + bool mCheckedBaseProto; 1.286 + bool mKeyHandlersRegistered; 1.287 + bool mChromeOnlyContent; 1.288 + 1.289 + nsAutoPtr<nsXBLPrototypeResources> mResources; // If we have any resources, this will be non-null. 1.290 + 1.291 + nsXBLDocumentInfo* mXBLDocInfoWeak; // A pointer back to our doc info. Weak, since it owns us. 1.292 + 1.293 + // A table for attribute containers. Namespace IDs are used as 1.294 + // keys in the table. Containers are InnerAttributeTables. 1.295 + // This table is used to efficiently handle attribute changes. 1.296 + nsAutoPtr<nsClassHashtable<nsUint32HashKey, InnerAttributeTable>> mAttributeTable; 1.297 + 1.298 + class IIDHashKey : public PLDHashEntryHdr 1.299 + { 1.300 + public: 1.301 + typedef const nsIID& KeyType; 1.302 + typedef const nsIID* KeyTypePointer; 1.303 + 1.304 + IIDHashKey(const nsIID* aKey) 1.305 + : mKey(*aKey) 1.306 + {} 1.307 + IIDHashKey(const IIDHashKey& aOther) 1.308 + : mKey(aOther.GetKey()) 1.309 + {} 1.310 + ~IIDHashKey() 1.311 + {} 1.312 + 1.313 + KeyType GetKey() const 1.314 + { 1.315 + return mKey; 1.316 + } 1.317 + bool KeyEquals(const KeyTypePointer aKey) const 1.318 + { 1.319 + return mKey.Equals(*aKey); 1.320 + } 1.321 + 1.322 + static KeyTypePointer KeyToPointer(KeyType aKey) 1.323 + { 1.324 + return &aKey; 1.325 + } 1.326 + static PLDHashNumber HashKey(const KeyTypePointer aKey) 1.327 + { 1.328 + // Just use the 32-bit m0 field. 1.329 + return aKey->m0; 1.330 + } 1.331 + 1.332 + enum { ALLOW_MEMMOVE = true }; 1.333 + 1.334 + private: 1.335 + nsIID mKey; 1.336 + }; 1.337 + nsInterfaceHashtable<IIDHashKey, nsIContent> mInterfaceTable; // A table of cached interfaces that we support. 1.338 + 1.339 + int32_t mBaseNameSpaceID; // If we extend a tagname/namespace, then that information will 1.340 + nsCOMPtr<nsIAtom> mBaseTag; // be stored in here. 1.341 + 1.342 + nsCOMArray<nsXBLKeyEventHandler> mKeyHandlers; 1.343 +}; 1.344 + 1.345 +#endif