michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef nsXBLBinding_h_ michael@0: #define nsXBLBinding_h_ michael@0: michael@0: #include "nsXBLService.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsAutoPtr.h" michael@0: #include "nsINodeList.h" michael@0: #include "nsIStyleRuleProcessor.h" michael@0: #include "nsClassHashtable.h" michael@0: #include "nsTArray.h" michael@0: #include "nsCycleCollectionParticipant.h" michael@0: #include "nsISupportsImpl.h" michael@0: #include "js/TypeDecls.h" michael@0: michael@0: class nsXBLPrototypeBinding; michael@0: class nsIContent; michael@0: class nsIAtom; michael@0: class nsIDocument; michael@0: class nsIScriptContext; michael@0: michael@0: namespace mozilla { michael@0: namespace dom { michael@0: michael@0: class ShadowRoot; michael@0: class XBLChildrenElement; michael@0: michael@0: } // namespace dom michael@0: } // namespace mozilla michael@0: michael@0: class nsAnonymousContentList; michael@0: michael@0: // *********************************************************************/ michael@0: // The XBLBinding class michael@0: michael@0: class nsXBLBinding MOZ_FINAL michael@0: { michael@0: public: michael@0: nsXBLBinding(nsXBLPrototypeBinding* aProtoBinding); michael@0: nsXBLBinding(mozilla::dom::ShadowRoot* aShadowRoot, nsXBLPrototypeBinding* aProtoBinding); michael@0: ~nsXBLBinding(); michael@0: michael@0: /** michael@0: * XBLBindings are refcounted. They are held onto in 3 ways: michael@0: * 1. The binding manager's binding table holds onto all bindings that are michael@0: * currently attached to a content node. michael@0: * 2. Bindings hold onto their base binding. This is important since michael@0: * the base binding itself may not be attached to anything. michael@0: * 3. The binding manager holds an additional reference to bindings michael@0: * which are queued to fire their constructors. michael@0: */ michael@0: michael@0: NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsXBLBinding) michael@0: michael@0: NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLBinding) michael@0: michael@0: nsXBLPrototypeBinding* PrototypeBinding() const { return mPrototypeBinding; } michael@0: nsIContent* GetAnonymousContent() { return mContent.get(); } michael@0: nsXBLBinding* GetBindingWithContent(); michael@0: michael@0: nsXBLBinding* GetBaseBinding() const { return mNextBinding; } michael@0: void SetBaseBinding(nsXBLBinding *aBinding); michael@0: michael@0: nsIContent* GetBoundElement() { return mBoundElement; } michael@0: void SetBoundElement(nsIContent *aElement); michael@0: michael@0: /* michael@0: * Does a lookup for a method or attribute provided by one of the bindings' michael@0: * prototype implementation. If found, |desc| will be set up appropriately, michael@0: * and wrapped into cx->compartment. michael@0: * michael@0: * May only be called when XBL code is being run in a separate scope, because michael@0: * otherwise we don't have untainted data with which to do a proper lookup. michael@0: */ michael@0: bool LookupMember(JSContext* aCx, JS::Handle aId, michael@0: JS::MutableHandle aDesc); michael@0: michael@0: /* michael@0: * Determines whether the binding has a field with the given name. michael@0: */ michael@0: bool HasField(nsString& aName); michael@0: michael@0: protected: michael@0: michael@0: /* michael@0: * Internal version. Requires that aCx is in appropriate xbl scope. michael@0: */ michael@0: bool LookupMemberInternal(JSContext* aCx, nsString& aName, michael@0: JS::Handle aNameAsId, michael@0: JS::MutableHandle aDesc, michael@0: JS::Handle aXBLScope); michael@0: michael@0: public: michael@0: michael@0: void MarkForDeath(); michael@0: bool MarkedForDeath() const { return mMarkedForDeath; } michael@0: michael@0: bool HasStyleSheets() const; michael@0: bool InheritsStyle() const; michael@0: bool ImplementsInterface(REFNSIID aIID) const; michael@0: michael@0: void GenerateAnonymousContent(); michael@0: void InstallAnonymousContent(nsIContent* aAnonParent, nsIContent* aElement, michael@0: bool aNativeAnon); michael@0: static void UninstallAnonymousContent(nsIDocument* aDocument, michael@0: nsIContent* aAnonParent); michael@0: void InstallEventHandlers(); michael@0: nsresult InstallImplementation(); michael@0: michael@0: void ExecuteAttachedHandler(); michael@0: void ExecuteDetachedHandler(); michael@0: void UnhookEventHandlers(); michael@0: michael@0: nsIAtom* GetBaseTag(int32_t* aNameSpaceID); michael@0: nsXBLBinding* RootBinding(); michael@0: michael@0: // Resolve all the fields for this binding and all ancestor bindings on the michael@0: // object |obj|. False return means a JS exception was set. michael@0: bool ResolveAllFields(JSContext *cx, JS::Handle obj) const; michael@0: michael@0: void AttributeChanged(nsIAtom* aAttribute, int32_t aNameSpaceID, michael@0: bool aRemoveFlag, bool aNotify); michael@0: michael@0: void ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocument); michael@0: michael@0: void WalkRules(nsIStyleRuleProcessor::EnumFunc aFunc, void* aData); michael@0: michael@0: static nsresult DoInitJSClass(JSContext *cx, JS::Handle obj, michael@0: const nsAFlatCString& aClassName, michael@0: nsXBLPrototypeBinding* aProtoBinding, michael@0: JS::MutableHandle aClassObject, michael@0: bool* aNew); michael@0: michael@0: bool AllowScripts(); michael@0: michael@0: mozilla::dom::XBLChildrenElement* FindInsertionPointFor(nsIContent* aChild); michael@0: michael@0: bool HasFilteredInsertionPoints() michael@0: { michael@0: return !mInsertionPoints.IsEmpty(); michael@0: } michael@0: michael@0: mozilla::dom::XBLChildrenElement* GetDefaultInsertionPoint() michael@0: { michael@0: return mDefaultInsertionPoint; michael@0: } michael@0: michael@0: // Removes all inserted node from insertion points under us. michael@0: void ClearInsertionPoints(); michael@0: michael@0: // Returns a live node list that iterates over the anonymous nodes generated michael@0: // by this binding. michael@0: nsAnonymousContentList* GetAnonymousNodeList(); michael@0: michael@0: // MEMBER VARIABLES michael@0: protected: michael@0: michael@0: bool mMarkedForDeath; michael@0: bool mUsingXBLScope; michael@0: michael@0: nsXBLPrototypeBinding* mPrototypeBinding; // Weak, but we're holding a ref to the docinfo michael@0: nsCOMPtr mContent; // Strong. Our anonymous content stays around with us. michael@0: nsRefPtr mNextBinding; // Strong. The derived binding owns the base class bindings. michael@0: michael@0: nsIContent* mBoundElement; // [WEAK] We have a reference, but we don't own it. michael@0: michael@0: // The elements that we found in our when we michael@0: // processed this binding. The default insertion point has no includes michael@0: // attribute and all other insertion points must have at least one includes michael@0: // attribute. These points must be up-to-date with respect to their parent's michael@0: // children, even if their parent has another binding attached to it, michael@0: // preventing us from rendering their contents directly. michael@0: nsRefPtr mDefaultInsertionPoint; michael@0: nsTArray > mInsertionPoints; michael@0: nsRefPtr mAnonymousContentList; michael@0: michael@0: mozilla::dom::XBLChildrenElement* FindInsertionPointForInternal(nsIContent* aChild); michael@0: }; michael@0: michael@0: #endif // nsXBLBinding_h_