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