gecko-dev/dom/xbl/nsXBLPrototypeBinding.h

384 строки
14 KiB
C
Исходник Обычный вид История

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
2012-05-21 15:12:37 +04:00
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
2000-09-28 00:23:49 +04:00
#ifndef nsXBLPrototypeBinding_h__
#define nsXBLPrototypeBinding_h__
#include "nsAutoPtr.h"
#include "nsClassHashtable.h"
#include "nsCOMArray.h"
2000-09-28 00:23:49 +04:00
#include "nsCOMPtr.h"
#include "nsICSSLoaderObserver.h"
#include "nsInterfaceHashtable.h"
#include "nsWeakReference.h"
#include "nsXBLDocumentInfo.h"
#include "nsXBLProtoImpl.h"
#include "nsXBLProtoImplMethod.h"
#include "nsXBLPrototypeHandler.h"
#include "nsXBLPrototypeResources.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/WeakPtr.h"
#include "mozilla/StyleSheet.h"
2000-09-28 00:23:49 +04:00
class nsAtom;
class nsIContent;
2000-09-28 00:23:49 +04:00
class nsIDocument;
class nsXBLAttributeEntry;
class nsXBLBinding;
class nsXBLProtoImplField;
2000-09-28 00:23:49 +04:00
// *********************************************************************/
// The XBLPrototypeBinding class
// Instances of this class are owned by the nsXBLDocumentInfo object returned
// by XBLDocumentInfo(). Consumers who want to refcount things should refcount
// that.
class nsXBLPrototypeBinding final :
public mozilla::SupportsWeakPtr<nsXBLPrototypeBinding>
{
public:
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(nsXBLPrototypeBinding)
mozilla::dom::Element* GetBindingElement() const { return mBinding; }
void SetBindingElement(mozilla::dom::Element* aElement);
2000-09-28 00:23:49 +04:00
nsIURI* BindingURI() const { return mBindingURI; }
nsIURI* AlternateBindingURI() const { return mAlternateBindingURI; }
nsIURI* DocURI() const { return mXBLDocInfoWeak->DocumentURI(); }
nsIURI* GetBaseBindingURI() const { return mBaseBindingURI; }
2000-09-28 00:23:49 +04:00
// Checks if aURI refers to this binding by comparing to both possible
// binding URIs.
bool CompareBindingURI(nsIURI* aURI) const;
bool GetAllowScripts() const;
2000-09-28 00:23:49 +04:00
nsresult BindingAttached(nsIContent* aBoundElement);
nsresult BindingDetached(nsIContent* aBoundElement);
2000-10-04 04:41:53 +04:00
// aBoundElement is passed in here because we need to get owner document
// and PresContext in nsXBLResourceLoader::LoadResources().
bool LoadResources(nsIContent* aBoundElement);
nsresult AddResource(nsAtom* aResourceType, const nsAString& aSrc);
bool InheritsStyle() const { return mInheritStyle; }
void SetInheritsStyle(bool aInheritStyle) { mInheritStyle = aInheritStyle; }
2000-09-28 00:23:49 +04:00
nsXBLPrototypeHandler* GetPrototypeHandlers() { return mPrototypeHandler; }
void SetPrototypeHandlers(nsXBLPrototypeHandler* aHandler) { mPrototypeHandler = aHandler; }
nsXBLProtoImplAnonymousMethod* GetConstructor();
nsresult SetConstructor(nsXBLProtoImplAnonymousMethod* aConstructor);
nsXBLProtoImplAnonymousMethod* GetDestructor();
nsresult SetDestructor(nsXBLProtoImplAnonymousMethod* aDestructor);
nsXBLProtoImplField* FindField(const nsString& aFieldName) const
{
return mImplementation ? mImplementation->FindField(aFieldName) : nullptr;
}
// Resolve all the fields for this binding on the object |obj|.
// False return means a JS exception was set.
bool ResolveAllFields(JSContext* cx, JS::Handle<JSObject*> obj) const
{
return !mImplementation || mImplementation->ResolveAllFields(cx, obj);
}
// Undefine all our fields from object |obj| (which should be a
// JSObject for a bound element).
void UndefineFields(JSContext* cx, JS::Handle<JSObject*> obj) const {
if (mImplementation) {
mImplementation->UndefineFields(cx, obj);
}
}
const nsString& ClassName() const {
return mImplementation ? mImplementation->mClassName : EmptyString();
}
nsresult InitClass(const nsString& aClassName, JSContext* aContext,
JS::Handle<JSObject*> aScriptObject,
JS::MutableHandle<JSObject*> aClassObject,
bool* aNew);
nsresult ConstructInterfaceTable(const nsAString& aImpls);
void SetImplementation(nsXBLProtoImpl* aImpl) { mImplementation = aImpl; }
nsXBLProtoImpl* GetImplementation() { return mImplementation; }
nsresult InstallImplementation(nsXBLBinding* aBinding);
bool HasImplementation() const { return mImplementation != nullptr; }
void AttributeChanged(nsAtom* aAttribute, int32_t aNameSpaceID,
bool aRemoveFlag,
mozilla::dom::Element* aChangedElement,
nsIContent* aAnonymousContent, bool aNotify);
2000-09-28 00:23:49 +04:00
void SetBasePrototype(nsXBLPrototypeBinding* aBinding);
nsXBLPrototypeBinding* GetBasePrototype() { return mBaseBinding; }
2000-09-28 00:23:49 +04:00
nsXBLDocumentInfo* XBLDocumentInfo() const { return mXBLDocInfoWeak; }
bool IsChrome() { return mXBLDocInfoWeak->IsChrome(); }
void SetInitialAttributes(mozilla::dom::Element* aBoundElement,
nsIContent* aAnonymousContent);
2000-09-28 00:23:49 +04:00
void AppendStyleSheet(mozilla::StyleSheet* aSheet);
void RemoveStyleSheet(mozilla::StyleSheet* aSheet);
void InsertStyleSheetAt(size_t aIndex, mozilla::StyleSheet* aSheet);
mozilla::StyleSheet* StyleSheetAt(size_t aIndex) const;
size_t SheetCount() const;
bool HasStyleSheets() const;
void AppendStyleSheetsTo(nsTArray<mozilla::StyleSheet*>& aResult) const;
#ifdef MOZ_OLD_STYLE
nsIStyleRuleProcessor* GetRuleProcessor();
#endif
const RawServoAuthorStyles* GetServoStyles() const
{
return mResources ? mResources->GetServoStyles() : nullptr;
}
RawServoAuthorStyles* GetServoStyles()
{
return mResources
? const_cast<RawServoAuthorStyles*>(mResources->GetServoStyles())
: nullptr;
}
mozilla::ServoStyleRuleMap* GetServoStyleRuleMap()
{
return mResources ? mResources->GetServoStyleRuleMap() : nullptr;
}
2000-09-28 00:23:49 +04:00
nsresult FlushSkinSheets();
nsAtom* GetBaseTag(int32_t* aNamespaceID);
void SetBaseTag(int32_t aNamespaceID, nsAtom* aTag);
2000-09-28 00:23:49 +04:00
bool ImplementsInterface(REFNSIID aIID) const;
nsresult AddResourceListener(nsIContent* aBoundElement);
void Initialize();
nsresult ResolveBaseBinding();
const nsCOMArray<nsXBLKeyEventHandler>* GetKeyEventHandlers()
{
if (!mKeyHandlersRegistered) {
CreateKeyHandlers();
mKeyHandlersRegistered = true;
}
return &mKeyHandlers;
}
private:
nsresult Read(nsIObjectInputStream* aStream,
nsXBLDocumentInfo* aDocInfo,
nsIDocument* aDocument,
uint8_t aFlags);
/**
* Read a new binding from the stream aStream into the xbl document aDocument.
* aDocInfo should be the xbl document info for the binding document.
* aFlags can contain XBLBinding_Serialize_InheritStyle to indicate that
* mInheritStyle flag should be set, and XBLBinding_Serialize_IsFirstBinding
* to indicate the first binding in a document.
* XBLBinding_Serialize_ChromeOnlyContent indicates that
* nsXBLPrototypeBinding::mChromeOnlyContent should be true.
* XBLBinding_Serialize_BindToUntrustedContent indicates that
* nsXBLPrototypeBinding::mBindToUntrustedContent should be true.
*/
public:
static nsresult ReadNewBinding(nsIObjectInputStream* aStream,
nsXBLDocumentInfo* aDocInfo,
nsIDocument* aDocument,
uint8_t aFlags);
/**
* Write this binding to the stream.
*/
nsresult Write(nsIObjectOutputStream* aStream);
/**
* Read a content node from aStream and return it in aChild.
* aDocument and aNim are the document and node info manager for the document
* the child will be inserted into.
*/
nsresult ReadContentNode(nsIObjectInputStream* aStream,
nsIDocument* aDocument,
nsNodeInfoManager* aNim,
nsIContent** aChild);
/**
* Write the content node aNode to aStream.
*
* This method is called recursively for each child descendant. For the topmost
* call, aNode must be an element.
*
* Text, CDATA and comment nodes are serialized as:
* the constant XBLBinding_Serialize_TextNode, XBLBinding_Serialize_CDATANode
* or XBLBinding_Serialize_CommentNode
* the text for the node
* Elements are serialized in the following format:
* node's namespace, written with WriteNamespace
* node's namespace prefix
* node's tag
* 32-bit attribute count
* table of attributes:
* attribute's namespace, written with WriteNamespace
* attribute's namespace prefix
* attribute's tag
* attribute's value
* attribute forwarding table:
* source namespace
* source attribute
* destination namespace
* destination attribute
* the constant XBLBinding_Serialize_NoMoreAttributes
* 32-bit count of the number of child nodes
* each child node is serialized in the same manner in sequence
* the constant XBLBinding_Serialize_NoContent
*/
nsresult WriteContentNode(nsIObjectOutputStream* aStream, nsIContent* aNode);
/**
* Read or write a namespace id from or to aStream. If the namespace matches
* one of the built-in ones defined in nsNameSpaceManager.h, it will be written as
* a single byte with that value. Otherwise, XBLBinding_Serialize_CustomNamespace is
* written out, followed by a string written with writeWStringZ.
*/
nsresult ReadNamespace(nsIObjectInputStream* aStream, int32_t& aNameSpaceID);
nsresult WriteNamespace(nsIObjectOutputStream* aStream, int32_t aNameSpaceID);
2000-09-28 00:23:49 +04:00
public:
nsXBLPrototypeBinding();
~nsXBLPrototypeBinding();
2000-09-28 00:23:49 +04:00
// Init must be called after construction to initialize the prototype
// binding. It may well throw errors (eg on out-of-memory). Do not confuse
// this with the Initialize() method, which must be called after the
// binding's handlers, properties, etc are all set.
nsresult Init(const nsACString& aRef,
nsXBLDocumentInfo* aInfo,
mozilla::dom::Element* aElement,
bool aFirstBinding = false);
void Traverse(nsCycleCollectionTraversalCallback &cb) const;
void Unlink();
void Trace(const TraceCallbacks& aCallbacks, void *aClosure) const;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
// Internal member functions.
2000-09-28 00:23:49 +04:00
public:
/**
* GetImmediateChild locates the immediate child of our binding element which
* has the localname given by aTag and is in the XBL namespace.
*/
mozilla::dom::Element* GetImmediateChild(nsAtom* aTag);
mozilla::dom::Element* LocateInstance(mozilla::dom::Element* aBoundElt,
nsIContent* aTemplRoot,
nsIContent* aCopyRoot,
mozilla::dom::Element* aTemplChild);
2000-09-28 00:23:49 +04:00
bool ChromeOnlyContent() { return mChromeOnlyContent; }
bool BindToUntrustedContent() { return mBindToUntrustedContent; }
typedef nsClassHashtable<nsRefPtrHashKey<nsAtom>, nsXBLAttributeEntry> InnerAttributeTable;
protected:
// Ensure that mAttributeTable has been created.
void EnsureAttributeTable();
// Ad an entry to the attribute table
void AddToAttributeTable(int32_t aSourceNamespaceID, nsAtom* aSourceTag,
int32_t aDestNamespaceID, nsAtom* aDestTag,
mozilla::dom::Element* aContent);
void ConstructAttributeTable(mozilla::dom::Element* aElement);
void CreateKeyHandlers();
2003-03-12 08:03:35 +03:00
private:
void EnsureResources();
2000-09-28 00:23:49 +04:00
// MEMBER VARIABLES
protected:
nsCOMPtr<nsIURI> mBindingURI;
nsCOMPtr<nsIURI> mAlternateBindingURI; // Alternate id-less URI that is only non-null on the first binding.
RefPtr<mozilla::dom::Element> mBinding; // Strong. We own a ref to our content element in the binding doc.
nsAutoPtr<nsXBLPrototypeHandler> mPrototypeHandler; // Strong. DocInfo owns us, and we own the handlers.
// the url of the base binding
nsCOMPtr<nsIURI> mBaseBindingURI;
nsXBLProtoImpl* mImplementation; // Our prototype implementation (includes methods, properties, fields,
// the constructor, and the destructor).
// Weak. The docinfo will own our base binding.
mozilla::WeakPtr<nsXBLPrototypeBinding> mBaseBinding;
bool mInheritStyle;
bool mCheckedBaseProto;
bool mKeyHandlersRegistered;
bool mChromeOnlyContent;
bool mBindToUntrustedContent;
nsAutoPtr<nsXBLPrototypeResources> mResources; // If we have any resources, this will be non-null.
nsXBLDocumentInfo* mXBLDocInfoWeak; // A pointer back to our doc info. Weak, since it owns us.
2000-09-28 00:23:49 +04:00
// A table for attribute containers. Namespace IDs are used as
// keys in the table. Containers are InnerAttributeTables.
// This table is used to efficiently handle attribute changes.
nsAutoPtr<nsClassHashtable<nsUint32HashKey, InnerAttributeTable>> mAttributeTable;
2000-09-28 00:23:49 +04:00
class IIDHashKey : public PLDHashEntryHdr
{
public:
typedef const nsIID& KeyType;
typedef const nsIID* KeyTypePointer;
explicit IIDHashKey(const nsIID* aKey)
: mKey(*aKey)
{}
IIDHashKey(const IIDHashKey& aOther)
: mKey(aOther.GetKey())
{}
~IIDHashKey()
{}
KeyType GetKey() const
{
return mKey;
}
bool KeyEquals(const KeyTypePointer aKey) const
{
return mKey.Equals(*aKey);
}
static KeyTypePointer KeyToPointer(KeyType aKey)
{
return &aKey;
}
static PLDHashNumber HashKey(const KeyTypePointer aKey)
{
// Just use the 32-bit m0 field.
return aKey->m0;
}
enum { ALLOW_MEMMOVE = true };
private:
nsIID mKey;
};
nsInterfaceHashtable<IIDHashKey, nsIContent> mInterfaceTable; // A table of cached interfaces that we support.
int32_t mBaseNameSpaceID; // If we extend a tagname/namespace, then that information will
RefPtr<nsAtom> mBaseTag; // be stored in here.
nsCOMArray<nsXBLKeyEventHandler> mKeyHandlers;
2000-09-28 00:23:49 +04:00
};
#endif