Backed out changeset 2450366cf7ca (bug 1891629) for causing win msix mochitest failures
[gecko.git] / dom / html / nsHTMLDocument.cpp
blob26165bb62224dc59dadc8188d6b21896717fd4ef
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"
13 #include "nsCOMPtr.h"
14 #include "nsString.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"
27 #include "nsIURI.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"
34 #include "nsError.h"
35 #include "nsIPrincipal.h"
36 #include "nsJSPrincipals.h"
37 #include "nsAttrName.h"
39 #include "nsNetCID.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"
54 // AHMED 12-2
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"
62 #include "nsRange.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"
72 #include "nsParser.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"
81 #include "nsIFrame.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;
91 #include "prtime.h"
93 // #define DEBUG_charset
95 // ==================================================================
96 // =
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);
111 if (NS_FAILED(rv)) {
112 *aInstancePtrResult = nullptr;
113 return rv;
116 doc->SetLoadedAsData(aLoadedAsData, /* aConsiderForMemoryReporting */ true);
117 doc.forget(aInstancePtrResult);
119 return NS_OK;
122 nsHTMLDocument::nsHTMLDocument()
123 : Document("text/html"),
124 mContentListHolder(nullptr),
125 mNumForms(0),
126 mLoadFlags(0),
127 mWarnedWidthHeight(false),
128 mIsPlainText(false),
129 mViewSource(false) {
130 mType = eHTML;
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);
151 return NS_OK;
154 void nsHTMLDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup) {
155 Document::Reset(aChannel, aLoadGroup);
157 if (aChannel) {
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);
169 mImages = nullptr;
170 mApplets = nullptr;
171 mEmbeds = nullptr;
172 mLinks = nullptr;
173 mAnchors = nullptr;
174 mScripts = nullptr;
176 mForms = nullptr;
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
180 // changed.
181 SetContentType(nsDependentCString("text/html"));
184 void nsHTMLDocument::TryReloadCharset(nsIDocumentViewer* aViewer,
185 int32_t& aCharsetSource,
186 NotNull<const Encoding*>& aEncoding) {
187 if (aViewer) {
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)) {
196 return;
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([&] {
213 if (aDocShell) {
214 nsDocShell::Cast(aDocShell)->ResetForcedAutodetection();
218 if (aCharsetSource >= kCharsetFromOtherComponent) {
219 return;
222 // mCharacterSet not updated yet for channel, so check aEncoding, too.
223 if (WillIgnoreCharsetOverride() || !IsAsciiCompatible(aEncoding)) {
224 return;
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) {
237 if (!aDocShell) {
238 return;
240 if (aCharsetSource >= kCharsetFromOtherComponent) {
241 return;
244 int32_t parentSource;
245 const Encoding* parentCharset;
246 nsCOMPtr<nsIPrincipal> parentPrincipal;
247 aDocShell->GetParentCharset(parentCharset, &parentSource,
248 getter_AddRefs(parentPrincipal));
249 if (!parentCharset) {
250 return;
252 if (kCharsetFromInitialUserForcedAutoDetection == parentSource ||
253 kCharsetFromFinalUserForcedAutoDetection == parentSource) {
254 if (WillIgnoreCharsetOverride() ||
255 !IsAsciiCompatible(aEncoding) || // if channel said UTF-16
256 !IsAsciiCompatible(parentCharset)) {
257 return;
259 aEncoding = WrapNotNull(parentCharset);
260 aCharsetSource = kCharsetFromParentFrame;
261 aForceAutoDetection = true;
262 return;
265 if (aCharsetSource >= kCharsetFromParentFrame) {
266 return;
269 if (kCharsetFromInitialAutoDetectionASCII <= parentSource) {
270 // Make sure that's OK
271 if (!NodePrincipal()->Equals(parentPrincipal) ||
272 !IsAsciiCompatible(parentCharset)) {
273 return;
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()) {
285 return false;
287 return nsContentUtils::IsChromeDoc(aDoc);
290 nsresult nsHTMLDocument::StartDocumentLoad(
291 const char* aCommand, nsIChannel* aChannel, nsILoadGroup* aLoadGroup,
292 nsISupports* aContainer, nsIStreamListener** aDocListener, bool aReset) {
293 if (!aCommand) {
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);
306 bool view =
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));
318 mIsPlainText =
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;
325 bool forceUtf8 =
326 mIsPlainText && nsContentUtils::IsUtf8OnlyPlainTextType(contentType);
328 bool loadAsHtml5 = true;
330 if (!mViewSource && xhtml) {
331 // We're parsing XHTML as XML, remember that.
332 mType = eXHTML;
333 SetCompatibilityMode(eCompatibility_FullStandards);
334 loadAsHtml5 = false;
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")) {
346 loadAsHtml5 = false;
351 nsresult rv = Document::StartDocumentLoad(aCommand, aChannel, aLoadGroup,
352 aContainer, aDocListener, aReset);
353 if (NS_FAILED(rv)) {
354 return rv;
357 nsCOMPtr<nsIURI> uri;
358 rv = aChannel->GetURI(getter_AddRefs(uri));
359 if (NS_FAILED(rv)) {
360 return rv;
363 nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aContainer));
365 bool loadWithPrototype = false;
366 RefPtr<nsHtml5Parser> html5Parser;
367 if (loadAsHtml5) {
368 html5Parser = nsHtml5Module::NewHtml5Parser();
369 mParser = html5Parser;
370 if (mIsPlainText) {
371 if (mViewSource) {
372 html5Parser->MarkAsNotScriptCreated("view-source-plain");
373 } else {
374 html5Parser->MarkAsNotScriptCreated("plain-text");
376 } else if (mViewSource && !html) {
377 html5Parser->MarkAsNotScriptCreated("view-source-xml");
378 } else {
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);
386 } else {
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
392 // mParentDocument.
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
396 // and parentViewer
397 nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
398 if (docShell) {
399 docShell->GetInProcessSameTypeParent(getter_AddRefs(parentAsItem));
402 nsCOMPtr<nsIDocShell> parent(do_QueryInterface(parentAsItem));
403 nsCOMPtr<nsIDocumentViewer> parentViewer;
404 if (parent) {
405 rv = parent->GetDocViewer(getter_AddRefs(parentViewer));
406 NS_ENSURE_SUCCESS(rv, rv);
409 nsCOMPtr<nsIDocumentViewer> viewer;
410 if (docShell) {
411 docShell->GetDocViewer(getter_AddRefs(viewer));
413 if (!viewer) {
414 viewer = std::move(parentViewer);
417 nsAutoCString urlSpec;
418 uri->GetSpec(urlSpec);
419 #ifdef DEBUG_charset
420 printf("Determining charset for %s\n", urlSpec.get());
421 #endif
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;
430 if (loadAsHtml5) {
431 executor = static_cast<nsHtml5TreeOpExecutor*>(mParser->GetContentSink());
434 if (forceUtf8) {
435 charsetSource = kCharsetFromUtf8OnlyMime;
436 } else if (!IsHTMLDocument() || !docShell) { // no docshell for text/html XHR
437 charsetSource =
438 IsHTMLDocument() ? kCharsetFromFallback : kCharsetFromDocTypeDefault;
439 TryChannelCharset(aChannel, charsetSource, encoding, executor);
440 } else {
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
456 // charset menu.
457 TryChannelCharset(aChannel, charsetSource, encoding, executor);
459 TryUserForcedCharset(viewer, docShell, charsetSource, encoding,
460 forceAutoDetection);
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...
470 rv = NS_OK;
471 nsCOMPtr<nsIStreamListener> listener = mParser->GetStreamListener();
472 listener.forget(aDocListener);
474 #ifdef DEBUG_charset
475 printf(" charset = %s source %d\n", charset.get(), charsetSource);
476 #endif
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,
485 docShell, aChannel);
486 mParser->SetContentSink(sink);
487 } else {
488 nsCOMPtr<nsIXMLContentSink> xmlsink;
489 NS_NewXMLContentSink(getter_AddRefs(xmlsink), this, uri, docShell,
490 aChannel);
491 mParser->SetContentSink(xmlsink);
493 } else {
494 if (loadAsHtml5) {
495 html5Parser->Initialize(this, uri, docShell, aChannel);
496 } else {
497 // about:blank *only*
498 nsCOMPtr<nsIHTMLContentSink> htmlsink;
499 NS_NewHTMLContentSink(getter_AddRefs(htmlsink), this, uri, docShell,
500 aChannel);
501 mParser->SetContentSink(htmlsink);
505 // parser the content of the URI
506 mParser->Parse(uri);
508 return rv;
511 bool nsHTMLDocument::UseWidthDeviceWidthFallbackViewport() const {
512 if (mIsPlainText) {
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.
516 return true;
518 return Document::UseWidthDeviceWidthFallbackViewport();
521 Element* nsHTMLDocument::GetUnfocusedKeyEventTarget() {
522 if (nsGenericHTMLElement* body = GetBody()) {
523 return body;
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()) {
532 return false;
535 nsCOMPtr<nsIURI> origURI = CreateInheritingURIForHost(aOrigHost);
536 if (!origURI) {
537 // Error: failed to parse input domain
538 return false;
541 nsCOMPtr<nsIURI> newURI =
542 RegistrableDomainSuffixOfInternal(aHostSuffixString, origURI);
543 if (!newURI) {
544 // Error: illegal domain
545 return false;
547 return true;
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);
560 if (!entry) {
561 return false;
564 nsBaseContentList* list = entry->GetNameContentList();
565 uint32_t length = list ? list->Length() : 0;
567 nsIContent* node;
568 if (length > 0) {
569 if (length > 1) {
570 // The list contains more than one element, return the whole list.
571 if (!ToJSValue(aCx, list, aRetval)) {
572 aError.NoteJSContextException(aCx);
573 return false;
575 return true;
578 // Only one element in the list, return the element instead of returning
579 // the list.
580 node = list->Item(0);
581 } else {
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)) {
586 return false;
589 node = e;
592 if (!ToJSValue(aCx, node, aRetval)) {
593 aError.NoteJSContextException(aCx);
594 return false;
597 return true;
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);
631 return NS_OK;
634 /* virtual */
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
640 // worthwhile:
641 // - mLinks
642 // - mAnchors
645 bool nsHTMLDocument::WillIgnoreCharsetOverride() {
646 if (mEncodingMenuDisabled) {
647 return true;
649 if (mType != eHTML) {
650 MOZ_ASSERT(mType == eXHTML);
651 return true;
653 if (mCharacterSetSource >= kCharsetFromByteOrderMark) {
654 return true;
656 if (!mCharacterSet->IsAsciiCompatible() &&
657 mCharacterSet != ISO_2022_JP_ENCODING) {
658 return true;
660 nsIURI* uri = GetOriginalURI();
661 if (uri) {
662 if (uri->SchemeIs("about")) {
663 return true;
665 bool isResource;
666 nsresult rv = NS_URIChainHasFlags(
667 uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &isResource);
668 if (NS_FAILED(rv) || isResource) {
669 return true;
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:
685 return false;
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;
707 if (!holder) {
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
713 // anymore.
714 FlushPendingNotifications(FlushType::Content);
716 RefPtr<nsContentList> htmlForms = GetExistingForms();
717 if (!htmlForms) {
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,
725 nsGkAtoms::form,
726 /* aDeep = */ true,
727 /* aLiveList = */ true);
730 RefPtr<nsContentList> htmlFormControls = new nsContentList(
731 this, nsHTMLDocument::MatchFormControls, nullptr, nullptr,
732 /* aDeep = */ true,
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);