/src/mozilla-central/dom/xbl/nsBindingManager.h
Line | Count | Source (jump to first uncovered line) |
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 nsBindingManager_h_ |
8 | | #define nsBindingManager_h_ |
9 | | |
10 | | #include "nsAutoPtr.h" |
11 | | #include "nsIContent.h" |
12 | | #include "nsStubMutationObserver.h" |
13 | | #include "nsHashKeys.h" |
14 | | #include "nsInterfaceHashtable.h" |
15 | | #include "nsRefPtrHashtable.h" |
16 | | #include "nsURIHashKey.h" |
17 | | #include "nsCycleCollectionParticipant.h" |
18 | | #include "nsXBLBinding.h" |
19 | | #include "nsTArray.h" |
20 | | #include "nsThreadUtils.h" |
21 | | #include "mozilla/MediaFeatureChange.h" |
22 | | #include "mozilla/MemoryReporting.h" |
23 | | #include "mozilla/StyleSheet.h" |
24 | | #include "mozilla/EventStates.h" |
25 | | |
26 | | struct ElementDependentRuleProcessorData; |
27 | | class nsIXPConnectWrappedJS; |
28 | | class nsAtom; |
29 | | class nsIDocument; |
30 | | class nsIURI; |
31 | | class nsXBLDocumentInfo; |
32 | | class nsIStreamListener; |
33 | | class nsXBLBinding; |
34 | | typedef nsTArray<RefPtr<nsXBLBinding> > nsBindingList; |
35 | | class nsIPrincipal; |
36 | | class nsITimer; |
37 | | |
38 | | class nsBindingManager final : public nsStubMutationObserver |
39 | | { |
40 | | ~nsBindingManager(); |
41 | | |
42 | | public: |
43 | | NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
44 | | |
45 | | NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED |
46 | | NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED |
47 | | NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED |
48 | | |
49 | | explicit nsBindingManager(nsIDocument* aDocument); |
50 | | |
51 | | nsXBLBinding* GetBindingWithContent(const nsIContent* aContent); |
52 | | |
53 | | void AddBoundContent(nsIContent* aContent); |
54 | | void RemoveBoundContent(nsIContent* aContent); |
55 | | |
56 | | /** |
57 | | * Notify the binding manager that an element |
58 | | * has been removed from its document, |
59 | | * so that it can update any bindings or |
60 | | * nsIAnonymousContentCreator-created anonymous |
61 | | * content that may depend on the document. |
62 | | * @param aContent the element that's being moved |
63 | | * @param aOldDocument the old document in which the |
64 | | * content resided. |
65 | | * @param aDestructorHandling whether or not to run the possible XBL |
66 | | * destructor. |
67 | | */ |
68 | | |
69 | | enum DestructorHandling { |
70 | | eRunDtor, |
71 | | eDoNotRunDtor |
72 | | }; |
73 | | void RemovedFromDocument(nsIContent* aContent, nsIDocument* aOldDocument, |
74 | | DestructorHandling aDestructorHandling) |
75 | 0 | { |
76 | 0 | if (aContent->HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) { |
77 | 0 | RemovedFromDocumentInternal(aContent, aOldDocument, aDestructorHandling); |
78 | 0 | } |
79 | 0 | } |
80 | | void RemovedFromDocumentInternal(nsIContent* aContent, |
81 | | nsIDocument* aOldDocument, |
82 | | DestructorHandling aDestructorHandling); |
83 | | |
84 | | nsAtom* ResolveTag(nsIContent* aContent, int32_t* aNameSpaceID); |
85 | | |
86 | | /** |
87 | | * Return the nodelist of "anonymous" kids for this node. This might |
88 | | * actually include some of the nodes actual DOM kids, if there are |
89 | | * <children> tags directly as kids of <content>. This will only end up |
90 | | * returning a non-null list for nodes which have a binding attached. |
91 | | */ |
92 | | nsINodeList* GetAnonymousNodesFor(nsIContent* aContent); |
93 | | |
94 | | nsresult ClearBinding(mozilla::dom::Element* aElement); |
95 | | nsresult LoadBindingDocument(nsIDocument* aBoundDoc, nsIURI* aURL, |
96 | | nsIPrincipal* aOriginPrincipal); |
97 | | |
98 | | nsresult AddToAttachedQueue(nsXBLBinding* aBinding); |
99 | | void RemoveFromAttachedQueue(nsXBLBinding* aBinding); |
100 | | void ProcessAttachedQueue(uint32_t aSkipSize = 0) |
101 | 0 | { |
102 | 0 | if (mProcessingAttachedStack || mAttachedStack.Length() <= aSkipSize) { |
103 | 0 | return; |
104 | 0 | } |
105 | 0 | |
106 | 0 | ProcessAttachedQueueInternal(aSkipSize); |
107 | 0 | } |
108 | | private: |
109 | | void ProcessAttachedQueueInternal(uint32_t aSkipSize); |
110 | | |
111 | | public: |
112 | | |
113 | | void ExecuteDetachedHandlers(); |
114 | | |
115 | | nsresult PutXBLDocumentInfo(nsXBLDocumentInfo* aDocumentInfo); |
116 | | nsXBLDocumentInfo* GetXBLDocumentInfo(nsIURI* aURI); |
117 | | void RemoveXBLDocumentInfo(nsXBLDocumentInfo* aDocumentInfo); |
118 | | |
119 | | nsresult PutLoadingDocListener(nsIURI* aURL, nsIStreamListener* aListener); |
120 | | nsIStreamListener* GetLoadingDocListener(nsIURI* aURL); |
121 | | void RemoveLoadingDocListener(nsIURI* aURL); |
122 | | |
123 | | void FlushSkinBindings(); |
124 | | |
125 | | nsresult GetBindingImplementation(nsIContent* aContent, REFNSIID aIID, void** aResult); |
126 | | |
127 | | |
128 | | void AppendAllSheets(nsTArray<mozilla::StyleSheet*>& aArray); |
129 | | |
130 | | void Traverse(nsIContent *aContent, nsCycleCollectionTraversalCallback &cb); |
131 | | |
132 | | NS_DECL_CYCLE_COLLECTION_CLASS(nsBindingManager) |
133 | | |
134 | | // Notify the binding manager when an outermost update begins and |
135 | | // ends. The end method can execute script. |
136 | | void BeginOutermostUpdate() |
137 | 0 | { |
138 | 0 | mAttachedStackSizeOnOutermost = mAttachedStack.Length(); |
139 | 0 | } |
140 | | |
141 | | void EndOutermostUpdate() |
142 | 0 | { |
143 | 0 | if (!mProcessingAttachedStack) { |
144 | 0 | ProcessAttachedQueue(mAttachedStackSizeOnOutermost); |
145 | 0 | mAttachedStackSizeOnOutermost = 0; |
146 | 0 | } |
147 | 0 | } |
148 | | |
149 | | // When removing an insertion point or a parent of one, clear the insertion |
150 | | // points and their insertion parents. |
151 | | void ClearInsertionPointsRecursively(nsIContent* aContent); |
152 | | |
153 | | // Called when the document is going away |
154 | | void DropDocumentReference(); |
155 | | |
156 | | nsIContent* FindNestedSingleInsertionPoint(nsIContent* aContainer, bool* aMulti); |
157 | | |
158 | | size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; |
159 | | |
160 | | // Enumerate each bound content's bindings (including its base bindings) |
161 | | // in mBoundContentSet. Return false from the callback to stop enumeration. |
162 | | using BoundContentProtoBindingCallback = |
163 | | std::function<bool (nsXBLPrototypeBinding*)>; |
164 | | |
165 | | bool EnumerateBoundContentProtoBindings( |
166 | | const BoundContentProtoBindingCallback&) const; |
167 | | |
168 | | protected: |
169 | | nsIXPConnectWrappedJS* GetWrappedJS(nsIContent* aContent); |
170 | | nsresult SetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS* aResult); |
171 | | |
172 | | // Called by ContentAppended and ContentInserted to handle a single child |
173 | | // insertion. aChild must not be null. aContainer may be null. |
174 | | // aAppend is true if this child is being appended, not inserted. |
175 | | void HandleChildInsertion(nsIContent* aContainer, nsIContent* aChild, |
176 | | bool aAppend); |
177 | | |
178 | | // Same as ProcessAttachedQueue, but also nulls out |
179 | | // mProcessAttachedQueueEvent |
180 | | void DoProcessAttachedQueue(); |
181 | | |
182 | | // Post an event to process the attached queue. |
183 | | void PostProcessAttachedQueueEvent(); |
184 | | |
185 | | // Call PostProcessAttachedQueueEvent() on a timer. |
186 | | static void PostPAQEventCallback(nsITimer* aTimer, void* aClosure); |
187 | | |
188 | | // MEMBER VARIABLES |
189 | | // A set of nsIContent that currently have a binding installed. |
190 | | nsAutoPtr<nsTHashtable<nsRefPtrHashKey<nsIContent> > > mBoundContentSet; |
191 | | |
192 | | // A mapping from nsIContent* to nsIXPWrappedJS* (an XPConnect |
193 | | // wrapper for JS objects). For XBL bindings that implement XPIDL |
194 | | // interfaces, and that get referred to from C++, this table caches |
195 | | // the XPConnect wrapper for the binding. By caching it, I control |
196 | | // its lifetime, and I prevent a re-wrap of the same script object |
197 | | // (in the case where multiple bindings in an XBL inheritance chain |
198 | | // both implement an XPIDL interface). |
199 | | typedef nsInterfaceHashtable<nsISupportsHashKey, nsIXPConnectWrappedJS> WrapperHashtable; |
200 | | nsAutoPtr<WrapperHashtable> mWrapperTable; |
201 | | |
202 | | // A mapping from a URL (a string) to nsXBLDocumentInfo*. This table |
203 | | // is the cache of all binding documents that have been loaded by a |
204 | | // given bound document. |
205 | | nsAutoPtr<nsRefPtrHashtable<nsURIHashKey,nsXBLDocumentInfo> > mDocumentTable; |
206 | | |
207 | | // A mapping from a URL (a string) to a nsIStreamListener. This |
208 | | // table is the currently loading binding docs. If they're in this |
209 | | // table, they have not yet finished loading. |
210 | | nsAutoPtr<nsInterfaceHashtable<nsURIHashKey,nsIStreamListener> > mLoadingDocTable; |
211 | | |
212 | | // A queue of binding attached event handlers that are awaiting execution. |
213 | | nsBindingList mAttachedStack; |
214 | | bool mProcessingAttachedStack; |
215 | | bool mDestroyed; |
216 | | uint32_t mAttachedStackSizeOnOutermost; |
217 | | |
218 | | // Our posted event to process the attached queue, if any |
219 | | friend class nsRunnableMethod<nsBindingManager>; |
220 | | RefPtr< nsRunnableMethod<nsBindingManager> > mProcessAttachedQueueEvent; |
221 | | |
222 | | // Our document. This is a weak ref; the document owns us |
223 | | nsIDocument* mDocument; |
224 | | }; |
225 | | |
226 | | #endif |