nsGenericHTMLElement.h (56096B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 #ifndef nsGenericHTMLElement_h___ 7 #define nsGenericHTMLElement_h___ 8 9 #include <cstdint> 10 11 #include "mozilla/Attributes.h" 12 #include "mozilla/EventForwards.h" 13 #include "mozilla/dom/BindingDeclarations.h" 14 #include "mozilla/dom/DOMRect.h" 15 #include "mozilla/dom/Element.h" 16 #include "mozilla/dom/PopoverData.h" 17 #include "mozilla/dom/ToggleEvent.h" 18 #include "mozilla/dom/ValidityState.h" 19 #include "nsContentCreatorFunctions.h" 20 #include "nsGkAtoms.h" 21 #include "nsIFormControl.h" 22 #include "nsNameSpaceManager.h" // for kNameSpaceID_None 23 #include "nsStyledElement.h" 24 25 class nsDOMTokenList; 26 class nsIFrame; 27 class nsILayoutHistoryState; 28 class nsIURI; 29 struct nsSize; 30 31 enum NonCustomCSSPropertyId : uint16_t; 32 33 namespace mozilla { 34 class EditorBase; 35 class ErrorResult; 36 class EventChainPostVisitor; 37 class EventChainPreVisitor; 38 class EventChainVisitor; 39 class EventListenerManager; 40 class PresState; 41 namespace dom { 42 class BooleanOrUnrestrictedDoubleOrString; 43 class ElementInternals; 44 class HTMLFormElement; 45 class OwningBooleanOrUnrestrictedDoubleOrString; 46 class TogglePopoverOptionsOrBoolean; 47 enum class FetchPriority : uint8_t; 48 struct ShowPopoverOptions; 49 } // namespace dom 50 } // namespace mozilla 51 52 using nsGenericHTMLElementBase = nsStyledElement; 53 54 /** 55 * A common superclass for HTML elements 56 */ 57 class nsGenericHTMLElement : public nsGenericHTMLElementBase { 58 public: 59 using ContentEditableState = mozilla::ContentEditableState; 60 using Element::Command; 61 using Element::Focus; 62 using Element::SetTabIndex; 63 64 explicit nsGenericHTMLElement( 65 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo) 66 : nsGenericHTMLElementBase(std::move(aNodeInfo)) { 67 NS_ASSERTION(mNodeInfo->NamespaceID() == kNameSpaceID_XHTML, 68 "Unexpected namespace"); 69 } 70 71 NS_INLINE_DECL_REFCOUNTING_INHERITED(nsGenericHTMLElement, 72 nsGenericHTMLElementBase) 73 74 NS_IMPL_FROMNODE(nsGenericHTMLElement, kNameSpaceID_XHTML) 75 76 // From Element 77 nsresult CopyInnerTo(mozilla::dom::Element* aDest); 78 79 void GetTitle(mozilla::dom::DOMString& aTitle) { 80 GetHTMLAttr(nsGkAtoms::title, aTitle); 81 } 82 void SetTitle(const nsAString& aTitle) { 83 SetHTMLAttr(nsGkAtoms::title, aTitle); 84 } 85 void GetLang(mozilla::dom::DOMString& aLang) { 86 GetHTMLAttr(nsGkAtoms::lang, aLang); 87 } 88 void SetLang(const nsAString& aLang) { SetHTMLAttr(nsGkAtoms::lang, aLang); } 89 bool Translate() const override; 90 void SetTranslate(bool aTranslate, mozilla::ErrorResult& aError) { 91 SetHTMLAttr(nsGkAtoms::translate, aTranslate ? u"yes"_ns : u"no"_ns, 92 aError); 93 } 94 void GetDir(nsAString& aDir) { GetHTMLEnumAttr(nsGkAtoms::dir, aDir); } 95 void SetDir(const nsAString& aDir, mozilla::ErrorResult& aError) { 96 SetHTMLAttr(nsGkAtoms::dir, aDir, aError); 97 } 98 void GetPopover(nsString& aPopover) const; 99 void SetPopover(const nsAString& aPopover, mozilla::ErrorResult& aError) { 100 SetOrRemoveNullableStringAttr(nsGkAtoms::popover, aPopover, aError); 101 } 102 103 void GetHidden(mozilla::dom::Nullable< 104 mozilla::dom::OwningBooleanOrUnrestrictedDoubleOrString>& 105 aHidden) const; 106 107 void SetHidden( 108 const mozilla::dom::Nullable< 109 mozilla::dom::BooleanOrUnrestrictedDoubleOrString>& aHidden, 110 mozilla::ErrorResult& aRv); 111 112 bool Inert() const { return GetBoolAttr(nsGkAtoms::inert); } 113 void SetInert(bool aInert, mozilla::ErrorResult& aError) { 114 SetHTMLBoolAttr(nsGkAtoms::inert, aInert, aError); 115 } 116 MOZ_CAN_RUN_SCRIPT void Click(mozilla::dom::CallerType aCallerType); 117 void GetAccessKey(nsString& aAccessKey) { 118 GetHTMLAttr(nsGkAtoms::accesskey, aAccessKey); 119 } 120 void SetAccessKey(const nsAString& aAccessKey, mozilla::ErrorResult& aError) { 121 SetHTMLAttr(nsGkAtoms::accesskey, aAccessKey, aError); 122 } 123 void GetAccessKeyLabel(nsString& aAccessKeyLabel); 124 virtual bool Draggable() const { 125 return AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable, 126 nsGkAtoms::_true, eIgnoreCase); 127 } 128 void SetDraggable(bool aDraggable, mozilla::ErrorResult& aError) { 129 SetHTMLAttr(nsGkAtoms::draggable, aDraggable ? u"true"_ns : u"false"_ns, 130 aError); 131 } 132 void GetContentEditable(nsString& aContentEditable) const { 133 switch (GetContentEditableState()) { 134 case ContentEditableState::True: 135 aContentEditable.AssignLiteral("true"); 136 return; 137 case ContentEditableState::False: 138 aContentEditable.AssignLiteral("false"); 139 return; 140 case ContentEditableState::PlainTextOnly: 141 aContentEditable.AssignLiteral("plaintext-only"); 142 return; 143 case ContentEditableState::Inherit: 144 aContentEditable.AssignLiteral("inherit"); 145 return; 146 } 147 } 148 void SetContentEditable(const nsAString& aContentEditable, 149 mozilla::ErrorResult& aError) { 150 if (aContentEditable.LowerCaseEqualsLiteral("inherit")) { 151 UnsetHTMLAttr(nsGkAtoms::contenteditable, aError); 152 } else if (aContentEditable.LowerCaseEqualsLiteral("true")) { 153 SetHTMLAttr(nsGkAtoms::contenteditable, u"true"_ns, aError); 154 } else if (aContentEditable.LowerCaseEqualsLiteral("false")) { 155 SetHTMLAttr(nsGkAtoms::contenteditable, u"false"_ns, aError); 156 } else if (aContentEditable.LowerCaseEqualsLiteral("plaintext-only")) { 157 SetHTMLAttr(nsGkAtoms::contenteditable, u"plaintext-only"_ns, aError); 158 } else { 159 aError.Throw(NS_ERROR_DOM_SYNTAX_ERR); 160 } 161 } 162 163 [[nodiscard]] bool IsContentEditable() const; 164 165 /** 166 * Returns ContentEditableState::True if the element has a contentEditable 167 * attribute and its value is "true" or an empty string. Returns 168 * ContentEditableState::False if the *element has a contentEditable attribute 169 * and its value is "false". Returns ContentEditableState::PlainTextOnly if 170 * the element has a contentEditable attribute and its value is 171 * "plaintext-only". Otherwise returns ContentEditableState::Inherit. 172 */ 173 [[nodiscard]] inline ContentEditableState GetContentEditableState() const { 174 if (!MayHaveContentEditableAttr()) { 175 return ContentEditableState::Inherit; 176 } 177 static constexpr AttrValuesArray kValidValuesExceptInherit[] = { 178 nsGkAtoms::_empty, nsGkAtoms::_true, nsGkAtoms::plaintextOnly, 179 nsGkAtoms::_false, nullptr}; 180 switch (mAttrs.FindAttrValueIn(kNameSpaceID_None, 181 nsGkAtoms::contenteditable, 182 kValidValuesExceptInherit, eIgnoreCase)) { 183 case 0: 184 case 1: 185 return ContentEditableState::True; 186 case 2: 187 return ContentEditableState::PlainTextOnly; 188 case 3: 189 return ContentEditableState::False; 190 default: 191 return ContentEditableState::Inherit; 192 } 193 } 194 195 mozilla::dom::PopoverAttributeState GetPopoverAttributeState() const; 196 void PopoverPseudoStateUpdate(bool aOpen, bool aNotify); 197 bool PopoverOpen() const; 198 bool CheckPopoverValidity(mozilla::dom::PopoverVisibilityState aExpectedState, 199 Document* aExpectedDocument, ErrorResult& aRv); 200 already_AddRefed<mozilla::dom::ToggleEvent> CreateToggleEvent( 201 const nsAString& aEventType, const nsAString& aOldState, 202 const nsAString& aNewState, mozilla::Cancelable, Element* aSource); 203 /** Returns true if the event has been cancelled. */ 204 MOZ_CAN_RUN_SCRIPT bool FireToggleEvent(const nsAString& aOldState, 205 const nsAString& aNewState, 206 const nsAString& aType, 207 Element* aSource); 208 MOZ_CAN_RUN_SCRIPT void QueuePopoverEventTask( 209 mozilla::dom::PopoverVisibilityState aOldState, Element* aSource); 210 MOZ_CAN_RUN_SCRIPT void RunPopoverToggleEventTask( 211 mozilla::dom::PopoverToggleEventTask* aTask, 212 mozilla::dom::PopoverVisibilityState aOldState, 213 mozilla::dom::Element* aSource); 214 MOZ_CAN_RUN_SCRIPT void ShowPopover( 215 const mozilla::dom::ShowPopoverOptions& aOptions, ErrorResult& aRv); 216 MOZ_CAN_RUN_SCRIPT void ShowPopoverInternal(Element* aInvoker, 217 ErrorResult& aRv); 218 MOZ_CAN_RUN_SCRIPT_BOUNDARY void HidePopoverWithoutRunningScript(); 219 MOZ_CAN_RUN_SCRIPT void HidePopoverInternal(bool aFocusPreviousElement, 220 bool aFireEvents, 221 mozilla::dom::Element* aSource, 222 ErrorResult& aRv); 223 MOZ_CAN_RUN_SCRIPT void HidePopover(ErrorResult& aRv); 224 MOZ_CAN_RUN_SCRIPT bool TogglePopover( 225 const mozilla::dom::TogglePopoverOptionsOrBoolean& aOptions, 226 ErrorResult& aRv); 227 MOZ_CAN_RUN_SCRIPT void FocusPopover(); 228 void ForgetPreviouslyFocusedElementAfterHidingPopover(); 229 MOZ_CAN_RUN_SCRIPT void FocusPreviousElementAfterHidingPopover(); 230 231 bool IsValidCommandAction(Command aCommand) const override; 232 233 MOZ_CAN_RUN_SCRIPT bool HandleCommandInternal(Element* aSource, 234 Command aCommand, 235 ErrorResult& aRv) override; 236 237 MOZ_CAN_RUN_SCRIPT void FocusCandidate(Element*, bool aClearUpFocus); 238 239 void SetNonce(const nsAString& aNonce) { 240 SetProperty(nsGkAtoms::nonce, new nsString(aNonce), 241 nsINode::DeleteProperty<nsString>, /* aTransfer = */ true); 242 } 243 void RemoveNonce() { RemoveProperty(nsGkAtoms::nonce); } 244 void GetNonce(nsAString& aNonce) const { 245 nsString* cspNonce = static_cast<nsString*>(GetProperty(nsGkAtoms::nonce)); 246 if (cspNonce) { 247 aNonce = *cspNonce; 248 } 249 } 250 251 /** Returns whether a form control should be default-focusable. */ 252 bool IsFormControlDefaultFocusable(mozilla::IsFocusableFlags) const; 253 254 /** 255 * Returns the count of descendants (inclusive of this node) in 256 * the uncomposed document that are explicitly set as editable. 257 */ 258 uint32_t EditableInclusiveDescendantCount(); 259 260 bool Spellcheck(); 261 void SetSpellcheck(bool aSpellcheck, mozilla::ErrorResult& aError) { 262 SetHTMLAttr(nsGkAtoms::spellcheck, aSpellcheck ? u"true"_ns : u"false"_ns, 263 aError); 264 } 265 266 MOZ_CAN_RUN_SCRIPT 267 void GetInnerText(mozilla::dom::DOMString& aValue, ErrorResult& aError); 268 MOZ_CAN_RUN_SCRIPT 269 void GetOuterText(mozilla::dom::DOMString& aValue, ErrorResult& aError) { 270 return GetInnerText(aValue, aError); 271 } 272 MOZ_CAN_RUN_SCRIPT void SetInnerText(const nsAString& aValue) { 273 SetInnerTextInternal(aValue, MutationEffectOnScript::DropTrustWorthiness); 274 } 275 MOZ_CAN_RUN_SCRIPT void SetInnerTextInternal( 276 const nsAString& aValue, MutationEffectOnScript aMutationEffectOnScript); 277 MOZ_CAN_RUN_SCRIPT void SetOuterText(const nsAString& aValue, 278 ErrorResult& aRv); 279 280 void GetInputMode(nsAString& aValue) { 281 GetEnumAttr(nsGkAtoms::inputmode, nullptr, aValue); 282 } 283 void SetInputMode(const nsAString& aValue, ErrorResult& aRv) { 284 SetHTMLAttr(nsGkAtoms::inputmode, aValue, aRv); 285 } 286 virtual void GetAutocapitalize(nsAString& aValue) const; 287 void SetAutocapitalize(const nsAString& aValue, ErrorResult& aRv) { 288 SetHTMLAttr(nsGkAtoms::autocapitalize, aValue, aRv); 289 } 290 291 void GetEnterKeyHint(nsAString& aValue) const { 292 GetEnumAttr(nsGkAtoms::enterkeyhint, nullptr, aValue); 293 } 294 void SetEnterKeyHint(const nsAString& aValue, ErrorResult& aRv) { 295 SetHTMLAttr(nsGkAtoms::enterkeyhint, aValue, aRv); 296 } 297 298 virtual bool Autocorrect() const; 299 void SetAutocorrect(bool aAutocorrect, mozilla::ErrorResult& aError) { 300 SetHTMLAttr(nsGkAtoms::autocorrect, aAutocorrect ? u"on"_ns : u"off"_ns, 301 aError); 302 } 303 304 /** 305 * Determine whether an attribute is an event (onclick, etc.) 306 * @param aName the attribute 307 * @return whether the name is an event handler name 308 */ 309 bool IsEventAttributeNameInternal(nsAtom* aName) override; 310 311 #define EVENT(name_, id_, type_, struct_) /* nothing; handled by nsINode */ 312 // The using nsINode::Get/SetOn* are to avoid warnings about shadowing the XPCOM 313 // getter and setter on nsINode. 314 #define FORWARDED_EVENT(name_, id_, type_, struct_) \ 315 using nsINode::GetOn##name_; \ 316 using nsINode::SetOn##name_; \ 317 mozilla::dom::EventHandlerNonNull* GetOn##name_(); \ 318 void SetOn##name_(mozilla::dom::EventHandlerNonNull* handler); 319 #define ERROR_EVENT(name_, id_, type_, struct_) \ 320 using nsINode::GetOn##name_; \ 321 using nsINode::SetOn##name_; \ 322 already_AddRefed<mozilla::dom::EventHandlerNonNull> GetOn##name_(); \ 323 void SetOn##name_(mozilla::dom::EventHandlerNonNull* handler); 324 #include "mozilla/EventNameList.h" // IWYU pragma: keep 325 #undef ERROR_EVENT 326 #undef FORWARDED_EVENT 327 #undef EVENT 328 // These methods are already implemented in nsIContent but we want something 329 // faster for HTMLElements ignoring the namespace checking. 330 // This is safe because we already know that we are in the HTML namespace. 331 inline bool IsHTMLElement() const { return true; } 332 333 inline bool IsHTMLElement(nsAtom* aTag) const { 334 return mNodeInfo->Equals(aTag); 335 } 336 337 template <typename First, typename... Args> 338 inline bool IsAnyOfHTMLElements(First aFirst, Args... aArgs) const { 339 return IsNodeInternal(aFirst, aArgs...); 340 } 341 342 // https://html.spec.whatwg.org/multipage/custom-elements.html#dom-attachinternals 343 virtual already_AddRefed<mozilla::dom::ElementInternals> AttachInternals( 344 ErrorResult& aRv); 345 346 mozilla::dom::ElementInternals* GetInternals() const; 347 348 bool IsFormAssociatedCustomElement() const; 349 350 // Returns true if the event should not be handled from GetEventTargetParent. 351 virtual bool IsDisabledForEvents(mozilla::WidgetEvent* aEvent) { 352 return false; 353 } 354 355 bool Autofocus() const { return GetBoolAttr(nsGkAtoms::autofocus); } 356 void SetAutofocus(bool aVal, ErrorResult& aRv) { 357 SetHTMLBoolAttr(nsGkAtoms::autofocus, aVal, aRv); 358 } 359 360 protected: 361 virtual ~nsGenericHTMLElement() = default; 362 363 public: 364 // Implementation for nsIContent 365 nsresult BindToTree(BindContext&, nsINode& aParent) override; 366 void UnbindFromTree(UnbindContext&) override; 367 368 Focusable IsFocusableWithoutStyle(mozilla::IsFocusableFlags aFlags = 369 mozilla::IsFocusableFlags(0)) override { 370 Focusable result; 371 IsHTMLFocusable(aFlags, &result.mFocusable, &result.mTabIndex); 372 return result; 373 } 374 /** 375 * Returns true if a subclass is not allowed to override the value returned 376 * in aIsFocusable. 377 */ 378 virtual bool IsHTMLFocusable(mozilla::IsFocusableFlags, bool* aIsFocusable, 379 int32_t* aTabIndex); 380 MOZ_CAN_RUN_SCRIPT 381 mozilla::Result<bool, nsresult> PerformAccesskey( 382 bool aKeyCausesActivation, bool aIsTrustedEvent) override; 383 384 /** 385 * Check if an event for an anchor can be handled 386 * @return true if the event can be handled, false otherwise 387 */ 388 bool CheckHandleEventForAnchorsPreconditions( 389 mozilla::EventChainVisitor& aVisitor); 390 void GetEventTargetParentForAnchors(mozilla::EventChainPreVisitor& aVisitor); 391 MOZ_CAN_RUN_SCRIPT 392 nsresult PostHandleEventForAnchors(mozilla::EventChainPostVisitor& aVisitor); 393 bool IsHTMLLink(nsIURI** aURI) const; 394 395 // HTML element methods 396 void Compact() { mAttrs.Compact(); } 397 398 void UpdateEditableState(bool aNotify) override; 399 400 bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, 401 const nsAString& aValue, 402 nsIPrincipal* aMaybeScriptedPrincipal, 403 nsAttrValue& aResult) override; 404 405 bool ParseBackgroundAttribute(int32_t aNamespaceID, nsAtom* aAttribute, 406 const nsAString& aValue, nsAttrValue& aResult); 407 408 NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override; 409 nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override; 410 411 /** 412 * Get the base target for any links within this piece 413 * of content. Generally, this is the document's base target, 414 * but certain content carries a local base for backward 415 * compatibility. 416 * 417 * @param aBaseTarget the base target [OUT] 418 */ 419 void GetBaseTarget(nsAString& aBaseTarget) const; 420 421 /** 422 * Parse an alignment attribute (top/middle/bottom/baseline) 423 * 424 * @param aString the string to parse 425 * @param aResult the resulting HTMLValue 426 * @return whether the value was parsed 427 */ 428 static bool ParseAlignValue(const nsAString& aString, nsAttrValue& aResult); 429 430 /** 431 * Parse a div align string to value (left/right/center/middle/justify) 432 * 433 * @param aString the string to parse 434 * @param aResult the resulting HTMLValue 435 * @return whether the value was parsed 436 */ 437 static bool ParseDivAlignValue(const nsAString& aString, 438 nsAttrValue& aResult); 439 440 /** 441 * Convert a table halign string to value (left/right/center/char/justify) 442 * 443 * @param aString the string to parse 444 * @param aResult the resulting HTMLValue 445 * @return whether the value was parsed 446 */ 447 static bool ParseTableHAlignValue(const nsAString& aString, 448 nsAttrValue& aResult); 449 450 /** 451 * Convert a table cell halign string to value 452 * 453 * @param aString the string to parse 454 * @param aResult the resulting HTMLValue 455 * @return whether the value was parsed 456 */ 457 static bool ParseTableCellHAlignValue(const nsAString& aString, 458 nsAttrValue& aResult); 459 460 /** 461 * Convert a table valign string to value (left/right/center/char/justify/ 462 * abscenter/absmiddle/middle) 463 * 464 * @param aString the string to parse 465 * @param aResult the resulting HTMLValue 466 * @return whether the value was parsed 467 */ 468 static bool ParseTableVAlignValue(const nsAString& aString, 469 nsAttrValue& aResult); 470 471 /** 472 * Convert an image attribute to value (width, height, hspace, vspace, border) 473 * 474 * @param aAttribute the attribute to parse 475 * @param aString the string to parse 476 * @param aResult the resulting HTMLValue 477 * @return whether the value was parsed 478 */ 479 static bool ParseImageAttribute(nsAtom* aAttribute, const nsAString& aString, 480 nsAttrValue& aResult); 481 482 static bool ParseReferrerAttribute(const nsAString& aString, 483 nsAttrValue& aResult); 484 485 /** 486 * Convert a frameborder string to value (yes/no/1/0) 487 * 488 * @param aString the string to parse 489 * @param aResult the resulting HTMLValue 490 * @return whether the value was parsed 491 */ 492 static bool ParseFrameborderValue(const nsAString& aString, 493 nsAttrValue& aResult); 494 495 /** 496 * Convert a scrolling string to value (yes/no/on/off/scroll/noscroll/auto) 497 * 498 * @param aString the string to parse 499 * @param aResult the resulting HTMLValue 500 * @return whether the value was parsed 501 */ 502 static bool ParseScrollingValue(const nsAString& aString, 503 nsAttrValue& aResult); 504 505 /* 506 * Attribute Mapping Helpers 507 */ 508 509 /** 510 * A style attribute mapping function for the most common attributes, to be 511 * called by subclasses' attribute mapping functions. Currently handles 512 * dir, lang and hidden, could handle others. 513 * 514 * @param aAttributes the list of attributes to map 515 * @param aData the returned rule data [INOUT] 516 * @see GetAttributeMappingFunction 517 */ 518 static void MapCommonAttributesInto(mozilla::MappedDeclarationsBuilder&); 519 /** 520 * Same as MapCommonAttributesInto except that it does not handle hidden. 521 * @see GetAttributeMappingFunction 522 */ 523 static void MapCommonAttributesIntoExceptHidden( 524 mozilla::MappedDeclarationsBuilder&); 525 526 static const MappedAttributeEntry sCommonAttributeMap[]; 527 static const MappedAttributeEntry sImageMarginSizeAttributeMap[]; 528 static const MappedAttributeEntry sImageBorderAttributeMap[]; 529 static const MappedAttributeEntry sImageAlignAttributeMap[]; 530 static const MappedAttributeEntry sDivAlignAttributeMap[]; 531 static const MappedAttributeEntry sBackgroundAttributeMap[]; 532 static const MappedAttributeEntry sBackgroundColorAttributeMap[]; 533 534 /** 535 * Helper to map the align attribute. 536 * @see GetAttributeMappingFunction 537 */ 538 static void MapImageAlignAttributeInto(mozilla::MappedDeclarationsBuilder&); 539 540 /** 541 * Helper to map the align attribute for things like <div>, <h1>, etc. 542 * @see GetAttributeMappingFunction 543 */ 544 static void MapDivAlignAttributeInto(mozilla::MappedDeclarationsBuilder&); 545 546 /** 547 * Helper to map the valign attribute for various table elements. 548 * @see GetAttributeMappingFunction 549 */ 550 static void MapTableVAlignAttributeInto(mozilla::MappedDeclarationsBuilder&); 551 552 /** 553 * Helper to map the align attribute for <table>. 554 * @see GetAttributeMappingFunction 555 */ 556 static void MapTableHAlignAttributeInto(mozilla::MappedDeclarationsBuilder&); 557 558 /** 559 * Helper to map the align attribute for various table elements. 560 * @see GetAttributeMappingFunction 561 */ 562 static void MapTableCellHAlignAttributeInto( 563 mozilla::MappedDeclarationsBuilder&); 564 565 /** 566 * Helper to map the image border attribute. 567 * @see GetAttributeMappingFunction 568 */ 569 static void MapImageBorderAttributeInto(mozilla::MappedDeclarationsBuilder&); 570 /** 571 * Helper to map the image margin attribute into a style struct. 572 * 573 * @param aAttributes the list of attributes to map 574 * @param aData the returned rule data [INOUT] 575 * @see GetAttributeMappingFunction 576 */ 577 static void MapImageMarginAttributeInto(mozilla::MappedDeclarationsBuilder&); 578 579 /** 580 * Helper to map a given dimension (width/height) into the declaration 581 * block, handling percentages and numbers. 582 */ 583 static void MapDimensionAttributeInto(mozilla::MappedDeclarationsBuilder&, 584 NonCustomCSSPropertyId, 585 const nsAttrValue&); 586 587 /** 588 * Maps the aspect ratio given width and height attributes. 589 */ 590 static void DoMapAspectRatio(const nsAttrValue& aWidth, 591 const nsAttrValue& aHeight, 592 mozilla::MappedDeclarationsBuilder&); 593 594 // Whether to map the width and height attributes to aspect-ratio. 595 enum class MapAspectRatio { No, Yes }; 596 597 /** 598 * Helper to map the image position attribute into a style struct. 599 */ 600 static void MapImageSizeAttributesInto(mozilla::MappedDeclarationsBuilder&, 601 MapAspectRatio = MapAspectRatio::No); 602 603 /** 604 * Helper to map the width and height attributes into the aspect-ratio 605 * property. 606 * 607 * If you also map the width/height attributes to width/height (as you should 608 * for any HTML element that isn't <canvas>) then you should use 609 * MapImageSizeAttributesInto instead, passing MapAspectRatio::Yes instead, as 610 * that'd be faster. 611 */ 612 static void MapAspectRatioInto(mozilla::MappedDeclarationsBuilder&); 613 614 /** 615 * Helper to map `width` attribute into a style struct. 616 * 617 * @param aAttributes the list of attributes to map 618 * @param aData the returned rule data [INOUT] 619 * @see GetAttributeMappingFunction 620 */ 621 static void MapWidthAttributeInto(mozilla::MappedDeclarationsBuilder&); 622 623 /** 624 * Helper to map `height` attribute. 625 * @see GetAttributeMappingFunction 626 */ 627 static void MapHeightAttributeInto(mozilla::MappedDeclarationsBuilder&); 628 /** 629 * Helper to map the background attribute 630 * @see GetAttributeMappingFunction 631 */ 632 static void MapBackgroundInto(mozilla::MappedDeclarationsBuilder&); 633 /** 634 * Helper to map the bgcolor attribute 635 * @see GetAttributeMappingFunction 636 */ 637 static void MapBGColorInto(mozilla::MappedDeclarationsBuilder&); 638 /** 639 * Helper to map the background attributes (currently background and bgcolor) 640 * @see GetAttributeMappingFunction 641 */ 642 static void MapBackgroundAttributesInto(mozilla::MappedDeclarationsBuilder&); 643 /** 644 * Helper to map the scrolling attribute on FRAME and IFRAME. 645 * @see GetAttributeMappingFunction 646 */ 647 static void MapScrollingAttributeInto(mozilla::MappedDeclarationsBuilder&); 648 649 // Form Helper Routines 650 /** 651 * Find an ancestor of this content node which is a form (could be null) 652 * @param aCurrentForm the current form for this node. If this is 653 * non-null, and no ancestor form is found, and the current form is in 654 * a connected subtree with the node, the current form will be 655 * returned. This is needed to handle cases when HTML elements have a 656 * current form that they're not descendants of. 657 * @note This method should not be called if the element has a form attribute. 658 */ 659 mozilla::dom::HTMLFormElement* FindAncestorForm( 660 mozilla::dom::HTMLFormElement* aCurrentForm = nullptr); 661 662 /** 663 * See if the document being tested has nav-quirks mode enabled. 664 * @param doc the document 665 */ 666 static bool InNavQuirksMode(Document*); 667 668 /** 669 * Gets the absolute URI value of an attribute, by resolving any relative 670 * URIs in the attribute against the baseuri of the element. If the attribute 671 * isn't a relative URI the value of the attribute is returned as is. Only 672 * works for attributes in null namespace. 673 * 674 * @param aAttr name of attribute. 675 * @param aBaseAttr name of base attribute. 676 * @param aResult result value [out] 677 */ 678 void GetURIAttr(nsAtom* aAttr, nsAtom* aBaseAttr, nsAString& aResult) const; 679 void GetURIAttr(nsAtom* aAttr, nsAtom* aBaseAttr, nsACString& aResult) const; 680 681 /** 682 * Gets the absolute URI values of an attribute, by resolving any relative 683 * URIs in the attribute against the baseuri of the element. If a substring 684 * isn't a relative URI, the substring is returned as is. Only works for 685 * attributes in null namespace. 686 */ 687 const nsAttrValue* GetURIAttr(nsAtom* aAttr, nsAtom* aBaseAttr, 688 nsIURI** aURI) const; 689 690 bool IsHidden() const { return HasAttr(nsGkAtoms::hidden); } 691 692 bool IsLabelable() const override; 693 694 static bool MatchLabelsElement(Element* aElement, int32_t aNamespaceID, 695 nsAtom* aAtom, void* aData); 696 697 already_AddRefed<nsINodeList> Labels(); 698 699 static bool LegacyTouchAPIEnabled(JSContext* aCx, JSObject* aObj); 700 701 // https://html.spec.whatwg.org/#dom-window-nameditem-filter 702 static inline bool CanHaveName(nsAtom* aTag) { 703 return aTag == nsGkAtoms::img || aTag == nsGkAtoms::form || 704 aTag == nsGkAtoms::embed || aTag == nsGkAtoms::object; 705 } 706 static inline bool ShouldExposeNameAsWindowProperty(Element* aElement) { 707 return aElement->IsHTMLElement() && 708 CanHaveName(aElement->NodeInfo()->NameAtom()); 709 } 710 // https://html.spec.whatwg.org/#dom-document-nameditem-filter 711 static inline bool ShouldExposeIdAsHTMLDocumentProperty(Element* aElement) { 712 if (!aElement->HasID() || aElement->IsInNativeAnonymousSubtree()) { 713 return false; 714 } 715 // XXX Not all objects is exposed per spec, but other browsers doesn't check 716 // if object is exposed, either. 717 if (aElement->IsHTMLElement(nsGkAtoms::object)) { 718 return true; 719 } 720 721 // Per spec, <img> is exposed by id only if it also has a nonempty 722 // name (which doesn't have to match the id or anything). 723 // HasName() is true precisely when name is nonempty. 724 return aElement->IsHTMLElement(nsGkAtoms::img) && aElement->HasName(); 725 } 726 static inline bool ShouldExposeNameAsHTMLDocumentProperty(Element* aElement) { 727 if (!aElement->HasName() || aElement->IsInNativeAnonymousSubtree()) { 728 return false; 729 } 730 // XXX Not all embeds/objects are exposed per spec, but other browser 731 // doesn't check if embeds/objects are exposed. 732 return aElement->IsAnyOfHTMLElements(nsGkAtoms::embed, nsGkAtoms::form, 733 nsGkAtoms::iframe, nsGkAtoms::img, 734 nsGkAtoms::object); 735 } 736 737 virtual inline void ResultForDialogSubmit(nsAString& aResult) { 738 GetAttr(nsGkAtoms::value, aResult); 739 } 740 741 // <https://html.spec.whatwg.org/#fetch-priority-attribute>. 742 static mozilla::dom::FetchPriority ToFetchPriority(const nsAString& aValue); 743 744 void GetFetchPriority(nsAString& aFetchPriority) const; 745 746 void SetFetchPriority(const nsAString& aFetchPriority) { 747 SetHTMLAttr(nsGkAtoms::fetchpriority, aFetchPriority); 748 } 749 750 private: 751 /** 752 * Add/remove this element to the documents name cache 753 */ 754 void AddToNameTable(nsAtom* aName); 755 void RemoveFromNameTable(); 756 757 /** 758 * Register or unregister an access key to this element based on the 759 * accesskey attribute. 760 */ 761 void RegUnRegAccessKey(bool aDoReg) override { 762 if (!HasFlag(NODE_HAS_ACCESSKEY)) { 763 return; 764 } 765 766 nsStyledElement::RegUnRegAccessKey(aDoReg); 767 } 768 769 protected: 770 void BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName, 771 const nsAttrValue* aValue, bool aNotify) override; 772 // TODO: Convert AfterSetAttr to MOZ_CAN_RUN_SCRIPT and get rid of 773 // kungFuDeathGrip in it. 774 MOZ_CAN_RUN_SCRIPT_BOUNDARY void AfterSetAttr( 775 int32_t aNamespaceID, nsAtom* aName, const nsAttrValue* aValue, 776 const nsAttrValue* aOldValue, nsIPrincipal* aMaybeScriptedPrincipal, 777 bool aNotify) override; 778 779 void OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName, 780 const nsAttrValueOrString& aValue, 781 bool aNotify) override; 782 783 MOZ_CAN_RUN_SCRIPT void AfterSetPopoverAttr(); 784 785 mozilla::EventListenerManager* GetEventListenerManagerForAttr( 786 nsAtom* aAttrName, bool* aDefer) override; 787 788 /** 789 * Handles dispatching a simulated click on `this` on space or enter. 790 * TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230) 791 */ 792 MOZ_CAN_RUN_SCRIPT_BOUNDARY void HandleKeyboardActivation( 793 mozilla::EventChainPostVisitor&); 794 795 /** Dispatch a simulated mouse click by keyboard to the given element. */ 796 MOZ_CAN_RUN_SCRIPT static nsresult DispatchSimulatedClick( 797 nsGenericHTMLElement* aElement, bool aIsTrusted, 798 nsPresContext* aPresContext); 799 800 /** 801 * Create a URI for the given aURISpec string. 802 * Returns INVALID_STATE_ERR and nulls *aURI if aURISpec is empty 803 * and the document's URI matches the element's base URI. 804 */ 805 nsresult NewURIFromString(const nsAString& aURISpec, nsIURI** aURI); 806 807 void GetHTMLAttr(nsAtom* aName, nsAString& aResult) const { 808 GetAttr(aName, aResult); 809 } 810 void GetHTMLAttr(nsAtom* aName, mozilla::dom::DOMString& aResult) const { 811 GetAttr(aName, aResult); 812 } 813 void GetHTMLEnumAttr(nsAtom* aName, nsAString& aResult) const { 814 GetEnumAttr(aName, nullptr, aResult); 815 } 816 void GetHTMLURIAttr(nsAtom* aName, nsAString& aResult) const { 817 GetURIAttr(aName, nullptr, aResult); 818 } 819 void GetHTMLURIAttr(nsAtom* aName, nsACString& aResult) const { 820 GetURIAttr(aName, nullptr, aResult); 821 } 822 823 void SetHTMLAttr(nsAtom* aName, const nsAString& aValue) { 824 SetAttr(kNameSpaceID_None, aName, aValue, true); 825 } 826 void SetHTMLAttr(nsAtom* aName, const nsAString& aValue, 827 mozilla::ErrorResult& aError) { 828 SetAttr(aName, aValue, aError); 829 } 830 void SetHTMLAttr(nsAtom* aName, const nsAString& aValue, 831 nsIPrincipal* aTriggeringPrincipal, 832 mozilla::ErrorResult& aError) { 833 SetAttr(aName, aValue, aTriggeringPrincipal, aError); 834 } 835 void UnsetHTMLAttr(nsAtom* aName, mozilla::ErrorResult& aError) { 836 UnsetAttr(aName, aError); 837 } 838 void SetHTMLBoolAttr(nsAtom* aName, bool aValue, 839 mozilla::ErrorResult& aError) { 840 if (aValue) { 841 SetHTMLAttr(aName, u""_ns, aError); 842 } else { 843 UnsetHTMLAttr(aName, aError); 844 } 845 } 846 template <typename T> 847 void SetHTMLIntAttr(nsAtom* aName, T aValue, mozilla::ErrorResult& aError) { 848 nsAutoString value; 849 value.AppendInt(aValue); 850 851 SetHTMLAttr(aName, value, aError); 852 } 853 854 /** 855 * Gets the integer-value of an attribute, returns specified default value 856 * if the attribute isn't set or isn't set to an integer. Only works for 857 * attributes in null namespace. 858 * 859 * @param aAttr name of attribute. 860 * @param aDefault default-value to return if attribute isn't set. 861 */ 862 int32_t GetIntAttr(nsAtom* aAttr, int32_t aDefault) const; 863 864 /** 865 * Sets value of attribute to specified integer. Only works for attributes 866 * in null namespace. 867 * 868 * @param aAttr name of attribute. 869 * @param aValue Integer value of attribute. 870 */ 871 nsresult SetIntAttr(nsAtom* aAttr, int32_t aValue); 872 873 /** 874 * Gets the unsigned integer-value of an attribute, returns specified default 875 * value if the attribute isn't set or isn't set to an integer. Only works for 876 * attributes in null namespace. 877 * 878 * @param aAttr name of attribute. 879 * @param aDefault default-value to return if attribute isn't set. 880 */ 881 uint32_t GetUnsignedIntAttr(nsAtom* aAttr, uint32_t aDefault) const; 882 883 /** 884 * Sets value of attribute to specified unsigned integer. Only works for 885 * attributes in null namespace. 886 * 887 * @param aAttr name of attribute. 888 * @param aValue Integer value of attribute. 889 * @param aDefault Default value (in case value is out of range). If the spec 890 * doesn't provide one, should be 1 if the value is limited to 891 * nonzero values, and 0 otherwise. 892 */ 893 void SetUnsignedIntAttr(nsAtom* aName, uint32_t aValue, uint32_t aDefault, 894 mozilla::ErrorResult& aError) { 895 nsAutoString value; 896 if (aValue > INT32_MAX) { 897 value.AppendInt(aDefault); 898 } else { 899 value.AppendInt(aValue); 900 } 901 902 SetHTMLAttr(aName, value, aError); 903 } 904 905 /** 906 * Gets the unsigned integer-value of an attribute that is stored as a 907 * dimension (i.e. could be an integer or a percentage), returns specified 908 * default value if the attribute isn't set or isn't set to a dimension. Only 909 * works for attributes in null namespace. 910 * 911 * @param aAttr name of attribute. 912 * @param aDefault default-value to return if attribute isn't set. 913 */ 914 uint32_t GetDimensionAttrAsUnsignedInt(nsAtom* aAttr, 915 uint32_t aDefault) const; 916 917 enum class Reflection { 918 Unlimited, 919 OnlyPositive, 920 }; 921 922 /** 923 * Sets value of attribute to specified double. Only works for attributes 924 * in null namespace. 925 * 926 * Implements 927 * https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#reflecting-content-attributes-in-idl-attributes:idl-double 928 * 929 * @param aAttr name of attribute. 930 * @param aValue Double value of attribute. 931 */ 932 template <Reflection Limited = Reflection::Unlimited> 933 void SetDoubleAttr(nsAtom* aAttr, double aValue, mozilla::ErrorResult& aRv) { 934 // 1. If the reflected IDL attribute is limited to only positive numbers and 935 // the given value is not greater than 0, then return. 936 if (Limited == Reflection::OnlyPositive && aValue <= 0) { 937 return; 938 } 939 940 // 2. Run this's set the content attribute with the given value, converted 941 // to the best representation of the number as a floating-point number. 942 nsAutoString value; 943 value.AppendFloat(aValue); 944 945 SetHTMLAttr(aAttr, value, aRv); 946 } 947 948 /** 949 * Locates the EditorBase associated with this node. In general this is 950 * equivalent to GetEditorInternal(), but for designmode or contenteditable, 951 * this may need to get an editor that's not actually on this element's 952 * associated TextControlFrame. This is used by the spellchecking routines 953 * to get the editor affected by changing the spellcheck attribute on this 954 * node. 955 */ 956 virtual already_AddRefed<mozilla::EditorBase> GetAssociatedEditor(); 957 958 /** 959 * Ensures all editors associated with a subtree are synced, for purposes of 960 * spellchecking. 961 */ 962 static void SyncEditorsOnSubtree(nsIContent* content); 963 964 [[nodiscard]] inline static bool IsEditableState( 965 ContentEditableState aState) { 966 return aState == ContentEditableState::True || 967 aState == ContentEditableState::PlainTextOnly; 968 } 969 970 // Used by A, AREA, LINK, and STYLE. 971 already_AddRefed<nsIURI> GetHrefURIForAnchors() const; 972 973 private: 974 MOZ_CAN_RUN_SCRIPT void ChangeEditableState(int32_t aChange); 975 }; 976 977 namespace mozilla::dom { 978 class HTMLFieldSetElement; 979 } // namespace mozilla::dom 980 981 #define HTML_ELEMENT_FLAG_BIT(n_) \ 982 NODE_FLAG_BIT(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + (n_)) 983 984 // HTMLElement specific bits 985 enum { 986 // Used to handle keyboard activation. 987 HTML_ELEMENT_ACTIVE_FOR_KEYBOARD = HTML_ELEMENT_FLAG_BIT(0), 988 // Similar to HTMLInputElement's mInhibitRestoration, used to prevent 989 // form-associated custom elements not created by a network parser from 990 // being restored. 991 HTML_ELEMENT_INHIBIT_RESTORATION = HTML_ELEMENT_FLAG_BIT(1), 992 993 // Remaining bits are type specific. 994 HTML_ELEMENT_TYPE_SPECIFIC_BITS_OFFSET = 995 ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 2, 996 }; 997 998 ASSERT_NODE_FLAGS_SPACE(HTML_ELEMENT_TYPE_SPECIFIC_BITS_OFFSET); 999 1000 #define FORM_ELEMENT_FLAG_BIT(n_) \ 1001 NODE_FLAG_BIT(HTML_ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + (n_)) 1002 1003 // Form element specific bits 1004 enum { 1005 // If this flag is set on an nsGenericHTMLFormElement or an HTMLImageElement, 1006 // that means that we have added ourselves to our mForm. It's possible to 1007 // have a non-null mForm, but not have this flag set. That happens when the 1008 // form is set via the content sink. 1009 ADDED_TO_FORM = FORM_ELEMENT_FLAG_BIT(0), 1010 1011 // If this flag is set on an nsGenericHTMLFormElement or an HTMLImageElement, 1012 // that means that its form is in the process of being unbound from the tree, 1013 // and this form element hasn't re-found its form in 1014 // nsGenericHTMLFormElement::UnbindFromTree yet. 1015 MAYBE_ORPHAN_FORM_ELEMENT = FORM_ELEMENT_FLAG_BIT(1), 1016 1017 // If this flag is set on an nsGenericHTMLElement or an HTMLImageElement, then 1018 // the element might be in the past names map of its form. 1019 MAY_BE_IN_PAST_NAMES_MAP = FORM_ELEMENT_FLAG_BIT(2) 1020 }; 1021 1022 // NOTE: I don't think it's possible to have both ADDED_TO_FORM and 1023 // MAYBE_ORPHAN_FORM_ELEMENT set at the same time, so if it becomes an issue we 1024 // can probably merge them into the same bit. --bz 1025 1026 ASSERT_NODE_FLAGS_SPACE(HTML_ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 3); 1027 1028 #undef FORM_ELEMENT_FLAG_BIT 1029 1030 /** 1031 * A helper class for form elements that can contain children 1032 */ 1033 class nsGenericHTMLFormElement : public nsGenericHTMLElement { 1034 public: 1035 nsGenericHTMLFormElement( 1036 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo); 1037 1038 // nsIContent 1039 void SaveSubtreeState() override; 1040 nsresult BindToTree(BindContext&, nsINode& aParent) override; 1041 void UnbindFromTree(UnbindContext&) override; 1042 1043 /** 1044 * This callback is called by a fieldest on all its elements whenever its 1045 * disabled attribute is changed so the element knows its disabled state 1046 * might have changed. 1047 * 1048 * @note Classes redefining this method should not do any content 1049 * state updates themselves but should just make sure to call into 1050 * nsGenericHTMLFormElement::FieldSetDisabledChanged. 1051 */ 1052 virtual void FieldSetDisabledChanged(bool aNotify); 1053 1054 void FieldSetFirstLegendChanged(bool aNotify) { UpdateFieldSet(aNotify); } 1055 1056 /** 1057 * This callback is called by a fieldset on all it's elements when it's being 1058 * destroyed. When called, the elements should check that aFieldset is there 1059 * first parent fieldset and null mFieldset in that case only. 1060 * 1061 * @param aFieldSet The fieldset being removed. 1062 */ 1063 void ForgetFieldSet(nsIContent* aFieldset); 1064 1065 void ClearForm(bool aRemoveFromForm, bool aUnbindOrDelete); 1066 1067 /** 1068 * Get the layout history object for a particular piece of content. 1069 * 1070 * @param aRead if true, won't return a layout history state if the 1071 * layout history state is empty. 1072 * @return the history state object 1073 */ 1074 already_AddRefed<nsILayoutHistoryState> GetLayoutHistory(bool aRead); 1075 1076 // Sets the user-interacted flag in 1077 // https://html.spec.whatwg.org/#user-interacted, if it applies. 1078 virtual void SetUserInteracted(bool aNotify) {} 1079 1080 protected: 1081 virtual ~nsGenericHTMLFormElement() = default; 1082 1083 void BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName, 1084 const nsAttrValue* aValue, bool aNotify) override; 1085 1086 void AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName, 1087 const nsAttrValue* aValue, const nsAttrValue* aOldValue, 1088 nsIPrincipal* aMaybeScriptedPrincipal, 1089 bool aNotify) override; 1090 1091 virtual void BeforeSetForm(mozilla::dom::HTMLFormElement* aForm, 1092 bool aBindToTree) {} 1093 1094 virtual void AfterClearForm(bool aUnbindOrDelete) {} 1095 1096 /** 1097 * Check our disabled content attribute and fieldset's (if it exists) disabled 1098 * state to decide whether our disabled flag should be toggled. 1099 */ 1100 virtual void UpdateDisabledState(bool aNotify); 1101 bool IsReadOnlyInternal() const final; 1102 1103 virtual void SetFormInternal(mozilla::dom::HTMLFormElement* aForm, 1104 bool aBindToTree) {} 1105 1106 virtual mozilla::dom::HTMLFormElement* GetFormInternal() const { 1107 return nullptr; 1108 } 1109 1110 virtual mozilla::dom::HTMLFieldSetElement* GetFieldSetInternal() const { 1111 return nullptr; 1112 } 1113 1114 virtual void SetFieldSetInternal( 1115 mozilla::dom::HTMLFieldSetElement* aFieldset) {} 1116 1117 /** 1118 * This method will update the form owner, using @form or looking to a parent. 1119 * 1120 * @param aBindToTree Whether the element is being attached to the tree. 1121 * @param aFormIdElement The element associated with the id in @form. If 1122 * aBindToTree is false, aFormIdElement *must* contain the element associated 1123 * with the id in @form. Otherwise, it *must* be null. 1124 * 1125 * @note Callers of UpdateFormOwner have to be sure the element is in a 1126 * document (GetUncomposedDoc() != nullptr). 1127 */ 1128 virtual void UpdateFormOwner(bool aBindToTree, Element* aFormIdElement); 1129 1130 /** 1131 * This method will update mFieldset and set it to the first fieldset parent. 1132 */ 1133 void UpdateFieldSet(bool aNotify); 1134 1135 /** 1136 * Add a form id observer which will observe when the element with the id in 1137 * @form will change. 1138 * 1139 * @return The element associated with the current id in @form (may be null). 1140 */ 1141 Element* AddFormIdObserver(); 1142 1143 /** 1144 * Remove the form id observer. 1145 */ 1146 void RemoveFormIdObserver(); 1147 1148 /** 1149 * This method is a a callback for IDTargetObserver (from Document). 1150 * It will be called each time the element associated with the id in @form 1151 * changes. 1152 */ 1153 static bool FormIdUpdated(Element* aOldElement, Element* aNewElement, 1154 void* aData); 1155 1156 // Returns true if the event should not be handled from GetEventTargetParent 1157 bool IsElementDisabledForEvents(mozilla::WidgetEvent* aEvent, 1158 nsIFrame* aFrame); 1159 1160 /** 1161 * Returns if the control can be disabled. 1162 */ 1163 virtual bool CanBeDisabled() const { return false; } 1164 1165 /** 1166 * Returns true if :read-write pseudo class may match the element even if the 1167 * element isn't part of designMode or contenteditable. 1168 */ 1169 virtual bool DoesReadWriteApply() const { return false; } 1170 1171 /** 1172 * Returns true if the element is a form associated element. 1173 * See https://html.spec.whatwg.org/#form-associated-element. 1174 */ 1175 virtual bool IsFormAssociatedElement() const { return false; } 1176 1177 /** 1178 * Save to presentation state. The form element will determine whether it 1179 * has anything to save and if so, create an entry in the layout history for 1180 * its pres context. 1181 */ 1182 virtual void SaveState() {} 1183 }; 1184 1185 class nsGenericHTMLFormControlElement : public nsGenericHTMLFormElement, 1186 public nsIFormControl { 1187 public: 1188 nsGenericHTMLFormControlElement( 1189 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, FormControlType); 1190 1191 NS_DECL_ISUPPORTS_INHERITED 1192 1193 NS_IMPL_FROMNODE_HELPER(nsGenericHTMLFormControlElement, 1194 IsHTMLFormControlElement()) 1195 1196 [[nodiscard]] nsIFormControl* GetAsFormControl() final { return this; } 1197 [[nodiscard]] const nsIFormControl* GetAsFormControl() const final { 1198 return this; 1199 } 1200 1201 // nsINode 1202 nsINode* GetScopeChainParent() const override; 1203 bool IsHTMLFormControlElement() const final { return true; } 1204 1205 // nsIContent 1206 IMEState GetDesiredIMEState() override; 1207 1208 // nsGenericHTMLElement 1209 // autocapitalize attribute support 1210 void GetAutocapitalize(nsAString& aValue) const override; 1211 // autocorrect attribute support 1212 bool Autocorrect() const override; 1213 bool IsHTMLFocusable(mozilla::IsFocusableFlags, bool* aIsFocusable, 1214 int32_t* aTabIndex) override; 1215 1216 // nsIFormControl 1217 mozilla::dom::HTMLFieldSetElement* GetFieldSet() override; 1218 mozilla::dom::HTMLFormElement* GetForm() const override { return mForm; } 1219 void SetForm(mozilla::dom::HTMLFormElement* aForm) override; 1220 void ClearForm(bool aRemoveFromForm, bool aUnbindOrDelete) override; 1221 1222 protected: 1223 virtual ~nsGenericHTMLFormControlElement(); 1224 1225 // Element 1226 bool IsLabelable() const override; 1227 1228 // nsGenericHTMLFormElement 1229 bool CanBeDisabled() const override; 1230 bool DoesReadWriteApply() const override; 1231 void SetFormInternal(mozilla::dom::HTMLFormElement* aForm, 1232 bool aBindToTree) override; 1233 mozilla::dom::HTMLFormElement* GetFormInternal() const override; 1234 mozilla::dom::HTMLFieldSetElement* GetFieldSetInternal() const override; 1235 void SetFieldSetInternal( 1236 mozilla::dom::HTMLFieldSetElement* aFieldset) override; 1237 bool IsFormAssociatedElement() const override { return true; } 1238 1239 /** 1240 * Update our required/optional flags to match the given aIsRequired boolean. 1241 */ 1242 void UpdateRequiredState(bool aIsRequired, bool aNotify); 1243 1244 bool IsAutocapitalizeOrAutocorrectInheriting() const; 1245 1246 nsresult SubmitDirnameDir(mozilla::dom::FormData* aFormData); 1247 1248 void GetFormAutofillState(nsAString& aState) const; 1249 void SetFormAutofillState(const nsAString& aState); 1250 1251 /** The form that contains this control */ 1252 mozilla::dom::HTMLFormElement* mForm; 1253 1254 /* This is a pointer to our closest fieldset parent if any */ 1255 mozilla::dom::HTMLFieldSetElement* mFieldSet; 1256 }; 1257 1258 enum class PopoverTargetAction : uint8_t { 1259 Toggle, 1260 Show, 1261 Hide, 1262 }; 1263 1264 class nsGenericHTMLFormControlElementWithState 1265 : public nsGenericHTMLFormControlElement { 1266 public: 1267 nsGenericHTMLFormControlElementWithState( 1268 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, 1269 mozilla::dom::FromParser aFromParser, FormControlType); 1270 1271 bool IsGenericHTMLFormControlElementWithState() const final { return true; } 1272 NS_IMPL_FROMNODE_HELPER(nsGenericHTMLFormControlElementWithState, 1273 IsGenericHTMLFormControlElementWithState()) 1274 1275 // Element 1276 bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, 1277 const nsAString& aValue, 1278 nsIPrincipal* aMaybeScriptedPrincipal, 1279 nsAttrValue& aResult) override; 1280 1281 // PopoverInvokerElement 1282 mozilla::dom::Element* GetPopoverTargetElement() const; 1283 void SetPopoverTargetElement(mozilla::dom::Element*); 1284 void GetPopoverTargetAction(nsAString& aValue) const { 1285 GetHTMLEnumAttr(nsGkAtoms::popovertargetaction, aValue); 1286 } 1287 void SetPopoverTargetAction(const nsAString& aValue) { 1288 SetHTMLAttr(nsGkAtoms::popovertargetaction, aValue); 1289 } 1290 1291 /** 1292 * https://html.spec.whatwg.org/#popover-target-attribute-activation-behavior 1293 */ 1294 MOZ_CAN_RUN_SCRIPT void HandlePopoverTargetAction(mozilla::dom::Element*); 1295 1296 /** 1297 * Get the presentation state for a piece of content, or create it if it does 1298 * not exist. Generally used by SaveState(). 1299 */ 1300 mozilla::PresState* GetPrimaryPresState(); 1301 1302 /** 1303 * Called when we have been cloned and adopted, and the information of the 1304 * node has been changed. 1305 */ 1306 void NodeInfoChanged(Document* aOldDoc) override; 1307 1308 void GetFormAction(nsString& aValue); 1309 1310 protected: 1311 /** 1312 * Restore from presentation state. You pass in the presentation state for 1313 * this form control (generated with GenerateStateKey() + "-C") and the form 1314 * control will grab its state from there. 1315 * 1316 * @param aState the pres state to use to restore the control 1317 * @return true if the form control was a checkbox and its 1318 * checked state was restored, false otherwise. 1319 */ 1320 virtual bool RestoreState(mozilla::PresState* aState) { return false; } 1321 1322 /** 1323 * Restore the state for a form control in response to the element being 1324 * inserted into the document by the parser. Ends up calling RestoreState(). 1325 * 1326 * GenerateStateKey() must already have been called. 1327 * 1328 * @return false if RestoreState() was not called, the return 1329 * value of RestoreState() otherwise. 1330 */ 1331 bool RestoreFormControlState(); 1332 1333 /* Generates the state key for saving the form state in the session if not 1334 computed already. The result is stored in mStateKey. */ 1335 void GenerateStateKey(); 1336 1337 int32_t GetParserInsertedControlNumberForStateKey() const override { 1338 return mControlNumber; 1339 } 1340 1341 /* Used to store the key to that element in the session. Is void until 1342 GenerateStateKey has been used */ 1343 nsCString mStateKey; 1344 1345 // A number for this form control that is unique within its owner document. 1346 // This is only set to a number for elements inserted into the document by 1347 // the parser from the network. Otherwise, it is -1. 1348 int32_t mControlNumber; 1349 }; 1350 1351 #define NS_INTERFACE_MAP_ENTRY_IF_TAG(_interface, _tag) \ 1352 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(_interface, \ 1353 mNodeInfo->Equals(nsGkAtoms::_tag)) 1354 1355 namespace mozilla::dom { 1356 1357 using HTMLContentCreatorFunction = 1358 nsGenericHTMLElement* (*)(already_AddRefed<mozilla::dom::NodeInfo>&&, 1359 mozilla::dom::FromParser); 1360 1361 } // namespace mozilla::dom 1362 1363 /** 1364 * A macro to declare the NS_NewHTMLXXXElement() functions. 1365 */ 1366 #define NS_DECLARE_NS_NEW_HTML_ELEMENT(_elementName) \ 1367 namespace mozilla { \ 1368 namespace dom { \ 1369 class HTML##_elementName##Element; \ 1370 } \ 1371 } \ 1372 nsGenericHTMLElement* NS_NewHTML##_elementName##Element( \ 1373 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, \ 1374 mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER); 1375 1376 #define NS_DECLARE_NS_NEW_HTML_ELEMENT_AS_SHARED(_elementName) \ 1377 inline nsGenericHTMLElement* NS_NewHTML##_elementName##Element( \ 1378 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, \ 1379 mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER) { \ 1380 return NS_NewHTMLSharedElement(std::move(aNodeInfo), aFromParser); \ 1381 } 1382 1383 /** 1384 * A macro to implement the NS_NewHTMLXXXElement() functions. 1385 */ 1386 #define NS_IMPL_NS_NEW_HTML_ELEMENT(_elementName) \ 1387 nsGenericHTMLElement* NS_NewHTML##_elementName##Element( \ 1388 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, \ 1389 mozilla::dom::FromParser aFromParser) { \ 1390 RefPtr<mozilla::dom::NodeInfo> nodeInfo(aNodeInfo); \ 1391 auto* nim = nodeInfo->NodeInfoManager(); \ 1392 MOZ_ASSERT(nim); \ 1393 return new (nim) \ 1394 mozilla::dom::HTML##_elementName##Element(nodeInfo.forget()); \ 1395 } 1396 1397 #define NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(_elementName) \ 1398 nsGenericHTMLElement* NS_NewHTML##_elementName##Element( \ 1399 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, \ 1400 mozilla::dom::FromParser aFromParser) { \ 1401 RefPtr<mozilla::dom::NodeInfo> nodeInfo(aNodeInfo); \ 1402 auto* nim = nodeInfo->NodeInfoManager(); \ 1403 MOZ_ASSERT(nim); \ 1404 return new (nim) mozilla::dom::HTML##_elementName##Element( \ 1405 nodeInfo.forget(), aFromParser); \ 1406 } 1407 1408 // Here, we expand 'NS_DECLARE_NS_NEW_HTML_ELEMENT()' by hand. 1409 // (Calling the macro directly (with no args) produces compiler warnings.) 1410 nsGenericHTMLElement* NS_NewHTMLElement( 1411 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, 1412 mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER); 1413 1414 // Distinct from the above in order to have function pointer that compared 1415 // unequal to a function pointer to the above. 1416 nsGenericHTMLElement* NS_NewCustomElement( 1417 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, 1418 mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER); 1419 1420 NS_DECLARE_NS_NEW_HTML_ELEMENT(Shared) 1421 NS_DECLARE_NS_NEW_HTML_ELEMENT(SharedList) 1422 1423 NS_DECLARE_NS_NEW_HTML_ELEMENT(Anchor) 1424 NS_DECLARE_NS_NEW_HTML_ELEMENT(Area) 1425 NS_DECLARE_NS_NEW_HTML_ELEMENT(Audio) 1426 NS_DECLARE_NS_NEW_HTML_ELEMENT(BR) 1427 NS_DECLARE_NS_NEW_HTML_ELEMENT(Body) 1428 NS_DECLARE_NS_NEW_HTML_ELEMENT(Button) 1429 NS_DECLARE_NS_NEW_HTML_ELEMENT(Canvas) 1430 NS_DECLARE_NS_NEW_HTML_ELEMENT(Content) 1431 NS_DECLARE_NS_NEW_HTML_ELEMENT(Mod) 1432 NS_DECLARE_NS_NEW_HTML_ELEMENT(Data) 1433 NS_DECLARE_NS_NEW_HTML_ELEMENT(DataList) 1434 NS_DECLARE_NS_NEW_HTML_ELEMENT(Details) 1435 NS_DECLARE_NS_NEW_HTML_ELEMENT(Dialog) 1436 NS_DECLARE_NS_NEW_HTML_ELEMENT(Div) 1437 NS_DECLARE_NS_NEW_HTML_ELEMENT(Embed) 1438 NS_DECLARE_NS_NEW_HTML_ELEMENT(FieldSet) 1439 NS_DECLARE_NS_NEW_HTML_ELEMENT(Font) 1440 NS_DECLARE_NS_NEW_HTML_ELEMENT(Form) 1441 NS_DECLARE_NS_NEW_HTML_ELEMENT(Frame) 1442 NS_DECLARE_NS_NEW_HTML_ELEMENT(FrameSet) 1443 NS_DECLARE_NS_NEW_HTML_ELEMENT(HR) 1444 NS_DECLARE_NS_NEW_HTML_ELEMENT_AS_SHARED(Head) 1445 NS_DECLARE_NS_NEW_HTML_ELEMENT(Heading) 1446 NS_DECLARE_NS_NEW_HTML_ELEMENT_AS_SHARED(Html) 1447 NS_DECLARE_NS_NEW_HTML_ELEMENT(IFrame) 1448 NS_DECLARE_NS_NEW_HTML_ELEMENT(Image) 1449 NS_DECLARE_NS_NEW_HTML_ELEMENT(Input) 1450 NS_DECLARE_NS_NEW_HTML_ELEMENT(LI) 1451 NS_DECLARE_NS_NEW_HTML_ELEMENT(Label) 1452 NS_DECLARE_NS_NEW_HTML_ELEMENT(Legend) 1453 NS_DECLARE_NS_NEW_HTML_ELEMENT(Link) 1454 NS_DECLARE_NS_NEW_HTML_ELEMENT(Marquee) 1455 NS_DECLARE_NS_NEW_HTML_ELEMENT(Map) 1456 NS_DECLARE_NS_NEW_HTML_ELEMENT(Menu) 1457 NS_DECLARE_NS_NEW_HTML_ELEMENT(Meta) 1458 NS_DECLARE_NS_NEW_HTML_ELEMENT(Meter) 1459 NS_DECLARE_NS_NEW_HTML_ELEMENT(Object) 1460 NS_DECLARE_NS_NEW_HTML_ELEMENT(OptGroup) 1461 NS_DECLARE_NS_NEW_HTML_ELEMENT(Option) 1462 NS_DECLARE_NS_NEW_HTML_ELEMENT(Output) 1463 NS_DECLARE_NS_NEW_HTML_ELEMENT(Paragraph) 1464 NS_DECLARE_NS_NEW_HTML_ELEMENT(Picture) 1465 NS_DECLARE_NS_NEW_HTML_ELEMENT(Pre) 1466 NS_DECLARE_NS_NEW_HTML_ELEMENT(Progress) 1467 NS_DECLARE_NS_NEW_HTML_ELEMENT(Script) 1468 NS_DECLARE_NS_NEW_HTML_ELEMENT(Select) 1469 NS_DECLARE_NS_NEW_HTML_ELEMENT(Slot) 1470 NS_DECLARE_NS_NEW_HTML_ELEMENT(Source) 1471 NS_DECLARE_NS_NEW_HTML_ELEMENT(Span) 1472 NS_DECLARE_NS_NEW_HTML_ELEMENT(Style) 1473 NS_DECLARE_NS_NEW_HTML_ELEMENT(Summary) 1474 NS_DECLARE_NS_NEW_HTML_ELEMENT(TableCaption) 1475 NS_DECLARE_NS_NEW_HTML_ELEMENT(TableCell) 1476 NS_DECLARE_NS_NEW_HTML_ELEMENT(TableCol) 1477 NS_DECLARE_NS_NEW_HTML_ELEMENT(Table) 1478 NS_DECLARE_NS_NEW_HTML_ELEMENT(TableRow) 1479 NS_DECLARE_NS_NEW_HTML_ELEMENT(TableSection) 1480 NS_DECLARE_NS_NEW_HTML_ELEMENT(Tbody) 1481 NS_DECLARE_NS_NEW_HTML_ELEMENT(Template) 1482 NS_DECLARE_NS_NEW_HTML_ELEMENT(TextArea) 1483 NS_DECLARE_NS_NEW_HTML_ELEMENT(Tfoot) 1484 NS_DECLARE_NS_NEW_HTML_ELEMENT(Thead) 1485 NS_DECLARE_NS_NEW_HTML_ELEMENT(Time) 1486 NS_DECLARE_NS_NEW_HTML_ELEMENT(Title) 1487 NS_DECLARE_NS_NEW_HTML_ELEMENT(Track) 1488 NS_DECLARE_NS_NEW_HTML_ELEMENT(Unknown) 1489 NS_DECLARE_NS_NEW_HTML_ELEMENT(Video) 1490 1491 #endif /* nsGenericHTMLElement_h___ */