content/base/src/Attr.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 /*
michael@0 7 * Implementation of DOM Core's nsIDOMAttr node.
michael@0 8 */
michael@0 9
michael@0 10 #include "mozilla/dom/Attr.h"
michael@0 11 #include "mozilla/dom/AttrBinding.h"
michael@0 12 #include "mozilla/dom/Element.h"
michael@0 13 #include "mozilla/EventDispatcher.h"
michael@0 14 #include "mozilla/InternalMutationEvent.h"
michael@0 15 #include "nsContentCreatorFunctions.h"
michael@0 16 #include "nsError.h"
michael@0 17 #include "nsUnicharUtils.h"
michael@0 18 #include "nsDOMString.h"
michael@0 19 #include "nsIContentInlines.h"
michael@0 20 #include "nsIDocument.h"
michael@0 21 #include "nsIDOMUserDataHandler.h"
michael@0 22 #include "nsGkAtoms.h"
michael@0 23 #include "nsCOMArray.h"
michael@0 24 #include "nsNameSpaceManager.h"
michael@0 25 #include "nsNodeUtils.h"
michael@0 26 #include "nsTextNode.h"
michael@0 27 #include "mozAutoDocUpdate.h"
michael@0 28 #include "nsWrapperCacheInlines.h"
michael@0 29
michael@0 30 nsIAttribute::nsIAttribute(nsDOMAttributeMap* aAttrMap,
michael@0 31 already_AddRefed<nsINodeInfo>& aNodeInfo,
michael@0 32 bool aNsAware)
michael@0 33 : nsINode(aNodeInfo), mAttrMap(aAttrMap), mNsAware(aNsAware)
michael@0 34 {
michael@0 35 }
michael@0 36
michael@0 37 nsIAttribute::~nsIAttribute()
michael@0 38 {
michael@0 39 }
michael@0 40
michael@0 41 namespace mozilla {
michael@0 42 namespace dom {
michael@0 43
michael@0 44 //----------------------------------------------------------------------
michael@0 45 bool Attr::sInitialized;
michael@0 46
michael@0 47 Attr::Attr(nsDOMAttributeMap *aAttrMap,
michael@0 48 already_AddRefed<nsINodeInfo>&& aNodeInfo,
michael@0 49 const nsAString &aValue, bool aNsAware)
michael@0 50 : nsIAttribute(aAttrMap, aNodeInfo, aNsAware), mValue(aValue)
michael@0 51 {
michael@0 52 NS_ABORT_IF_FALSE(mNodeInfo, "We must get a nodeinfo here!");
michael@0 53 NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::ATTRIBUTE_NODE,
michael@0 54 "Wrong nodeType");
michael@0 55
michael@0 56 // We don't add a reference to our content. It will tell us
michael@0 57 // to drop our reference when it goes away.
michael@0 58
michael@0 59 SetIsDOMBinding();
michael@0 60 }
michael@0 61
michael@0 62 NS_IMPL_CYCLE_COLLECTION_CLASS(Attr)
michael@0 63
michael@0 64 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Attr)
michael@0 65 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
michael@0 66
michael@0 67 if (!nsINode::Traverse(tmp, cb)) {
michael@0 68 return NS_SUCCESS_INTERRUPTED_TRAVERSE;
michael@0 69 }
michael@0 70 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAttrMap)
michael@0 71 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
michael@0 72
michael@0 73 NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(Attr)
michael@0 74
michael@0 75 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Attr)
michael@0 76 nsINode::Unlink(tmp);
michael@0 77 NS_IMPL_CYCLE_COLLECTION_UNLINK(mAttrMap)
michael@0 78 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
michael@0 79
michael@0 80 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(Attr)
michael@0 81 Element* ownerElement = tmp->GetElement();
michael@0 82 if (tmp->IsBlack()) {
michael@0 83 if (ownerElement) {
michael@0 84 // The attribute owns the element via attribute map so we can
michael@0 85 // mark it when the attribute is certainly alive.
michael@0 86 mozilla::dom::FragmentOrElement::MarkNodeChildren(ownerElement);
michael@0 87 }
michael@0 88 return true;
michael@0 89 }
michael@0 90 if (ownerElement &&
michael@0 91 mozilla::dom::FragmentOrElement::CanSkip(ownerElement, true)) {
michael@0 92 return true;
michael@0 93 }
michael@0 94 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
michael@0 95
michael@0 96 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(Attr)
michael@0 97 return tmp->IsBlackAndDoesNotNeedTracing(static_cast<nsIAttribute*>(tmp));
michael@0 98 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
michael@0 99
michael@0 100 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(Attr)
michael@0 101 return tmp->IsBlack();
michael@0 102 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
michael@0 103
michael@0 104 // QueryInterface implementation for Attr
michael@0 105 NS_INTERFACE_TABLE_HEAD(Attr)
michael@0 106 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
michael@0 107 NS_INTERFACE_TABLE(Attr, nsINode, nsIDOMAttr, nsIAttribute, nsIDOMNode,
michael@0 108 nsIDOMEventTarget, EventTarget)
michael@0 109 NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(Attr)
michael@0 110 NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISupportsWeakReference,
michael@0 111 new nsNodeSupportsWeakRefTearoff(this))
michael@0 112 NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMXPathNSResolver,
michael@0 113 new nsNode3Tearoff(this))
michael@0 114 NS_INTERFACE_MAP_END
michael@0 115
michael@0 116 NS_IMPL_CYCLE_COLLECTING_ADDREF(Attr)
michael@0 117 NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(Attr,
michael@0 118 nsNodeUtils::LastRelease(this))
michael@0 119
michael@0 120 void
michael@0 121 Attr::SetMap(nsDOMAttributeMap *aMap)
michael@0 122 {
michael@0 123 if (mAttrMap && !aMap && sInitialized) {
michael@0 124 // We're breaking a relationship with content and not getting a new one,
michael@0 125 // need to locally cache value. GetValue() does that.
michael@0 126 GetValue(mValue);
michael@0 127 }
michael@0 128
michael@0 129 mAttrMap = aMap;
michael@0 130 }
michael@0 131
michael@0 132 Element*
michael@0 133 Attr::GetElement() const
michael@0 134 {
michael@0 135 if (!mAttrMap) {
michael@0 136 return nullptr;
michael@0 137 }
michael@0 138 nsIContent* content = mAttrMap->GetContent();
michael@0 139 return content ? content->AsElement() : nullptr;
michael@0 140 }
michael@0 141
michael@0 142 nsresult
michael@0 143 Attr::SetOwnerDocument(nsIDocument* aDocument)
michael@0 144 {
michael@0 145 NS_ASSERTION(aDocument, "Missing document");
michael@0 146
michael@0 147 nsIDocument *doc = OwnerDoc();
michael@0 148 NS_ASSERTION(doc != aDocument, "bad call to Attr::SetOwnerDocument");
michael@0 149 doc->DeleteAllPropertiesFor(this);
michael@0 150
michael@0 151 nsCOMPtr<nsINodeInfo> newNodeInfo;
michael@0 152 newNodeInfo = aDocument->NodeInfoManager()->
michael@0 153 GetNodeInfo(mNodeInfo->NameAtom(), mNodeInfo->GetPrefixAtom(),
michael@0 154 mNodeInfo->NamespaceID(),
michael@0 155 nsIDOMNode::ATTRIBUTE_NODE);
michael@0 156 NS_ASSERTION(newNodeInfo, "GetNodeInfo lies");
michael@0 157 mNodeInfo.swap(newNodeInfo);
michael@0 158
michael@0 159 return NS_OK;
michael@0 160 }
michael@0 161
michael@0 162 NS_IMETHODIMP
michael@0 163 Attr::GetName(nsAString& aName)
michael@0 164 {
michael@0 165 aName = NodeName();
michael@0 166 return NS_OK;
michael@0 167 }
michael@0 168
michael@0 169 already_AddRefed<nsIAtom>
michael@0 170 Attr::GetNameAtom(nsIContent* aContent)
michael@0 171 {
michael@0 172 if (!mNsAware &&
michael@0 173 mNodeInfo->NamespaceID() == kNameSpaceID_None &&
michael@0 174 aContent->IsInHTMLDocument() &&
michael@0 175 aContent->IsHTML()) {
michael@0 176 nsString name;
michael@0 177 mNodeInfo->GetName(name);
michael@0 178 nsAutoString lowercaseName;
michael@0 179 nsContentUtils::ASCIIToLower(name, lowercaseName);
michael@0 180 return do_GetAtom(lowercaseName);
michael@0 181 }
michael@0 182 nsCOMPtr<nsIAtom> nameAtom = mNodeInfo->NameAtom();
michael@0 183 return nameAtom.forget();
michael@0 184 }
michael@0 185
michael@0 186 NS_IMETHODIMP
michael@0 187 Attr::GetValue(nsAString& aValue)
michael@0 188 {
michael@0 189 Element* element = GetElement();
michael@0 190 if (element) {
michael@0 191 nsCOMPtr<nsIAtom> nameAtom = GetNameAtom(element);
michael@0 192 element->GetAttr(mNodeInfo->NamespaceID(), nameAtom, aValue);
michael@0 193 }
michael@0 194 else {
michael@0 195 aValue = mValue;
michael@0 196 }
michael@0 197
michael@0 198 return NS_OK;
michael@0 199 }
michael@0 200
michael@0 201 void
michael@0 202 Attr::SetValue(const nsAString& aValue, ErrorResult& aRv)
michael@0 203 {
michael@0 204 Element* element = GetElement();
michael@0 205 if (!element) {
michael@0 206 mValue = aValue;
michael@0 207 return;
michael@0 208 }
michael@0 209
michael@0 210 nsCOMPtr<nsIAtom> nameAtom = GetNameAtom(element);
michael@0 211 aRv = element->SetAttr(mNodeInfo->NamespaceID(),
michael@0 212 nameAtom,
michael@0 213 mNodeInfo->GetPrefixAtom(),
michael@0 214 aValue,
michael@0 215 true);
michael@0 216 }
michael@0 217
michael@0 218 NS_IMETHODIMP
michael@0 219 Attr::SetValue(const nsAString& aValue)
michael@0 220 {
michael@0 221 ErrorResult rv;
michael@0 222 SetValue(aValue, rv);
michael@0 223 return rv.ErrorCode();
michael@0 224 }
michael@0 225
michael@0 226 bool
michael@0 227 Attr::Specified() const
michael@0 228 {
michael@0 229 return true;
michael@0 230 }
michael@0 231
michael@0 232 NS_IMETHODIMP
michael@0 233 Attr::GetSpecified(bool* aSpecified)
michael@0 234 {
michael@0 235 NS_ENSURE_ARG_POINTER(aSpecified);
michael@0 236 *aSpecified = Specified();
michael@0 237 return NS_OK;
michael@0 238 }
michael@0 239
michael@0 240 Element*
michael@0 241 Attr::GetOwnerElement(ErrorResult& aRv)
michael@0 242 {
michael@0 243 OwnerDoc()->WarnOnceAbout(nsIDocument::eOwnerElement);
michael@0 244 return GetElement();
michael@0 245 }
michael@0 246
michael@0 247 NS_IMETHODIMP
michael@0 248 Attr::GetOwnerElement(nsIDOMElement** aOwnerElement)
michael@0 249 {
michael@0 250 NS_ENSURE_ARG_POINTER(aOwnerElement);
michael@0 251 OwnerDoc()->WarnOnceAbout(nsIDocument::eOwnerElement);
michael@0 252
michael@0 253 Element* element = GetElement();
michael@0 254 if (element) {
michael@0 255 return CallQueryInterface(element, aOwnerElement);
michael@0 256 }
michael@0 257
michael@0 258 *aOwnerElement = nullptr;
michael@0 259
michael@0 260 return NS_OK;
michael@0 261 }
michael@0 262
michael@0 263 void
michael@0 264 Attr::GetNodeValueInternal(nsAString& aNodeValue)
michael@0 265 {
michael@0 266 OwnerDoc()->WarnOnceAbout(nsIDocument::eNodeValue);
michael@0 267
michael@0 268 GetValue(aNodeValue);
michael@0 269 }
michael@0 270
michael@0 271 void
michael@0 272 Attr::SetNodeValueInternal(const nsAString& aNodeValue, ErrorResult& aError)
michael@0 273 {
michael@0 274 OwnerDoc()->WarnOnceAbout(nsIDocument::eNodeValue);
michael@0 275
michael@0 276 aError = SetValue(aNodeValue);
michael@0 277 }
michael@0 278
michael@0 279 nsresult
michael@0 280 Attr::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
michael@0 281 {
michael@0 282 nsAutoString value;
michael@0 283 const_cast<Attr*>(this)->GetValue(value);
michael@0 284
michael@0 285 nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
michael@0 286 *aResult = new Attr(nullptr, ni.forget(), value, mNsAware);
michael@0 287 if (!*aResult) {
michael@0 288 return NS_ERROR_OUT_OF_MEMORY;
michael@0 289 }
michael@0 290
michael@0 291 NS_ADDREF(*aResult);
michael@0 292
michael@0 293 return NS_OK;
michael@0 294 }
michael@0 295
michael@0 296 already_AddRefed<nsIURI>
michael@0 297 Attr::GetBaseURI(bool aTryUseXHRDocBaseURI) const
michael@0 298 {
michael@0 299 Element* parent = GetElement();
michael@0 300
michael@0 301 return parent ? parent->GetBaseURI(aTryUseXHRDocBaseURI) : nullptr;
michael@0 302 }
michael@0 303
michael@0 304 void
michael@0 305 Attr::GetTextContentInternal(nsAString& aTextContent)
michael@0 306 {
michael@0 307 OwnerDoc()->WarnOnceAbout(nsIDocument::eTextContent);
michael@0 308
michael@0 309 GetValue(aTextContent);
michael@0 310 }
michael@0 311
michael@0 312 void
michael@0 313 Attr::SetTextContentInternal(const nsAString& aTextContent,
michael@0 314 ErrorResult& aError)
michael@0 315 {
michael@0 316 OwnerDoc()->WarnOnceAbout(nsIDocument::eTextContent);
michael@0 317
michael@0 318 SetNodeValueInternal(aTextContent, aError);
michael@0 319 }
michael@0 320
michael@0 321 NS_IMETHODIMP
michael@0 322 Attr::GetIsId(bool* aReturn)
michael@0 323 {
michael@0 324 Element* element = GetElement();
michael@0 325 if (!element) {
michael@0 326 *aReturn = false;
michael@0 327 return NS_OK;
michael@0 328 }
michael@0 329
michael@0 330 nsIAtom* idAtom = element->GetIDAttributeName();
michael@0 331 if (!idAtom) {
michael@0 332 *aReturn = false;
michael@0 333 return NS_OK;
michael@0 334 }
michael@0 335
michael@0 336 *aReturn = mNodeInfo->Equals(idAtom, kNameSpaceID_None);
michael@0 337 return NS_OK;
michael@0 338 }
michael@0 339
michael@0 340 bool
michael@0 341 Attr::IsNodeOfType(uint32_t aFlags) const
michael@0 342 {
michael@0 343 return !(aFlags & ~eATTRIBUTE);
michael@0 344 }
michael@0 345
michael@0 346 uint32_t
michael@0 347 Attr::GetChildCount() const
michael@0 348 {
michael@0 349 return 0;
michael@0 350 }
michael@0 351
michael@0 352 nsIContent *
michael@0 353 Attr::GetChildAt(uint32_t aIndex) const
michael@0 354 {
michael@0 355 return nullptr;
michael@0 356 }
michael@0 357
michael@0 358 nsIContent * const *
michael@0 359 Attr::GetChildArray(uint32_t* aChildCount) const
michael@0 360 {
michael@0 361 *aChildCount = 0;
michael@0 362 return nullptr;
michael@0 363 }
michael@0 364
michael@0 365 int32_t
michael@0 366 Attr::IndexOf(const nsINode* aPossibleChild) const
michael@0 367 {
michael@0 368 return -1;
michael@0 369 }
michael@0 370
michael@0 371 nsresult
michael@0 372 Attr::InsertChildAt(nsIContent* aKid, uint32_t aIndex,
michael@0 373 bool aNotify)
michael@0 374 {
michael@0 375 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 376 }
michael@0 377
michael@0 378 void
michael@0 379 Attr::RemoveChildAt(uint32_t aIndex, bool aNotify)
michael@0 380 {
michael@0 381 }
michael@0 382
michael@0 383 nsresult
michael@0 384 Attr::PreHandleEvent(EventChainPreVisitor& aVisitor)
michael@0 385 {
michael@0 386 aVisitor.mCanHandle = true;
michael@0 387 return NS_OK;
michael@0 388 }
michael@0 389
michael@0 390 void
michael@0 391 Attr::Initialize()
michael@0 392 {
michael@0 393 sInitialized = true;
michael@0 394 }
michael@0 395
michael@0 396 void
michael@0 397 Attr::Shutdown()
michael@0 398 {
michael@0 399 sInitialized = false;
michael@0 400 }
michael@0 401
michael@0 402 JSObject*
michael@0 403 Attr::WrapObject(JSContext* aCx)
michael@0 404 {
michael@0 405 return AttrBinding::Wrap(aCx, this);
michael@0 406 }
michael@0 407
michael@0 408 } // namespace dom
michael@0 409 } // namespace mozilla

mercurial