1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/base/src/Element.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,2894 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 sw=2 et tw=79: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +/* 1.11 + * Base class for all element classes; this provides an implementation 1.12 + * of DOM Core's nsIDOMElement, implements nsIContent, provides 1.13 + * utility methods for subclasses, and so forth. 1.14 + */ 1.15 + 1.16 +#include "mozilla/dom/ElementInlines.h" 1.17 + 1.18 +#include "mozilla/DebugOnly.h" 1.19 +#include "mozilla/dom/Attr.h" 1.20 +#include "nsDOMAttributeMap.h" 1.21 +#include "nsIAtom.h" 1.22 +#include "nsIContentInlines.h" 1.23 +#include "nsINodeInfo.h" 1.24 +#include "nsIDocumentInlines.h" 1.25 +#include "nsIDOMNodeList.h" 1.26 +#include "nsIDOMDocument.h" 1.27 +#include "nsIContentIterator.h" 1.28 +#include "nsFocusManager.h" 1.29 +#include "nsILinkHandler.h" 1.30 +#include "nsIScriptGlobalObject.h" 1.31 +#include "nsIURL.h" 1.32 +#include "nsNetUtil.h" 1.33 +#include "nsIFrame.h" 1.34 +#include "nsIAnonymousContentCreator.h" 1.35 +#include "nsIPresShell.h" 1.36 +#include "nsPresContext.h" 1.37 +#include "nsStyleConsts.h" 1.38 +#include "nsString.h" 1.39 +#include "nsUnicharUtils.h" 1.40 +#include "nsIDOMEvent.h" 1.41 +#include "nsDOMCID.h" 1.42 +#include "nsIServiceManager.h" 1.43 +#include "nsIDOMCSSStyleDeclaration.h" 1.44 +#include "nsDOMCSSAttrDeclaration.h" 1.45 +#include "nsNameSpaceManager.h" 1.46 +#include "nsContentList.h" 1.47 +#include "nsDOMTokenList.h" 1.48 +#include "nsXBLPrototypeBinding.h" 1.49 +#include "nsError.h" 1.50 +#include "nsDOMString.h" 1.51 +#include "nsIScriptSecurityManager.h" 1.52 +#include "nsIDOMMutationEvent.h" 1.53 +#include "mozilla/AsyncEventDispatcher.h" 1.54 +#include "mozilla/ContentEvents.h" 1.55 +#include "mozilla/EventDispatcher.h" 1.56 +#include "mozilla/EventListenerManager.h" 1.57 +#include "mozilla/EventStateManager.h" 1.58 +#include "mozilla/EventStates.h" 1.59 +#include "mozilla/InternalMutationEvent.h" 1.60 +#include "mozilla/MouseEvents.h" 1.61 +#include "mozilla/TextEvents.h" 1.62 +#include "nsNodeUtils.h" 1.63 +#include "mozilla/dom/DirectionalityUtils.h" 1.64 +#include "nsDocument.h" 1.65 +#include "nsAttrValueOrString.h" 1.66 +#include "nsAttrValueInlines.h" 1.67 +#ifdef MOZ_XUL 1.68 +#include "nsXULElement.h" 1.69 +#endif /* MOZ_XUL */ 1.70 +#include "nsFrameManager.h" 1.71 +#include "nsFrameSelection.h" 1.72 +#ifdef DEBUG 1.73 +#include "nsRange.h" 1.74 +#endif 1.75 + 1.76 +#include "nsBindingManager.h" 1.77 +#include "nsXBLBinding.h" 1.78 +#include "nsPIDOMWindow.h" 1.79 +#include "nsPIBoxObject.h" 1.80 +#include "mozilla/dom/DOMRect.h" 1.81 +#include "nsSVGUtils.h" 1.82 +#include "nsLayoutUtils.h" 1.83 +#include "nsGkAtoms.h" 1.84 +#include "nsContentUtils.h" 1.85 +#include "ChildIterator.h" 1.86 + 1.87 +#include "nsIDOMEventListener.h" 1.88 +#include "nsIWebNavigation.h" 1.89 +#include "nsIBaseWindow.h" 1.90 +#include "nsIWidget.h" 1.91 + 1.92 +#include "nsNodeInfoManager.h" 1.93 +#include "nsICategoryManager.h" 1.94 +#include "nsIDOMDocumentType.h" 1.95 +#include "nsIDOMUserDataHandler.h" 1.96 +#include "nsGenericHTMLElement.h" 1.97 +#include "nsIEditor.h" 1.98 +#include "nsIEditorIMESupport.h" 1.99 +#include "nsContentCreatorFunctions.h" 1.100 +#include "nsIControllers.h" 1.101 +#include "nsView.h" 1.102 +#include "nsViewManager.h" 1.103 +#include "nsIScrollableFrame.h" 1.104 +#include "mozilla/css/StyleRule.h" /* For nsCSSSelectorList */ 1.105 +#include "nsCSSRuleProcessor.h" 1.106 +#include "nsRuleProcessorData.h" 1.107 +#include "nsTextNode.h" 1.108 + 1.109 +#ifdef MOZ_XUL 1.110 +#include "nsIXULDocument.h" 1.111 +#endif /* MOZ_XUL */ 1.112 + 1.113 +#include "nsCycleCollectionParticipant.h" 1.114 +#include "nsCCUncollectableMarker.h" 1.115 + 1.116 +#include "mozAutoDocUpdate.h" 1.117 + 1.118 +#include "nsCSSParser.h" 1.119 +#include "prprf.h" 1.120 +#include "nsDOMMutationObserver.h" 1.121 +#include "nsSVGFeatures.h" 1.122 +#include "nsWrapperCacheInlines.h" 1.123 +#include "xpcpublic.h" 1.124 +#include "nsIScriptError.h" 1.125 +#include "mozilla/Telemetry.h" 1.126 + 1.127 +#include "mozilla/CORSMode.h" 1.128 +#include "mozilla/dom/ShadowRoot.h" 1.129 + 1.130 +#include "nsStyledElement.h" 1.131 +#include "nsXBLService.h" 1.132 +#include "nsITextControlElement.h" 1.133 +#include "nsITextControlFrame.h" 1.134 +#include "nsISupportsImpl.h" 1.135 +#include "mozilla/dom/DocumentFragment.h" 1.136 +#include "mozilla/IntegerPrintfMacros.h" 1.137 + 1.138 +using namespace mozilla; 1.139 +using namespace mozilla::dom; 1.140 + 1.141 +NS_IMETHODIMP 1.142 +Element::QueryInterface(REFNSIID aIID, void** aInstancePtr) 1.143 +{ 1.144 + NS_ASSERTION(aInstancePtr, 1.145 + "QueryInterface requires a non-NULL destination!"); 1.146 + nsresult rv = FragmentOrElement::QueryInterface(aIID, aInstancePtr); 1.147 + if (NS_SUCCEEDED(rv)) { 1.148 + return NS_OK; 1.149 + } 1.150 + 1.151 + // Give the binding manager a chance to get an interface for this element. 1.152 + return OwnerDoc()->BindingManager()->GetBindingImplementation(this, aIID, 1.153 + aInstancePtr); 1.154 +} 1.155 + 1.156 +EventStates 1.157 +Element::IntrinsicState() const 1.158 +{ 1.159 + return IsEditable() ? NS_EVENT_STATE_MOZ_READWRITE : 1.160 + NS_EVENT_STATE_MOZ_READONLY; 1.161 +} 1.162 + 1.163 +void 1.164 +Element::NotifyStateChange(EventStates aStates) 1.165 +{ 1.166 + nsIDocument* doc = GetCurrentDoc(); 1.167 + if (doc) { 1.168 + nsAutoScriptBlocker scriptBlocker; 1.169 + doc->ContentStateChanged(this, aStates); 1.170 + } 1.171 +} 1.172 + 1.173 +void 1.174 +Element::UpdateLinkState(EventStates aState) 1.175 +{ 1.176 + NS_ABORT_IF_FALSE(!aState.HasAtLeastOneOfStates(~(NS_EVENT_STATE_VISITED | 1.177 + NS_EVENT_STATE_UNVISITED)), 1.178 + "Unexpected link state bits"); 1.179 + mState = 1.180 + (mState & ~(NS_EVENT_STATE_VISITED | NS_EVENT_STATE_UNVISITED)) | 1.181 + aState; 1.182 +} 1.183 + 1.184 +void 1.185 +Element::UpdateState(bool aNotify) 1.186 +{ 1.187 + EventStates oldState = mState; 1.188 + mState = IntrinsicState() | (oldState & ESM_MANAGED_STATES); 1.189 + if (aNotify) { 1.190 + EventStates changedStates = oldState ^ mState; 1.191 + if (!changedStates.IsEmpty()) { 1.192 + nsIDocument* doc = GetCurrentDoc(); 1.193 + if (doc) { 1.194 + nsAutoScriptBlocker scriptBlocker; 1.195 + doc->ContentStateChanged(this, changedStates); 1.196 + } 1.197 + } 1.198 + } 1.199 +} 1.200 + 1.201 +void 1.202 +nsIContent::UpdateEditableState(bool aNotify) 1.203 +{ 1.204 + // Guaranteed to be non-element content 1.205 + NS_ASSERTION(!IsElement(), "What happened here?"); 1.206 + nsIContent *parent = GetParent(); 1.207 + 1.208 + // Skip over unknown native anonymous content to avoid setting a flag we 1.209 + // can't clear later 1.210 + bool isUnknownNativeAnon = false; 1.211 + if (IsInNativeAnonymousSubtree()) { 1.212 + isUnknownNativeAnon = true; 1.213 + nsCOMPtr<nsIContent> root = this; 1.214 + while (root && !root->IsRootOfNativeAnonymousSubtree()) { 1.215 + root = root->GetParent(); 1.216 + } 1.217 + // root should always be true here, but isn't -- bug 999416 1.218 + if (root) { 1.219 + nsIFrame* rootFrame = root->GetPrimaryFrame(); 1.220 + if (rootFrame) { 1.221 + nsIFrame* parentFrame = rootFrame->GetParent(); 1.222 + nsITextControlFrame* textCtrl = do_QueryFrame(parentFrame); 1.223 + isUnknownNativeAnon = !textCtrl; 1.224 + } 1.225 + } 1.226 + } 1.227 + 1.228 + SetEditableFlag(parent && parent->HasFlag(NODE_IS_EDITABLE) && 1.229 + !isUnknownNativeAnon); 1.230 +} 1.231 + 1.232 +void 1.233 +Element::UpdateEditableState(bool aNotify) 1.234 +{ 1.235 + nsIContent *parent = GetParent(); 1.236 + 1.237 + SetEditableFlag(parent && parent->HasFlag(NODE_IS_EDITABLE)); 1.238 + if (aNotify) { 1.239 + UpdateState(aNotify); 1.240 + } else { 1.241 + // Avoid calling UpdateState in this very common case, because 1.242 + // this gets called for pretty much every single element on 1.243 + // insertion into the document and UpdateState can be slow for 1.244 + // some kinds of elements even when not notifying. 1.245 + if (IsEditable()) { 1.246 + RemoveStatesSilently(NS_EVENT_STATE_MOZ_READONLY); 1.247 + AddStatesSilently(NS_EVENT_STATE_MOZ_READWRITE); 1.248 + } else { 1.249 + RemoveStatesSilently(NS_EVENT_STATE_MOZ_READWRITE); 1.250 + AddStatesSilently(NS_EVENT_STATE_MOZ_READONLY); 1.251 + } 1.252 + } 1.253 +} 1.254 + 1.255 +EventStates 1.256 +Element::StyleStateFromLocks() const 1.257 +{ 1.258 + EventStates locks = LockedStyleStates(); 1.259 + EventStates state = mState | locks; 1.260 + 1.261 + if (locks.HasState(NS_EVENT_STATE_VISITED)) { 1.262 + return state & ~NS_EVENT_STATE_UNVISITED; 1.263 + } 1.264 + if (locks.HasState(NS_EVENT_STATE_UNVISITED)) { 1.265 + return state & ~NS_EVENT_STATE_VISITED; 1.266 + } 1.267 + return state; 1.268 +} 1.269 + 1.270 +EventStates 1.271 +Element::LockedStyleStates() const 1.272 +{ 1.273 + EventStates* locks = 1.274 + static_cast<EventStates*>(GetProperty(nsGkAtoms::lockedStyleStates)); 1.275 + if (locks) { 1.276 + return *locks; 1.277 + } 1.278 + return EventStates(); 1.279 +} 1.280 + 1.281 +void 1.282 +Element::NotifyStyleStateChange(EventStates aStates) 1.283 +{ 1.284 + nsIDocument* doc = GetCurrentDoc(); 1.285 + if (doc) { 1.286 + nsIPresShell *presShell = doc->GetShell(); 1.287 + if (presShell) { 1.288 + nsAutoScriptBlocker scriptBlocker; 1.289 + presShell->ContentStateChanged(doc, this, aStates); 1.290 + } 1.291 + } 1.292 +} 1.293 + 1.294 +void 1.295 +Element::LockStyleStates(EventStates aStates) 1.296 +{ 1.297 + EventStates* locks = new EventStates(LockedStyleStates()); 1.298 + 1.299 + *locks |= aStates; 1.300 + 1.301 + if (aStates.HasState(NS_EVENT_STATE_VISITED)) { 1.302 + *locks &= ~NS_EVENT_STATE_UNVISITED; 1.303 + } 1.304 + if (aStates.HasState(NS_EVENT_STATE_UNVISITED)) { 1.305 + *locks &= ~NS_EVENT_STATE_VISITED; 1.306 + } 1.307 + 1.308 + SetProperty(nsGkAtoms::lockedStyleStates, locks, 1.309 + nsINode::DeleteProperty<EventStates>); 1.310 + SetHasLockedStyleStates(); 1.311 + 1.312 + NotifyStyleStateChange(aStates); 1.313 +} 1.314 + 1.315 +void 1.316 +Element::UnlockStyleStates(EventStates aStates) 1.317 +{ 1.318 + EventStates* locks = new EventStates(LockedStyleStates()); 1.319 + 1.320 + *locks &= ~aStates; 1.321 + 1.322 + if (locks->IsEmpty()) { 1.323 + DeleteProperty(nsGkAtoms::lockedStyleStates); 1.324 + ClearHasLockedStyleStates(); 1.325 + delete locks; 1.326 + } 1.327 + else { 1.328 + SetProperty(nsGkAtoms::lockedStyleStates, locks, 1.329 + nsINode::DeleteProperty<EventStates>); 1.330 + } 1.331 + 1.332 + NotifyStyleStateChange(aStates); 1.333 +} 1.334 + 1.335 +void 1.336 +Element::ClearStyleStateLocks() 1.337 +{ 1.338 + EventStates locks = LockedStyleStates(); 1.339 + 1.340 + DeleteProperty(nsGkAtoms::lockedStyleStates); 1.341 + ClearHasLockedStyleStates(); 1.342 + 1.343 + NotifyStyleStateChange(locks); 1.344 +} 1.345 + 1.346 +bool 1.347 +Element::GetBindingURL(nsIDocument *aDocument, css::URLValue **aResult) 1.348 +{ 1.349 + // If we have a frame the frame has already loaded the binding. And 1.350 + // otherwise, don't do anything else here unless we're dealing with 1.351 + // XUL or an HTML element that may have a plugin-related overlay 1.352 + // (i.e. object, embed, or applet). 1.353 + bool isXULorPluginElement = (IsXUL() || 1.354 + IsHTML(nsGkAtoms::object) || 1.355 + IsHTML(nsGkAtoms::embed) || 1.356 + IsHTML(nsGkAtoms::applet)); 1.357 + nsIPresShell *shell = aDocument->GetShell(); 1.358 + if (!shell || GetPrimaryFrame() || !isXULorPluginElement) { 1.359 + *aResult = nullptr; 1.360 + 1.361 + return true; 1.362 + } 1.363 + 1.364 + // Get the computed -moz-binding directly from the style context 1.365 + nsPresContext *pctx = shell->GetPresContext(); 1.366 + NS_ENSURE_TRUE(pctx, false); 1.367 + 1.368 + nsRefPtr<nsStyleContext> sc = pctx->StyleSet()->ResolveStyleFor(this, 1.369 + nullptr); 1.370 + NS_ENSURE_TRUE(sc, false); 1.371 + 1.372 + *aResult = sc->StyleDisplay()->mBinding; 1.373 + 1.374 + return true; 1.375 +} 1.376 + 1.377 +JSObject* 1.378 +Element::WrapObject(JSContext *aCx) 1.379 +{ 1.380 + JS::Rooted<JSObject*> obj(aCx, nsINode::WrapObject(aCx)); 1.381 + if (!obj) { 1.382 + return nullptr; 1.383 + } 1.384 + 1.385 + // Custom element prototype swizzling. 1.386 + CustomElementData* data = GetCustomElementData(); 1.387 + if (obj && data) { 1.388 + // If this is a registered custom element then fix the prototype. 1.389 + JSAutoCompartment ac(aCx, obj); 1.390 + nsDocument* document = static_cast<nsDocument*>(OwnerDoc()); 1.391 + JS::Rooted<JSObject*> prototype(aCx); 1.392 + document->GetCustomPrototype(NodeInfo()->NamespaceID(), data->mType, &prototype); 1.393 + if (prototype) { 1.394 + if (!JS_WrapObject(aCx, &prototype) || !JS_SetPrototype(aCx, obj, prototype)) { 1.395 + dom::Throw(aCx, NS_ERROR_FAILURE); 1.396 + return nullptr; 1.397 + } 1.398 + } 1.399 + } 1.400 + 1.401 + nsIDocument* doc; 1.402 + if (HasFlag(NODE_FORCE_XBL_BINDINGS)) { 1.403 + doc = OwnerDoc(); 1.404 + } 1.405 + else { 1.406 + doc = GetCurrentDoc(); 1.407 + } 1.408 + 1.409 + if (!doc) { 1.410 + // There's no baseclass that cares about this call so we just 1.411 + // return here. 1.412 + return obj; 1.413 + } 1.414 + 1.415 + // We must ensure that the XBL Binding is installed before we hand 1.416 + // back this object. 1.417 + 1.418 + if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR) && GetXBLBinding()) { 1.419 + // There's already a binding for this element so nothing left to 1.420 + // be done here. 1.421 + 1.422 + // In theory we could call ExecuteAttachedHandler here when it's safe to 1.423 + // run script if we also removed the binding from the PAQ queue, but that 1.424 + // seems like a scary change that would mosly just add more 1.425 + // inconsistencies. 1.426 + return obj; 1.427 + } 1.428 + 1.429 + // Make sure the style context goes away _before_ we load the binding 1.430 + // since that can destroy the relevant presshell. 1.431 + mozilla::css::URLValue *bindingURL; 1.432 + bool ok = GetBindingURL(doc, &bindingURL); 1.433 + if (!ok) { 1.434 + dom::Throw(aCx, NS_ERROR_FAILURE); 1.435 + return nullptr; 1.436 + } 1.437 + 1.438 + if (!bindingURL) { 1.439 + // No binding, nothing left to do here. 1.440 + return obj; 1.441 + } 1.442 + 1.443 + nsCOMPtr<nsIURI> uri = bindingURL->GetURI(); 1.444 + nsCOMPtr<nsIPrincipal> principal = bindingURL->mOriginPrincipal; 1.445 + 1.446 + // We have a binding that must be installed. 1.447 + bool dummy; 1.448 + 1.449 + nsXBLService* xblService = nsXBLService::GetInstance(); 1.450 + if (!xblService) { 1.451 + dom::Throw(aCx, NS_ERROR_NOT_AVAILABLE); 1.452 + return nullptr; 1.453 + } 1.454 + 1.455 + { 1.456 + // Make a scope so that ~nsRefPtr can GC before returning obj. 1.457 + nsRefPtr<nsXBLBinding> binding; 1.458 + xblService->LoadBindings(this, uri, principal, getter_AddRefs(binding), &dummy); 1.459 + 1.460 + if (binding) { 1.461 + if (nsContentUtils::IsSafeToRunScript()) { 1.462 + binding->ExecuteAttachedHandler(); 1.463 + } 1.464 + else { 1.465 + nsContentUtils::AddScriptRunner( 1.466 + NS_NewRunnableMethod(binding, &nsXBLBinding::ExecuteAttachedHandler)); 1.467 + } 1.468 + } 1.469 + } 1.470 + 1.471 + return obj; 1.472 +} 1.473 + 1.474 +nsDOMTokenList* 1.475 +Element::GetClassList() 1.476 +{ 1.477 + Element::nsDOMSlots *slots = DOMSlots(); 1.478 + 1.479 + if (!slots->mClassList) { 1.480 + nsIAtom* classAttr = GetClassAttributeName(); 1.481 + if (classAttr) { 1.482 + slots->mClassList = new nsDOMTokenList(this, classAttr); 1.483 + } 1.484 + } 1.485 + 1.486 + return slots->mClassList; 1.487 +} 1.488 + 1.489 +void 1.490 +Element::GetClassList(nsISupports** aClassList) 1.491 +{ 1.492 + NS_IF_ADDREF(*aClassList = GetClassList()); 1.493 +} 1.494 + 1.495 +already_AddRefed<nsIHTMLCollection> 1.496 +Element::GetElementsByTagName(const nsAString& aLocalName) 1.497 +{ 1.498 + return NS_GetContentList(this, kNameSpaceID_Unknown, aLocalName); 1.499 +} 1.500 + 1.501 +void 1.502 +Element::GetElementsByTagName(const nsAString& aLocalName, 1.503 + nsIDOMHTMLCollection** aResult) 1.504 +{ 1.505 + *aResult = GetElementsByTagName(aLocalName).take(); 1.506 +} 1.507 + 1.508 +nsIFrame* 1.509 +Element::GetStyledFrame() 1.510 +{ 1.511 + nsIFrame *frame = GetPrimaryFrame(Flush_Layout); 1.512 + return frame ? nsLayoutUtils::GetStyleFrame(frame) : nullptr; 1.513 +} 1.514 + 1.515 +nsIScrollableFrame* 1.516 +Element::GetScrollFrame(nsIFrame **aStyledFrame, bool aFlushLayout) 1.517 +{ 1.518 + // it isn't clear what to return for SVG nodes, so just return nothing 1.519 + if (IsSVG()) { 1.520 + if (aStyledFrame) { 1.521 + *aStyledFrame = nullptr; 1.522 + } 1.523 + return nullptr; 1.524 + } 1.525 + 1.526 + // Inline version of GetStyledFrame to use Flush_None if needed. 1.527 + nsIFrame* frame = GetPrimaryFrame(aFlushLayout ? Flush_Layout : Flush_None); 1.528 + if (frame) { 1.529 + frame = nsLayoutUtils::GetStyleFrame(frame); 1.530 + } 1.531 + 1.532 + if (aStyledFrame) { 1.533 + *aStyledFrame = frame; 1.534 + } 1.535 + if (!frame) { 1.536 + return nullptr; 1.537 + } 1.538 + 1.539 + // menu frames implement GetScrollTargetFrame but we don't want 1.540 + // to use it here. Similar for comboboxes. 1.541 + nsIAtom* type = frame->GetType(); 1.542 + if (type != nsGkAtoms::menuFrame && type != nsGkAtoms::comboboxControlFrame) { 1.543 + nsIScrollableFrame *scrollFrame = frame->GetScrollTargetFrame(); 1.544 + if (scrollFrame) 1.545 + return scrollFrame; 1.546 + } 1.547 + 1.548 + nsIDocument* doc = OwnerDoc(); 1.549 + bool quirksMode = doc->GetCompatibilityMode() == eCompatibility_NavQuirks; 1.550 + Element* elementWithRootScrollInfo = 1.551 + quirksMode ? doc->GetBodyElement() : doc->GetRootElement(); 1.552 + if (this == elementWithRootScrollInfo) { 1.553 + // In quirks mode, the scroll info for the body element should map to the 1.554 + // root scrollable frame. 1.555 + // In strict mode, the scroll info for the root element should map to the 1.556 + // the root scrollable frame. 1.557 + return frame->PresContext()->PresShell()->GetRootScrollFrameAsScrollable(); 1.558 + } 1.559 + 1.560 + return nullptr; 1.561 +} 1.562 + 1.563 +void 1.564 +Element::ScrollIntoView(bool aTop) 1.565 +{ 1.566 + nsIDocument *document = GetCurrentDoc(); 1.567 + if (!document) { 1.568 + return; 1.569 + } 1.570 + 1.571 + // Get the presentation shell 1.572 + nsCOMPtr<nsIPresShell> presShell = document->GetShell(); 1.573 + if (!presShell) { 1.574 + return; 1.575 + } 1.576 + 1.577 + int16_t vpercent = aTop ? nsIPresShell::SCROLL_TOP : 1.578 + nsIPresShell::SCROLL_BOTTOM; 1.579 + 1.580 + presShell->ScrollContentIntoView(this, 1.581 + nsIPresShell::ScrollAxis( 1.582 + vpercent, 1.583 + nsIPresShell::SCROLL_ALWAYS), 1.584 + nsIPresShell::ScrollAxis(), 1.585 + nsIPresShell::SCROLL_OVERFLOW_HIDDEN); 1.586 +} 1.587 + 1.588 +bool 1.589 +Element::ScrollByNoFlush(int32_t aDx, int32_t aDy) 1.590 +{ 1.591 + nsIScrollableFrame* sf = GetScrollFrame(nullptr, false); 1.592 + if (!sf) { 1.593 + return false; 1.594 + } 1.595 + 1.596 + nsWeakFrame weakRef(sf->GetScrolledFrame()); 1.597 + 1.598 + CSSIntPoint before = sf->GetScrollPositionCSSPixels(); 1.599 + sf->ScrollToCSSPixelsApproximate(CSSIntPoint(before.x + aDx, before.y + aDy)); 1.600 + 1.601 + // The frame was destroyed, can't keep on scrolling. 1.602 + if (!weakRef.IsAlive()) { 1.603 + return false; 1.604 + } 1.605 + 1.606 + CSSIntPoint after = sf->GetScrollPositionCSSPixels(); 1.607 + return (before != after); 1.608 +} 1.609 + 1.610 +static nsSize GetScrollRectSizeForOverflowVisibleFrame(nsIFrame* aFrame) 1.611 +{ 1.612 + if (!aFrame) { 1.613 + return nsSize(0,0); 1.614 + } 1.615 + 1.616 + nsRect paddingRect = aFrame->GetPaddingRectRelativeToSelf(); 1.617 + nsOverflowAreas overflowAreas(paddingRect, paddingRect); 1.618 + // Add the scrollable overflow areas of children (if any) to the paddingRect. 1.619 + // It's important to start with the paddingRect, otherwise if there are no 1.620 + // children the overflow rect will be 0,0,0,0 which will force the point 0,0 1.621 + // to be included in the final rect. 1.622 + nsLayoutUtils::UnionChildOverflow(aFrame, overflowAreas); 1.623 + // Make sure that an empty padding-rect's edges are included, by adding 1.624 + // the padding-rect in again with UnionEdges. 1.625 + nsRect overflowRect = 1.626 + overflowAreas.ScrollableOverflow().UnionEdges(paddingRect); 1.627 + return nsLayoutUtils::GetScrolledRect(aFrame, 1.628 + overflowRect, paddingRect.Size(), 1.629 + aFrame->StyleVisibility()->mDirection).Size(); 1.630 +} 1.631 + 1.632 +int32_t 1.633 +Element::ScrollHeight() 1.634 +{ 1.635 + if (IsSVG()) 1.636 + return 0; 1.637 + 1.638 + nsIScrollableFrame* sf = GetScrollFrame(); 1.639 + nscoord height; 1.640 + if (sf) { 1.641 + height = sf->GetScrollRange().height + sf->GetScrollPortRect().height; 1.642 + } else { 1.643 + height = GetScrollRectSizeForOverflowVisibleFrame(GetStyledFrame()).height; 1.644 + } 1.645 + 1.646 + return nsPresContext::AppUnitsToIntCSSPixels(height); 1.647 +} 1.648 + 1.649 +int32_t 1.650 +Element::ScrollWidth() 1.651 +{ 1.652 + if (IsSVG()) 1.653 + return 0; 1.654 + 1.655 + nsIScrollableFrame* sf = GetScrollFrame(); 1.656 + nscoord width; 1.657 + if (sf) { 1.658 + width = sf->GetScrollRange().width + sf->GetScrollPortRect().width; 1.659 + } else { 1.660 + width = GetScrollRectSizeForOverflowVisibleFrame(GetStyledFrame()).width; 1.661 + } 1.662 + 1.663 + return nsPresContext::AppUnitsToIntCSSPixels(width); 1.664 +} 1.665 + 1.666 +nsRect 1.667 +Element::GetClientAreaRect() 1.668 +{ 1.669 + nsIFrame* styledFrame; 1.670 + nsIScrollableFrame* sf = GetScrollFrame(&styledFrame); 1.671 + 1.672 + if (sf) { 1.673 + return sf->GetScrollPortRect(); 1.674 + } 1.675 + 1.676 + if (styledFrame && 1.677 + (styledFrame->StyleDisplay()->mDisplay != NS_STYLE_DISPLAY_INLINE || 1.678 + styledFrame->IsFrameOfType(nsIFrame::eReplaced))) { 1.679 + // Special case code to make client area work even when there isn't 1.680 + // a scroll view, see bug 180552, bug 227567. 1.681 + return styledFrame->GetPaddingRect() - styledFrame->GetPositionIgnoringScrolling(); 1.682 + } 1.683 + 1.684 + // SVG nodes reach here and just return 0 1.685 + return nsRect(0, 0, 0, 0); 1.686 +} 1.687 + 1.688 +already_AddRefed<DOMRect> 1.689 +Element::GetBoundingClientRect() 1.690 +{ 1.691 + nsRefPtr<DOMRect> rect = new DOMRect(this); 1.692 + 1.693 + nsIFrame* frame = GetPrimaryFrame(Flush_Layout); 1.694 + if (!frame) { 1.695 + // display:none, perhaps? Return the empty rect 1.696 + return rect.forget(); 1.697 + } 1.698 + 1.699 + nsRect r = nsLayoutUtils::GetAllInFlowRectsUnion(frame, 1.700 + nsLayoutUtils::GetContainingBlockForClientRect(frame), 1.701 + nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS); 1.702 + rect->SetLayoutRect(r); 1.703 + return rect.forget(); 1.704 +} 1.705 + 1.706 +already_AddRefed<DOMRectList> 1.707 +Element::GetClientRects() 1.708 +{ 1.709 + nsRefPtr<DOMRectList> rectList = new DOMRectList(this); 1.710 + 1.711 + nsIFrame* frame = GetPrimaryFrame(Flush_Layout); 1.712 + if (!frame) { 1.713 + // display:none, perhaps? Return an empty list 1.714 + return rectList.forget(); 1.715 + } 1.716 + 1.717 + nsLayoutUtils::RectListBuilder builder(rectList); 1.718 + nsLayoutUtils::GetAllInFlowRects(frame, 1.719 + nsLayoutUtils::GetContainingBlockForClientRect(frame), &builder, 1.720 + nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS); 1.721 + return rectList.forget(); 1.722 +} 1.723 + 1.724 + 1.725 +//---------------------------------------------------------------------- 1.726 + 1.727 +void 1.728 +Element::AddToIdTable(nsIAtom* aId) 1.729 +{ 1.730 + NS_ASSERTION(HasID(), "Node doesn't have an ID?"); 1.731 + if (HasFlag(NODE_IS_IN_SHADOW_TREE)) { 1.732 + ShadowRoot* containingShadow = GetContainingShadow(); 1.733 + containingShadow->AddToIdTable(this, aId); 1.734 + } else { 1.735 + nsIDocument* doc = GetCurrentDoc(); 1.736 + if (doc && (!IsInAnonymousSubtree() || doc->IsXUL())) { 1.737 + doc->AddToIdTable(this, aId); 1.738 + } 1.739 + } 1.740 +} 1.741 + 1.742 +void 1.743 +Element::RemoveFromIdTable() 1.744 +{ 1.745 + if (HasID()) { 1.746 + RemoveFromIdTable(DoGetID()); 1.747 + } 1.748 +} 1.749 + 1.750 +void 1.751 +Element::RemoveFromIdTable(nsIAtom* aId) 1.752 +{ 1.753 + NS_ASSERTION(HasID(), "Node doesn't have an ID?"); 1.754 + if (HasFlag(NODE_IS_IN_SHADOW_TREE)) { 1.755 + ShadowRoot* containingShadow = GetContainingShadow(); 1.756 + // Check for containingShadow because it may have 1.757 + // been deleted during unlinking. 1.758 + if (containingShadow) { 1.759 + containingShadow->RemoveFromIdTable(this, aId); 1.760 + } 1.761 + } else { 1.762 + nsIDocument* doc = GetCurrentDoc(); 1.763 + if (doc && (!IsInAnonymousSubtree() || doc->IsXUL())) { 1.764 + // id can be null during mutation events evilness. Also, XUL elements 1.765 + // loose their proto attributes during cc-unlink, so this can happen 1.766 + // during cc-unlink too. 1.767 + if (aId) { 1.768 + doc->RemoveFromIdTable(this, aId); 1.769 + } 1.770 + } 1.771 + } 1.772 +} 1.773 + 1.774 +already_AddRefed<ShadowRoot> 1.775 +Element::CreateShadowRoot(ErrorResult& aError) 1.776 +{ 1.777 + nsAutoScriptBlocker scriptBlocker; 1.778 + 1.779 + nsCOMPtr<nsINodeInfo> nodeInfo; 1.780 + nodeInfo = mNodeInfo->NodeInfoManager()->GetNodeInfo( 1.781 + nsGkAtoms::documentFragmentNodeName, nullptr, kNameSpaceID_None, 1.782 + nsIDOMNode::DOCUMENT_FRAGMENT_NODE); 1.783 + 1.784 + nsRefPtr<nsXBLDocumentInfo> docInfo = new nsXBLDocumentInfo(OwnerDoc()); 1.785 + 1.786 + nsXBLPrototypeBinding* protoBinding = new nsXBLPrototypeBinding(); 1.787 + aError = protoBinding->Init(NS_LITERAL_CSTRING("shadowroot"), 1.788 + docInfo, this, true); 1.789 + if (aError.Failed()) { 1.790 + delete protoBinding; 1.791 + return nullptr; 1.792 + } 1.793 + 1.794 + // Unlike for XBL, false is the default for inheriting style. 1.795 + protoBinding->SetInheritsStyle(false); 1.796 + 1.797 + // Calling SetPrototypeBinding takes ownership of protoBinding. 1.798 + docInfo->SetPrototypeBinding(NS_LITERAL_CSTRING("shadowroot"), protoBinding); 1.799 + 1.800 + nsRefPtr<ShadowRoot> shadowRoot = new ShadowRoot(this, nodeInfo.forget(), 1.801 + protoBinding); 1.802 + 1.803 + // Replace the old ShadowRoot with the new one and let the old 1.804 + // ShadowRoot know about the younger ShadowRoot because the old 1.805 + // ShadowRoot is projected into the younger ShadowRoot's shadow 1.806 + // insertion point (if it exists). 1.807 + ShadowRoot* olderShadow = GetShadowRoot(); 1.808 + SetShadowRoot(shadowRoot); 1.809 + if (olderShadow) { 1.810 + olderShadow->SetYoungerShadow(shadowRoot); 1.811 + } 1.812 + 1.813 + // xblBinding takes ownership of docInfo. 1.814 + nsRefPtr<nsXBLBinding> xblBinding = new nsXBLBinding(shadowRoot, protoBinding); 1.815 + shadowRoot->SetAssociatedBinding(xblBinding); 1.816 + xblBinding->SetBoundElement(this); 1.817 + 1.818 + SetXBLBinding(xblBinding); 1.819 + 1.820 + // Recreate the frame for the bound content because binding a ShadowRoot 1.821 + // changes how things are rendered. 1.822 + nsIDocument* doc = GetCurrentDoc(); 1.823 + if (doc) { 1.824 + nsIPresShell *shell = doc->GetShell(); 1.825 + if (shell) { 1.826 + shell->RecreateFramesFor(this); 1.827 + } 1.828 + } 1.829 + 1.830 + return shadowRoot.forget(); 1.831 +} 1.832 + 1.833 +void 1.834 +Element::GetAttribute(const nsAString& aName, DOMString& aReturn) 1.835 +{ 1.836 + const nsAttrValue* val = 1.837 + mAttrsAndChildren.GetAttr(aName, 1.838 + IsHTML() && IsInHTMLDocument() ? 1.839 + eIgnoreCase : eCaseMatters); 1.840 + if (val) { 1.841 + val->ToString(aReturn); 1.842 + } else { 1.843 + if (IsXUL()) { 1.844 + // XXX should be SetDOMStringToNull(aReturn); 1.845 + // See bug 232598 1.846 + // aReturn is already empty 1.847 + } else { 1.848 + aReturn.SetNull(); 1.849 + } 1.850 + } 1.851 +} 1.852 + 1.853 +void 1.854 +Element::SetAttribute(const nsAString& aName, 1.855 + const nsAString& aValue, 1.856 + ErrorResult& aError) 1.857 +{ 1.858 + const nsAttrName* name = InternalGetExistingAttrNameFromQName(aName); 1.859 + 1.860 + if (!name) { 1.861 + aError = nsContentUtils::CheckQName(aName, false); 1.862 + if (aError.Failed()) { 1.863 + return; 1.864 + } 1.865 + 1.866 + nsCOMPtr<nsIAtom> nameAtom; 1.867 + if (IsHTML() && IsInHTMLDocument()) { 1.868 + nsAutoString lower; 1.869 + nsresult rv = nsContentUtils::ASCIIToLower(aName, lower); 1.870 + if (NS_SUCCEEDED(rv)) { 1.871 + nameAtom = do_GetAtom(lower); 1.872 + } 1.873 + } 1.874 + else { 1.875 + nameAtom = do_GetAtom(aName); 1.876 + } 1.877 + if (!nameAtom) { 1.878 + aError.Throw(NS_ERROR_OUT_OF_MEMORY); 1.879 + return; 1.880 + } 1.881 + aError = SetAttr(kNameSpaceID_None, nameAtom, aValue, true); 1.882 + return; 1.883 + } 1.884 + 1.885 + aError = SetAttr(name->NamespaceID(), name->LocalName(), name->GetPrefix(), 1.886 + aValue, true); 1.887 + return; 1.888 +} 1.889 + 1.890 +void 1.891 +Element::RemoveAttribute(const nsAString& aName, ErrorResult& aError) 1.892 +{ 1.893 + const nsAttrName* name = InternalGetExistingAttrNameFromQName(aName); 1.894 + 1.895 + if (!name) { 1.896 + // If there is no canonical nsAttrName for this attribute name, then the 1.897 + // attribute does not exist and we can't get its namespace ID and 1.898 + // local name below, so we return early. 1.899 + return; 1.900 + } 1.901 + 1.902 + // Hold a strong reference here so that the atom or nodeinfo doesn't go 1.903 + // away during UnsetAttr. If it did UnsetAttr would be left with a 1.904 + // dangling pointer as argument without knowing it. 1.905 + nsAttrName tmp(*name); 1.906 + 1.907 + aError = UnsetAttr(name->NamespaceID(), name->LocalName(), true); 1.908 +} 1.909 + 1.910 +Attr* 1.911 +Element::GetAttributeNode(const nsAString& aName) 1.912 +{ 1.913 + OwnerDoc()->WarnOnceAbout(nsIDocument::eGetAttributeNode); 1.914 + return Attributes()->GetNamedItem(aName); 1.915 +} 1.916 + 1.917 +already_AddRefed<Attr> 1.918 +Element::SetAttributeNode(Attr& aNewAttr, ErrorResult& aError) 1.919 +{ 1.920 + OwnerDoc()->WarnOnceAbout(nsIDocument::eSetAttributeNode); 1.921 + 1.922 + return Attributes()->SetNamedItem(aNewAttr, aError); 1.923 +} 1.924 + 1.925 +already_AddRefed<Attr> 1.926 +Element::RemoveAttributeNode(Attr& aAttribute, 1.927 + ErrorResult& aError) 1.928 +{ 1.929 + OwnerDoc()->WarnOnceAbout(nsIDocument::eRemoveAttributeNode); 1.930 + return Attributes()->RemoveNamedItem(aAttribute.NodeName(), aError); 1.931 +} 1.932 + 1.933 +void 1.934 +Element::GetAttributeNS(const nsAString& aNamespaceURI, 1.935 + const nsAString& aLocalName, 1.936 + nsAString& aReturn) 1.937 +{ 1.938 + int32_t nsid = 1.939 + nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI); 1.940 + 1.941 + if (nsid == kNameSpaceID_Unknown) { 1.942 + // Unknown namespace means no attribute. 1.943 + SetDOMStringToNull(aReturn); 1.944 + return; 1.945 + } 1.946 + 1.947 + nsCOMPtr<nsIAtom> name = do_GetAtom(aLocalName); 1.948 + bool hasAttr = GetAttr(nsid, name, aReturn); 1.949 + if (!hasAttr) { 1.950 + SetDOMStringToNull(aReturn); 1.951 + } 1.952 +} 1.953 + 1.954 +void 1.955 +Element::SetAttributeNS(const nsAString& aNamespaceURI, 1.956 + const nsAString& aQualifiedName, 1.957 + const nsAString& aValue, 1.958 + ErrorResult& aError) 1.959 +{ 1.960 + nsCOMPtr<nsINodeInfo> ni; 1.961 + aError = 1.962 + nsContentUtils::GetNodeInfoFromQName(aNamespaceURI, aQualifiedName, 1.963 + mNodeInfo->NodeInfoManager(), 1.964 + nsIDOMNode::ATTRIBUTE_NODE, 1.965 + getter_AddRefs(ni)); 1.966 + if (aError.Failed()) { 1.967 + return; 1.968 + } 1.969 + 1.970 + aError = SetAttr(ni->NamespaceID(), ni->NameAtom(), ni->GetPrefixAtom(), 1.971 + aValue, true); 1.972 +} 1.973 + 1.974 +void 1.975 +Element::RemoveAttributeNS(const nsAString& aNamespaceURI, 1.976 + const nsAString& aLocalName, 1.977 + ErrorResult& aError) 1.978 +{ 1.979 + nsCOMPtr<nsIAtom> name = do_GetAtom(aLocalName); 1.980 + int32_t nsid = 1.981 + nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI); 1.982 + 1.983 + if (nsid == kNameSpaceID_Unknown) { 1.984 + // If the namespace ID is unknown, it means there can't possibly be an 1.985 + // existing attribute. We would need a known namespace ID to pass into 1.986 + // UnsetAttr, so we return early if we don't have one. 1.987 + return; 1.988 + } 1.989 + 1.990 + aError = UnsetAttr(nsid, name, true); 1.991 +} 1.992 + 1.993 +Attr* 1.994 +Element::GetAttributeNodeNS(const nsAString& aNamespaceURI, 1.995 + const nsAString& aLocalName) 1.996 +{ 1.997 + OwnerDoc()->WarnOnceAbout(nsIDocument::eGetAttributeNodeNS); 1.998 + 1.999 + return GetAttributeNodeNSInternal(aNamespaceURI, aLocalName); 1.1000 +} 1.1001 + 1.1002 +Attr* 1.1003 +Element::GetAttributeNodeNSInternal(const nsAString& aNamespaceURI, 1.1004 + const nsAString& aLocalName) 1.1005 +{ 1.1006 + return Attributes()->GetNamedItemNS(aNamespaceURI, aLocalName); 1.1007 +} 1.1008 + 1.1009 +already_AddRefed<Attr> 1.1010 +Element::SetAttributeNodeNS(Attr& aNewAttr, 1.1011 + ErrorResult& aError) 1.1012 +{ 1.1013 + OwnerDoc()->WarnOnceAbout(nsIDocument::eSetAttributeNodeNS); 1.1014 + return Attributes()->SetNamedItemNS(aNewAttr, aError); 1.1015 +} 1.1016 + 1.1017 +already_AddRefed<nsIHTMLCollection> 1.1018 +Element::GetElementsByTagNameNS(const nsAString& aNamespaceURI, 1.1019 + const nsAString& aLocalName, 1.1020 + ErrorResult& aError) 1.1021 +{ 1.1022 + int32_t nameSpaceId = kNameSpaceID_Wildcard; 1.1023 + 1.1024 + if (!aNamespaceURI.EqualsLiteral("*")) { 1.1025 + aError = 1.1026 + nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI, 1.1027 + nameSpaceId); 1.1028 + if (aError.Failed()) { 1.1029 + return nullptr; 1.1030 + } 1.1031 + } 1.1032 + 1.1033 + NS_ASSERTION(nameSpaceId != kNameSpaceID_Unknown, "Unexpected namespace ID!"); 1.1034 + 1.1035 + return NS_GetContentList(this, nameSpaceId, aLocalName); 1.1036 +} 1.1037 + 1.1038 +nsresult 1.1039 +Element::GetElementsByTagNameNS(const nsAString& namespaceURI, 1.1040 + const nsAString& localName, 1.1041 + nsIDOMHTMLCollection** aResult) 1.1042 +{ 1.1043 + mozilla::ErrorResult rv; 1.1044 + nsCOMPtr<nsIHTMLCollection> list = 1.1045 + GetElementsByTagNameNS(namespaceURI, localName, rv); 1.1046 + if (rv.Failed()) { 1.1047 + return rv.ErrorCode(); 1.1048 + } 1.1049 + list.forget(aResult); 1.1050 + return NS_OK; 1.1051 +} 1.1052 + 1.1053 +bool 1.1054 +Element::HasAttributeNS(const nsAString& aNamespaceURI, 1.1055 + const nsAString& aLocalName) const 1.1056 +{ 1.1057 + int32_t nsid = 1.1058 + nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI); 1.1059 + 1.1060 + if (nsid == kNameSpaceID_Unknown) { 1.1061 + // Unknown namespace means no attr... 1.1062 + return false; 1.1063 + } 1.1064 + 1.1065 + nsCOMPtr<nsIAtom> name = do_GetAtom(aLocalName); 1.1066 + return HasAttr(nsid, name); 1.1067 +} 1.1068 + 1.1069 +already_AddRefed<nsIHTMLCollection> 1.1070 +Element::GetElementsByClassName(const nsAString& aClassNames) 1.1071 +{ 1.1072 + return nsContentUtils::GetElementsByClassName(this, aClassNames); 1.1073 +} 1.1074 + 1.1075 +nsresult 1.1076 +Element::GetElementsByClassName(const nsAString& aClassNames, 1.1077 + nsIDOMHTMLCollection** aResult) 1.1078 +{ 1.1079 + *aResult = 1.1080 + nsContentUtils::GetElementsByClassName(this, aClassNames).take(); 1.1081 + return NS_OK; 1.1082 +} 1.1083 + 1.1084 +nsresult 1.1085 +Element::BindToTree(nsIDocument* aDocument, nsIContent* aParent, 1.1086 + nsIContent* aBindingParent, 1.1087 + bool aCompileEventHandlers) 1.1088 +{ 1.1089 + NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!"); 1.1090 + NS_PRECONDITION((NODE_FROM(aParent, aDocument)->OwnerDoc() == OwnerDoc()), 1.1091 + "Must have the same owner document"); 1.1092 + NS_PRECONDITION(!aParent || aDocument == aParent->GetCurrentDoc(), 1.1093 + "aDocument must be current doc of aParent"); 1.1094 + NS_PRECONDITION(!GetCurrentDoc(), "Already have a document. Unbind first!"); 1.1095 + // Note that as we recurse into the kids, they'll have a non-null parent. So 1.1096 + // only assert if our parent is _changing_ while we have a parent. 1.1097 + NS_PRECONDITION(!GetParent() || aParent == GetParent(), 1.1098 + "Already have a parent. Unbind first!"); 1.1099 + NS_PRECONDITION(!GetBindingParent() || 1.1100 + aBindingParent == GetBindingParent() || 1.1101 + (!aBindingParent && aParent && 1.1102 + aParent->GetBindingParent() == GetBindingParent()), 1.1103 + "Already have a binding parent. Unbind first!"); 1.1104 + NS_PRECONDITION(!aParent || !aDocument || 1.1105 + !aParent->HasFlag(NODE_FORCE_XBL_BINDINGS), 1.1106 + "Parent in document but flagged as forcing XBL"); 1.1107 + NS_PRECONDITION(aBindingParent != this, 1.1108 + "Content must not be its own binding parent"); 1.1109 + NS_PRECONDITION(!IsRootOfNativeAnonymousSubtree() || 1.1110 + aBindingParent == aParent, 1.1111 + "Native anonymous content must have its parent as its " 1.1112 + "own binding parent"); 1.1113 + NS_PRECONDITION(aBindingParent || !aParent || 1.1114 + aBindingParent == aParent->GetBindingParent(), 1.1115 + "We should be passed the right binding parent"); 1.1116 + 1.1117 +#ifdef MOZ_XUL 1.1118 + // First set the binding parent 1.1119 + nsXULElement* xulElem = nsXULElement::FromContent(this); 1.1120 + if (xulElem) { 1.1121 + xulElem->SetXULBindingParent(aBindingParent); 1.1122 + } 1.1123 + else 1.1124 +#endif 1.1125 + { 1.1126 + if (aBindingParent) { 1.1127 + nsDOMSlots *slots = DOMSlots(); 1.1128 + 1.1129 + slots->mBindingParent = aBindingParent; // Weak, so no addref happens. 1.1130 + } 1.1131 + } 1.1132 + NS_ASSERTION(!aBindingParent || IsRootOfNativeAnonymousSubtree() || 1.1133 + !HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE) || 1.1134 + (aParent && aParent->IsInNativeAnonymousSubtree()), 1.1135 + "Trying to re-bind content from native anonymous subtree to " 1.1136 + "non-native anonymous parent!"); 1.1137 + if (aParent) { 1.1138 + if (aParent->IsInNativeAnonymousSubtree()) { 1.1139 + SetFlags(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE); 1.1140 + } 1.1141 + if (aParent->HasFlag(NODE_CHROME_ONLY_ACCESS)) { 1.1142 + SetFlags(NODE_CHROME_ONLY_ACCESS); 1.1143 + } 1.1144 + if (aParent->HasFlag(NODE_IS_IN_SHADOW_TREE)) { 1.1145 + SetFlags(NODE_IS_IN_SHADOW_TREE); 1.1146 + } 1.1147 + ShadowRoot* parentContainingShadow = aParent->GetContainingShadow(); 1.1148 + if (parentContainingShadow) { 1.1149 + DOMSlots()->mContainingShadow = parentContainingShadow; 1.1150 + } 1.1151 + } 1.1152 + 1.1153 + bool hadForceXBL = HasFlag(NODE_FORCE_XBL_BINDINGS); 1.1154 + 1.1155 + // Now set the parent and set the "Force attach xbl" flag if needed. 1.1156 + if (aParent) { 1.1157 + if (!GetParent()) { 1.1158 + NS_ADDREF(aParent); 1.1159 + } 1.1160 + mParent = aParent; 1.1161 + 1.1162 + if (aParent->HasFlag(NODE_FORCE_XBL_BINDINGS)) { 1.1163 + SetFlags(NODE_FORCE_XBL_BINDINGS); 1.1164 + } 1.1165 + } 1.1166 + else { 1.1167 + mParent = aDocument; 1.1168 + } 1.1169 + SetParentIsContent(aParent); 1.1170 + 1.1171 + // XXXbz sXBL/XBL2 issue! 1.1172 + 1.1173 + // Finally, set the document 1.1174 + if (aDocument) { 1.1175 + // Notify XBL- & nsIAnonymousContentCreator-generated 1.1176 + // anonymous content that the document is changing. 1.1177 + // XXXbz ordering issues here? Probably not, since ChangeDocumentFor is 1.1178 + // just pretty broken anyway.... Need to get it working. 1.1179 + // XXXbz XBL doesn't handle this (asserts), and we don't really want 1.1180 + // to be doing this during parsing anyway... sort this out. 1.1181 + // aDocument->BindingManager()->ChangeDocumentFor(this, nullptr, 1.1182 + // aDocument); 1.1183 + 1.1184 + // We no longer need to track the subtree pointer (and in fact we'll assert 1.1185 + // if we do this any later). 1.1186 + ClearSubtreeRootPointer(); 1.1187 + 1.1188 + // Being added to a document. 1.1189 + SetInDocument(); 1.1190 + 1.1191 + if (GetCustomElementData()) { 1.1192 + // Enqueue an attached callback for the custom element. 1.1193 + aDocument->EnqueueLifecycleCallback(nsIDocument::eAttached, this); 1.1194 + } 1.1195 + 1.1196 + // Unset this flag since we now really are in a document. 1.1197 + UnsetFlags(NODE_FORCE_XBL_BINDINGS | 1.1198 + // And clear the lazy frame construction bits. 1.1199 + NODE_NEEDS_FRAME | NODE_DESCENDANTS_NEED_FRAMES | 1.1200 + // And the restyle bits 1.1201 + ELEMENT_ALL_RESTYLE_FLAGS); 1.1202 + 1.1203 + // Propagate scoped style sheet tracking bit. 1.1204 + SetIsElementInStyleScope(mParent->IsElementInStyleScope()); 1.1205 + } else { 1.1206 + // If we're not in the doc, update our subtree pointer. 1.1207 + SetSubtreeRootPointer(aParent->SubtreeRoot()); 1.1208 + } 1.1209 + 1.1210 + // This has to be here, rather than in nsGenericHTMLElement::BindToTree, 1.1211 + // because it has to happen after updating the parent pointer, but before 1.1212 + // recursively binding the kids. 1.1213 + if (IsHTML()) { 1.1214 + SetDirOnBind(this, aParent); 1.1215 + } 1.1216 + 1.1217 + // If NODE_FORCE_XBL_BINDINGS was set we might have anonymous children 1.1218 + // that also need to be told that they are moving. 1.1219 + nsresult rv; 1.1220 + if (hadForceXBL) { 1.1221 + nsBindingManager* bmgr = OwnerDoc()->BindingManager(); 1.1222 + 1.1223 + nsXBLBinding* contBinding = bmgr->GetBindingWithContent(this); 1.1224 + // First check if we have a binding... 1.1225 + if (contBinding) { 1.1226 + nsCOMPtr<nsIContent> anonRoot = contBinding->GetAnonymousContent(); 1.1227 + bool allowScripts = contBinding->AllowScripts(); 1.1228 + for (nsCOMPtr<nsIContent> child = anonRoot->GetFirstChild(); 1.1229 + child; 1.1230 + child = child->GetNextSibling()) { 1.1231 + rv = child->BindToTree(aDocument, this, this, allowScripts); 1.1232 + NS_ENSURE_SUCCESS(rv, rv); 1.1233 + } 1.1234 + } 1.1235 + } 1.1236 + 1.1237 + UpdateEditableState(false); 1.1238 + 1.1239 + // Now recurse into our kids 1.1240 + for (nsIContent* child = GetFirstChild(); child; 1.1241 + child = child->GetNextSibling()) { 1.1242 + rv = child->BindToTree(aDocument, this, aBindingParent, 1.1243 + aCompileEventHandlers); 1.1244 + NS_ENSURE_SUCCESS(rv, rv); 1.1245 + } 1.1246 + 1.1247 + nsNodeUtils::ParentChainChanged(this); 1.1248 + 1.1249 + if (HasID()) { 1.1250 + AddToIdTable(DoGetID()); 1.1251 + } 1.1252 + 1.1253 + if (MayHaveStyle() && !IsXUL()) { 1.1254 + // XXXbz if we already have a style attr parsed, this won't do 1.1255 + // anything... need to fix that. 1.1256 + // If MayHaveStyle() is true, we must be an nsStyledElement 1.1257 + static_cast<nsStyledElement*>(this)->ReparseStyleAttribute(false); 1.1258 + } 1.1259 + 1.1260 + if (aDocument) { 1.1261 + // If we're in a document now, let our mapped attrs know what their new 1.1262 + // sheet is. This is safe to run for non-mapped-attribute elements too; 1.1263 + // it'll just do a small bit of unnecessary work. But most elements in 1.1264 + // practice are mapped-attribute elements. 1.1265 + nsHTMLStyleSheet* sheet = aDocument->GetAttributeStyleSheet(); 1.1266 + if (sheet) { 1.1267 + mAttrsAndChildren.SetMappedAttrStyleSheet(sheet); 1.1268 + } 1.1269 + } 1.1270 + 1.1271 + // XXXbz script execution during binding can trigger some of these 1.1272 + // postcondition asserts.... But we do want that, since things will 1.1273 + // generally be quite broken when that happens. 1.1274 + NS_POSTCONDITION(aDocument == GetCurrentDoc(), "Bound to wrong document"); 1.1275 + NS_POSTCONDITION(aParent == GetParent(), "Bound to wrong parent"); 1.1276 + NS_POSTCONDITION(aBindingParent == GetBindingParent(), 1.1277 + "Bound to wrong binding parent"); 1.1278 + 1.1279 + return NS_OK; 1.1280 +} 1.1281 + 1.1282 +class RemoveFromBindingManagerRunnable : public nsRunnable { 1.1283 +public: 1.1284 + RemoveFromBindingManagerRunnable(nsBindingManager* aManager, 1.1285 + Element* aElement, 1.1286 + nsIDocument* aDoc): 1.1287 + mManager(aManager), mElement(aElement), mDoc(aDoc) 1.1288 + {} 1.1289 + 1.1290 + NS_IMETHOD Run() 1.1291 + { 1.1292 + // It may be the case that the element was removed from the 1.1293 + // DOM, causing this runnable to be created, then inserted back 1.1294 + // into the document before the this runnable had a chance to 1.1295 + // tear down the binding. Only tear down the binding if the element 1.1296 + // is still no longer in the DOM. nsXBLService::LoadBinding tears 1.1297 + // down the old binding if the element is inserted back into the 1.1298 + // DOM and loads a different binding. 1.1299 + if (!mElement->IsInDoc()) { 1.1300 + mManager->RemovedFromDocumentInternal(mElement, mDoc); 1.1301 + } 1.1302 + 1.1303 + return NS_OK; 1.1304 + } 1.1305 + 1.1306 +private: 1.1307 + nsRefPtr<nsBindingManager> mManager; 1.1308 + nsRefPtr<Element> mElement; 1.1309 + nsCOMPtr<nsIDocument> mDoc; 1.1310 +}; 1.1311 + 1.1312 +void 1.1313 +Element::UnbindFromTree(bool aDeep, bool aNullParent) 1.1314 +{ 1.1315 + NS_PRECONDITION(aDeep || (!GetCurrentDoc() && !GetBindingParent()), 1.1316 + "Shallow unbind won't clear document and binding parent on " 1.1317 + "kids!"); 1.1318 + 1.1319 + RemoveFromIdTable(); 1.1320 + 1.1321 + // Make sure to unbind this node before doing the kids 1.1322 + nsIDocument *document = 1.1323 + HasFlag(NODE_FORCE_XBL_BINDINGS) ? OwnerDoc() : GetCurrentDoc(); 1.1324 + 1.1325 + if (aNullParent) { 1.1326 + if (IsFullScreenAncestor()) { 1.1327 + // The element being removed is an ancestor of the full-screen element, 1.1328 + // exit full-screen state. 1.1329 + nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, 1.1330 + NS_LITERAL_CSTRING("DOM"), OwnerDoc(), 1.1331 + nsContentUtils::eDOM_PROPERTIES, 1.1332 + "RemovedFullScreenElement"); 1.1333 + // Fully exit full-screen. 1.1334 + nsIDocument::ExitFullscreen(OwnerDoc(), /* async */ false); 1.1335 + } 1.1336 + if (HasPointerLock()) { 1.1337 + nsIDocument::UnlockPointer(); 1.1338 + } 1.1339 + if (GetParent()) { 1.1340 + nsINode* p = mParent; 1.1341 + mParent = nullptr; 1.1342 + NS_RELEASE(p); 1.1343 + } else { 1.1344 + mParent = nullptr; 1.1345 + } 1.1346 + SetParentIsContent(false); 1.1347 + } 1.1348 + ClearInDocument(); 1.1349 + 1.1350 + // Begin keeping track of our subtree root. 1.1351 + SetSubtreeRootPointer(aNullParent ? this : mParent->SubtreeRoot()); 1.1352 + 1.1353 + if (document) { 1.1354 + // Notify XBL- & nsIAnonymousContentCreator-generated 1.1355 + // anonymous content that the document is changing. 1.1356 + if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) { 1.1357 + nsContentUtils::AddScriptRunner( 1.1358 + new RemoveFromBindingManagerRunnable(document->BindingManager(), this, 1.1359 + document)); 1.1360 + } 1.1361 + 1.1362 + document->ClearBoxObjectFor(this); 1.1363 + 1.1364 + if (GetCustomElementData()) { 1.1365 + // Enqueue a detached callback for the custom element. 1.1366 + document->EnqueueLifecycleCallback(nsIDocument::eDetached, this); 1.1367 + } 1.1368 + } 1.1369 + 1.1370 + // Ensure that CSS transitions don't continue on an element at a 1.1371 + // different place in the tree (even if reinserted before next 1.1372 + // animation refresh). 1.1373 + // FIXME (Bug 522599): Need a test for this. 1.1374 + if (HasFlag(NODE_HAS_PROPERTIES)) { 1.1375 + DeleteProperty(nsGkAtoms::transitionsOfBeforeProperty); 1.1376 + DeleteProperty(nsGkAtoms::transitionsOfAfterProperty); 1.1377 + DeleteProperty(nsGkAtoms::transitionsProperty); 1.1378 + DeleteProperty(nsGkAtoms::animationsOfBeforeProperty); 1.1379 + DeleteProperty(nsGkAtoms::animationsOfAfterProperty); 1.1380 + DeleteProperty(nsGkAtoms::animationsProperty); 1.1381 + } 1.1382 + 1.1383 + // Unset this since that's what the old code effectively did. 1.1384 + UnsetFlags(NODE_FORCE_XBL_BINDINGS | NODE_IS_IN_SHADOW_TREE); 1.1385 + 1.1386 +#ifdef MOZ_XUL 1.1387 + nsXULElement* xulElem = nsXULElement::FromContent(this); 1.1388 + if (xulElem) { 1.1389 + xulElem->SetXULBindingParent(nullptr); 1.1390 + } 1.1391 + else 1.1392 +#endif 1.1393 + { 1.1394 + nsDOMSlots *slots = GetExistingDOMSlots(); 1.1395 + if (slots) { 1.1396 + slots->mBindingParent = nullptr; 1.1397 + slots->mContainingShadow = nullptr; 1.1398 + } 1.1399 + } 1.1400 + 1.1401 + // This has to be here, rather than in nsGenericHTMLElement::UnbindFromTree, 1.1402 + // because it has to happen after unsetting the parent pointer, but before 1.1403 + // recursively unbinding the kids. 1.1404 + if (IsHTML()) { 1.1405 + ResetDir(this); 1.1406 + } 1.1407 + 1.1408 + if (aDeep) { 1.1409 + // Do the kids. Don't call GetChildCount() here since that'll force 1.1410 + // XUL to generate template children, which there is no need for since 1.1411 + // all we're going to do is unbind them anyway. 1.1412 + uint32_t i, n = mAttrsAndChildren.ChildCount(); 1.1413 + 1.1414 + for (i = 0; i < n; ++i) { 1.1415 + // Note that we pass false for aNullParent here, since we don't want 1.1416 + // the kids to forget us. We _do_ want them to forget their binding 1.1417 + // parent, though, since this only walks non-anonymous kids. 1.1418 + mAttrsAndChildren.ChildAt(i)->UnbindFromTree(true, false); 1.1419 + } 1.1420 + } 1.1421 + 1.1422 + nsNodeUtils::ParentChainChanged(this); 1.1423 +} 1.1424 + 1.1425 +nsICSSDeclaration* 1.1426 +Element::GetSMILOverrideStyle() 1.1427 +{ 1.1428 + Element::nsDOMSlots *slots = DOMSlots(); 1.1429 + 1.1430 + if (!slots->mSMILOverrideStyle) { 1.1431 + slots->mSMILOverrideStyle = new nsDOMCSSAttributeDeclaration(this, true); 1.1432 + } 1.1433 + 1.1434 + return slots->mSMILOverrideStyle; 1.1435 +} 1.1436 + 1.1437 +css::StyleRule* 1.1438 +Element::GetSMILOverrideStyleRule() 1.1439 +{ 1.1440 + Element::nsDOMSlots *slots = GetExistingDOMSlots(); 1.1441 + return slots ? slots->mSMILOverrideStyleRule.get() : nullptr; 1.1442 +} 1.1443 + 1.1444 +nsresult 1.1445 +Element::SetSMILOverrideStyleRule(css::StyleRule* aStyleRule, 1.1446 + bool aNotify) 1.1447 +{ 1.1448 + Element::nsDOMSlots *slots = DOMSlots(); 1.1449 + 1.1450 + slots->mSMILOverrideStyleRule = aStyleRule; 1.1451 + 1.1452 + if (aNotify) { 1.1453 + nsIDocument* doc = GetCurrentDoc(); 1.1454 + // Only need to request a restyle if we're in a document. (We might not 1.1455 + // be in a document, if we're clearing animation effects on a target node 1.1456 + // that's been detached since the previous animation sample.) 1.1457 + if (doc) { 1.1458 + nsCOMPtr<nsIPresShell> shell = doc->GetShell(); 1.1459 + if (shell) { 1.1460 + shell->RestyleForAnimation(this, eRestyle_Self); 1.1461 + } 1.1462 + } 1.1463 + } 1.1464 + 1.1465 + return NS_OK; 1.1466 +} 1.1467 + 1.1468 +bool 1.1469 +Element::IsLabelable() const 1.1470 +{ 1.1471 + return false; 1.1472 +} 1.1473 + 1.1474 +css::StyleRule* 1.1475 +Element::GetInlineStyleRule() 1.1476 +{ 1.1477 + return nullptr; 1.1478 +} 1.1479 + 1.1480 +nsresult 1.1481 +Element::SetInlineStyleRule(css::StyleRule* aStyleRule, 1.1482 + const nsAString* aSerialized, 1.1483 + bool aNotify) 1.1484 +{ 1.1485 + NS_NOTYETIMPLEMENTED("Element::SetInlineStyleRule"); 1.1486 + return NS_ERROR_NOT_IMPLEMENTED; 1.1487 +} 1.1488 + 1.1489 +NS_IMETHODIMP_(bool) 1.1490 +Element::IsAttributeMapped(const nsIAtom* aAttribute) const 1.1491 +{ 1.1492 + return false; 1.1493 +} 1.1494 + 1.1495 +nsChangeHint 1.1496 +Element::GetAttributeChangeHint(const nsIAtom* aAttribute, 1.1497 + int32_t aModType) const 1.1498 +{ 1.1499 + return nsChangeHint(0); 1.1500 +} 1.1501 + 1.1502 +nsIAtom * 1.1503 +Element::GetClassAttributeName() const 1.1504 +{ 1.1505 + return nullptr; 1.1506 +} 1.1507 + 1.1508 +bool 1.1509 +Element::FindAttributeDependence(const nsIAtom* aAttribute, 1.1510 + const MappedAttributeEntry* const aMaps[], 1.1511 + uint32_t aMapCount) 1.1512 +{ 1.1513 + for (uint32_t mapindex = 0; mapindex < aMapCount; ++mapindex) { 1.1514 + for (const MappedAttributeEntry* map = aMaps[mapindex]; 1.1515 + map->attribute; ++map) { 1.1516 + if (aAttribute == *map->attribute) { 1.1517 + return true; 1.1518 + } 1.1519 + } 1.1520 + } 1.1521 + 1.1522 + return false; 1.1523 +} 1.1524 + 1.1525 +already_AddRefed<nsINodeInfo> 1.1526 +Element::GetExistingAttrNameFromQName(const nsAString& aStr) const 1.1527 +{ 1.1528 + const nsAttrName* name = InternalGetExistingAttrNameFromQName(aStr); 1.1529 + if (!name) { 1.1530 + return nullptr; 1.1531 + } 1.1532 + 1.1533 + nsCOMPtr<nsINodeInfo> nodeInfo; 1.1534 + if (name->IsAtom()) { 1.1535 + nodeInfo = mNodeInfo->NodeInfoManager()-> 1.1536 + GetNodeInfo(name->Atom(), nullptr, kNameSpaceID_None, 1.1537 + nsIDOMNode::ATTRIBUTE_NODE); 1.1538 + } 1.1539 + else { 1.1540 + nodeInfo = name->NodeInfo(); 1.1541 + } 1.1542 + 1.1543 + return nodeInfo.forget(); 1.1544 +} 1.1545 + 1.1546 +// static 1.1547 +bool 1.1548 +Element::ShouldBlur(nsIContent *aContent) 1.1549 +{ 1.1550 + // Determine if the current element is focused, if it is not focused 1.1551 + // then we should not try to blur 1.1552 + nsIDocument *document = aContent->GetDocument(); 1.1553 + if (!document) 1.1554 + return false; 1.1555 + 1.1556 + nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(document->GetWindow()); 1.1557 + if (!window) 1.1558 + return false; 1.1559 + 1.1560 + nsCOMPtr<nsPIDOMWindow> focusedFrame; 1.1561 + nsIContent* contentToBlur = 1.1562 + nsFocusManager::GetFocusedDescendant(window, false, getter_AddRefs(focusedFrame)); 1.1563 + if (contentToBlur == aContent) 1.1564 + return true; 1.1565 + 1.1566 + // if focus on this element would get redirected, then check the redirected 1.1567 + // content as well when blurring. 1.1568 + return (contentToBlur && nsFocusManager::GetRedirectedFocus(aContent) == contentToBlur); 1.1569 +} 1.1570 + 1.1571 +bool 1.1572 +Element::IsNodeOfType(uint32_t aFlags) const 1.1573 +{ 1.1574 + return !(aFlags & ~eCONTENT); 1.1575 +} 1.1576 + 1.1577 +/* static */ 1.1578 +nsresult 1.1579 +Element::DispatchEvent(nsPresContext* aPresContext, 1.1580 + WidgetEvent* aEvent, 1.1581 + nsIContent* aTarget, 1.1582 + bool aFullDispatch, 1.1583 + nsEventStatus* aStatus) 1.1584 +{ 1.1585 + NS_PRECONDITION(aTarget, "Must have target"); 1.1586 + NS_PRECONDITION(aEvent, "Must have source event"); 1.1587 + NS_PRECONDITION(aStatus, "Null out param?"); 1.1588 + 1.1589 + if (!aPresContext) { 1.1590 + return NS_OK; 1.1591 + } 1.1592 + 1.1593 + nsCOMPtr<nsIPresShell> shell = aPresContext->GetPresShell(); 1.1594 + if (!shell) { 1.1595 + return NS_OK; 1.1596 + } 1.1597 + 1.1598 + if (aFullDispatch) { 1.1599 + return shell->HandleEventWithTarget(aEvent, nullptr, aTarget, aStatus); 1.1600 + } 1.1601 + 1.1602 + return shell->HandleDOMEventWithTarget(aTarget, aEvent, aStatus); 1.1603 +} 1.1604 + 1.1605 +/* static */ 1.1606 +nsresult 1.1607 +Element::DispatchClickEvent(nsPresContext* aPresContext, 1.1608 + WidgetInputEvent* aSourceEvent, 1.1609 + nsIContent* aTarget, 1.1610 + bool aFullDispatch, 1.1611 + const EventFlags* aExtraEventFlags, 1.1612 + nsEventStatus* aStatus) 1.1613 +{ 1.1614 + NS_PRECONDITION(aTarget, "Must have target"); 1.1615 + NS_PRECONDITION(aSourceEvent, "Must have source event"); 1.1616 + NS_PRECONDITION(aStatus, "Null out param?"); 1.1617 + 1.1618 + WidgetMouseEvent event(aSourceEvent->mFlags.mIsTrusted, NS_MOUSE_CLICK, 1.1619 + aSourceEvent->widget, WidgetMouseEvent::eReal); 1.1620 + event.refPoint = aSourceEvent->refPoint; 1.1621 + uint32_t clickCount = 1; 1.1622 + float pressure = 0; 1.1623 + uint16_t inputSource = 0; 1.1624 + WidgetMouseEvent* sourceMouseEvent = aSourceEvent->AsMouseEvent(); 1.1625 + if (sourceMouseEvent) { 1.1626 + clickCount = sourceMouseEvent->clickCount; 1.1627 + pressure = sourceMouseEvent->pressure; 1.1628 + inputSource = sourceMouseEvent->inputSource; 1.1629 + } else if (aSourceEvent->eventStructType == NS_KEY_EVENT) { 1.1630 + inputSource = nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD; 1.1631 + } 1.1632 + event.pressure = pressure; 1.1633 + event.clickCount = clickCount; 1.1634 + event.inputSource = inputSource; 1.1635 + event.modifiers = aSourceEvent->modifiers; 1.1636 + if (aExtraEventFlags) { 1.1637 + // Be careful not to overwrite existing flags! 1.1638 + event.mFlags.Union(*aExtraEventFlags); 1.1639 + } 1.1640 + 1.1641 + return DispatchEvent(aPresContext, &event, aTarget, aFullDispatch, aStatus); 1.1642 +} 1.1643 + 1.1644 +nsIFrame* 1.1645 +Element::GetPrimaryFrame(mozFlushType aType) 1.1646 +{ 1.1647 + nsIDocument* doc = GetCurrentDoc(); 1.1648 + if (!doc) { 1.1649 + return nullptr; 1.1650 + } 1.1651 + 1.1652 + // Cause a flush, so we get up-to-date frame 1.1653 + // information 1.1654 + if (aType != Flush_None) { 1.1655 + doc->FlushPendingNotifications(aType); 1.1656 + } 1.1657 + 1.1658 + return GetPrimaryFrame(); 1.1659 +} 1.1660 + 1.1661 +//---------------------------------------------------------------------- 1.1662 +nsresult 1.1663 +Element::LeaveLink(nsPresContext* aPresContext) 1.1664 +{ 1.1665 + nsILinkHandler *handler = aPresContext->GetLinkHandler(); 1.1666 + if (!handler) { 1.1667 + return NS_OK; 1.1668 + } 1.1669 + 1.1670 + return handler->OnLeaveLink(); 1.1671 +} 1.1672 + 1.1673 +nsresult 1.1674 +Element::SetEventHandler(nsIAtom* aEventName, 1.1675 + const nsAString& aValue, 1.1676 + bool aDefer) 1.1677 +{ 1.1678 + nsIDocument *ownerDoc = OwnerDoc(); 1.1679 + if (ownerDoc->IsLoadedAsData()) { 1.1680 + // Make this a no-op rather than throwing an error to avoid 1.1681 + // the error causing problems setting the attribute. 1.1682 + return NS_OK; 1.1683 + } 1.1684 + 1.1685 + NS_PRECONDITION(aEventName, "Must have event name!"); 1.1686 + bool defer = true; 1.1687 + EventListenerManager* manager = 1.1688 + GetEventListenerManagerForAttr(aEventName, &defer); 1.1689 + if (!manager) { 1.1690 + return NS_OK; 1.1691 + } 1.1692 + 1.1693 + defer = defer && aDefer; // only defer if everyone agrees... 1.1694 + manager->SetEventHandler(aEventName, aValue, 1.1695 + nsIProgrammingLanguage::JAVASCRIPT, 1.1696 + defer, !nsContentUtils::IsChromeDoc(ownerDoc), 1.1697 + this); 1.1698 + return NS_OK; 1.1699 +} 1.1700 + 1.1701 + 1.1702 +//---------------------------------------------------------------------- 1.1703 + 1.1704 +const nsAttrName* 1.1705 +Element::InternalGetExistingAttrNameFromQName(const nsAString& aStr) const 1.1706 +{ 1.1707 + return mAttrsAndChildren.GetExistingAttrNameFromQName(aStr); 1.1708 +} 1.1709 + 1.1710 +bool 1.1711 +Element::MaybeCheckSameAttrVal(int32_t aNamespaceID, 1.1712 + nsIAtom* aName, 1.1713 + nsIAtom* aPrefix, 1.1714 + const nsAttrValueOrString& aValue, 1.1715 + bool aNotify, 1.1716 + nsAttrValue& aOldValue, 1.1717 + uint8_t* aModType, 1.1718 + bool* aHasListeners) 1.1719 +{ 1.1720 + bool modification = false; 1.1721 + *aHasListeners = aNotify && 1.1722 + nsContentUtils::HasMutationListeners(this, 1.1723 + NS_EVENT_BITS_MUTATION_ATTRMODIFIED, 1.1724 + this); 1.1725 + 1.1726 + // If we have no listeners and aNotify is false, we are almost certainly 1.1727 + // coming from the content sink and will almost certainly have no previous 1.1728 + // value. Even if we do, setting the value is cheap when we have no 1.1729 + // listeners and don't plan to notify. The check for aNotify here is an 1.1730 + // optimization, the check for *aHasListeners is a correctness issue. 1.1731 + if (*aHasListeners || aNotify) { 1.1732 + nsAttrInfo info(GetAttrInfo(aNamespaceID, aName)); 1.1733 + if (info.mValue) { 1.1734 + // Check whether the old value is the same as the new one. Note that we 1.1735 + // only need to actually _get_ the old value if we have listeners or 1.1736 + // if the element is a custom element (because it may have an 1.1737 + // attribute changed callback). 1.1738 + if (*aHasListeners || GetCustomElementData()) { 1.1739 + // Need to store the old value. 1.1740 + // 1.1741 + // If the current attribute value contains a pointer to some other data 1.1742 + // structure that gets updated in the process of setting the attribute 1.1743 + // we'll no longer have the old value of the attribute. Therefore, we 1.1744 + // should serialize the attribute value now to keep a snapshot. 1.1745 + // 1.1746 + // We have to serialize the value anyway in order to create the 1.1747 + // mutation event so there's no cost in doing it now. 1.1748 + aOldValue.SetToSerialized(*info.mValue); 1.1749 + } 1.1750 + bool valueMatches = aValue.EqualsAsStrings(*info.mValue); 1.1751 + if (valueMatches && aPrefix == info.mName->GetPrefix()) { 1.1752 + return true; 1.1753 + } 1.1754 + modification = true; 1.1755 + } 1.1756 + } 1.1757 + *aModType = modification ? 1.1758 + static_cast<uint8_t>(nsIDOMMutationEvent::MODIFICATION) : 1.1759 + static_cast<uint8_t>(nsIDOMMutationEvent::ADDITION); 1.1760 + return false; 1.1761 +} 1.1762 + 1.1763 +bool 1.1764 +Element::OnlyNotifySameValueSet(int32_t aNamespaceID, nsIAtom* aName, 1.1765 + nsIAtom* aPrefix, 1.1766 + const nsAttrValueOrString& aValue, 1.1767 + bool aNotify, nsAttrValue& aOldValue, 1.1768 + uint8_t* aModType, bool* aHasListeners) 1.1769 +{ 1.1770 + if (!MaybeCheckSameAttrVal(aNamespaceID, aName, aPrefix, aValue, aNotify, 1.1771 + aOldValue, aModType, aHasListeners)) { 1.1772 + return false; 1.1773 + } 1.1774 + 1.1775 + nsAutoScriptBlocker scriptBlocker; 1.1776 + nsNodeUtils::AttributeSetToCurrentValue(this, aNamespaceID, aName); 1.1777 + return true; 1.1778 +} 1.1779 + 1.1780 +nsresult 1.1781 +Element::SetAttr(int32_t aNamespaceID, nsIAtom* aName, 1.1782 + nsIAtom* aPrefix, const nsAString& aValue, 1.1783 + bool aNotify) 1.1784 +{ 1.1785 + // Keep this in sync with SetParsedAttr below 1.1786 + 1.1787 + NS_ENSURE_ARG_POINTER(aName); 1.1788 + NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown, 1.1789 + "Don't call SetAttr with unknown namespace"); 1.1790 + 1.1791 + if (!mAttrsAndChildren.CanFitMoreAttrs()) { 1.1792 + return NS_ERROR_FAILURE; 1.1793 + } 1.1794 + 1.1795 + uint8_t modType; 1.1796 + bool hasListeners; 1.1797 + nsAttrValueOrString value(aValue); 1.1798 + nsAttrValue oldValue; 1.1799 + 1.1800 + if (OnlyNotifySameValueSet(aNamespaceID, aName, aPrefix, value, aNotify, 1.1801 + oldValue, &modType, &hasListeners)) { 1.1802 + return NS_OK; 1.1803 + } 1.1804 + 1.1805 + nsresult rv = BeforeSetAttr(aNamespaceID, aName, &value, aNotify); 1.1806 + NS_ENSURE_SUCCESS(rv, rv); 1.1807 + 1.1808 + if (aNotify) { 1.1809 + nsNodeUtils::AttributeWillChange(this, aNamespaceID, aName, modType); 1.1810 + } 1.1811 + 1.1812 + // Hold a script blocker while calling ParseAttribute since that can call 1.1813 + // out to id-observers 1.1814 + nsAutoScriptBlocker scriptBlocker; 1.1815 + 1.1816 + nsAttrValue attrValue; 1.1817 + if (!ParseAttribute(aNamespaceID, aName, aValue, attrValue)) { 1.1818 + attrValue.SetTo(aValue); 1.1819 + } 1.1820 + 1.1821 + return SetAttrAndNotify(aNamespaceID, aName, aPrefix, oldValue, 1.1822 + attrValue, modType, hasListeners, aNotify, 1.1823 + kCallAfterSetAttr); 1.1824 +} 1.1825 + 1.1826 +nsresult 1.1827 +Element::SetParsedAttr(int32_t aNamespaceID, nsIAtom* aName, 1.1828 + nsIAtom* aPrefix, nsAttrValue& aParsedValue, 1.1829 + bool aNotify) 1.1830 +{ 1.1831 + // Keep this in sync with SetAttr above 1.1832 + 1.1833 + NS_ENSURE_ARG_POINTER(aName); 1.1834 + NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown, 1.1835 + "Don't call SetAttr with unknown namespace"); 1.1836 + 1.1837 + if (!mAttrsAndChildren.CanFitMoreAttrs()) { 1.1838 + return NS_ERROR_FAILURE; 1.1839 + } 1.1840 + 1.1841 + 1.1842 + uint8_t modType; 1.1843 + bool hasListeners; 1.1844 + nsAttrValueOrString value(aParsedValue); 1.1845 + nsAttrValue oldValue; 1.1846 + 1.1847 + if (OnlyNotifySameValueSet(aNamespaceID, aName, aPrefix, value, aNotify, 1.1848 + oldValue, &modType, &hasListeners)) { 1.1849 + return NS_OK; 1.1850 + } 1.1851 + 1.1852 + nsresult rv = BeforeSetAttr(aNamespaceID, aName, &value, aNotify); 1.1853 + NS_ENSURE_SUCCESS(rv, rv); 1.1854 + 1.1855 + if (aNotify) { 1.1856 + nsNodeUtils::AttributeWillChange(this, aNamespaceID, aName, modType); 1.1857 + } 1.1858 + 1.1859 + return SetAttrAndNotify(aNamespaceID, aName, aPrefix, oldValue, 1.1860 + aParsedValue, modType, hasListeners, aNotify, 1.1861 + kCallAfterSetAttr); 1.1862 +} 1.1863 + 1.1864 +nsresult 1.1865 +Element::SetAttrAndNotify(int32_t aNamespaceID, 1.1866 + nsIAtom* aName, 1.1867 + nsIAtom* aPrefix, 1.1868 + const nsAttrValue& aOldValue, 1.1869 + nsAttrValue& aParsedValue, 1.1870 + uint8_t aModType, 1.1871 + bool aFireMutation, 1.1872 + bool aNotify, 1.1873 + bool aCallAfterSetAttr) 1.1874 +{ 1.1875 + nsresult rv; 1.1876 + 1.1877 + nsIDocument* document = GetCurrentDoc(); 1.1878 + mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify); 1.1879 + 1.1880 + nsMutationGuard::DidMutate(); 1.1881 + 1.1882 + // Copy aParsedValue for later use since it will be lost when we call 1.1883 + // SetAndTakeMappedAttr below 1.1884 + nsAttrValue aValueForAfterSetAttr; 1.1885 + if (aCallAfterSetAttr) { 1.1886 + aValueForAfterSetAttr.SetTo(aParsedValue); 1.1887 + } 1.1888 + 1.1889 + bool hadValidDir = false; 1.1890 + bool hadDirAuto = false; 1.1891 + 1.1892 + if (aNamespaceID == kNameSpaceID_None) { 1.1893 + if (aName == nsGkAtoms::dir) { 1.1894 + hadValidDir = HasValidDir() || IsHTML(nsGkAtoms::bdi); 1.1895 + hadDirAuto = HasDirAuto(); // already takes bdi into account 1.1896 + } 1.1897 + 1.1898 + // XXXbz Perhaps we should push up the attribute mapping function 1.1899 + // stuff to Element? 1.1900 + if (!IsAttributeMapped(aName) || 1.1901 + !SetMappedAttribute(document, aName, aParsedValue, &rv)) { 1.1902 + rv = mAttrsAndChildren.SetAndTakeAttr(aName, aParsedValue); 1.1903 + } 1.1904 + } 1.1905 + else { 1.1906 + nsCOMPtr<nsINodeInfo> ni; 1.1907 + ni = mNodeInfo->NodeInfoManager()->GetNodeInfo(aName, aPrefix, 1.1908 + aNamespaceID, 1.1909 + nsIDOMNode::ATTRIBUTE_NODE); 1.1910 + 1.1911 + rv = mAttrsAndChildren.SetAndTakeAttr(ni, aParsedValue); 1.1912 + } 1.1913 + NS_ENSURE_SUCCESS(rv, rv); 1.1914 + 1.1915 + if (document || HasFlag(NODE_FORCE_XBL_BINDINGS)) { 1.1916 + nsRefPtr<nsXBLBinding> binding = GetXBLBinding(); 1.1917 + if (binding) { 1.1918 + binding->AttributeChanged(aName, aNamespaceID, false, aNotify); 1.1919 + } 1.1920 + } 1.1921 + 1.1922 + UpdateState(aNotify); 1.1923 + 1.1924 + nsIDocument* ownerDoc = OwnerDoc(); 1.1925 + if (ownerDoc && GetCustomElementData()) { 1.1926 + nsCOMPtr<nsIAtom> oldValueAtom = aOldValue.GetAsAtom(); 1.1927 + nsCOMPtr<nsIAtom> newValueAtom = aValueForAfterSetAttr.GetAsAtom(); 1.1928 + LifecycleCallbackArgs args = { 1.1929 + nsDependentAtomString(aName), 1.1930 + aModType == nsIDOMMutationEvent::ADDITION ? 1.1931 + NullString() : nsDependentAtomString(oldValueAtom), 1.1932 + nsDependentAtomString(newValueAtom) 1.1933 + }; 1.1934 + 1.1935 + ownerDoc->EnqueueLifecycleCallback(nsIDocument::eAttributeChanged, this, &args); 1.1936 + } 1.1937 + 1.1938 + if (aCallAfterSetAttr) { 1.1939 + rv = AfterSetAttr(aNamespaceID, aName, &aValueForAfterSetAttr, aNotify); 1.1940 + NS_ENSURE_SUCCESS(rv, rv); 1.1941 + 1.1942 + if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::dir) { 1.1943 + OnSetDirAttr(this, &aValueForAfterSetAttr, 1.1944 + hadValidDir, hadDirAuto, aNotify); 1.1945 + } 1.1946 + } 1.1947 + 1.1948 + if (aNotify) { 1.1949 + nsNodeUtils::AttributeChanged(this, aNamespaceID, aName, aModType); 1.1950 + } 1.1951 + 1.1952 + if (aFireMutation) { 1.1953 + InternalMutationEvent mutation(true, NS_MUTATION_ATTRMODIFIED); 1.1954 + 1.1955 + nsAutoString ns; 1.1956 + nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNamespaceID, ns); 1.1957 + Attr* attrNode = 1.1958 + GetAttributeNodeNSInternal(ns, nsDependentAtomString(aName)); 1.1959 + mutation.mRelatedNode = attrNode; 1.1960 + 1.1961 + mutation.mAttrName = aName; 1.1962 + nsAutoString newValue; 1.1963 + GetAttr(aNamespaceID, aName, newValue); 1.1964 + if (!newValue.IsEmpty()) { 1.1965 + mutation.mNewAttrValue = do_GetAtom(newValue); 1.1966 + } 1.1967 + if (!aOldValue.IsEmptyString()) { 1.1968 + mutation.mPrevAttrValue = aOldValue.GetAsAtom(); 1.1969 + } 1.1970 + mutation.mAttrChange = aModType; 1.1971 + 1.1972 + mozAutoSubtreeModified subtree(OwnerDoc(), this); 1.1973 + (new AsyncEventDispatcher(this, mutation))->RunDOMEventWhenSafe(); 1.1974 + } 1.1975 + 1.1976 + return NS_OK; 1.1977 +} 1.1978 + 1.1979 +bool 1.1980 +Element::ParseAttribute(int32_t aNamespaceID, 1.1981 + nsIAtom* aAttribute, 1.1982 + const nsAString& aValue, 1.1983 + nsAttrValue& aResult) 1.1984 +{ 1.1985 + return false; 1.1986 +} 1.1987 + 1.1988 +bool 1.1989 +Element::SetMappedAttribute(nsIDocument* aDocument, 1.1990 + nsIAtom* aName, 1.1991 + nsAttrValue& aValue, 1.1992 + nsresult* aRetval) 1.1993 +{ 1.1994 + *aRetval = NS_OK; 1.1995 + return false; 1.1996 +} 1.1997 + 1.1998 +EventListenerManager* 1.1999 +Element::GetEventListenerManagerForAttr(nsIAtom* aAttrName, 1.2000 + bool* aDefer) 1.2001 +{ 1.2002 + *aDefer = true; 1.2003 + return GetOrCreateListenerManager(); 1.2004 +} 1.2005 + 1.2006 +Element::nsAttrInfo 1.2007 +Element::GetAttrInfo(int32_t aNamespaceID, nsIAtom* aName) const 1.2008 +{ 1.2009 + NS_ASSERTION(nullptr != aName, "must have attribute name"); 1.2010 + NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown, 1.2011 + "must have a real namespace ID!"); 1.2012 + 1.2013 + int32_t index = mAttrsAndChildren.IndexOfAttr(aName, aNamespaceID); 1.2014 + if (index >= 0) { 1.2015 + return nsAttrInfo(mAttrsAndChildren.AttrNameAt(index), 1.2016 + mAttrsAndChildren.AttrAt(index)); 1.2017 + } 1.2018 + 1.2019 + return nsAttrInfo(nullptr, nullptr); 1.2020 +} 1.2021 + 1.2022 + 1.2023 +bool 1.2024 +Element::GetAttr(int32_t aNameSpaceID, nsIAtom* aName, 1.2025 + nsAString& aResult) const 1.2026 +{ 1.2027 + DOMString str; 1.2028 + bool haveAttr = GetAttr(aNameSpaceID, aName, str); 1.2029 + str.ToString(aResult); 1.2030 + return haveAttr; 1.2031 +} 1.2032 + 1.2033 +int32_t 1.2034 +Element::FindAttrValueIn(int32_t aNameSpaceID, 1.2035 + nsIAtom* aName, 1.2036 + AttrValuesArray* aValues, 1.2037 + nsCaseTreatment aCaseSensitive) const 1.2038 +{ 1.2039 + NS_ASSERTION(aName, "Must have attr name"); 1.2040 + NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace"); 1.2041 + NS_ASSERTION(aValues, "Null value array"); 1.2042 + 1.2043 + const nsAttrValue* val = mAttrsAndChildren.GetAttr(aName, aNameSpaceID); 1.2044 + if (val) { 1.2045 + for (int32_t i = 0; aValues[i]; ++i) { 1.2046 + if (val->Equals(*aValues[i], aCaseSensitive)) { 1.2047 + return i; 1.2048 + } 1.2049 + } 1.2050 + return ATTR_VALUE_NO_MATCH; 1.2051 + } 1.2052 + return ATTR_MISSING; 1.2053 +} 1.2054 + 1.2055 +nsresult 1.2056 +Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName, 1.2057 + bool aNotify) 1.2058 +{ 1.2059 + NS_ASSERTION(nullptr != aName, "must have attribute name"); 1.2060 + 1.2061 + int32_t index = mAttrsAndChildren.IndexOfAttr(aName, aNameSpaceID); 1.2062 + if (index < 0) { 1.2063 + return NS_OK; 1.2064 + } 1.2065 + 1.2066 + nsresult rv = BeforeSetAttr(aNameSpaceID, aName, nullptr, aNotify); 1.2067 + NS_ENSURE_SUCCESS(rv, rv); 1.2068 + 1.2069 + nsIDocument *document = GetCurrentDoc(); 1.2070 + mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify); 1.2071 + 1.2072 + if (aNotify) { 1.2073 + nsNodeUtils::AttributeWillChange(this, aNameSpaceID, aName, 1.2074 + nsIDOMMutationEvent::REMOVAL); 1.2075 + } 1.2076 + 1.2077 + bool hasMutationListeners = aNotify && 1.2078 + nsContentUtils::HasMutationListeners(this, 1.2079 + NS_EVENT_BITS_MUTATION_ATTRMODIFIED, 1.2080 + this); 1.2081 + 1.2082 + // Grab the attr node if needed before we remove it from the attr map 1.2083 + nsRefPtr<Attr> attrNode; 1.2084 + if (hasMutationListeners) { 1.2085 + nsAutoString ns; 1.2086 + nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNameSpaceID, ns); 1.2087 + attrNode = GetAttributeNodeNSInternal(ns, nsDependentAtomString(aName)); 1.2088 + } 1.2089 + 1.2090 + // Clear binding to nsIDOMMozNamedAttrMap 1.2091 + nsDOMSlots *slots = GetExistingDOMSlots(); 1.2092 + if (slots && slots->mAttributeMap) { 1.2093 + slots->mAttributeMap->DropAttribute(aNameSpaceID, aName); 1.2094 + } 1.2095 + 1.2096 + // The id-handling code, and in the future possibly other code, need to 1.2097 + // react to unexpected attribute changes. 1.2098 + nsMutationGuard::DidMutate(); 1.2099 + 1.2100 + bool hadValidDir = false; 1.2101 + bool hadDirAuto = false; 1.2102 + 1.2103 + if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::dir) { 1.2104 + hadValidDir = HasValidDir() || IsHTML(nsGkAtoms::bdi); 1.2105 + hadDirAuto = HasDirAuto(); // already takes bdi into account 1.2106 + } 1.2107 + 1.2108 + nsAttrValue oldValue; 1.2109 + rv = mAttrsAndChildren.RemoveAttrAt(index, oldValue); 1.2110 + NS_ENSURE_SUCCESS(rv, rv); 1.2111 + 1.2112 + if (document || HasFlag(NODE_FORCE_XBL_BINDINGS)) { 1.2113 + nsRefPtr<nsXBLBinding> binding = GetXBLBinding(); 1.2114 + if (binding) { 1.2115 + binding->AttributeChanged(aName, aNameSpaceID, true, aNotify); 1.2116 + } 1.2117 + } 1.2118 + 1.2119 + UpdateState(aNotify); 1.2120 + 1.2121 + nsIDocument* ownerDoc = OwnerDoc(); 1.2122 + if (ownerDoc && GetCustomElementData()) { 1.2123 + nsCOMPtr<nsIAtom> oldValueAtom = oldValue.GetAsAtom(); 1.2124 + LifecycleCallbackArgs args = { 1.2125 + nsDependentAtomString(aName), 1.2126 + nsDependentAtomString(oldValueAtom), 1.2127 + NullString() 1.2128 + }; 1.2129 + 1.2130 + ownerDoc->EnqueueLifecycleCallback(nsIDocument::eAttributeChanged, this, &args); 1.2131 + } 1.2132 + 1.2133 + if (aNotify) { 1.2134 + nsNodeUtils::AttributeChanged(this, aNameSpaceID, aName, 1.2135 + nsIDOMMutationEvent::REMOVAL); 1.2136 + } 1.2137 + 1.2138 + rv = AfterSetAttr(aNameSpaceID, aName, nullptr, aNotify); 1.2139 + NS_ENSURE_SUCCESS(rv, rv); 1.2140 + 1.2141 + if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::dir) { 1.2142 + OnSetDirAttr(this, nullptr, hadValidDir, hadDirAuto, aNotify); 1.2143 + } 1.2144 + 1.2145 + if (hasMutationListeners) { 1.2146 + InternalMutationEvent mutation(true, NS_MUTATION_ATTRMODIFIED); 1.2147 + 1.2148 + mutation.mRelatedNode = attrNode; 1.2149 + mutation.mAttrName = aName; 1.2150 + 1.2151 + nsAutoString value; 1.2152 + oldValue.ToString(value); 1.2153 + if (!value.IsEmpty()) 1.2154 + mutation.mPrevAttrValue = do_GetAtom(value); 1.2155 + mutation.mAttrChange = nsIDOMMutationEvent::REMOVAL; 1.2156 + 1.2157 + mozAutoSubtreeModified subtree(OwnerDoc(), this); 1.2158 + (new AsyncEventDispatcher(this, mutation))->RunDOMEventWhenSafe(); 1.2159 + } 1.2160 + 1.2161 + return NS_OK; 1.2162 +} 1.2163 + 1.2164 +const nsAttrName* 1.2165 +Element::GetAttrNameAt(uint32_t aIndex) const 1.2166 +{ 1.2167 + return mAttrsAndChildren.GetSafeAttrNameAt(aIndex); 1.2168 +} 1.2169 + 1.2170 +uint32_t 1.2171 +Element::GetAttrCount() const 1.2172 +{ 1.2173 + return mAttrsAndChildren.AttrCount(); 1.2174 +} 1.2175 + 1.2176 +void 1.2177 +Element::DescribeAttribute(uint32_t index, nsAString& aOutDescription) const 1.2178 +{ 1.2179 + // name 1.2180 + mAttrsAndChildren.AttrNameAt(index)->GetQualifiedName(aOutDescription); 1.2181 + 1.2182 + // value 1.2183 + aOutDescription.AppendLiteral("=\""); 1.2184 + nsAutoString value; 1.2185 + mAttrsAndChildren.AttrAt(index)->ToString(value); 1.2186 + for (int i = value.Length(); i >= 0; --i) { 1.2187 + if (value[i] == char16_t('"')) 1.2188 + value.Insert(char16_t('\\'), uint32_t(i)); 1.2189 + } 1.2190 + aOutDescription.Append(value); 1.2191 + aOutDescription.AppendLiteral("\""); 1.2192 +} 1.2193 + 1.2194 +#ifdef DEBUG 1.2195 +void 1.2196 +Element::ListAttributes(FILE* out) const 1.2197 +{ 1.2198 + uint32_t index, count = mAttrsAndChildren.AttrCount(); 1.2199 + for (index = 0; index < count; index++) { 1.2200 + nsAutoString attributeDescription; 1.2201 + DescribeAttribute(index, attributeDescription); 1.2202 + 1.2203 + fputs(" ", out); 1.2204 + fputs(NS_LossyConvertUTF16toASCII(attributeDescription).get(), out); 1.2205 + } 1.2206 +} 1.2207 + 1.2208 +void 1.2209 +Element::List(FILE* out, int32_t aIndent, 1.2210 + const nsCString& aPrefix) const 1.2211 +{ 1.2212 + int32_t indent; 1.2213 + for (indent = aIndent; --indent >= 0; ) fputs(" ", out); 1.2214 + 1.2215 + fputs(aPrefix.get(), out); 1.2216 + 1.2217 + fputs(NS_LossyConvertUTF16toASCII(mNodeInfo->QualifiedName()).get(), out); 1.2218 + 1.2219 + fprintf(out, "@%p", (void *)this); 1.2220 + 1.2221 + ListAttributes(out); 1.2222 + 1.2223 + fprintf(out, " state=[%llx]", 1.2224 + static_cast<unsigned long long>(State().GetInternalValue())); 1.2225 + fprintf(out, " flags=[%08x]", static_cast<unsigned int>(GetFlags())); 1.2226 + if (IsCommonAncestorForRangeInSelection()) { 1.2227 + nsRange::RangeHashTable* ranges = 1.2228 + static_cast<nsRange::RangeHashTable*>(GetProperty(nsGkAtoms::range)); 1.2229 + fprintf(out, " ranges:%d", ranges ? ranges->Count() : 0); 1.2230 + } 1.2231 + fprintf(out, " primaryframe=%p", static_cast<void*>(GetPrimaryFrame())); 1.2232 + fprintf(out, " refcount=%" PRIuPTR "<", mRefCnt.get()); 1.2233 + 1.2234 + nsIContent* child = GetFirstChild(); 1.2235 + if (child) { 1.2236 + fputs("\n", out); 1.2237 + 1.2238 + for (; child; child = child->GetNextSibling()) { 1.2239 + child->List(out, aIndent + 1); 1.2240 + } 1.2241 + 1.2242 + for (indent = aIndent; --indent >= 0; ) fputs(" ", out); 1.2243 + } 1.2244 + 1.2245 + fputs(">\n", out); 1.2246 + 1.2247 + Element* nonConstThis = const_cast<Element*>(this); 1.2248 + 1.2249 + // XXX sXBL/XBL2 issue! Owner or current document? 1.2250 + nsIDocument *document = OwnerDoc(); 1.2251 + 1.2252 + // Note: not listing nsIAnonymousContentCreator-created content... 1.2253 + 1.2254 + nsBindingManager* bindingManager = document->BindingManager(); 1.2255 + nsCOMPtr<nsIDOMNodeList> anonymousChildren; 1.2256 + bindingManager->GetAnonymousNodesFor(nonConstThis, 1.2257 + getter_AddRefs(anonymousChildren)); 1.2258 + 1.2259 + if (anonymousChildren) { 1.2260 + uint32_t length = 0; 1.2261 + anonymousChildren->GetLength(&length); 1.2262 + 1.2263 + for (indent = aIndent; --indent >= 0; ) fputs(" ", out); 1.2264 + fputs("anonymous-children<\n", out); 1.2265 + 1.2266 + for (uint32_t i = 0; i < length; ++i) { 1.2267 + nsCOMPtr<nsIDOMNode> node; 1.2268 + anonymousChildren->Item(i, getter_AddRefs(node)); 1.2269 + nsCOMPtr<nsIContent> child = do_QueryInterface(node); 1.2270 + child->List(out, aIndent + 1); 1.2271 + } 1.2272 + 1.2273 + for (indent = aIndent; --indent >= 0; ) fputs(" ", out); 1.2274 + fputs(">\n", out); 1.2275 + 1.2276 + bool outHeader = false; 1.2277 + ExplicitChildIterator iter(nonConstThis); 1.2278 + for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) { 1.2279 + if (!outHeader) { 1.2280 + outHeader = true; 1.2281 + 1.2282 + for (indent = aIndent; --indent >= 0; ) fputs(" ", out); 1.2283 + fputs("content-list<\n", out); 1.2284 + } 1.2285 + 1.2286 + child->List(out, aIndent + 1); 1.2287 + } 1.2288 + 1.2289 + if (outHeader) { 1.2290 + for (indent = aIndent; --indent >= 0; ) fputs(" ", out); 1.2291 + fputs(">\n", out); 1.2292 + } 1.2293 + } 1.2294 +} 1.2295 + 1.2296 +void 1.2297 +Element::DumpContent(FILE* out, int32_t aIndent, 1.2298 + bool aDumpAll) const 1.2299 +{ 1.2300 + int32_t indent; 1.2301 + for (indent = aIndent; --indent >= 0; ) fputs(" ", out); 1.2302 + 1.2303 + const nsString& buf = mNodeInfo->QualifiedName(); 1.2304 + fputs("<", out); 1.2305 + fputs(NS_LossyConvertUTF16toASCII(buf).get(), out); 1.2306 + 1.2307 + if(aDumpAll) ListAttributes(out); 1.2308 + 1.2309 + fputs(">", out); 1.2310 + 1.2311 + if(aIndent) fputs("\n", out); 1.2312 + 1.2313 + for (nsIContent* child = GetFirstChild(); 1.2314 + child; 1.2315 + child = child->GetNextSibling()) { 1.2316 + int32_t indent = aIndent ? aIndent + 1 : 0; 1.2317 + child->DumpContent(out, indent, aDumpAll); 1.2318 + } 1.2319 + for (indent = aIndent; --indent >= 0; ) fputs(" ", out); 1.2320 + fputs("</", out); 1.2321 + fputs(NS_LossyConvertUTF16toASCII(buf).get(), out); 1.2322 + fputs(">", out); 1.2323 + 1.2324 + if(aIndent) fputs("\n", out); 1.2325 +} 1.2326 +#endif 1.2327 + 1.2328 +void 1.2329 +Element::Describe(nsAString& aOutDescription) const 1.2330 +{ 1.2331 + aOutDescription.Append(mNodeInfo->QualifiedName()); 1.2332 + aOutDescription.AppendPrintf("@%p", (void *)this); 1.2333 + 1.2334 + uint32_t index, count = mAttrsAndChildren.AttrCount(); 1.2335 + for (index = 0; index < count; index++) { 1.2336 + aOutDescription.Append(' '); 1.2337 + nsAutoString attributeDescription; 1.2338 + DescribeAttribute(index, attributeDescription); 1.2339 + aOutDescription.Append(attributeDescription); 1.2340 + } 1.2341 +} 1.2342 + 1.2343 +bool 1.2344 +Element::CheckHandleEventForLinksPrecondition(EventChainVisitor& aVisitor, 1.2345 + nsIURI** aURI) const 1.2346 +{ 1.2347 + if (aVisitor.mEventStatus == nsEventStatus_eConsumeNoDefault || 1.2348 + (!aVisitor.mEvent->mFlags.mIsTrusted && 1.2349 + (aVisitor.mEvent->message != NS_MOUSE_CLICK) && 1.2350 + (aVisitor.mEvent->message != NS_KEY_PRESS) && 1.2351 + (aVisitor.mEvent->message != NS_UI_ACTIVATE)) || 1.2352 + !aVisitor.mPresContext || 1.2353 + aVisitor.mEvent->mFlags.mMultipleActionsPrevented) { 1.2354 + return false; 1.2355 + } 1.2356 + 1.2357 + // Make sure we actually are a link 1.2358 + return IsLink(aURI); 1.2359 +} 1.2360 + 1.2361 +nsresult 1.2362 +Element::PreHandleEventForLinks(EventChainPreVisitor& aVisitor) 1.2363 +{ 1.2364 + // Optimisation: return early if this event doesn't interest us. 1.2365 + // IMPORTANT: this switch and the switch below it must be kept in sync! 1.2366 + switch (aVisitor.mEvent->message) { 1.2367 + case NS_MOUSE_ENTER_SYNTH: 1.2368 + case NS_FOCUS_CONTENT: 1.2369 + case NS_MOUSE_EXIT_SYNTH: 1.2370 + case NS_BLUR_CONTENT: 1.2371 + break; 1.2372 + default: 1.2373 + return NS_OK; 1.2374 + } 1.2375 + 1.2376 + // Make sure we meet the preconditions before continuing 1.2377 + nsCOMPtr<nsIURI> absURI; 1.2378 + if (!CheckHandleEventForLinksPrecondition(aVisitor, getter_AddRefs(absURI))) { 1.2379 + return NS_OK; 1.2380 + } 1.2381 + 1.2382 + nsresult rv = NS_OK; 1.2383 + 1.2384 + // We do the status bar updates in PreHandleEvent so that the status bar gets 1.2385 + // updated even if the event is consumed before we have a chance to set it. 1.2386 + switch (aVisitor.mEvent->message) { 1.2387 + // Set the status bar similarly for mouseover and focus 1.2388 + case NS_MOUSE_ENTER_SYNTH: 1.2389 + aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault; 1.2390 + // FALL THROUGH 1.2391 + case NS_FOCUS_CONTENT: { 1.2392 + InternalFocusEvent* focusEvent = aVisitor.mEvent->AsFocusEvent(); 1.2393 + if (!focusEvent || !focusEvent->isRefocus) { 1.2394 + nsAutoString target; 1.2395 + GetLinkTarget(target); 1.2396 + nsContentUtils::TriggerLink(this, aVisitor.mPresContext, absURI, target, 1.2397 + false, true, true); 1.2398 + // Make sure any ancestor links don't also TriggerLink 1.2399 + aVisitor.mEvent->mFlags.mMultipleActionsPrevented = true; 1.2400 + } 1.2401 + break; 1.2402 + } 1.2403 + case NS_MOUSE_EXIT_SYNTH: 1.2404 + aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault; 1.2405 + // FALL THROUGH 1.2406 + case NS_BLUR_CONTENT: 1.2407 + rv = LeaveLink(aVisitor.mPresContext); 1.2408 + if (NS_SUCCEEDED(rv)) { 1.2409 + aVisitor.mEvent->mFlags.mMultipleActionsPrevented = true; 1.2410 + } 1.2411 + break; 1.2412 + 1.2413 + default: 1.2414 + // switch not in sync with the optimization switch earlier in this function 1.2415 + NS_NOTREACHED("switch statements not in sync"); 1.2416 + return NS_ERROR_UNEXPECTED; 1.2417 + } 1.2418 + 1.2419 + return rv; 1.2420 +} 1.2421 + 1.2422 +nsresult 1.2423 +Element::PostHandleEventForLinks(EventChainPostVisitor& aVisitor) 1.2424 +{ 1.2425 + // Optimisation: return early if this event doesn't interest us. 1.2426 + // IMPORTANT: this switch and the switch below it must be kept in sync! 1.2427 + switch (aVisitor.mEvent->message) { 1.2428 + case NS_MOUSE_BUTTON_DOWN: 1.2429 + case NS_MOUSE_CLICK: 1.2430 + case NS_UI_ACTIVATE: 1.2431 + case NS_KEY_PRESS: 1.2432 + break; 1.2433 + default: 1.2434 + return NS_OK; 1.2435 + } 1.2436 + 1.2437 + // Make sure we meet the preconditions before continuing 1.2438 + nsCOMPtr<nsIURI> absURI; 1.2439 + if (!CheckHandleEventForLinksPrecondition(aVisitor, getter_AddRefs(absURI))) { 1.2440 + return NS_OK; 1.2441 + } 1.2442 + 1.2443 + nsresult rv = NS_OK; 1.2444 + 1.2445 + switch (aVisitor.mEvent->message) { 1.2446 + case NS_MOUSE_BUTTON_DOWN: 1.2447 + { 1.2448 + if (aVisitor.mEvent->AsMouseEvent()->button == 1.2449 + WidgetMouseEvent::eLeftButton) { 1.2450 + // don't make the link grab the focus if there is no link handler 1.2451 + nsILinkHandler *handler = aVisitor.mPresContext->GetLinkHandler(); 1.2452 + nsIDocument *document = GetCurrentDoc(); 1.2453 + if (handler && document) { 1.2454 + nsIFocusManager* fm = nsFocusManager::GetFocusManager(); 1.2455 + if (fm) { 1.2456 + aVisitor.mEvent->mFlags.mMultipleActionsPrevented = true; 1.2457 + nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(this); 1.2458 + fm->SetFocus(elem, nsIFocusManager::FLAG_BYMOUSE | 1.2459 + nsIFocusManager::FLAG_NOSCROLL); 1.2460 + } 1.2461 + 1.2462 + EventStateManager::SetActiveManager( 1.2463 + aVisitor.mPresContext->EventStateManager(), this); 1.2464 + } 1.2465 + } 1.2466 + } 1.2467 + break; 1.2468 + 1.2469 + case NS_MOUSE_CLICK: { 1.2470 + WidgetMouseEvent* mouseEvent = aVisitor.mEvent->AsMouseEvent(); 1.2471 + if (mouseEvent->IsLeftClickEvent()) { 1.2472 + if (mouseEvent->IsControl() || mouseEvent->IsMeta() || 1.2473 + mouseEvent->IsAlt() ||mouseEvent->IsShift()) { 1.2474 + break; 1.2475 + } 1.2476 + 1.2477 + // The default action is simply to dispatch DOMActivate 1.2478 + nsCOMPtr<nsIPresShell> shell = aVisitor.mPresContext->GetPresShell(); 1.2479 + if (shell) { 1.2480 + // single-click 1.2481 + nsEventStatus status = nsEventStatus_eIgnore; 1.2482 + InternalUIEvent actEvent(mouseEvent->mFlags.mIsTrusted, NS_UI_ACTIVATE); 1.2483 + actEvent.detail = 1; 1.2484 + 1.2485 + rv = shell->HandleDOMEventWithTarget(this, &actEvent, &status); 1.2486 + if (NS_SUCCEEDED(rv)) { 1.2487 + aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault; 1.2488 + } 1.2489 + } 1.2490 + } 1.2491 + break; 1.2492 + } 1.2493 + case NS_UI_ACTIVATE: 1.2494 + { 1.2495 + if (aVisitor.mEvent->originalTarget == this) { 1.2496 + nsAutoString target; 1.2497 + GetLinkTarget(target); 1.2498 + nsContentUtils::TriggerLink(this, aVisitor.mPresContext, absURI, target, 1.2499 + true, true, 1.2500 + aVisitor.mEvent->mFlags.mIsTrusted); 1.2501 + aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault; 1.2502 + } 1.2503 + } 1.2504 + break; 1.2505 + 1.2506 + case NS_KEY_PRESS: 1.2507 + { 1.2508 + WidgetKeyboardEvent* keyEvent = aVisitor.mEvent->AsKeyboardEvent(); 1.2509 + if (keyEvent && keyEvent->keyCode == NS_VK_RETURN) { 1.2510 + nsEventStatus status = nsEventStatus_eIgnore; 1.2511 + rv = DispatchClickEvent(aVisitor.mPresContext, keyEvent, this, 1.2512 + false, nullptr, &status); 1.2513 + if (NS_SUCCEEDED(rv)) { 1.2514 + aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault; 1.2515 + } 1.2516 + } 1.2517 + } 1.2518 + break; 1.2519 + 1.2520 + default: 1.2521 + // switch not in sync with the optimization switch earlier in this function 1.2522 + NS_NOTREACHED("switch statements not in sync"); 1.2523 + return NS_ERROR_UNEXPECTED; 1.2524 + } 1.2525 + 1.2526 + return rv; 1.2527 +} 1.2528 + 1.2529 +void 1.2530 +Element::GetLinkTarget(nsAString& aTarget) 1.2531 +{ 1.2532 + aTarget.Truncate(); 1.2533 +} 1.2534 + 1.2535 +bool 1.2536 +Element::MozMatchesSelector(const nsAString& aSelector, 1.2537 + ErrorResult& aError) 1.2538 +{ 1.2539 + nsCSSSelectorList* selectorList = ParseSelectorList(aSelector, aError); 1.2540 + if (!selectorList) { 1.2541 + // Either we failed (and aError already has the exception), or this 1.2542 + // is a pseudo-element-only selector that matches nothing. 1.2543 + return false; 1.2544 + } 1.2545 + 1.2546 + OwnerDoc()->FlushPendingLinkUpdates(); 1.2547 + TreeMatchContext matchingContext(false, 1.2548 + nsRuleWalker::eRelevantLinkUnvisited, 1.2549 + OwnerDoc(), 1.2550 + TreeMatchContext::eNeverMatchVisited); 1.2551 + matchingContext.SetHasSpecifiedScope(); 1.2552 + matchingContext.AddScopeElement(this); 1.2553 + return nsCSSRuleProcessor::SelectorListMatches(this, matchingContext, 1.2554 + selectorList); 1.2555 +} 1.2556 + 1.2557 +static const nsAttrValue::EnumTable kCORSAttributeTable[] = { 1.2558 + // Order matters here 1.2559 + // See ParseCORSValue 1.2560 + { "anonymous", CORS_ANONYMOUS }, 1.2561 + { "use-credentials", CORS_USE_CREDENTIALS }, 1.2562 + { 0 } 1.2563 +}; 1.2564 + 1.2565 +/* static */ void 1.2566 +Element::ParseCORSValue(const nsAString& aValue, 1.2567 + nsAttrValue& aResult) 1.2568 +{ 1.2569 + DebugOnly<bool> success = 1.2570 + aResult.ParseEnumValue(aValue, kCORSAttributeTable, false, 1.2571 + // default value is anonymous if aValue is 1.2572 + // not a value we understand 1.2573 + &kCORSAttributeTable[0]); 1.2574 + MOZ_ASSERT(success); 1.2575 +} 1.2576 + 1.2577 +/* static */ CORSMode 1.2578 +Element::StringToCORSMode(const nsAString& aValue) 1.2579 +{ 1.2580 + if (aValue.IsVoid()) { 1.2581 + return CORS_NONE; 1.2582 + } 1.2583 + 1.2584 + nsAttrValue val; 1.2585 + Element::ParseCORSValue(aValue, val); 1.2586 + return CORSMode(val.GetEnumValue()); 1.2587 +} 1.2588 + 1.2589 +/* static */ CORSMode 1.2590 +Element::AttrValueToCORSMode(const nsAttrValue* aValue) 1.2591 +{ 1.2592 + if (!aValue) { 1.2593 + return CORS_NONE; 1.2594 + } 1.2595 + 1.2596 + return CORSMode(aValue->GetEnumValue()); 1.2597 +} 1.2598 + 1.2599 +static const char* 1.2600 +GetFullScreenError(nsIDocument* aDoc) 1.2601 +{ 1.2602 + // Block fullscreen requests in the chrome document when the fullscreen API 1.2603 + // is configured for content only. 1.2604 + if (nsContentUtils::IsFullscreenApiContentOnly() && 1.2605 + nsContentUtils::IsChromeDoc(aDoc)) { 1.2606 + return "FullScreenDeniedContentOnly"; 1.2607 + } 1.2608 + 1.2609 + nsCOMPtr<nsPIDOMWindow> win = aDoc->GetWindow(); 1.2610 + if (aDoc->NodePrincipal()->GetAppStatus() >= nsIPrincipal::APP_STATUS_INSTALLED) { 1.2611 + // Request is in a web app and in the same origin as the web app. 1.2612 + // Don't enforce as strict security checks for web apps, the user 1.2613 + // is supposed to have trust in them. However documents cross-origin 1.2614 + // to the web app must still confirm to the normal security checks. 1.2615 + return nullptr; 1.2616 + } 1.2617 + 1.2618 + if (!nsContentUtils::IsRequestFullScreenAllowed()) { 1.2619 + return "FullScreenDeniedNotInputDriven"; 1.2620 + } 1.2621 + 1.2622 + if (nsContentUtils::IsSitePermDeny(aDoc->NodePrincipal(), "fullscreen")) { 1.2623 + return "FullScreenDeniedBlocked"; 1.2624 + } 1.2625 + 1.2626 + return nullptr; 1.2627 +} 1.2628 + 1.2629 +void 1.2630 +Element::MozRequestFullScreen() 1.2631 +{ 1.2632 + // Only grant full-screen requests if this is called from inside a trusted 1.2633 + // event handler (i.e. inside an event handler for a user initiated event). 1.2634 + // This stops the full-screen from being abused similar to the popups of old, 1.2635 + // and it also makes it harder for bad guys' script to go full-screen and 1.2636 + // spoof the browser chrome/window and phish logins etc. 1.2637 + // Note that requests for fullscreen inside a web app's origin are exempt 1.2638 + // from this restriction. 1.2639 + const char* error = GetFullScreenError(OwnerDoc()); 1.2640 + if (error) { 1.2641 + nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, 1.2642 + NS_LITERAL_CSTRING("DOM"), OwnerDoc(), 1.2643 + nsContentUtils::eDOM_PROPERTIES, 1.2644 + error); 1.2645 + nsRefPtr<AsyncEventDispatcher> asyncDispatcher = 1.2646 + new AsyncEventDispatcher(OwnerDoc(), 1.2647 + NS_LITERAL_STRING("mozfullscreenerror"), 1.2648 + true, 1.2649 + false); 1.2650 + asyncDispatcher->PostDOMEvent(); 1.2651 + return; 1.2652 + } 1.2653 + 1.2654 + OwnerDoc()->AsyncRequestFullScreen(this); 1.2655 + 1.2656 + return; 1.2657 +} 1.2658 + 1.2659 +void 1.2660 +Element::MozRequestPointerLock() 1.2661 +{ 1.2662 + OwnerDoc()->RequestPointerLock(this); 1.2663 +} 1.2664 + 1.2665 +NS_IMETHODIMP 1.2666 +Element::GetInnerHTML(nsAString& aInnerHTML) 1.2667 +{ 1.2668 + GetMarkup(false, aInnerHTML); 1.2669 + return NS_OK; 1.2670 +} 1.2671 + 1.2672 +void 1.2673 +Element::SetInnerHTML(const nsAString& aInnerHTML, ErrorResult& aError) 1.2674 +{ 1.2675 + SetInnerHTMLInternal(aInnerHTML, aError); 1.2676 +} 1.2677 + 1.2678 +void 1.2679 +Element::GetOuterHTML(nsAString& aOuterHTML) 1.2680 +{ 1.2681 + GetMarkup(true, aOuterHTML); 1.2682 +} 1.2683 + 1.2684 +void 1.2685 +Element::SetOuterHTML(const nsAString& aOuterHTML, ErrorResult& aError) 1.2686 +{ 1.2687 + nsCOMPtr<nsINode> parent = GetParentNode(); 1.2688 + if (!parent) { 1.2689 + return; 1.2690 + } 1.2691 + 1.2692 + if (parent->NodeType() == nsIDOMNode::DOCUMENT_NODE) { 1.2693 + aError.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); 1.2694 + return; 1.2695 + } 1.2696 + 1.2697 + if (OwnerDoc()->IsHTML()) { 1.2698 + nsIAtom* localName; 1.2699 + int32_t namespaceID; 1.2700 + if (parent->IsElement()) { 1.2701 + localName = static_cast<nsIContent*>(parent.get())->Tag(); 1.2702 + namespaceID = static_cast<nsIContent*>(parent.get())->GetNameSpaceID(); 1.2703 + } else { 1.2704 + NS_ASSERTION(parent->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE, 1.2705 + "How come the parent isn't a document, a fragment or an element?"); 1.2706 + localName = nsGkAtoms::body; 1.2707 + namespaceID = kNameSpaceID_XHTML; 1.2708 + } 1.2709 + nsRefPtr<DocumentFragment> fragment = 1.2710 + new DocumentFragment(OwnerDoc()->NodeInfoManager()); 1.2711 + nsContentUtils::ParseFragmentHTML(aOuterHTML, 1.2712 + fragment, 1.2713 + localName, 1.2714 + namespaceID, 1.2715 + OwnerDoc()->GetCompatibilityMode() == 1.2716 + eCompatibility_NavQuirks, 1.2717 + true); 1.2718 + parent->ReplaceChild(*fragment, *this, aError); 1.2719 + return; 1.2720 + } 1.2721 + 1.2722 + nsCOMPtr<nsINode> context; 1.2723 + if (parent->IsElement()) { 1.2724 + context = parent; 1.2725 + } else { 1.2726 + NS_ASSERTION(parent->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE, 1.2727 + "How come the parent isn't a document, a fragment or an element?"); 1.2728 + nsCOMPtr<nsINodeInfo> info = 1.2729 + OwnerDoc()->NodeInfoManager()->GetNodeInfo(nsGkAtoms::body, 1.2730 + nullptr, 1.2731 + kNameSpaceID_XHTML, 1.2732 + nsIDOMNode::ELEMENT_NODE); 1.2733 + context = NS_NewHTMLBodyElement(info.forget(), FROM_PARSER_FRAGMENT); 1.2734 + } 1.2735 + 1.2736 + nsCOMPtr<nsIDOMDocumentFragment> df; 1.2737 + aError = nsContentUtils::CreateContextualFragment(context, 1.2738 + aOuterHTML, 1.2739 + true, 1.2740 + getter_AddRefs(df)); 1.2741 + if (aError.Failed()) { 1.2742 + return; 1.2743 + } 1.2744 + nsCOMPtr<nsINode> fragment = do_QueryInterface(df); 1.2745 + parent->ReplaceChild(*fragment, *this, aError); 1.2746 +} 1.2747 + 1.2748 +enum nsAdjacentPosition { 1.2749 + eBeforeBegin, 1.2750 + eAfterBegin, 1.2751 + eBeforeEnd, 1.2752 + eAfterEnd 1.2753 +}; 1.2754 + 1.2755 +void 1.2756 +Element::InsertAdjacentHTML(const nsAString& aPosition, const nsAString& aText, 1.2757 + ErrorResult& aError) 1.2758 +{ 1.2759 + nsAdjacentPosition position; 1.2760 + if (aPosition.LowerCaseEqualsLiteral("beforebegin")) { 1.2761 + position = eBeforeBegin; 1.2762 + } else if (aPosition.LowerCaseEqualsLiteral("afterbegin")) { 1.2763 + position = eAfterBegin; 1.2764 + } else if (aPosition.LowerCaseEqualsLiteral("beforeend")) { 1.2765 + position = eBeforeEnd; 1.2766 + } else if (aPosition.LowerCaseEqualsLiteral("afterend")) { 1.2767 + position = eAfterEnd; 1.2768 + } else { 1.2769 + aError.Throw(NS_ERROR_DOM_SYNTAX_ERR); 1.2770 + return; 1.2771 + } 1.2772 + 1.2773 + nsCOMPtr<nsIContent> destination; 1.2774 + if (position == eBeforeBegin || position == eAfterEnd) { 1.2775 + destination = GetParent(); 1.2776 + if (!destination) { 1.2777 + aError.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); 1.2778 + return; 1.2779 + } 1.2780 + } else { 1.2781 + destination = this; 1.2782 + } 1.2783 + 1.2784 + nsIDocument* doc = OwnerDoc(); 1.2785 + 1.2786 + // Needed when insertAdjacentHTML is used in combination with contenteditable 1.2787 + mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, true); 1.2788 + nsAutoScriptLoaderDisabler sld(doc); 1.2789 + 1.2790 + // Batch possible DOMSubtreeModified events. 1.2791 + mozAutoSubtreeModified subtree(doc, nullptr); 1.2792 + 1.2793 + // Parse directly into destination if possible 1.2794 + if (doc->IsHTML() && !OwnerDoc()->MayHaveDOMMutationObservers() && 1.2795 + (position == eBeforeEnd || 1.2796 + (position == eAfterEnd && !GetNextSibling()) || 1.2797 + (position == eAfterBegin && !GetFirstChild()))) { 1.2798 + int32_t oldChildCount = destination->GetChildCount(); 1.2799 + int32_t contextNs = destination->GetNameSpaceID(); 1.2800 + nsIAtom* contextLocal = destination->Tag(); 1.2801 + if (contextLocal == nsGkAtoms::html && contextNs == kNameSpaceID_XHTML) { 1.2802 + // For compat with IE6 through IE9. Willful violation of HTML5 as of 1.2803 + // 2011-04-06. CreateContextualFragment does the same already. 1.2804 + // Spec bug: http://www.w3.org/Bugs/Public/show_bug.cgi?id=12434 1.2805 + contextLocal = nsGkAtoms::body; 1.2806 + } 1.2807 + aError = nsContentUtils::ParseFragmentHTML(aText, 1.2808 + destination, 1.2809 + contextLocal, 1.2810 + contextNs, 1.2811 + doc->GetCompatibilityMode() == 1.2812 + eCompatibility_NavQuirks, 1.2813 + true); 1.2814 + // HTML5 parser has notified, but not fired mutation events. 1.2815 + nsContentUtils::FireMutationEventsForDirectParsing(doc, destination, 1.2816 + oldChildCount); 1.2817 + return; 1.2818 + } 1.2819 + 1.2820 + // couldn't parse directly 1.2821 + nsCOMPtr<nsIDOMDocumentFragment> df; 1.2822 + aError = nsContentUtils::CreateContextualFragment(destination, 1.2823 + aText, 1.2824 + true, 1.2825 + getter_AddRefs(df)); 1.2826 + if (aError.Failed()) { 1.2827 + return; 1.2828 + } 1.2829 + 1.2830 + nsCOMPtr<nsINode> fragment = do_QueryInterface(df); 1.2831 + 1.2832 + // Suppress assertion about node removal mutation events that can't have 1.2833 + // listeners anyway, because no one has had the chance to register mutation 1.2834 + // listeners on the fragment that comes from the parser. 1.2835 + nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker; 1.2836 + 1.2837 + nsAutoMutationBatch mb(destination, true, false); 1.2838 + switch (position) { 1.2839 + case eBeforeBegin: 1.2840 + destination->InsertBefore(*fragment, this, aError); 1.2841 + break; 1.2842 + case eAfterBegin: 1.2843 + static_cast<nsINode*>(this)->InsertBefore(*fragment, GetFirstChild(), 1.2844 + aError); 1.2845 + break; 1.2846 + case eBeforeEnd: 1.2847 + static_cast<nsINode*>(this)->AppendChild(*fragment, aError); 1.2848 + break; 1.2849 + case eAfterEnd: 1.2850 + destination->InsertBefore(*fragment, GetNextSibling(), aError); 1.2851 + break; 1.2852 + } 1.2853 +} 1.2854 + 1.2855 +nsIEditor* 1.2856 +Element::GetEditorInternal() 1.2857 +{ 1.2858 + nsCOMPtr<nsITextControlElement> textCtrl = do_QueryInterface(this); 1.2859 + return textCtrl ? textCtrl->GetTextEditor() : nullptr; 1.2860 +} 1.2861 + 1.2862 +nsresult 1.2863 +Element::SetBoolAttr(nsIAtom* aAttr, bool aValue) 1.2864 +{ 1.2865 + if (aValue) { 1.2866 + return SetAttr(kNameSpaceID_None, aAttr, EmptyString(), true); 1.2867 + } 1.2868 + 1.2869 + return UnsetAttr(kNameSpaceID_None, aAttr, true); 1.2870 +} 1.2871 + 1.2872 +Directionality 1.2873 +Element::GetComputedDirectionality() const 1.2874 +{ 1.2875 + nsIFrame* frame = GetPrimaryFrame(); 1.2876 + if (frame) { 1.2877 + return frame->StyleVisibility()->mDirection == NS_STYLE_DIRECTION_LTR 1.2878 + ? eDir_LTR : eDir_RTL; 1.2879 + } 1.2880 + 1.2881 + return GetDirectionality(); 1.2882 +} 1.2883 + 1.2884 +float 1.2885 +Element::FontSizeInflation() 1.2886 +{ 1.2887 + nsIFrame* frame = GetPrimaryFrame(); 1.2888 + if (!frame) { 1.2889 + return -1.0; 1.2890 + } 1.2891 + 1.2892 + if (nsLayoutUtils::FontSizeInflationEnabled(frame->PresContext())) { 1.2893 + return nsLayoutUtils::FontSizeInflationFor(frame); 1.2894 + } 1.2895 + 1.2896 + return 1.0; 1.2897 +}