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 Communicator client code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Ms2ger <ms2ger@gmail.com>
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either of the GNU General Public License Version 2 or later (the "GPL"),
27 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : /*
40 : * Implementation of DOM Core's nsIDOMAttr node.
41 : */
42 :
43 : #include "nsDOMAttribute.h"
44 : #include "nsGenericElement.h"
45 : #include "mozilla/dom/Element.h"
46 : #include "nsContentCreatorFunctions.h"
47 : #include "nsINameSpaceManager.h"
48 : #include "nsDOMError.h"
49 : #include "nsUnicharUtils.h"
50 : #include "nsDOMString.h"
51 : #include "nsIDocument.h"
52 : #include "nsIDOMDocument.h"
53 : #include "nsIDOMUserDataHandler.h"
54 : #include "nsEventDispatcher.h"
55 : #include "nsGkAtoms.h"
56 : #include "nsCOMArray.h"
57 : #include "nsNodeUtils.h"
58 : #include "nsEventListenerManager.h"
59 : #include "nsTextNode.h"
60 : #include "mozAutoDocUpdate.h"
61 : #include "nsMutationEvent.h"
62 : #include "nsAsyncDOMEvent.h"
63 : #include "nsWrapperCacheInlines.h"
64 :
65 : using namespace mozilla::dom;
66 :
67 : //----------------------------------------------------------------------
68 : bool nsDOMAttribute::sInitialized;
69 :
70 996 : nsDOMAttribute::nsDOMAttribute(nsDOMAttributeMap *aAttrMap,
71 : already_AddRefed<nsINodeInfo> aNodeInfo,
72 : const nsAString &aValue, bool aNsAware)
73 996 : : nsIAttribute(aAttrMap, aNodeInfo, aNsAware), mValue(aValue), mChild(nsnull)
74 : {
75 996 : NS_ABORT_IF_FALSE(mNodeInfo, "We must get a nodeinfo here!");
76 996 : NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::ATTRIBUTE_NODE,
77 : "Wrong nodeType");
78 :
79 : // We don't add a reference to our content. It will tell us
80 : // to drop our reference when it goes away.
81 :
82 996 : EnsureChildState();
83 :
84 996 : nsIContent* content = GetContentInternal();
85 996 : if (content) {
86 943 : content->AddMutationObserver(this);
87 : }
88 996 : }
89 :
90 2988 : nsDOMAttribute::~nsDOMAttribute()
91 : {
92 996 : if (mChild) {
93 46 : static_cast<nsTextNode*>(mChild)->UnbindFromAttribute();
94 46 : NS_RELEASE(mChild);
95 46 : mFirstChild = nsnull;
96 : }
97 :
98 996 : nsIContent* content = GetContentInternal();
99 996 : if (content) {
100 0 : content->RemoveMutationObserver(this);
101 : }
102 3984 : }
103 :
104 1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMAttribute)
105 :
106 945 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMAttribute)
107 945 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
108 :
109 945 : if (!nsINode::Traverse(tmp, cb)) {
110 0 : return NS_SUCCESS_INTERRUPTED_TRAVERSE;
111 : }
112 :
113 945 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mChild)
114 945 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
115 :
116 945 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDOMAttribute)
117 945 : nsINode::Trace(tmp, aCallback, aClosure);
118 945 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
119 :
120 945 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMAttribute)
121 945 : nsINode::Unlink(tmp);
122 945 : if (tmp->mChild) {
123 938 : static_cast<nsTextNode*>(tmp->mChild)->UnbindFromAttribute();
124 938 : NS_RELEASE(tmp->mChild);
125 938 : tmp->mFirstChild = nsnull;
126 : }
127 945 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
128 :
129 974 : DOMCI_NODE_DATA(Attr, nsDOMAttribute)
130 :
131 : // QueryInterface implementation for nsDOMAttribute
132 24634 : NS_INTERFACE_TABLE_HEAD(nsDOMAttribute)
133 24634 : NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
134 20910 : NS_NODE_INTERFACE_TABLE5(nsDOMAttribute, nsIDOMAttr, nsIAttribute, nsIDOMNode,
135 : nsIDOMEventTarget, nsIMutationObserver)
136 14707 : NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsDOMAttribute)
137 1720 : NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISupportsWeakReference,
138 : new nsNodeSupportsWeakRefTearoff(this))
139 1720 : NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMXPathNSResolver,
140 : new nsNode3Tearoff(this))
141 1720 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Attr)
142 1698 : NS_INTERFACE_MAP_END
143 :
144 9887 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMAttribute)
145 9887 : NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(nsDOMAttribute,
146 : nsNodeUtils::LastRelease(this))
147 :
148 : void
149 947 : nsDOMAttribute::SetMap(nsDOMAttributeMap *aMap)
150 : {
151 947 : if (mAttrMap && !aMap && sInitialized) {
152 : // We're breaking a relationship with content and not getting a new one,
153 : // need to locally cache value. GetValue() does that.
154 945 : GetValue(mValue);
155 : }
156 :
157 947 : nsIContent* content = GetContentInternal();
158 947 : if (content) {
159 945 : content->RemoveMutationObserver(this);
160 : }
161 :
162 947 : mAttrMap = aMap;
163 :
164 : // If we have a new content, we sholud start listening to it.
165 947 : content = GetContentInternal();
166 947 : if (content) {
167 2 : content->AddMutationObserver(this);
168 : }
169 947 : }
170 :
171 : nsIContent*
172 0 : nsDOMAttribute::GetContent() const
173 : {
174 0 : return GetContentInternal();
175 : }
176 :
177 : nsresult
178 0 : nsDOMAttribute::SetOwnerDocument(nsIDocument* aDocument)
179 : {
180 0 : NS_ASSERTION(aDocument, "Missing document");
181 :
182 0 : nsIDocument *doc = OwnerDoc();
183 0 : NS_ASSERTION(doc != aDocument, "bad call to nsDOMAttribute::SetOwnerDocument");
184 0 : doc->DeleteAllPropertiesFor(this);
185 :
186 0 : nsCOMPtr<nsINodeInfo> newNodeInfo;
187 : newNodeInfo = aDocument->NodeInfoManager()->
188 : GetNodeInfo(mNodeInfo->NameAtom(), mNodeInfo->GetPrefixAtom(),
189 : mNodeInfo->NamespaceID(),
190 0 : nsIDOMNode::ATTRIBUTE_NODE);
191 0 : NS_ENSURE_TRUE(newNodeInfo, NS_ERROR_OUT_OF_MEMORY);
192 0 : NS_ASSERTION(newNodeInfo, "GetNodeInfo lies");
193 0 : mNodeInfo.swap(newNodeInfo);
194 :
195 0 : return NS_OK;
196 : }
197 :
198 : NS_IMETHODIMP
199 4829 : nsDOMAttribute::GetName(nsAString& aName)
200 : {
201 4829 : aName = NodeName();
202 4829 : return NS_OK;
203 : }
204 :
205 : already_AddRefed<nsIAtom>
206 3459 : nsDOMAttribute::GetNameAtom(nsIContent* aContent)
207 : {
208 3459 : nsIAtom* result = nsnull;
209 3471 : if (!mNsAware &&
210 6 : mNodeInfo->NamespaceID() == kNameSpaceID_None &&
211 6 : aContent->IsInHTMLDocument() &&
212 0 : aContent->IsHTML()) {
213 0 : nsString name;
214 0 : mNodeInfo->GetName(name);
215 0 : nsAutoString lowercaseName;
216 0 : nsContentUtils::ASCIIToLower(name, lowercaseName);
217 0 : nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(lowercaseName);
218 0 : nameAtom.swap(result);
219 : } else {
220 6918 : nsCOMPtr<nsIAtom> nameAtom = mNodeInfo->NameAtom();
221 3459 : nameAtom.swap(result);
222 : }
223 3459 : return result;
224 : }
225 :
226 : NS_IMETHODIMP
227 3626 : nsDOMAttribute::GetValue(nsAString& aValue)
228 : {
229 3626 : nsIContent* content = GetContentInternal();
230 3626 : if (content) {
231 6914 : nsCOMPtr<nsIAtom> nameAtom = GetNameAtom(content);
232 3457 : content->GetAttr(mNodeInfo->NamespaceID(), nameAtom, aValue);
233 : }
234 : else {
235 169 : aValue = mValue;
236 : }
237 :
238 3626 : return NS_OK;
239 : }
240 :
241 : NS_IMETHODIMP
242 0 : nsDOMAttribute::SetValue(const nsAString& aValue)
243 : {
244 0 : nsresult rv = NS_OK;
245 0 : nsIContent* content = GetContentInternal();
246 0 : if (content) {
247 0 : nsCOMPtr<nsIAtom> nameAtom = GetNameAtom(content);
248 : rv = content->SetAttr(mNodeInfo->NamespaceID(),
249 : nameAtom,
250 : mNodeInfo->GetPrefixAtom(),
251 : aValue,
252 0 : true);
253 : }
254 : else {
255 0 : mValue = aValue;
256 :
257 0 : if (mChild) {
258 0 : if (mValue.IsEmpty()) {
259 0 : doRemoveChild(true);
260 : } else {
261 0 : mChild->SetText(mValue, false);
262 : }
263 : } else {
264 0 : EnsureChildState();
265 : }
266 : }
267 :
268 0 : return rv;
269 : }
270 :
271 :
272 : NS_IMETHODIMP
273 0 : nsDOMAttribute::GetSpecified(bool* aSpecified)
274 : {
275 0 : NS_ENSURE_ARG_POINTER(aSpecified);
276 0 : OwnerDoc()->WarnOnceAbout(nsIDocument::eSpecified);
277 :
278 0 : *aSpecified = true;
279 0 : return NS_OK;
280 : }
281 :
282 : NS_IMETHODIMP
283 0 : nsDOMAttribute::GetOwnerElement(nsIDOMElement** aOwnerElement)
284 : {
285 0 : NS_ENSURE_ARG_POINTER(aOwnerElement);
286 0 : OwnerDoc()->WarnOnceAbout(nsIDocument::eOwnerElement);
287 :
288 0 : nsIContent* content = GetContentInternal();
289 0 : if (content) {
290 0 : return CallQueryInterface(content, aOwnerElement);
291 : }
292 :
293 0 : *aOwnerElement = nsnull;
294 :
295 0 : return NS_OK;
296 : }
297 :
298 : NS_IMETHODIMP
299 0 : nsDOMAttribute::GetNodeName(nsAString& aNodeName)
300 : {
301 0 : OwnerDoc()->WarnOnceAbout(nsIDocument::eNodeName);
302 :
303 0 : return GetName(aNodeName);
304 : }
305 :
306 : NS_IMETHODIMP
307 204 : nsDOMAttribute::GetNodeValue(nsAString& aNodeValue)
308 : {
309 204 : OwnerDoc()->WarnOnceAbout(nsIDocument::eNodeValue);
310 :
311 204 : return GetValue(aNodeValue);
312 : }
313 :
314 : NS_IMETHODIMP
315 0 : nsDOMAttribute::SetNodeValue(const nsAString& aNodeValue)
316 : {
317 0 : OwnerDoc()->WarnOnceAbout(nsIDocument::eNodeValue);
318 :
319 0 : return SetValue(aNodeValue);
320 : }
321 :
322 : NS_IMETHODIMP
323 0 : nsDOMAttribute::GetNodeType(PRUint16* aNodeType)
324 : {
325 0 : NS_ENSURE_ARG_POINTER(aNodeType);
326 0 : OwnerDoc()->WarnOnceAbout(nsIDocument::eNodeType);
327 :
328 0 : *aNodeType = (PRUint16)nsIDOMNode::ATTRIBUTE_NODE;
329 0 : return NS_OK;
330 : }
331 :
332 : NS_IMETHODIMP
333 0 : nsDOMAttribute::GetParentNode(nsIDOMNode** aParentNode)
334 : {
335 0 : NS_ENSURE_ARG_POINTER(aParentNode);
336 0 : OwnerDoc()->WarnOnceAbout(nsIDocument::eParentNode);
337 :
338 0 : *aParentNode = nsnull;
339 0 : return NS_OK;
340 : }
341 :
342 : NS_IMETHODIMP
343 0 : nsDOMAttribute::GetParentElement(nsIDOMElement** aParentElement)
344 : {
345 0 : *aParentElement = nsnull;
346 0 : return NS_OK;
347 : }
348 :
349 : NS_IMETHODIMP
350 0 : nsDOMAttribute::GetChildNodes(nsIDOMNodeList** aChildNodes)
351 : {
352 0 : OwnerDoc()->WarnOnceAbout(nsIDocument::eChildNodes);
353 :
354 0 : return nsINode::GetChildNodes(aChildNodes);
355 : }
356 :
357 : NS_IMETHODIMP
358 0 : nsDOMAttribute::HasChildNodes(bool* aHasChildNodes)
359 : {
360 0 : OwnerDoc()->WarnOnceAbout(nsIDocument::eHasChildNodes);
361 :
362 0 : *aHasChildNodes = mFirstChild != nsnull;
363 :
364 0 : return NS_OK;
365 : }
366 :
367 : NS_IMETHODIMP
368 0 : nsDOMAttribute::HasAttributes(bool* aHasAttributes)
369 : {
370 0 : NS_ENSURE_ARG_POINTER(aHasAttributes);
371 0 : OwnerDoc()->WarnOnceAbout(nsIDocument::eHasAttributes);
372 :
373 0 : *aHasAttributes = false;
374 :
375 0 : return NS_OK;
376 : }
377 :
378 : NS_IMETHODIMP
379 0 : nsDOMAttribute::GetFirstChild(nsIDOMNode** aFirstChild)
380 : {
381 0 : *aFirstChild = nsnull;
382 :
383 0 : OwnerDoc()->WarnOnceAbout(nsIDocument::eFirstChild);
384 :
385 0 : if (mFirstChild) {
386 0 : CallQueryInterface(mFirstChild, aFirstChild);
387 : }
388 :
389 0 : return NS_OK;
390 : }
391 :
392 : NS_IMETHODIMP
393 0 : nsDOMAttribute::GetLastChild(nsIDOMNode** aLastChild)
394 : {
395 0 : OwnerDoc()->WarnOnceAbout(nsIDocument::eLastChild);
396 :
397 0 : return GetFirstChild(aLastChild);
398 : }
399 :
400 : NS_IMETHODIMP
401 0 : nsDOMAttribute::GetPreviousSibling(nsIDOMNode** aPreviousSibling)
402 : {
403 0 : NS_ENSURE_ARG_POINTER(aPreviousSibling);
404 :
405 0 : OwnerDoc()->WarnOnceAbout(nsIDocument::ePreviousSibling);
406 :
407 0 : *aPreviousSibling = nsnull;
408 0 : return NS_OK;
409 : }
410 :
411 : NS_IMETHODIMP
412 0 : nsDOMAttribute::GetNextSibling(nsIDOMNode** aNextSibling)
413 : {
414 0 : NS_ENSURE_ARG_POINTER(aNextSibling);
415 :
416 0 : OwnerDoc()->WarnOnceAbout(nsIDocument::eNextSibling);
417 :
418 0 : *aNextSibling = nsnull;
419 0 : return NS_OK;
420 : }
421 :
422 : NS_IMETHODIMP
423 0 : nsDOMAttribute::GetAttributes(nsIDOMNamedNodeMap** aAttributes)
424 : {
425 0 : NS_ENSURE_ARG_POINTER(aAttributes);
426 :
427 0 : OwnerDoc()->WarnOnceAbout(nsIDocument::eAttributes);
428 :
429 0 : *aAttributes = nsnull;
430 0 : return NS_OK;
431 : }
432 :
433 : NS_IMETHODIMP
434 0 : nsDOMAttribute::InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild, nsIDOMNode** aReturn)
435 : {
436 0 : OwnerDoc()->WarnOnceAbout(nsIDocument::eInsertBefore);
437 :
438 0 : return ReplaceOrInsertBefore(false, aNewChild, aRefChild, aReturn);
439 : }
440 :
441 : NS_IMETHODIMP
442 0 : nsDOMAttribute::ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild, nsIDOMNode** aReturn)
443 : {
444 0 : OwnerDoc()->WarnOnceAbout(nsIDocument::eReplaceChild);
445 :
446 0 : return ReplaceOrInsertBefore(true, aNewChild, aOldChild, aReturn);
447 : }
448 :
449 : NS_IMETHODIMP
450 0 : nsDOMAttribute::RemoveChild(nsIDOMNode* aOldChild, nsIDOMNode** aReturn)
451 : {
452 0 : OwnerDoc()->WarnOnceAbout(nsIDocument::eRemoveChild);
453 :
454 0 : return nsINode::RemoveChild(aOldChild, aReturn);
455 : }
456 :
457 : NS_IMETHODIMP
458 0 : nsDOMAttribute::AppendChild(nsIDOMNode* aNewChild, nsIDOMNode** aReturn)
459 : {
460 0 : OwnerDoc()->WarnOnceAbout(nsIDocument::eAppendChild);
461 :
462 0 : return InsertBefore(aNewChild, nsnull, aReturn);
463 : }
464 :
465 : nsresult
466 48 : nsDOMAttribute::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
467 : {
468 96 : nsAutoString value;
469 48 : const_cast<nsDOMAttribute*>(this)->GetValue(value);
470 :
471 96 : nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
472 96 : *aResult = new nsDOMAttribute(nsnull, ni.forget(), value, mNsAware);
473 48 : if (!*aResult) {
474 0 : return NS_ERROR_OUT_OF_MEMORY;
475 : }
476 :
477 48 : NS_ADDREF(*aResult);
478 :
479 48 : return NS_OK;
480 : }
481 :
482 : NS_IMETHODIMP
483 48 : nsDOMAttribute::CloneNode(bool aDeep, PRUint8 aOptionalArgc, nsIDOMNode** aResult)
484 : {
485 48 : OwnerDoc()->WarnOnceAbout(nsIDocument::eCloneNode);
486 :
487 48 : if (!aOptionalArgc) {
488 0 : aDeep = true;
489 : }
490 :
491 48 : return nsNodeUtils::CloneNodeImpl(this, aDeep, true, aResult);
492 : }
493 :
494 : NS_IMETHODIMP
495 0 : nsDOMAttribute::GetOwnerDocument(nsIDOMDocument** aOwnerDocument)
496 : {
497 0 : OwnerDoc()->WarnOnceAbout(nsIDocument::eOwnerDocument);
498 :
499 0 : return nsINode::GetOwnerDocument(aOwnerDocument);
500 : }
501 :
502 : NS_IMETHODIMP
503 133 : nsDOMAttribute::GetNamespaceURI(nsAString& aNamespaceURI)
504 : {
505 133 : return mNodeInfo->GetNamespaceURI(aNamespaceURI);
506 : }
507 :
508 : NS_IMETHODIMP
509 0 : nsDOMAttribute::GetPrefix(nsAString& aPrefix)
510 : {
511 0 : mNodeInfo->GetPrefix(aPrefix);
512 0 : return NS_OK;
513 : }
514 :
515 : NS_IMETHODIMP
516 34 : nsDOMAttribute::GetLocalName(nsAString& aLocalName)
517 : {
518 34 : mNodeInfo->GetName(aLocalName);
519 34 : return NS_OK;
520 : }
521 :
522 : NS_IMETHODIMP
523 0 : nsDOMAttribute::Normalize()
524 : {
525 0 : OwnerDoc()->WarnOnceAbout(nsIDocument::eNormalize);
526 :
527 : // Nothing to do here
528 0 : return NS_OK;
529 : }
530 :
531 : NS_IMETHODIMP
532 0 : nsDOMAttribute::IsSupported(const nsAString& aFeature,
533 : const nsAString& aVersion,
534 : bool* aReturn)
535 : {
536 0 : OwnerDoc()->WarnOnceAbout(nsIDocument::eIsSupported);
537 :
538 : return nsGenericElement::InternalIsSupported(static_cast<nsIDOMAttr*>(this),
539 0 : aFeature, aVersion, aReturn);
540 : }
541 :
542 : already_AddRefed<nsIURI>
543 0 : nsDOMAttribute::GetBaseURI() const
544 : {
545 0 : nsINode *parent = GetContentInternal();
546 :
547 0 : return parent ? parent->GetBaseURI() : nsnull;
548 : }
549 :
550 : NS_IMETHODIMP
551 0 : nsDOMAttribute::GetDOMBaseURI(nsAString &aURI)
552 : {
553 0 : return nsINode::GetDOMBaseURI(aURI);
554 : }
555 :
556 : NS_IMETHODIMP
557 0 : nsDOMAttribute::CompareDocumentPosition(nsIDOMNode *other,
558 : PRUint16 *aResult)
559 : {
560 0 : return nsINode::CompareDocumentPosition(other, aResult);
561 : }
562 :
563 : NS_IMETHODIMP
564 0 : nsDOMAttribute::IsEqualNode(nsIDOMNode* aOther, bool* aResult)
565 : {
566 0 : OwnerDoc()->WarnOnceAbout(nsIDocument::eIsEqualNode);
567 :
568 0 : return nsINode::IsEqualNode(aOther, aResult);
569 : }
570 :
571 : NS_IMETHODIMP
572 0 : nsDOMAttribute::GetTextContent(nsAString &aTextContent)
573 : {
574 0 : OwnerDoc()->WarnOnceAbout(nsIDocument::eTextContent);
575 :
576 0 : return GetNodeValue(aTextContent);
577 : }
578 :
579 : NS_IMETHODIMP
580 0 : nsDOMAttribute::SetTextContent(const nsAString& aTextContent)
581 : {
582 0 : OwnerDoc()->WarnOnceAbout(nsIDocument::eTextContent);
583 :
584 0 : return SetNodeValue(aTextContent);
585 : }
586 :
587 : NS_IMETHODIMP
588 0 : nsDOMAttribute::Contains(nsIDOMNode* aOther, bool* aReturn)
589 : {
590 0 : return nsINode::Contains(aOther, aReturn);
591 : }
592 :
593 : NS_IMETHODIMP
594 0 : nsDOMAttribute::LookupPrefix(const nsAString & namespaceURI,
595 : nsAString & aResult)
596 : {
597 0 : SetDOMStringToNull(aResult);
598 0 : return NS_OK;
599 : }
600 :
601 : NS_IMETHODIMP
602 0 : nsDOMAttribute::IsDefaultNamespace(const nsAString & namespaceURI,
603 : bool *aResult)
604 : {
605 0 : *aResult = namespaceURI.IsEmpty();
606 0 : return NS_OK;
607 : }
608 :
609 : NS_IMETHODIMP
610 0 : nsDOMAttribute::LookupNamespaceURI(const nsAString & prefix,
611 : nsAString & aResult)
612 : {
613 0 : SetDOMStringToNull(aResult);
614 0 : return NS_OK;
615 : }
616 :
617 : NS_IMETHODIMP
618 0 : nsDOMAttribute::SetUserData(const nsAString & key,
619 : nsIVariant *data, nsIDOMUserDataHandler *handler,
620 : nsIVariant **aResult)
621 : {
622 0 : return nsINode::SetUserData(key, data, handler, aResult);
623 : }
624 :
625 : NS_IMETHODIMP
626 0 : nsDOMAttribute::GetUserData(const nsAString & key, nsIVariant **aResult)
627 : {
628 0 : return nsINode::GetUserData(key, aResult);
629 : }
630 :
631 : NS_IMETHODIMP
632 0 : nsDOMAttribute::GetIsId(bool* aReturn)
633 : {
634 0 : nsIContent* content = GetContentInternal();
635 0 : if (!content)
636 : {
637 0 : *aReturn = false;
638 0 : return NS_OK;
639 : }
640 :
641 0 : nsIAtom* idAtom = content->GetIDAttributeName();
642 0 : if (!idAtom)
643 : {
644 0 : *aReturn = false;
645 0 : return NS_OK;
646 : }
647 :
648 0 : *aReturn = mNodeInfo->Equals(idAtom, kNameSpaceID_None);
649 0 : return NS_OK;
650 : }
651 :
652 : bool
653 7055 : nsDOMAttribute::IsNodeOfType(PRUint32 aFlags) const
654 : {
655 7055 : return !(aFlags & ~eATTRIBUTE);
656 : }
657 :
658 : PRUint32
659 0 : nsDOMAttribute::GetChildCount() const
660 : {
661 0 : return mFirstChild ? 1 : 0;
662 : }
663 :
664 : nsIContent *
665 48 : nsDOMAttribute::GetChildAt(PRUint32 aIndex) const
666 : {
667 48 : return aIndex == 0 ? mFirstChild : nsnull;
668 : }
669 :
670 : nsIContent * const *
671 0 : nsDOMAttribute::GetChildArray(PRUint32* aChildCount) const
672 : {
673 0 : *aChildCount = GetChildCount();
674 0 : return &mFirstChild;
675 : }
676 :
677 : PRInt32
678 0 : nsDOMAttribute::IndexOf(nsINode* aPossibleChild) const
679 : {
680 0 : if (!aPossibleChild || aPossibleChild != mFirstChild) {
681 0 : return -1;
682 : }
683 :
684 0 : return 0;
685 : }
686 :
687 : nsresult
688 0 : nsDOMAttribute::InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
689 : bool aNotify)
690 : {
691 0 : return NS_ERROR_NOT_IMPLEMENTED;
692 : }
693 :
694 : nsresult
695 0 : nsDOMAttribute::AppendChildTo(nsIContent* aKid, bool aNotify)
696 : {
697 0 : return NS_ERROR_NOT_IMPLEMENTED;
698 : }
699 :
700 : nsresult
701 0 : nsDOMAttribute::RemoveChildAt(PRUint32 aIndex, bool aNotify)
702 : {
703 0 : if (aIndex != 0 || !mChild) {
704 0 : return NS_OK;
705 : }
706 :
707 0 : doRemoveChild(aNotify);
708 :
709 0 : nsString nullString;
710 0 : SetDOMStringToNull(nullString);
711 0 : SetValue(nullString);
712 0 : return NS_OK;
713 : }
714 :
715 : nsresult
716 0 : nsDOMAttribute::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
717 : {
718 0 : aVisitor.mCanHandle = true;
719 0 : return NS_OK;
720 : }
721 :
722 : void
723 998 : nsDOMAttribute::EnsureChildState()
724 : {
725 998 : NS_PRECONDITION(!mChild, "Someone screwed up");
726 :
727 1996 : nsAutoString value;
728 998 : GetValue(value);
729 :
730 998 : if (!value.IsEmpty()) {
731 984 : NS_NewTextNode(&mChild, mNodeInfo->NodeInfoManager());
732 :
733 984 : static_cast<nsTextNode*>(mChild)->BindToAttribute(this);
734 984 : mFirstChild = mChild;
735 :
736 984 : mChild->SetText(value, false);
737 : }
738 998 : }
739 :
740 : void
741 4 : nsDOMAttribute::AttributeChanged(nsIDocument* aDocument,
742 : Element* aElement,
743 : PRInt32 aNameSpaceID,
744 : nsIAtom* aAttribute,
745 : PRInt32 aModType)
746 : {
747 4 : nsIContent* content = GetContentInternal();
748 4 : if (aElement != content) {
749 2 : return;
750 : }
751 :
752 2 : if (aNameSpaceID != mNodeInfo->NamespaceID()) {
753 0 : return;
754 : }
755 :
756 4 : nsCOMPtr<nsIAtom> nameAtom = GetNameAtom(content);
757 2 : if (nameAtom != aAttribute) {
758 : return;
759 : }
760 :
761 4 : nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
762 :
763 : // Just blow away our mChild and recreate it if needed
764 2 : if (mChild) {
765 0 : doRemoveChild(true);
766 : }
767 2 : EnsureChildState();
768 : }
769 :
770 : void
771 1404 : nsDOMAttribute::Initialize()
772 : {
773 1404 : sInitialized = true;
774 1404 : }
775 :
776 : void
777 1403 : nsDOMAttribute::Shutdown()
778 : {
779 1403 : sInitialized = false;
780 1403 : }
781 :
782 : void
783 0 : nsDOMAttribute::doRemoveChild(bool aNotify)
784 : {
785 0 : NS_ASSERTION(mChild && mFirstChild, "Why are we here?");
786 0 : NS_ASSERTION(mChild == mFirstChild, "Something got out of sync!");
787 :
788 0 : nsRefPtr<nsTextNode> child = static_cast<nsTextNode*>(mChild);
789 0 : nsMutationGuard::DidMutate();
790 0 : mozAutoDocUpdate updateBatch(OwnerDoc(), UPDATE_CONTENT_MODEL, aNotify);
791 :
792 0 : NS_RELEASE(mChild);
793 0 : mFirstChild = nsnull;
794 :
795 0 : if (aNotify) {
796 0 : nsNodeUtils::AttributeChildRemoved(this, child);
797 : }
798 :
799 0 : child->UnbindFromAttribute();
800 4392 : }
801 :
|