1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef nsXBLBinding_h_ 8 #define nsXBLBinding_h_ 9 10 #include "nsXBLService.h" 11 #include "nsCOMPtr.h" 12 #include "nsINodeList.h" 13 #ifdef MOZ_OLD_STYLE 14 #include "nsIStyleRuleProcessor.h" 15 #endif 16 #include "nsClassHashtable.h" 17 #include "nsTArray.h" 18 #include "nsCycleCollectionParticipant.h" 19 #include "nsISupportsImpl.h" 20 #include "js/TypeDecls.h" 21 22 class nsXBLPrototypeBinding; 23 class nsIContent; 24 class nsAtom; 25 class nsIDocument; 26 struct RawServoAuthorStyles; 27 28 namespace mozilla { 29 namespace dom { 30 31 class ShadowRoot; 32 class XBLChildrenElement; 33 34 } // namespace dom 35 } // namespace mozilla 36 37 class nsAnonymousContentList; 38 39 // *********************************************************************/ 40 // The XBLBinding class 41 42 class nsXBLBinding final { 43 public: 44 explicit nsXBLBinding(nsXBLPrototypeBinding* aProtoBinding); 45 nsXBLBinding(mozilla::dom::ShadowRoot* aShadowRoot, 46 nsXBLPrototypeBinding* aProtoBinding); 47 48 /** 49 * XBLBindings are refcounted. They are held onto in 3 ways: 50 * 1. The binding manager's binding table holds onto all bindings that are 51 * currently attached to a content node. 52 * 2. Bindings hold onto their base binding. This is important since 53 * the base binding itself may not be attached to anything. 54 * 3. The binding manager holds an additional reference to bindings 55 * which are queued to fire their constructors. 56 */ 57 58 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsXBLBinding) 59 NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLBinding)60 NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLBinding) 61 62 nsXBLPrototypeBinding* PrototypeBinding() const { return mPrototypeBinding; } GetAnonymousContent()63 nsIContent* GetAnonymousContent() { return mContent.get(); } 64 nsXBLBinding* GetBindingWithContent(); 65 GetBaseBinding()66 nsXBLBinding* GetBaseBinding() const { return mNextBinding; } 67 void SetBaseBinding(nsXBLBinding* aBinding); 68 GetBoundElement()69 mozilla::dom::Element* GetBoundElement() { return mBoundElement; } 70 void SetBoundElement(mozilla::dom::Element* aElement); 71 72 /* 73 * Does a lookup for a method or attribute provided by one of the bindings' 74 * prototype implementation. If found, |desc| will be set up appropriately, 75 * and wrapped into cx->compartment. 76 * 77 * May only be called when XBL code is being run in a separate scope, because 78 * otherwise we don't have untainted data with which to do a proper lookup. 79 */ 80 bool LookupMember(JSContext* aCx, JS::Handle<jsid> aId, 81 JS::MutableHandle<JS::PropertyDescriptor> aDesc); 82 83 /* 84 * Determines whether the binding has a field with the given name. 85 */ 86 bool HasField(nsString& aName); 87 88 protected: 89 ~nsXBLBinding(); 90 91 /* 92 * Internal version. Requires that aCx is in appropriate xbl scope. 93 */ 94 bool LookupMemberInternal(JSContext* aCx, nsString& aName, 95 JS::Handle<jsid> aNameAsId, 96 JS::MutableHandle<JS::PropertyDescriptor> aDesc, 97 JS::Handle<JSObject*> aXBLScope); 98 99 public: 100 void MarkForDeath(); MarkedForDeath()101 bool MarkedForDeath() const { return mMarkedForDeath; } 102 103 bool HasStyleSheets() const; 104 bool InheritsStyle() const; 105 bool ImplementsInterface(REFNSIID aIID) const; 106 107 void GenerateAnonymousContent(); 108 void BindAnonymousContent(nsIContent* aAnonParent, nsIContent* aElement, 109 bool aNativeAnon); 110 static void UnbindAnonymousContent(nsIDocument* aDocument, 111 nsIContent* aAnonParent, 112 bool aNullParent = true); 113 void InstallEventHandlers(); 114 nsresult InstallImplementation(); 115 116 void ExecuteAttachedHandler(); 117 void ExecuteDetachedHandler(); 118 void UnhookEventHandlers(); 119 120 nsAtom* GetBaseTag(int32_t* aNameSpaceID); 121 nsXBLBinding* RootBinding(); 122 123 // Resolve all the fields for this binding and all ancestor bindings on the 124 // object |obj|. False return means a JS exception was set. 125 bool ResolveAllFields(JSContext* cx, JS::Handle<JSObject*> obj) const; 126 127 void AttributeChanged(nsAtom* aAttribute, int32_t aNameSpaceID, 128 bool aRemoveFlag, bool aNotify); 129 130 void ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocument); 131 132 #ifdef MOZ_OLD_STYLE 133 void WalkRules(nsIStyleRuleProcessor::EnumFunc aFunc, void* aData); 134 #endif 135 136 const RawServoAuthorStyles* GetServoStyles() const; 137 138 static nsresult DoInitJSClass(JSContext* cx, JS::Handle<JSObject*> obj, 139 const nsString& aClassName, 140 nsXBLPrototypeBinding* aProtoBinding, 141 JS::MutableHandle<JSObject*> aClassObject, 142 bool* aNew); 143 144 bool AllowScripts(); 145 146 mozilla::dom::XBLChildrenElement* FindInsertionPointFor(nsIContent* aChild); 147 HasFilteredInsertionPoints()148 bool HasFilteredInsertionPoints() { return !mInsertionPoints.IsEmpty(); } 149 GetDefaultInsertionPoint()150 mozilla::dom::XBLChildrenElement* GetDefaultInsertionPoint() { 151 return mDefaultInsertionPoint; 152 } 153 154 // Removes all inserted node from <xbl:children> insertion points under us. 155 void ClearInsertionPoints(); 156 157 // Returns a live node list that iterates over the anonymous nodes generated 158 // by this binding. 159 nsAnonymousContentList* GetAnonymousNodeList(); 160 161 nsIURI* GetSourceDocURI(); 162 163 // MEMBER VARIABLES 164 protected: 165 bool mMarkedForDeath; 166 bool mUsingContentXBLScope; 167 bool mIsShadowRootBinding; 168 169 nsXBLPrototypeBinding* 170 mPrototypeBinding; // Weak, but we're holding a ref to the docinfo 171 nsCOMPtr<nsIContent> 172 mContent; // Strong. Our anonymous content stays around with us. 173 RefPtr<nsXBLBinding> mNextBinding; // Strong. The derived binding owns the 174 // base class bindings. 175 176 mozilla::dom::Element* 177 mBoundElement; // [WEAK] We have a reference, but we don't own it. 178 179 // The <xbl:children> elements that we found in our <xbl:content> when we 180 // processed this binding. The default insertion point has no includes 181 // attribute and all other insertion points must have at least one includes 182 // attribute. These points must be up-to-date with respect to their parent's 183 // children, even if their parent has another binding attached to it, 184 // preventing us from rendering their contents directly. 185 RefPtr<mozilla::dom::XBLChildrenElement> mDefaultInsertionPoint; 186 nsTArray<RefPtr<mozilla::dom::XBLChildrenElement> > mInsertionPoints; 187 RefPtr<nsAnonymousContentList> mAnonymousContentList; 188 189 mozilla::dom::XBLChildrenElement* FindInsertionPointForInternal( 190 nsIContent* aChild); 191 }; 192 193 #endif // nsXBLBinding_h_ 194