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 : * Pierre Phaneuf <pp@ludusdesign.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 : #include "nsXMLElement.h"
40 : #include "nsContentUtils.h" // nsAutoScriptBlocker
41 :
42 : nsresult
43 36770 : NS_NewXMLElement(nsIContent** aInstancePtrResult, already_AddRefed<nsINodeInfo> aNodeInfo)
44 : {
45 36770 : nsXMLElement* it = new nsXMLElement(aNodeInfo);
46 36770 : NS_ADDREF(*aInstancePtrResult = it);
47 36770 : return NS_OK;
48 : }
49 :
50 8110 : DOMCI_NODE_DATA(Element, nsXMLElement)
51 :
52 : // QueryInterface implementation for nsXMLElement
53 1836095 : NS_INTERFACE_TABLE_HEAD(nsXMLElement)
54 : NS_NODE_OFFSET_AND_INTERFACE_TABLE_BEGIN(nsXMLElement)
55 : NS_INTERFACE_TABLE_ENTRY(nsXMLElement, nsIDOMNode)
56 : NS_INTERFACE_TABLE_ENTRY(nsXMLElement, nsIDOMElement)
57 1836095 : NS_OFFSET_AND_INTERFACE_TABLE_END
58 1827869 : NS_ELEMENT_INTERFACE_TABLE_TO_MAP_SEGUE
59 637 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Element)
60 523 : NS_ELEMENT_INTERFACE_MAP_END
61 :
62 703731 : NS_IMPL_ADDREF_INHERITED(nsXMLElement, nsGenericElement)
63 703721 : NS_IMPL_RELEASE_INHERITED(nsXMLElement, nsGenericElement)
64 :
65 516 : NS_IMPL_ELEMENT_CLONE(nsXMLElement)
66 :
67 : nsresult
68 0 : nsXMLElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
69 : bool aNotify)
70 : {
71 0 : nsAutoScriptBlocker scriptBlocker;
72 0 : bool isId = false;
73 0 : if (aAttribute == GetIDAttributeName() &&
74 : aNameSpaceID == kNameSpaceID_None) {
75 : // Have to do this before clearing flag. See RemoveFromIdTable
76 0 : RemoveFromIdTable();
77 0 : isId = true;
78 : }
79 :
80 0 : nsMutationGuard guard;
81 :
82 0 : nsresult rv = nsGenericElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify);
83 :
84 0 : if (isId &&
85 0 : (!guard.Mutated(0) ||
86 0 : !mNodeInfo->GetIDAttributeAtom() ||
87 0 : !HasAttr(kNameSpaceID_None, GetIDAttributeName()))) {
88 0 : ClearHasID();
89 : }
90 :
91 0 : return rv;
92 : }
93 :
94 : nsIAtom *
95 11593 : nsXMLElement::GetIDAttributeName() const
96 : {
97 11593 : return mNodeInfo->GetIDAttributeAtom();
98 : }
99 :
100 : nsIAtom*
101 336 : nsXMLElement::DoGetID() const
102 : {
103 336 : NS_ASSERTION(HasID(), "Unexpected call");
104 :
105 336 : const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(GetIDAttributeName());
106 336 : return attrVal ? attrVal->GetAtomValue() : nsnull;
107 : }
108 :
109 : void
110 0 : nsXMLElement::NodeInfoChanged(nsINodeInfo* aOldNodeInfo)
111 : {
112 0 : NS_ASSERTION(!IsInDoc() ||
113 : aOldNodeInfo->GetDocument() == mNodeInfo->GetDocument(),
114 : "Can only change document if we're not inside one");
115 0 : nsIDocument* doc = GetCurrentDoc();
116 :
117 0 : if (HasID() && doc) {
118 : const nsAttrValue* attrVal =
119 0 : mAttrsAndChildren.GetAttr(aOldNodeInfo->GetIDAttributeAtom());
120 0 : if (attrVal) {
121 0 : doc->RemoveFromIdTable(this, attrVal->GetAtomValue());
122 : }
123 : }
124 :
125 0 : ClearHasID();
126 :
127 0 : nsIAtom* IDName = GetIDAttributeName();
128 0 : if (IDName) {
129 0 : const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(IDName);
130 0 : if (attrVal) {
131 0 : SetHasID();
132 0 : if (attrVal->Type() == nsAttrValue::eString) {
133 0 : nsString idVal(attrVal->GetStringValue());
134 :
135 : // Create an atom from the value and set it into the attribute list.
136 0 : const_cast<nsAttrValue*>(attrVal)->ParseAtom(idVal);
137 : }
138 0 : NS_ASSERTION(attrVal->Type() == nsAttrValue::eAtom,
139 : "Should be atom by now");
140 0 : if (doc) {
141 0 : doc->AddToIdTable(this, attrVal->GetAtomValue());
142 : }
143 : }
144 : }
145 0 : }
146 :
147 : bool
148 11259 : nsXMLElement::ParseAttribute(PRInt32 aNamespaceID,
149 : nsIAtom* aAttribute,
150 : const nsAString& aValue,
151 : nsAttrValue& aResult)
152 : {
153 11259 : if (aAttribute == GetIDAttributeName() &&
154 : aNamespaceID == kNameSpaceID_None) {
155 : // Store id as an atom. id="" means that the element has no id,
156 : // not that it has an emptystring as the id.
157 192 : RemoveFromIdTable();
158 192 : if (aValue.IsEmpty()) {
159 0 : ClearHasID();
160 0 : return false;
161 : }
162 192 : aResult.ParseAtom(aValue);
163 192 : SetHasID();
164 192 : AddToIdTable(aResult.GetAtomValue());
165 192 : return true;
166 : }
167 :
168 11067 : return false;
169 : }
170 :
171 : nsresult
172 37104 : nsXMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
173 : nsIContent* aBindingParent,
174 : bool aCompileEventHandlers)
175 : {
176 : nsresult rv = nsGenericElement::BindToTree(aDocument, aParent,
177 : aBindingParent,
178 37104 : aCompileEventHandlers);
179 37104 : NS_ENSURE_SUCCESS(rv, rv);
180 :
181 37104 : if (aDocument && HasID() && !GetBindingParent()) {
182 112 : aDocument->AddToIdTable(this, DoGetID());
183 : }
184 :
185 37104 : return NS_OK;
186 : }
187 :
188 : void
189 116959 : nsXMLElement::UnbindFromTree(bool aDeep, bool aNullParent)
190 : {
191 116959 : RemoveFromIdTable();
192 :
193 116959 : return nsGenericElement::UnbindFromTree(aDeep, aNullParent);
194 : }
|