1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is Mozilla Foundation.
18 : * Portions created by the Initial Developer are Copyright (C) 2006
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : * Jonas Sicking <jonas@sicking.cc> (Original Author)
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either the GNU General Public License Version 2 or later (the "GPL"), or
26 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #ifndef nsNodeUtils_h___
39 : #define nsNodeUtils_h___
40 :
41 : #include "nsINode.h"
42 :
43 : struct CharacterDataChangeInfo;
44 : struct JSContext;
45 : struct JSObject;
46 : class nsIVariant;
47 : class nsIDOMNode;
48 : class nsIDOMUserDataHandler;
49 : template<class E> class nsCOMArray;
50 : class nsCycleCollectionTraversalCallback;
51 :
52 : class nsNodeUtils
53 : {
54 : public:
55 : /**
56 : * Send CharacterDataWillChange notifications to nsIMutationObservers.
57 : * @param aContent Node whose data changed
58 : * @param aInfo Struct with information details about the change
59 : * @see nsIMutationObserver::CharacterDataWillChange
60 : */
61 : static void CharacterDataWillChange(nsIContent* aContent,
62 : CharacterDataChangeInfo* aInfo);
63 :
64 : /**
65 : * Send CharacterDataChanged notifications to nsIMutationObservers.
66 : * @param aContent Node whose data changed
67 : * @param aInfo Struct with information details about the change
68 : * @see nsIMutationObserver::CharacterDataChanged
69 : */
70 : static void CharacterDataChanged(nsIContent* aContent,
71 : CharacterDataChangeInfo* aInfo);
72 :
73 : /**
74 : * Send AttributeWillChange notifications to nsIMutationObservers.
75 : * @param aElement Element whose data will change
76 : * @param aNameSpaceID Namespace of changing attribute
77 : * @param aAttribute Local-name of changing attribute
78 : * @param aModType Type of change (add/change/removal)
79 : * @see nsIMutationObserver::AttributeWillChange
80 : */
81 : static void AttributeWillChange(mozilla::dom::Element* aElement,
82 : PRInt32 aNameSpaceID,
83 : nsIAtom* aAttribute,
84 : PRInt32 aModType);
85 :
86 : /**
87 : * Send AttributeChanged notifications to nsIMutationObservers.
88 : * @param aElement Element whose data changed
89 : * @param aNameSpaceID Namespace of changed attribute
90 : * @param aAttribute Local-name of changed attribute
91 : * @param aModType Type of change (add/change/removal)
92 : * @see nsIMutationObserver::AttributeChanged
93 : */
94 : static void AttributeChanged(mozilla::dom::Element* aElement,
95 : PRInt32 aNameSpaceID,
96 : nsIAtom* aAttribute,
97 : PRInt32 aModType);
98 :
99 : /**
100 : * Send ContentAppended notifications to nsIMutationObservers
101 : * @param aContainer Node into which new child/children were added
102 : * @param aFirstNewContent First new child
103 : * @param aNewIndexInContainer Index of first new child
104 : * @see nsIMutationObserver::ContentAppended
105 : */
106 : static void ContentAppended(nsIContent* aContainer,
107 : nsIContent* aFirstNewContent,
108 : PRInt32 aNewIndexInContainer);
109 :
110 : /**
111 : * Send ContentInserted notifications to nsIMutationObservers
112 : * @param aContainer Node into which new child was inserted
113 : * @param aChild Newly inserted child
114 : * @param aIndexInContainer Index of new child
115 : * @see nsIMutationObserver::ContentInserted
116 : */
117 : static void ContentInserted(nsINode* aContainer,
118 : nsIContent* aChild,
119 : PRInt32 aIndexInContainer);
120 : /**
121 : * Send ContentRemoved notifications to nsIMutationObservers
122 : * @param aContainer Node from which child was removed
123 : * @param aChild Removed child
124 : * @param aIndexInContainer Index of removed child
125 : * @see nsIMutationObserver::ContentRemoved
126 : */
127 : static void ContentRemoved(nsINode* aContainer,
128 : nsIContent* aChild,
129 : PRInt32 aIndexInContainer,
130 : nsIContent* aPreviousSibling);
131 : /**
132 : * Send AttributeChildRemoved notifications to nsIMutationObservers.
133 : * @param aAttribute Attribute from which the child has been removed.
134 : * @param aChild Removed child.
135 : * @see nsIMutationObserver2::AttributeChildRemoved.
136 : */
137 : static void AttributeChildRemoved(nsINode* aAttribute, nsIContent* aChild);
138 : /**
139 : * Send ParentChainChanged notifications to nsIMutationObservers
140 : * @param aContent The piece of content that had its parent changed.
141 : * @see nsIMutationObserver::ParentChainChanged
142 : */
143 : static void ParentChainChanged(nsIContent *aContent);
144 :
145 : /**
146 : * To be called when reference count of aNode drops to zero.
147 : * @param aNode The node which is going to be deleted.
148 : */
149 : static void LastRelease(nsINode* aNode);
150 :
151 : /**
152 : * Clones aNode, its attributes and, if aDeep is true, its descendant nodes
153 : * If aNewNodeInfoManager is not null, it is used to create new nodeinfos for
154 : * the clones. aNodesWithProperties will be filled with all the nodes that
155 : * have properties, and every node in it will be followed by its clone.
156 : *
157 : * @param aNode Node to clone.
158 : * @param aDeep If true the function will be called recursively on
159 : * descendants of the node
160 : * @param aNewNodeInfoManager The nodeinfo manager to use to create new
161 : * nodeinfos for aNode and its attributes and
162 : * descendants. May be null if the nodeinfos
163 : * shouldn't be changed.
164 : * @param aNodesWithProperties All nodes (from amongst aNode and its
165 : * descendants) with properties. Every node will
166 : * be followed by its clone.
167 : * @param aResult *aResult will contain the cloned node.
168 : */
169 262 : static nsresult Clone(nsINode *aNode, bool aDeep,
170 : nsNodeInfoManager *aNewNodeInfoManager,
171 : nsCOMArray<nsINode> &aNodesWithProperties,
172 : nsIDOMNode **aResult)
173 : {
174 : return CloneAndAdopt(aNode, true, aDeep, aNewNodeInfoManager, nsnull,
175 262 : nsnull, aNodesWithProperties, aResult);
176 : }
177 :
178 : /**
179 : * Walks aNode, its attributes and descendant nodes. If aNewNodeInfoManager is
180 : * not null, it is used to create new nodeinfos for the nodes. Also reparents
181 : * the XPConnect wrappers for the nodes in aNewScope if aCx is not null.
182 : * aNodesWithProperties will be filled with all the nodes that have
183 : * properties.
184 : *
185 : * @param aNode Node to adopt.
186 : * @param aNewNodeInfoManager The nodeinfo manager to use to create new
187 : * nodeinfos for aNode and its attributes and
188 : * descendants. May be null if the nodeinfos
189 : * shouldn't be changed.
190 : * @param aCx Context to use for reparenting the wrappers, or null if no
191 : * reparenting should be done. Must be null if aNewNodeInfoManager
192 : * is null.
193 : * @param aNewScope New scope for the wrappers. May be null if aCx is null.
194 : * @param aNodesWithProperties All nodes (from amongst aNode and its
195 : * descendants) with properties.
196 : */
197 0 : static nsresult Adopt(nsINode *aNode, nsNodeInfoManager *aNewNodeInfoManager,
198 : JSContext *aCx, JSObject *aNewScope,
199 : nsCOMArray<nsINode> &aNodesWithProperties)
200 : {
201 : nsresult rv = CloneAndAdopt(aNode, false, true, aNewNodeInfoManager,
202 : aCx, aNewScope, aNodesWithProperties,
203 0 : nsnull);
204 :
205 0 : nsMutationGuard::DidMutate();
206 :
207 0 : return rv;
208 : }
209 :
210 : /**
211 : * Call registered userdata handlers for operation aOperation for the nodes in
212 : * aNodesWithProperties. If aCloned is true aNodesWithProperties should
213 : * contain both the original and the cloned nodes (and only the userdata
214 : * handlers registered for the original nodes will be called).
215 : *
216 : * @param aNodesWithProperties Contains the nodes that might have properties
217 : * registered on them. If aCloned is true every
218 : * one of those nodes should be immediately
219 : * followed in the array by the cloned node.
220 : * @param aOwnerDocument The ownerDocument of the original nodes.
221 : * @param aOperation The operation to call a userdata handler for.
222 : * @param aCloned If true aNodesWithProperties will contain both original
223 : * and cloned nodes.
224 : */
225 : static nsresult CallUserDataHandlers(nsCOMArray<nsINode> &aNodesWithProperties,
226 : nsIDocument *aOwnerDocument,
227 : PRUint16 aOperation, bool aCloned);
228 :
229 : /**
230 : * Helper for the cycle collector to traverse the DOM UserData and
231 : * UserDataHandlers for aNode.
232 : *
233 : * @param aNode the node to traverse UserData and UserDataHandlers for
234 : * @param aCb the cycle collection callback
235 : */
236 : static void TraverseUserData(nsINode* aNode,
237 : nsCycleCollectionTraversalCallback &aCb);
238 :
239 : /**
240 : * A basic implementation of the DOM cloneNode method. Calls nsINode::Clone to
241 : * do the actual cloning of the node.
242 : *
243 : * @param aNode the node to clone
244 : * @param aDeep if true all descendants will be cloned too
245 : * @param aCallUserDataHandlers if true, user data handlers will be called
246 : * @param aResult the clone
247 : */
248 : static nsresult CloneNodeImpl(nsINode *aNode, bool aDeep,
249 : bool aCallUserDataHandlers,
250 : nsIDOMNode **aResult);
251 :
252 : /**
253 : * Release the UserData and UserDataHandlers for aNode.
254 : *
255 : * @param aNode the node to release the UserData and UserDataHandlers for
256 : */
257 : static void UnlinkUserData(nsINode *aNode);
258 :
259 : private:
260 : /**
261 : * Walks aNode, its attributes and, if aDeep is true, its descendant nodes.
262 : * If aClone is true the nodes will be cloned. If aNewNodeInfoManager is
263 : * not null, it is used to create new nodeinfos for the nodes. Also reparents
264 : * the XPConnect wrappers for the nodes in aNewScope if aCx is not null.
265 : * aNodesWithProperties will be filled with all the nodes that have
266 : * properties.
267 : *
268 : * @param aNode Node to adopt/clone.
269 : * @param aClone If true the node will be cloned and the cloned node will
270 : * be in aResult.
271 : * @param aDeep If true the function will be called recursively on
272 : * descendants of the node
273 : * @param aNewNodeInfoManager The nodeinfo manager to use to create new
274 : * nodeinfos for aNode and its attributes and
275 : * descendants. May be null if the nodeinfos
276 : * shouldn't be changed.
277 : * @param aCx Context to use for reparenting the wrappers, or null if no
278 : * reparenting should be done. Must be null if aClone is true or
279 : * if aNewNodeInfoManager is null.
280 : * @param aNewScope New scope for the wrappers. May be null if aCx is null.
281 : * @param aNodesWithProperties All nodes (from amongst aNode and its
282 : * descendants) with properties. If aClone is
283 : * true every node will be followed by its
284 : * clone.
285 : * @param aResult If aClone is false then aResult must be null, else
286 : * *aResult will contain the cloned node.
287 : */
288 262 : static nsresult CloneAndAdopt(nsINode *aNode, bool aClone, bool aDeep,
289 : nsNodeInfoManager *aNewNodeInfoManager,
290 : JSContext *aCx, JSObject *aNewScope,
291 : nsCOMArray<nsINode> &aNodesWithProperties,
292 : nsIDOMNode **aResult)
293 : {
294 262 : NS_ASSERTION(!aClone == !aResult,
295 : "aResult must be null when adopting and non-null when "
296 : "cloning");
297 :
298 524 : nsCOMPtr<nsINode> clone;
299 : nsresult rv = CloneAndAdopt(aNode, aClone, aDeep, aNewNodeInfoManager,
300 : aCx, aNewScope, aNodesWithProperties,
301 262 : nsnull, getter_AddRefs(clone));
302 262 : NS_ENSURE_SUCCESS(rv, rv);
303 :
304 262 : return clone ? CallQueryInterface(clone, aResult) : NS_OK;
305 : }
306 :
307 : /**
308 : * See above for arguments that aren't described here.
309 : *
310 : * @param aParent If aClone is true the cloned node will be appended to
311 : * aParent's children. May be null. If not null then aNode
312 : * must be an nsIContent.
313 : * @param aResult If aClone is true then *aResult will contain the cloned
314 : * node.
315 : */
316 : static nsresult CloneAndAdopt(nsINode *aNode, bool aClone, bool aDeep,
317 : nsNodeInfoManager *aNewNodeInfoManager,
318 : JSContext *aCx, JSObject *aNewScope,
319 : nsCOMArray<nsINode> &aNodesWithProperties,
320 : nsINode *aParent, nsINode **aResult);
321 : };
322 :
323 : #endif // nsNodeUtils_h___
|