dom/xbl/nsXBLPrototypeBinding.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial