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"
14 #include "nsGlobalWindow.h"
16 #include "nsPrintfCString.h"
17 #include "nsReadableUtils.h"
18 #include "nsUnicharUtils.h"
19 #include "nsGlobalWindowInner.h"
20 #include "nsIHTMLContentSink.h"
21 #include "nsIProtocolHandler.h"
22 #include "nsIXMLContentSink.h"
23 #include "nsHTMLParts.h"
24 #include "nsHTMLStyleSheet.h"
25 #include "nsGkAtoms.h"
26 #include "nsPresContext.h"
27 #include "nsPIDOMWindow.h"
28 #include "nsDOMString.h"
29 #include "nsIStreamListener.h"
31 #include "nsNetUtil.h"
32 #include "nsIContentViewer.h"
33 #include "nsDocShell.h"
34 #include "nsDocShellLoadTypes.h"
35 #include "nsIScriptContext.h"
36 #include "nsContentList.h"
38 #include "nsIPrincipal.h"
39 #include "nsJSPrincipals.h"
40 #include "nsAttrName.h"
43 #include "nsParserCIID.h"
44 #include "mozilla/parser/PrototypeDocumentParser.h"
45 #include "mozilla/dom/PrototypeDocumentContentSink.h"
46 #include "nsNameSpaceManager.h"
47 #include "nsGenericHTMLElement.h"
48 #include "mozilla/css/Loader.h"
49 #include "nsFrameSelection.h"
51 #include "nsContentUtils.h"
52 #include "nsJSUtils.h"
53 #include "DocumentInlines.h"
54 #include "nsICachingChannel.h"
55 #include "nsIContentViewer.h"
56 #include "nsIScriptElement.h"
57 #include "nsArrayUtils.h"
60 #include "nsBidiUtils.h"
62 #include "mozilla/Encoding.h"
63 #include "mozilla/EventListenerManager.h"
64 #include "mozilla/IdentifierMapEntry.h"
65 #include "mozilla/LoadInfo.h"
66 #include "nsNodeInfoManager.h"
68 #include "mozAutoDocUpdate.h"
69 #include "nsCCUncollectableMarker.h"
70 #include "nsHtml5Module.h"
71 #include "mozilla/dom/Element.h"
72 #include "mozilla/Preferences.h"
73 #include "nsMimeTypes.h"
74 #include "nsIRequest.h"
75 #include "nsHtml5TreeOpExecutor.h"
76 #include "nsHtml5Parser.h"
77 #include "nsSandboxFlags.h"
78 #include "mozilla/dom/HTMLBodyElement.h"
79 #include "mozilla/dom/HTMLDocumentBinding.h"
80 #include "mozilla/dom/nsCSPContext.h"
81 #include "mozilla/dom/Selection.h"
82 #include "mozilla/dom/ShadowIncludingTreeIterator.h"
83 #include "nsCharsetSource.h"
84 #include "nsFocusManager.h"
86 #include "nsIContent.h"
87 #include "mozilla/StyleSheet.h"
88 #include "mozilla/StyleSheetInlines.h"
89 #include "mozilla/Unused.h"
91 using namespace mozilla
;
92 using namespace mozilla::dom
;
96 //#define DEBUG_charset
98 static NS_DEFINE_CID(kCParserCID
, NS_PARSER_CID
);
100 // ==================================================================
102 // ==================================================================
104 static bool IsAsciiCompatible(const Encoding
* aEncoding
) {
105 return aEncoding
->IsAsciiCompatible() || aEncoding
== ISO_2022_JP_ENCODING
;
108 nsresult
NS_NewHTMLDocument(Document
** aInstancePtrResult
, bool aLoadedAsData
) {
109 RefPtr
<nsHTMLDocument
> doc
= new nsHTMLDocument();
111 nsresult rv
= doc
->Init();
114 *aInstancePtrResult
= nullptr;
118 doc
->SetLoadedAsData(aLoadedAsData
);
119 doc
.forget(aInstancePtrResult
);
124 nsHTMLDocument::nsHTMLDocument()
125 : Document("text/html"),
126 mContentListHolder(nullptr),
129 mWarnedWidthHeight(false),
130 mIsPlainText(false) {
132 mDefaultElementType
= kNameSpaceID_XHTML
;
133 mCompatMode
= eCompatibility_NavQuirks
;
136 nsHTMLDocument::~nsHTMLDocument() = default;
138 JSObject
* nsHTMLDocument::WrapNode(JSContext
* aCx
,
139 JS::Handle
<JSObject
*> aGivenProto
) {
140 return HTMLDocument_Binding::Wrap(aCx
, this, aGivenProto
);
143 nsresult
nsHTMLDocument::Init() {
144 nsresult rv
= Document::Init();
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 SetContentTypeInternal(nsDependentCString("text/html"));
184 void nsHTMLDocument::TryHintCharset(nsIContentViewer
* aCv
,
185 int32_t& aCharsetSource
,
186 NotNull
<const Encoding
*>& aEncoding
) {
188 int32_t requestCharsetSource
;
189 nsresult rv
= aCv
->GetHintCharacterSetSource(&requestCharsetSource
);
191 if (NS_SUCCEEDED(rv
) && kCharsetUninitialized
!= requestCharsetSource
) {
192 auto requestCharset
= aCv
->GetHintCharset();
193 aCv
->SetHintCharacterSetSource((int32_t)(kCharsetUninitialized
));
195 if (requestCharsetSource
<= aCharsetSource
) return;
197 if (requestCharset
&& IsAsciiCompatible(requestCharset
)) {
198 aCharsetSource
= requestCharsetSource
;
199 aEncoding
= WrapNotNull(requestCharset
);
205 void nsHTMLDocument::TryUserForcedCharset(nsIContentViewer
* aCv
,
206 nsIDocShell
* aDocShell
,
207 int32_t& aCharsetSource
,
208 NotNull
<const Encoding
*>& aEncoding
) {
209 if (kCharsetFromUserForced
<= aCharsetSource
) return;
211 // mCharacterSet not updated yet for channel, so check aEncoding, too.
212 if (WillIgnoreCharsetOverride() || !IsAsciiCompatible(aEncoding
)) {
217 // This is the Character Encoding menu code path in Firefox
218 auto encoding
= nsDocShell::Cast(aDocShell
)->GetForcedCharset();
221 if (!IsAsciiCompatible(encoding
)) {
224 aEncoding
= WrapNotNull(encoding
);
225 aCharsetSource
= kCharsetFromUserForced
;
226 aDocShell
->SetCharset(EmptyCString());
231 void nsHTMLDocument::TryCacheCharset(nsICachingChannel
* aCachingChannel
,
232 int32_t& aCharsetSource
,
233 NotNull
<const Encoding
*>& aEncoding
) {
236 if (kCharsetFromCache
<= aCharsetSource
) {
240 nsCString cachedCharset
;
241 rv
= aCachingChannel
->GetCacheTokenCachedCharset(cachedCharset
);
242 if (NS_FAILED(rv
) || cachedCharset
.IsEmpty()) {
245 // The canonical names changed, so the cache may have an old name.
246 const Encoding
* encoding
= Encoding::ForLabelNoReplacement(cachedCharset
);
250 // Check IsAsciiCompatible() even in the cache case, because the value
251 // might be stale and in the case of a stale charset that is not a rough
252 // ASCII superset, the parser has no way to recover.
253 if (!encoding
->IsAsciiCompatible() && encoding
!= ISO_2022_JP_ENCODING
) {
256 aEncoding
= WrapNotNull(encoding
);
257 aCharsetSource
= kCharsetFromCache
;
260 void nsHTMLDocument::TryParentCharset(nsIDocShell
* aDocShell
,
261 int32_t& aCharsetSource
,
262 NotNull
<const Encoding
*>& aEncoding
) {
266 if (aCharsetSource
>= kCharsetFromUserForced
) {
270 int32_t parentSource
;
271 const Encoding
* parentCharset
;
272 nsCOMPtr
<nsIPrincipal
> parentPrincipal
;
273 aDocShell
->GetParentCharset(parentCharset
, &parentSource
,
274 getter_AddRefs(parentPrincipal
));
275 if (!parentCharset
) {
278 if (kCharsetFromUserForced
== parentSource
||
279 kCharsetFromUserForcedAutoDetection
== parentSource
) {
280 if (WillIgnoreCharsetOverride() ||
281 !IsAsciiCompatible(aEncoding
) || // if channel said UTF-16
282 !IsAsciiCompatible(parentCharset
)) {
285 aEncoding
= WrapNotNull(parentCharset
);
286 aCharsetSource
= kCharsetFromUserForced
;
290 if (aCharsetSource
>= kCharsetFromParentFrame
) {
294 if (kCharsetFromCache
<= parentSource
) {
295 // Make sure that's OK
296 if (!NodePrincipal()->Equals(parentPrincipal
) ||
297 !IsAsciiCompatible(parentCharset
)) {
301 aEncoding
= WrapNotNull(parentCharset
);
302 aCharsetSource
= kCharsetFromParentFrame
;
306 // Using a prototype document is only allowed with chrome privilege.
307 bool ShouldUsePrototypeDocument(nsIChannel
* aChannel
, Document
* aDoc
) {
308 if (!aChannel
|| !aDoc
||
309 !StaticPrefs::dom_prototype_document_cache_enabled()) {
312 return nsContentUtils::IsChromeDoc(aDoc
);
315 nsresult
nsHTMLDocument::StartDocumentLoad(const char* aCommand
,
316 nsIChannel
* aChannel
,
317 nsILoadGroup
* aLoadGroup
,
318 nsISupports
* aContainer
,
319 nsIStreamListener
** aDocListener
,
320 bool aReset
, nsIContentSink
* aSink
) {
322 MOZ_ASSERT(false, "Command is mandatory");
323 return NS_ERROR_INVALID_POINTER
;
326 MOZ_ASSERT(false, "Got a sink override. Should not happen for HTML doc.");
327 return NS_ERROR_INVALID_ARG
;
329 if (mType
!= eHTML
) {
330 MOZ_ASSERT(mType
== eXHTML
);
331 MOZ_ASSERT(false, "Must not set HTML doc to XHTML mode before load start.");
332 return NS_ERROR_DOM_INVALID_STATE_ERR
;
335 nsAutoCString contentType
;
336 aChannel
->GetContentType(contentType
);
339 !strcmp(aCommand
, "view") || !strcmp(aCommand
, "external-resource");
340 bool viewSource
= !strcmp(aCommand
, "view-source");
341 bool asData
= !strcmp(aCommand
, kLoadAsData
);
342 if (!(view
|| viewSource
|| asData
)) {
343 MOZ_ASSERT(false, "Bad parser command");
344 return NS_ERROR_INVALID_ARG
;
347 bool html
= contentType
.EqualsLiteral(TEXT_HTML
);
348 bool xhtml
= !html
&& (contentType
.EqualsLiteral(APPLICATION_XHTML_XML
) ||
349 contentType
.EqualsLiteral(APPLICATION_WAPXHTML_XML
));
351 !html
&& !xhtml
&& nsContentUtils::IsPlainTextType(contentType
);
352 if (!(html
|| xhtml
|| mIsPlainText
|| viewSource
)) {
353 MOZ_ASSERT(false, "Channel with bad content type.");
354 return NS_ERROR_INVALID_ARG
;
358 mIsPlainText
&& nsContentUtils::IsUtf8OnlyPlainTextType(contentType
);
360 bool loadAsHtml5
= true;
362 if (!viewSource
&& xhtml
) {
363 // We're parsing XHTML as XML, remember that.
365 SetCompatibilityMode(eCompatibility_FullStandards
);
369 // TODO: Proper about:blank treatment is bug 543435
370 if (loadAsHtml5
&& view
) {
371 // mDocumentURI hasn't been set, yet, so get the URI from the channel
372 nsCOMPtr
<nsIURI
> uri
;
373 aChannel
->GetOriginalURI(getter_AddRefs(uri
));
374 // Adapted from nsDocShell:
375 // GetSpec can be expensive for some URIs, so check the scheme first.
376 if (uri
&& uri
->SchemeIs("about")) {
377 if (uri
->GetSpecOrDefault().EqualsLiteral("about:blank")) {
383 nsresult rv
= Document::StartDocumentLoad(aCommand
, aChannel
, aLoadGroup
,
384 aContainer
, aDocListener
, aReset
);
389 nsCOMPtr
<nsIURI
> uri
;
390 rv
= aChannel
->GetURI(getter_AddRefs(uri
));
395 nsCOMPtr
<nsICachingChannel
> cachingChan
= do_QueryInterface(aChannel
);
396 nsCOMPtr
<nsIDocShell
> docShell(do_QueryInterface(aContainer
));
398 bool loadWithPrototype
= false;
399 RefPtr
<nsHtml5Parser
> html5Parser
;
401 html5Parser
= nsHtml5Module::NewHtml5Parser();
402 mParser
= html5Parser
;
405 html5Parser
->MarkAsNotScriptCreated("view-source-plain");
407 html5Parser
->MarkAsNotScriptCreated("plain-text");
409 } else if (viewSource
&& !html
) {
410 html5Parser
->MarkAsNotScriptCreated("view-source-xml");
412 html5Parser
->MarkAsNotScriptCreated(aCommand
);
414 } else if (xhtml
&& ShouldUsePrototypeDocument(aChannel
, this)) {
415 loadWithPrototype
= true;
416 nsCOMPtr
<nsIURI
> originalURI
;
417 aChannel
->GetOriginalURI(getter_AddRefs(originalURI
));
418 mParser
= new mozilla::parser::PrototypeDocumentParser(originalURI
, this);
420 mParser
= do_CreateInstance(kCParserCID
, &rv
);
421 NS_ENSURE_SUCCESS(rv
, rv
);
424 // Look for the parent document. Note that at this point we don't have our
425 // content viewer set up yet, and therefore do not have a useful
428 // in this block of code, if we get an error result, we return it
429 // but if we get a null pointer, that's perfectly legal for parent
430 // and parentContentViewer
431 nsCOMPtr
<nsIDocShellTreeItem
> parentAsItem
;
433 docShell
->GetInProcessSameTypeParent(getter_AddRefs(parentAsItem
));
436 nsCOMPtr
<nsIDocShell
> parent(do_QueryInterface(parentAsItem
));
437 nsCOMPtr
<nsIContentViewer
> parentContentViewer
;
439 rv
= parent
->GetContentViewer(getter_AddRefs(parentContentViewer
));
440 NS_ENSURE_SUCCESS(rv
, rv
);
443 nsCOMPtr
<nsIContentViewer
> cv
;
445 docShell
->GetContentViewer(getter_AddRefs(cv
));
448 cv
= std::move(parentContentViewer
);
451 nsAutoCString urlSpec
;
452 uri
->GetSpec(urlSpec
);
454 printf("Determining charset for %s\n", urlSpec
.get());
457 // These are the charset source and charset for our document
458 int32_t charsetSource
;
459 auto encoding
= UTF_8_ENCODING
;
461 // For error reporting and referrer policy setting
462 nsHtml5TreeOpExecutor
* executor
= nullptr;
464 executor
= static_cast<nsHtml5TreeOpExecutor
*>(mParser
->GetContentSink());
468 charsetSource
= kCharsetFromUtf8OnlyMime
;
469 } else if (!IsHTMLDocument() || !docShell
) { // no docshell for text/html XHR
471 IsHTMLDocument() ? kCharsetFromFallback
: kCharsetFromDocTypeDefault
;
472 TryChannelCharset(aChannel
, charsetSource
, encoding
, executor
);
474 NS_ASSERTION(docShell
, "Unexpected null value");
476 charsetSource
= kCharsetUninitialized
;
477 // Used for .in and .lk TLDs. .jp is handled in the parser.
478 encoding
= WINDOWS_1252_ENCODING
;
480 // The following will try to get the character encoding from various
481 // sources. Each Try* function will return early if the source is already
482 // at least as large as any of the sources it might look at. Some of
483 // these functions (like TryHintCharset and TryParentCharset) can set
484 // charsetSource to various values depending on where the charset they
485 // end up finding originally comes from.
487 // Try the channel's charset (e.g., charset from HTTP
488 // "Content-Type" header) first. This way, we get to reject overrides in
489 // TryParentCharset and TryUserForcedCharset if the channel said UTF-16.
490 // This is to avoid socially engineered XSS by adding user-supplied
491 // content to a UTF-16 site such that the byte have a dangerous
492 // interpretation as ASCII and the user can be lured to using the
494 TryChannelCharset(aChannel
, charsetSource
, encoding
, executor
);
496 TryUserForcedCharset(cv
, docShell
, charsetSource
, encoding
);
498 TryHintCharset(cv
, charsetSource
, encoding
); // For encoding reload
499 TryParentCharset(docShell
, charsetSource
, encoding
);
501 if (cachingChan
&& !urlSpec
.IsEmpty()) {
502 TryCacheCharset(cachingChan
, charsetSource
, encoding
);
506 SetDocumentCharacterSetSource(charsetSource
);
507 SetDocumentCharacterSet(encoding
);
510 nsAutoCString charset
;
511 encoding
->Name(charset
);
512 rv
= cachingChan
->SetCacheTokenCachedCharset(charset
);
513 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
), "cannot SetMetaDataElement");
514 rv
= NS_OK
; // don't propagate error
517 // Set the parser as the stream listener for the document loader...
519 nsCOMPtr
<nsIStreamListener
> listener
= mParser
->GetStreamListener();
520 listener
.forget(aDocListener
);
523 printf(" charset = %s source %d\n", charset
.get(), charsetSource
);
525 mParser
->SetDocumentCharset(encoding
, charsetSource
);
526 mParser
->SetCommand(aCommand
);
528 if (!IsHTMLDocument()) {
529 MOZ_ASSERT(!loadAsHtml5
);
530 if (loadWithPrototype
) {
531 nsCOMPtr
<nsIContentSink
> sink
;
532 NS_NewPrototypeDocumentContentSink(getter_AddRefs(sink
), this, uri
,
534 mParser
->SetContentSink(sink
);
536 nsCOMPtr
<nsIXMLContentSink
> xmlsink
;
537 NS_NewXMLContentSink(getter_AddRefs(xmlsink
), this, uri
, docShell
,
539 mParser
->SetContentSink(xmlsink
);
543 html5Parser
->Initialize(this, uri
, docShell
, aChannel
);
545 // about:blank *only*
546 nsCOMPtr
<nsIHTMLContentSink
> htmlsink
;
547 NS_NewHTMLContentSink(getter_AddRefs(htmlsink
), this, uri
, docShell
,
549 mParser
->SetContentSink(htmlsink
);
553 // parser the content of the URI
554 mParser
->Parse(uri
, nullptr, (void*)this);
559 bool nsHTMLDocument::UseWidthDeviceWidthFallbackViewport() const {
561 // Plain text documents are simple enough that font inflation doesn't offer
562 // any appreciable advantage over defaulting to "width=device-width" and
563 // subsequently turning on word-wrapping.
566 return Document::UseWidthDeviceWidthFallbackViewport();
569 Element
* nsHTMLDocument::GetUnfocusedKeyEventTarget() {
570 if (nsGenericHTMLElement
* body
= GetBody()) {
573 return Document::GetUnfocusedKeyEventTarget();
576 bool nsHTMLDocument::IsRegistrableDomainSuffixOfOrEqualTo(
577 const nsAString
& aHostSuffixString
, const nsACString
& aOrigHost
) {
578 // https://html.spec.whatwg.org/multipage/browsers.html#is-a-registrable-domain-suffix-of-or-is-equal-to
579 if (aHostSuffixString
.IsEmpty()) {
583 nsCOMPtr
<nsIURI
> origURI
= CreateInheritingURIForHost(aOrigHost
);
585 // Error: failed to parse input domain
589 nsCOMPtr
<nsIURI
> newURI
=
590 RegistrableDomainSuffixOfInternal(aHostSuffixString
, origURI
);
592 // Error: illegal domain
598 void nsHTMLDocument::AddedForm() { ++mNumForms
; }
600 void nsHTMLDocument::RemovedForm() { --mNumForms
; }
602 int32_t nsHTMLDocument::GetNumFormsSynchronous() { return mNumForms
; }
604 bool nsHTMLDocument::ResolveName(JSContext
* aCx
, const nsAString
& aName
,
605 JS::MutableHandle
<JS::Value
> aRetval
,
606 ErrorResult
& aError
) {
607 IdentifierMapEntry
* entry
= mIdentifierMap
.GetEntry(aName
);
612 nsBaseContentList
* list
= entry
->GetNameContentList();
613 uint32_t length
= list
? list
->Length() : 0;
618 // The list contains more than one element, return the whole list.
619 if (!ToJSValue(aCx
, list
, aRetval
)) {
620 aError
.NoteJSContextException(aCx
);
626 // Only one element in the list, return the element instead of returning
628 node
= list
->Item(0);
630 // No named items were found, see if there's one registerd by id for aName.
631 Element
* e
= entry
->GetIdElement();
633 if (!e
|| !nsGenericHTMLElement::ShouldExposeIdAsHTMLDocumentProperty(e
)) {
640 if (!ToJSValue(aCx
, node
, aRetval
)) {
641 aError
.NoteJSContextException(aCx
);
648 void nsHTMLDocument::GetSupportedNames(nsTArray
<nsString
>& aNames
) {
649 for (auto iter
= mIdentifierMap
.Iter(); !iter
.Done(); iter
.Next()) {
650 IdentifierMapEntry
* entry
= iter
.Get();
651 if (entry
->HasNameElement() ||
652 entry
->HasIdElementExposedAsHTMLDocumentProperty()) {
653 aNames
.AppendElement(entry
->GetKeyAsString());
658 //----------------------------
660 // forms related stuff
662 bool nsHTMLDocument::MatchFormControls(Element
* aElement
, int32_t aNamespaceID
,
663 nsAtom
* aAtom
, void* aData
) {
664 return aElement
->IsNodeOfType(nsIContent::eHTML_FORM_CONTROL
);
667 nsresult
nsHTMLDocument::Clone(dom::NodeInfo
* aNodeInfo
,
668 nsINode
** aResult
) const {
669 NS_ASSERTION(aNodeInfo
->NodeInfoManager() == mNodeInfoManager
,
670 "Can't import this document into another document!");
672 RefPtr
<nsHTMLDocument
> clone
= new nsHTMLDocument();
673 nsresult rv
= CloneDocHelper(clone
.get());
674 NS_ENSURE_SUCCESS(rv
, rv
);
676 // State from nsHTMLDocument
677 clone
->mLoadFlags
= mLoadFlags
;
679 clone
.forget(aResult
);
684 void nsHTMLDocument::DocAddSizeOfExcludingThis(
685 nsWindowSizes
& aWindowSizes
) const {
686 Document::DocAddSizeOfExcludingThis(aWindowSizes
);
688 // Measurement of the following members may be added later if DMD finds it is
694 bool nsHTMLDocument::WillIgnoreCharsetOverride() {
695 if (mEncodingMenuDisabled
) {
698 if (mType
!= eHTML
) {
699 MOZ_ASSERT(mType
== eXHTML
);
702 if (mCharacterSetSource
>= kCharsetFromByteOrderMark
) {
705 if (!mCharacterSet
->IsAsciiCompatible() &&
706 mCharacterSet
!= ISO_2022_JP_ENCODING
) {
709 nsIURI
* uri
= GetOriginalURI();
711 if (uri
->SchemeIs("about")) {
715 nsresult rv
= NS_URIChainHasFlags(
716 uri
, nsIProtocolHandler::URI_IS_UI_RESOURCE
, &isResource
);
717 if (NS_FAILED(rv
) || isResource
) {
724 void nsHTMLDocument::GetFormsAndFormControls(nsContentList
** aFormList
,
725 nsContentList
** aFormControlList
) {
726 RefPtr
<ContentListHolder
> holder
= mContentListHolder
;
728 // Flush our content model so it'll be up to date
729 // If this becomes unnecessary and the following line is removed,
730 // please also remove the corresponding flush operation from
731 // nsHtml5TreeBuilderCppSupplement.h. (Look for "See bug 497861." there.)
732 // XXXsmaug nsHtml5TreeBuilderCppSupplement doesn't seem to have such flush
734 FlushPendingNotifications(FlushType::Content
);
736 RefPtr
<nsContentList
> htmlForms
= GetExistingForms();
738 // If the document doesn't have an existing forms content list, create a
739 // new one which will be released soon by ContentListHolder. The idea is
740 // that we don't have that list hanging around for a long time and slowing
741 // down future DOM mutations.
743 // Please keep this in sync with Document::Forms().
744 htmlForms
= new nsContentList(this, kNameSpaceID_XHTML
, nsGkAtoms::form
,
747 /* aLiveList = */ true);
750 RefPtr
<nsContentList
> htmlFormControls
= new nsContentList(
751 this, nsHTMLDocument::MatchFormControls
, nullptr, nullptr,
753 /* aMatchAtom = */ nullptr,
754 /* aMatchNameSpaceId = */ kNameSpaceID_None
,
755 /* aFuncMayDependOnAttr = */ true,
756 /* aLiveList = */ true);
758 holder
= new ContentListHolder(this, htmlForms
, htmlFormControls
);
759 RefPtr
<ContentListHolder
> runnable
= holder
;
761 Dispatch(TaskCategory::GarbageCollection
, runnable
.forget()))) {
762 mContentListHolder
= holder
;
766 NS_ADDREF(*aFormList
= holder
->mFormList
);
767 NS_ADDREF(*aFormControlList
= holder
->mFormControlList
);