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/. */
7 #include "nsHTMLDocument.h"
9 #include "mozilla/DebugOnly.h"
10 #include "mozilla/PresShell.h"
11 #include "mozilla/StaticPrefs_intl.h"
12 #include "nsCommandManager.h"
15 #include "nsPrintfCString.h"
16 #include "nsReadableUtils.h"
17 #include "nsUnicharUtils.h"
18 #include "nsIHTMLContentSink.h"
19 #include "nsIProtocolHandler.h"
20 #include "nsIXMLContentSink.h"
21 #include "nsHTMLParts.h"
22 #include "nsGkAtoms.h"
23 #include "nsPresContext.h"
24 #include "nsPIDOMWindow.h"
25 #include "nsDOMString.h"
26 #include "nsIStreamListener.h"
28 #include "nsNetUtil.h"
29 #include "nsIDocumentViewer.h"
30 #include "nsDocShell.h"
31 #include "nsDocShellLoadTypes.h"
32 #include "nsIScriptContext.h"
33 #include "nsContentList.h"
35 #include "nsIPrincipal.h"
36 #include "nsJSPrincipals.h"
37 #include "nsAttrName.h"
40 #include "mozilla/parser/PrototypeDocumentParser.h"
41 #include "mozilla/dom/PrototypeDocumentContentSink.h"
42 #include "nsNameSpaceManager.h"
43 #include "nsGenericHTMLElement.h"
44 #include "mozilla/css/Loader.h"
45 #include "nsFrameSelection.h"
47 #include "nsContentUtils.h"
48 #include "nsJSUtils.h"
49 #include "DocumentInlines.h"
50 #include "nsICachingChannel.h"
51 #include "nsIScriptElement.h"
52 #include "nsArrayUtils.h"
55 #include "nsBidiUtils.h"
57 #include "mozilla/Encoding.h"
58 #include "mozilla/EventListenerManager.h"
59 #include "mozilla/IdentifierMapEntry.h"
60 #include "mozilla/LoadInfo.h"
61 #include "nsNodeInfoManager.h"
63 #include "mozAutoDocUpdate.h"
64 #include "nsCCUncollectableMarker.h"
65 #include "nsHtml5Module.h"
66 #include "mozilla/dom/Element.h"
67 #include "mozilla/Preferences.h"
68 #include "nsMimeTypes.h"
69 #include "nsIRequest.h"
70 #include "nsHtml5TreeOpExecutor.h"
71 #include "nsHtml5Parser.h"
73 #include "nsSandboxFlags.h"
74 #include "mozilla/dom/HTMLBodyElement.h"
75 #include "mozilla/dom/HTMLDocumentBinding.h"
76 #include "mozilla/dom/nsCSPContext.h"
77 #include "mozilla/dom/Selection.h"
78 #include "mozilla/dom/ShadowIncludingTreeIterator.h"
79 #include "nsCharsetSource.h"
80 #include "nsFocusManager.h"
82 #include "nsIContent.h"
83 #include "mozilla/ScopeExit.h"
84 #include "mozilla/StyleSheet.h"
85 #include "mozilla/StyleSheetInlines.h"
86 #include "mozilla/Unused.h"
88 using namespace mozilla
;
89 using namespace mozilla::dom
;
93 // #define DEBUG_charset
95 // ==================================================================
97 // ==================================================================
99 static bool IsAsciiCompatible(const Encoding
* aEncoding
) {
100 return aEncoding
->IsAsciiCompatible() || aEncoding
== ISO_2022_JP_ENCODING
;
103 nsresult
NS_NewHTMLDocument(Document
** aInstancePtrResult
,
104 nsIPrincipal
* aPrincipal
,
105 nsIPrincipal
* aPartitionedPrincipal
,
106 bool aLoadedAsData
) {
107 RefPtr
<nsHTMLDocument
> doc
= new nsHTMLDocument();
109 nsresult rv
= doc
->Init(aPrincipal
, aPartitionedPrincipal
);
112 *aInstancePtrResult
= nullptr;
116 doc
->SetLoadedAsData(aLoadedAsData
, /* aConsiderForMemoryReporting */ true);
117 doc
.forget(aInstancePtrResult
);
122 nsHTMLDocument::nsHTMLDocument()
123 : Document("text/html"),
124 mContentListHolder(nullptr),
127 mWarnedWidthHeight(false),
131 mDefaultElementType
= kNameSpaceID_XHTML
;
132 mCompatMode
= eCompatibility_NavQuirks
;
135 nsHTMLDocument::~nsHTMLDocument() = default;
137 JSObject
* nsHTMLDocument::WrapNode(JSContext
* aCx
,
138 JS::Handle
<JSObject
*> aGivenProto
) {
139 return HTMLDocument_Binding::Wrap(aCx
, this, aGivenProto
);
142 nsresult
nsHTMLDocument::Init(nsIPrincipal
* aPrincipal
,
143 nsIPrincipal
* aPartitionedPrincipal
) {
144 nsresult rv
= Document::Init(aPrincipal
, aPartitionedPrincipal
);
145 NS_ENSURE_SUCCESS(rv
, rv
);
147 // Now reset the compatibility mode of the CSSLoader
148 // to match our compat mode.
149 CSSLoader()->SetCompatibilityMode(mCompatMode
);
154 void nsHTMLDocument::Reset(nsIChannel
* aChannel
, nsILoadGroup
* aLoadGroup
) {
155 Document::Reset(aChannel
, aLoadGroup
);
158 aChannel
->GetLoadFlags(&mLoadFlags
);
162 void nsHTMLDocument::ResetToURI(nsIURI
* aURI
, nsILoadGroup
* aLoadGroup
,
163 nsIPrincipal
* aPrincipal
,
164 nsIPrincipal
* aPartitionedPrincipal
) {
165 mLoadFlags
= nsIRequest::LOAD_NORMAL
;
167 Document::ResetToURI(aURI
, aLoadGroup
, aPrincipal
, aPartitionedPrincipal
);
178 // Make the content type default to "text/html", we are a HTML
179 // document, after all. Once we start getting data, this may be
181 SetContentType(nsDependentCString("text/html"));
184 void nsHTMLDocument::TryReloadCharset(nsIDocumentViewer
* aViewer
,
185 int32_t& aCharsetSource
,
186 NotNull
<const Encoding
*>& aEncoding
) {
188 int32_t reloadEncodingSource
;
189 const auto reloadEncoding
=
190 aViewer
->GetReloadEncodingAndSource(&reloadEncodingSource
);
191 if (kCharsetUninitialized
!= reloadEncodingSource
) {
192 aViewer
->ForgetReloadEncoding();
194 if (reloadEncodingSource
<= aCharsetSource
||
195 !IsAsciiCompatible(aEncoding
)) {
199 if (reloadEncoding
&& IsAsciiCompatible(reloadEncoding
)) {
200 aCharsetSource
= reloadEncodingSource
;
201 aEncoding
= WrapNotNull(reloadEncoding
);
207 void nsHTMLDocument::TryUserForcedCharset(nsIDocumentViewer
* aViewer
,
208 nsIDocShell
* aDocShell
,
209 int32_t& aCharsetSource
,
210 NotNull
<const Encoding
*>& aEncoding
,
211 bool& aForceAutoDetection
) {
212 auto resetForce
= MakeScopeExit([&] {
214 nsDocShell::Cast(aDocShell
)->ResetForcedAutodetection();
218 if (aCharsetSource
>= kCharsetFromOtherComponent
) {
222 // mCharacterSet not updated yet for channel, so check aEncoding, too.
223 if (WillIgnoreCharsetOverride() || !IsAsciiCompatible(aEncoding
)) {
227 if (aDocShell
&& nsDocShell::Cast(aDocShell
)->GetForcedAutodetection()) {
228 // This is the Character Encoding menu code path in Firefox
229 aForceAutoDetection
= true;
233 void nsHTMLDocument::TryParentCharset(nsIDocShell
* aDocShell
,
234 int32_t& aCharsetSource
,
235 NotNull
<const Encoding
*>& aEncoding
,
236 bool& aForceAutoDetection
) {
240 if (aCharsetSource
>= kCharsetFromOtherComponent
) {
244 int32_t parentSource
;
245 const Encoding
* parentCharset
;
246 nsCOMPtr
<nsIPrincipal
> parentPrincipal
;
247 aDocShell
->GetParentCharset(parentCharset
, &parentSource
,
248 getter_AddRefs(parentPrincipal
));
249 if (!parentCharset
) {
252 if (kCharsetFromInitialUserForcedAutoDetection
== parentSource
||
253 kCharsetFromFinalUserForcedAutoDetection
== parentSource
) {
254 if (WillIgnoreCharsetOverride() ||
255 !IsAsciiCompatible(aEncoding
) || // if channel said UTF-16
256 !IsAsciiCompatible(parentCharset
)) {
259 aEncoding
= WrapNotNull(parentCharset
);
260 aCharsetSource
= kCharsetFromParentFrame
;
261 aForceAutoDetection
= true;
265 if (aCharsetSource
>= kCharsetFromParentFrame
) {
269 if (kCharsetFromInitialAutoDetectionASCII
<= parentSource
) {
270 // Make sure that's OK
271 if (!NodePrincipal()->Equals(parentPrincipal
) ||
272 !IsAsciiCompatible(parentCharset
)) {
276 aEncoding
= WrapNotNull(parentCharset
);
277 aCharsetSource
= kCharsetFromParentFrame
;
281 // Using a prototype document is only allowed with chrome privilege.
282 bool ShouldUsePrototypeDocument(nsIChannel
* aChannel
, Document
* aDoc
) {
283 if (!aChannel
|| !aDoc
||
284 !StaticPrefs::dom_prototype_document_cache_enabled()) {
287 return nsContentUtils::IsChromeDoc(aDoc
);
290 nsresult
nsHTMLDocument::StartDocumentLoad(
291 const char* aCommand
, nsIChannel
* aChannel
, nsILoadGroup
* aLoadGroup
,
292 nsISupports
* aContainer
, nsIStreamListener
** aDocListener
, bool aReset
) {
294 MOZ_ASSERT(false, "Command is mandatory");
295 return NS_ERROR_INVALID_POINTER
;
297 if (mType
!= eHTML
) {
298 MOZ_ASSERT(mType
== eXHTML
);
299 MOZ_ASSERT(false, "Must not set HTML doc to XHTML mode before load start.");
300 return NS_ERROR_DOM_INVALID_STATE_ERR
;
303 nsAutoCString contentType
;
304 aChannel
->GetContentType(contentType
);
307 !strcmp(aCommand
, "view") || !strcmp(aCommand
, "external-resource");
308 mViewSource
= !strcmp(aCommand
, "view-source");
309 bool asData
= !strcmp(aCommand
, kLoadAsData
);
310 if (!(view
|| mViewSource
|| asData
)) {
311 MOZ_ASSERT(false, "Bad parser command");
312 return NS_ERROR_INVALID_ARG
;
315 bool html
= contentType
.EqualsLiteral(TEXT_HTML
);
316 bool xhtml
= !html
&& (contentType
.EqualsLiteral(APPLICATION_XHTML_XML
) ||
317 contentType
.EqualsLiteral(APPLICATION_WAPXHTML_XML
));
319 !html
&& !xhtml
&& nsContentUtils::IsPlainTextType(contentType
);
320 if (!(html
|| xhtml
|| mIsPlainText
|| mViewSource
)) {
321 MOZ_ASSERT(false, "Channel with bad content type.");
322 return NS_ERROR_INVALID_ARG
;
326 mIsPlainText
&& nsContentUtils::IsUtf8OnlyPlainTextType(contentType
);
328 bool loadAsHtml5
= true;
330 if (!mViewSource
&& xhtml
) {
331 // We're parsing XHTML as XML, remember that.
333 SetCompatibilityMode(eCompatibility_FullStandards
);
337 // TODO: Proper about:blank treatment is bug 543435
338 if (loadAsHtml5
&& view
) {
339 // mDocumentURI hasn't been set, yet, so get the URI from the channel
340 nsCOMPtr
<nsIURI
> uri
;
341 aChannel
->GetOriginalURI(getter_AddRefs(uri
));
342 // Adapted from nsDocShell:
343 // GetSpec can be expensive for some URIs, so check the scheme first.
344 if (uri
&& uri
->SchemeIs("about")) {
345 if (uri
->GetSpecOrDefault().EqualsLiteral("about:blank")) {
351 nsresult rv
= Document::StartDocumentLoad(aCommand
, aChannel
, aLoadGroup
,
352 aContainer
, aDocListener
, aReset
);
357 nsCOMPtr
<nsIURI
> uri
;
358 rv
= aChannel
->GetURI(getter_AddRefs(uri
));
363 nsCOMPtr
<nsIDocShell
> docShell(do_QueryInterface(aContainer
));
365 bool loadWithPrototype
= false;
366 RefPtr
<nsHtml5Parser
> html5Parser
;
368 html5Parser
= nsHtml5Module::NewHtml5Parser();
369 mParser
= html5Parser
;
372 html5Parser
->MarkAsNotScriptCreated("view-source-plain");
374 html5Parser
->MarkAsNotScriptCreated("plain-text");
376 } else if (mViewSource
&& !html
) {
377 html5Parser
->MarkAsNotScriptCreated("view-source-xml");
379 html5Parser
->MarkAsNotScriptCreated(aCommand
);
381 } else if (xhtml
&& ShouldUsePrototypeDocument(aChannel
, this)) {
382 loadWithPrototype
= true;
383 nsCOMPtr
<nsIURI
> originalURI
;
384 aChannel
->GetOriginalURI(getter_AddRefs(originalURI
));
385 mParser
= new mozilla::parser::PrototypeDocumentParser(originalURI
, this);
387 mParser
= new nsParser();
390 // Look for the parent document. Note that at this point we don't have our
391 // content viewer set up yet, and therefore do not have a useful
394 // in this block of code, if we get an error result, we return it
395 // but if we get a null pointer, that's perfectly legal for parent
397 nsCOMPtr
<nsIDocShellTreeItem
> parentAsItem
;
399 docShell
->GetInProcessSameTypeParent(getter_AddRefs(parentAsItem
));
402 nsCOMPtr
<nsIDocShell
> parent(do_QueryInterface(parentAsItem
));
403 nsCOMPtr
<nsIDocumentViewer
> parentViewer
;
405 rv
= parent
->GetDocViewer(getter_AddRefs(parentViewer
));
406 NS_ENSURE_SUCCESS(rv
, rv
);
409 nsCOMPtr
<nsIDocumentViewer
> viewer
;
411 docShell
->GetDocViewer(getter_AddRefs(viewer
));
414 viewer
= std::move(parentViewer
);
417 nsAutoCString urlSpec
;
418 uri
->GetSpec(urlSpec
);
420 printf("Determining charset for %s\n", urlSpec
.get());
423 // These are the charset source and charset for our document
424 bool forceAutoDetection
= false;
425 int32_t charsetSource
= kCharsetUninitialized
;
426 auto encoding
= UTF_8_ENCODING
;
428 // For error reporting and referrer policy setting
429 nsHtml5TreeOpExecutor
* executor
= nullptr;
431 executor
= static_cast<nsHtml5TreeOpExecutor
*>(mParser
->GetContentSink());
435 charsetSource
= kCharsetFromUtf8OnlyMime
;
436 } else if (!IsHTMLDocument() || !docShell
) { // no docshell for text/html XHR
438 IsHTMLDocument() ? kCharsetFromFallback
: kCharsetFromDocTypeDefault
;
439 TryChannelCharset(aChannel
, charsetSource
, encoding
, executor
);
441 NS_ASSERTION(docShell
, "Unexpected null value");
443 // The following will try to get the character encoding from various
444 // sources. Each Try* function will return early if the source is already
445 // at least as large as any of the sources it might look at. Some of
446 // these functions (like TryReloadCharset and TryParentCharset) can set
447 // charsetSource to various values depending on where the charset they
448 // end up finding originally comes from.
450 // Try the channel's charset (e.g., charset from HTTP
451 // "Content-Type" header) first. This way, we get to reject overrides in
452 // TryParentCharset and TryUserForcedCharset if the channel said UTF-16.
453 // This is to avoid socially engineered XSS by adding user-supplied
454 // content to a UTF-16 site such that the byte have a dangerous
455 // interpretation as ASCII and the user can be lured to using the
457 TryChannelCharset(aChannel
, charsetSource
, encoding
, executor
);
459 TryUserForcedCharset(viewer
, docShell
, charsetSource
, encoding
,
462 TryReloadCharset(viewer
, charsetSource
, encoding
); // For encoding reload
463 TryParentCharset(docShell
, charsetSource
, encoding
, forceAutoDetection
);
466 SetDocumentCharacterSetSource(charsetSource
);
467 SetDocumentCharacterSet(encoding
);
469 // Set the parser as the stream listener for the document loader...
471 nsCOMPtr
<nsIStreamListener
> listener
= mParser
->GetStreamListener();
472 listener
.forget(aDocListener
);
475 printf(" charset = %s source %d\n", charset
.get(), charsetSource
);
477 mParser
->SetDocumentCharset(encoding
, charsetSource
, forceAutoDetection
);
478 mParser
->SetCommand(aCommand
);
480 if (!IsHTMLDocument()) {
481 MOZ_ASSERT(!loadAsHtml5
);
482 if (loadWithPrototype
) {
483 nsCOMPtr
<nsIContentSink
> sink
;
484 NS_NewPrototypeDocumentContentSink(getter_AddRefs(sink
), this, uri
,
486 mParser
->SetContentSink(sink
);
488 nsCOMPtr
<nsIXMLContentSink
> xmlsink
;
489 NS_NewXMLContentSink(getter_AddRefs(xmlsink
), this, uri
, docShell
,
491 mParser
->SetContentSink(xmlsink
);
495 html5Parser
->Initialize(this, uri
, docShell
, aChannel
);
497 // about:blank *only*
498 nsCOMPtr
<nsIHTMLContentSink
> htmlsink
;
499 NS_NewHTMLContentSink(getter_AddRefs(htmlsink
), this, uri
, docShell
,
501 mParser
->SetContentSink(htmlsink
);
505 // parser the content of the URI
511 bool nsHTMLDocument::UseWidthDeviceWidthFallbackViewport() const {
513 // Plain text documents are simple enough that font inflation doesn't offer
514 // any appreciable advantage over defaulting to "width=device-width" and
515 // subsequently turning on word-wrapping.
518 return Document::UseWidthDeviceWidthFallbackViewport();
521 Element
* nsHTMLDocument::GetUnfocusedKeyEventTarget() {
522 if (nsGenericHTMLElement
* body
= GetBody()) {
525 return Document::GetUnfocusedKeyEventTarget();
528 bool nsHTMLDocument::IsRegistrableDomainSuffixOfOrEqualTo(
529 const nsAString
& aHostSuffixString
, const nsACString
& aOrigHost
) {
530 // https://html.spec.whatwg.org/multipage/browsers.html#is-a-registrable-domain-suffix-of-or-is-equal-to
531 if (aHostSuffixString
.IsEmpty()) {
535 nsCOMPtr
<nsIURI
> origURI
= CreateInheritingURIForHost(aOrigHost
);
537 // Error: failed to parse input domain
541 nsCOMPtr
<nsIURI
> newURI
=
542 RegistrableDomainSuffixOfInternal(aHostSuffixString
, origURI
);
544 // Error: illegal domain
550 void nsHTMLDocument::AddedForm() { ++mNumForms
; }
552 void nsHTMLDocument::RemovedForm() { --mNumForms
; }
554 int32_t nsHTMLDocument::GetNumFormsSynchronous() const { return mNumForms
; }
556 bool nsHTMLDocument::ResolveName(JSContext
* aCx
, const nsAString
& aName
,
557 JS::MutableHandle
<JS::Value
> aRetval
,
558 ErrorResult
& aError
) {
559 IdentifierMapEntry
* entry
= mIdentifierMap
.GetEntry(aName
);
564 nsBaseContentList
* list
= entry
->GetNameContentList();
565 uint32_t length
= list
? list
->Length() : 0;
570 // The list contains more than one element, return the whole list.
571 if (!ToJSValue(aCx
, list
, aRetval
)) {
572 aError
.NoteJSContextException(aCx
);
578 // Only one element in the list, return the element instead of returning
580 node
= list
->Item(0);
582 // No named items were found, see if there's one registerd by id for aName.
583 Element
* e
= entry
->GetIdElement();
585 if (!e
|| !nsGenericHTMLElement::ShouldExposeIdAsHTMLDocumentProperty(e
)) {
592 if (!ToJSValue(aCx
, node
, aRetval
)) {
593 aError
.NoteJSContextException(aCx
);
600 void nsHTMLDocument::GetSupportedNames(nsTArray
<nsString
>& aNames
) {
601 for (const auto& entry
: mIdentifierMap
) {
602 if (entry
.HasNameElement() ||
603 entry
.HasIdElementExposedAsHTMLDocumentProperty()) {
604 aNames
.AppendElement(entry
.GetKeyAsString());
609 //----------------------------
611 // forms related stuff
613 bool nsHTMLDocument::MatchFormControls(Element
* aElement
, int32_t aNamespaceID
,
614 nsAtom
* aAtom
, void* aData
) {
615 return aElement
->IsHTMLFormControlElement();
618 nsresult
nsHTMLDocument::Clone(dom::NodeInfo
* aNodeInfo
,
619 nsINode
** aResult
) const {
620 NS_ASSERTION(aNodeInfo
->NodeInfoManager() == mNodeInfoManager
,
621 "Can't import this document into another document!");
623 RefPtr
<nsHTMLDocument
> clone
= new nsHTMLDocument();
624 nsresult rv
= CloneDocHelper(clone
.get());
625 NS_ENSURE_SUCCESS(rv
, rv
);
627 // State from nsHTMLDocument
628 clone
->mLoadFlags
= mLoadFlags
;
630 clone
.forget(aResult
);
635 void nsHTMLDocument::DocAddSizeOfExcludingThis(
636 nsWindowSizes
& aWindowSizes
) const {
637 Document::DocAddSizeOfExcludingThis(aWindowSizes
);
639 // Measurement of the following members may be added later if DMD finds it is
645 bool nsHTMLDocument::WillIgnoreCharsetOverride() {
646 if (mEncodingMenuDisabled
) {
649 if (mType
!= eHTML
) {
650 MOZ_ASSERT(mType
== eXHTML
);
653 if (mCharacterSetSource
>= kCharsetFromByteOrderMark
) {
656 if (!mCharacterSet
->IsAsciiCompatible() &&
657 mCharacterSet
!= ISO_2022_JP_ENCODING
) {
660 nsIURI
* uri
= GetOriginalURI();
662 if (uri
->SchemeIs("about")) {
666 nsresult rv
= NS_URIChainHasFlags(
667 uri
, nsIProtocolHandler::URI_IS_UI_RESOURCE
, &isResource
);
668 if (NS_FAILED(rv
) || isResource
) {
673 switch (mCharacterSetSource
) {
674 case kCharsetUninitialized
:
675 case kCharsetFromFallback
:
676 case kCharsetFromDocTypeDefault
:
677 case kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8
:
678 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD
:
679 case kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII
:
680 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD
:
681 case kCharsetFromParentFrame
:
682 case kCharsetFromXmlDeclaration
:
683 case kCharsetFromMetaTag
:
684 case kCharsetFromChannel
:
688 bool potentialEffect
= false;
689 nsIPrincipal
* parentPrincipal
= NodePrincipal();
691 auto subDoc
= [&potentialEffect
, parentPrincipal
](Document
& aSubDoc
) {
692 if (parentPrincipal
->Equals(aSubDoc
.NodePrincipal()) &&
693 !aSubDoc
.WillIgnoreCharsetOverride()) {
694 potentialEffect
= true;
695 return CallState::Stop
;
697 return CallState::Continue
;
699 EnumerateSubDocuments(subDoc
);
701 return !potentialEffect
;
704 void nsHTMLDocument::GetFormsAndFormControls(nsContentList
** aFormList
,
705 nsContentList
** aFormControlList
) {
706 RefPtr
<ContentListHolder
> holder
= mContentListHolder
;
708 // Flush our content model so it'll be up to date
709 // If this becomes unnecessary and the following line is removed,
710 // please also remove the corresponding flush operation from
711 // nsHtml5TreeBuilderCppSupplement.h. (Look for "See bug 497861." there.)
712 // XXXsmaug nsHtml5TreeBuilderCppSupplement doesn't seem to have such flush
714 FlushPendingNotifications(FlushType::Content
);
716 RefPtr
<nsContentList
> htmlForms
= GetExistingForms();
718 // If the document doesn't have an existing forms content list, create a
719 // new one which will be released soon by ContentListHolder. The idea is
720 // that we don't have that list hanging around for a long time and slowing
721 // down future DOM mutations.
723 // Please keep this in sync with Document::Forms().
724 htmlForms
= new nsContentList(this, kNameSpaceID_XHTML
, nsGkAtoms::form
,
727 /* aLiveList = */ true);
730 RefPtr
<nsContentList
> htmlFormControls
= new nsContentList(
731 this, nsHTMLDocument::MatchFormControls
, nullptr, nullptr,
733 /* aMatchAtom = */ nullptr,
734 /* aMatchNameSpaceId = */ kNameSpaceID_None
,
735 /* aFuncMayDependOnAttr = */ true,
736 /* aLiveList = */ true);
738 holder
= new ContentListHolder(this, htmlForms
, htmlFormControls
);
739 RefPtr
<ContentListHolder
> runnable
= holder
;
740 if (NS_SUCCEEDED(Dispatch(runnable
.forget()))) {
741 mContentListHolder
= holder
;
745 NS_ADDREF(*aFormList
= holder
->mFormList
);
746 NS_ADDREF(*aFormControlList
= holder
->mFormControlList
);