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/. */
8 * Base class for the XML and HTML content sinks, which construct a
9 * DOM based on information from the parser.
12 #include "nsContentSink.h"
13 #include "mozilla/Components.h"
14 #include "mozilla/PresShell.h"
15 #include "mozilla/StaticPrefs_browser.h"
16 #include "mozilla/StaticPrefs_content.h"
17 #include "mozilla/dom/Document.h"
18 #include "mozilla/dom/LinkStyle.h"
19 #include "mozilla/css/Loader.h"
20 #include "mozilla/dom/MutationObservers.h"
21 #include "mozilla/dom/SRILogHelper.h"
22 #include "mozilla/StoragePrincipalHelper.h"
23 #include "nsIDocShell.h"
24 #include "nsILoadContext.h"
25 #include "nsIPrefetchService.h"
27 #include "nsNetUtil.h"
28 #include "nsIMIMEHeaderParam.h"
29 #include "nsIProtocolHandler.h"
30 #include "nsIHttpChannel.h"
31 #include "nsIContent.h"
32 #include "nsPresContext.h"
33 #include "nsViewManager.h"
35 #include "nsGkAtoms.h"
36 #include "nsGlobalWindowInner.h"
38 #include "nsIOfflineCacheUpdate.h"
39 #include "nsIApplicationCache.h"
40 #include "nsIApplicationCacheChannel.h"
41 #include "nsICookieService.h"
42 #include "nsContentUtils.h"
43 #include "nsNodeInfoManager.h"
44 #include "nsIAppShell.h"
45 #include "nsIWidget.h"
46 #include "nsWidgetsCID.h"
47 #include "mozAutoDocUpdate.h"
48 #include "nsIWebNavigation.h"
49 #include "nsGenericHTMLElement.h"
50 #include "nsHTMLDNSPrefetch.h"
51 #include "nsIObserverService.h"
52 #include "mozilla/Preferences.h"
53 #include "mozilla/dom/ServiceWorkerDescriptor.h"
54 #include "mozilla/dom/ScriptLoader.h"
55 #include "nsParserConstants.h"
56 #include "nsSandboxFlags.h"
58 #include "HTMLLinkElement.h"
59 using namespace mozilla
;
60 using namespace mozilla::css
;
61 using namespace mozilla::dom
;
63 LazyLogModule
gContentSinkLogModuleInfo("nscontentsink");
65 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsContentSink
)
66 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsContentSink
)
68 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsContentSink
)
69 NS_INTERFACE_MAP_ENTRY(nsICSSLoaderObserver
)
70 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
71 NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver
)
72 NS_INTERFACE_MAP_ENTRY(nsIMutationObserver
)
73 NS_INTERFACE_MAP_ENTRY(nsITimerCallback
)
74 NS_INTERFACE_MAP_ENTRY(nsINamed
)
75 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIDocumentObserver
)
78 NS_IMPL_CYCLE_COLLECTION_CLASS(nsContentSink
)
80 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsContentSink
)
82 tmp
->mDocument
->RemoveObserver(tmp
);
84 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument
)
85 NS_IMPL_CYCLE_COLLECTION_UNLINK(mParser
)
86 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell
)
87 NS_IMPL_CYCLE_COLLECTION_UNLINK(mCSSLoader
)
88 NS_IMPL_CYCLE_COLLECTION_UNLINK(mNodeInfoManager
)
89 NS_IMPL_CYCLE_COLLECTION_UNLINK(mScriptLoader
)
90 NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE
91 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
92 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsContentSink
)
93 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument
)
94 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParser
)
95 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocShell
)
96 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCSSLoader
)
97 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNodeInfoManager
)
98 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScriptLoader
)
99 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
101 nsContentSink::nsContentSink()
103 mLastNotificationTime(0),
105 mDynamicLowerValue(0),
108 mDeferredLayoutStart(0),
109 mDeferredFlushTags(0),
110 mIsDocumentObserver(0),
111 mRunsToCompletion(0),
112 mIsBlockingOnload(false),
114 mHasPendingEvent(false),
115 mCurrentParseEndTime(0),
117 mLastSampledUserEventTime(0),
118 mInMonolithicContainer(0),
120 mUpdatesInNotification(0),
121 mPendingSheetCount(0) {
122 NS_ASSERTION(!mLayoutStarted
, "What?");
123 NS_ASSERTION(!mDynamicLowerValue
, "What?");
124 NS_ASSERTION(!mParsing
, "What?");
125 NS_ASSERTION(mLastSampledUserEventTime
== 0, "What?");
126 NS_ASSERTION(mDeflectedCount
== 0, "What?");
127 NS_ASSERTION(!mDroppedTimer
, "What?");
128 NS_ASSERTION(mInMonolithicContainer
== 0, "What?");
129 NS_ASSERTION(mInNotification
== 0, "What?");
130 NS_ASSERTION(!mDeferredLayoutStart
, "What?");
133 nsContentSink::~nsContentSink() {
135 // Remove ourselves just to be safe, though we really should have
136 // been removed in DidBuildModel if everything worked right.
137 mDocument
->RemoveObserver(this);
141 nsresult
nsContentSink::Init(Document
* aDoc
, nsIURI
* aURI
,
142 nsISupports
* aContainer
, nsIChannel
* aChannel
) {
143 MOZ_ASSERT(aDoc
, "null ptr");
144 MOZ_ASSERT(aURI
, "null ptr");
146 if (!aDoc
|| !aURI
) {
147 return NS_ERROR_NULL_POINTER
;
153 mDocShell
= do_QueryInterface(aContainer
);
154 mScriptLoader
= mDocument
->ScriptLoader();
156 if (!mRunsToCompletion
) {
158 uint32_t loadType
= 0;
159 mDocShell
->GetLoadType(&loadType
);
160 mDocument
->SetChangeScrollPosWhenScrollingToRef(
161 (loadType
& nsIDocShell::LOAD_CMD_HISTORY
) == 0);
164 ProcessHTTPHeaders(aChannel
);
167 mCSSLoader
= aDoc
->CSSLoader();
169 mNodeInfoManager
= aDoc
->NodeInfoManager();
171 mBackoffCount
= StaticPrefs::content_notify_backoffcount();
173 if (StaticPrefs::content_sink_enable_perf_mode() != 0) {
174 mDynamicLowerValue
= StaticPrefs::content_sink_enable_perf_mode() == 1;
175 FavorPerformanceHint(!mDynamicLowerValue
, 0);
182 nsContentSink::StyleSheetLoaded(StyleSheet
* aSheet
, bool aWasDeferred
,
184 MOZ_ASSERT(!mRunsToCompletion
, "How come a fragment parser observed sheets?");
188 MOZ_ASSERT(mPendingSheetCount
> 0, "How'd that happen?");
189 --mPendingSheetCount
;
191 const bool loadedAllSheets
= !mPendingSheetCount
;
192 if (loadedAllSheets
&& (mDeferredLayoutStart
|| mDeferredFlushTags
)) {
193 if (mDeferredFlushTags
) {
196 if (mDeferredLayoutStart
) {
197 // We might not have really started layout, since this sheet was still
198 // loading. Do it now. Probably doesn't matter whether we do this
199 // before or after we unblock scripts, but before feels saner. Note
200 // that if mDeferredLayoutStart is true, that means any subclass
201 // StartLayout() stuff that needs to happen has already happened, so
202 // we don't need to worry about it.
206 // Go ahead and try to scroll to our ref if we have one
210 mScriptLoader
->RemoveParserBlockingScriptExecutionBlocker();
212 if (loadedAllSheets
&&
213 mDocument
->GetReadyStateEnum() >= Document::READYSTATE_INTERACTIVE
) {
214 mScriptLoader
->DeferCheckpointReached();
220 nsresult
nsContentSink::ProcessHTTPHeaders(nsIChannel
* aChannel
) {
221 nsCOMPtr
<nsIHttpChannel
> httpchannel(do_QueryInterface(aChannel
));
227 // Note that the only header we care about is the "link" header, since we
228 // have all the infrastructure for kicking off stylesheet loads.
230 nsAutoCString linkHeader
;
232 nsresult rv
= httpchannel
->GetResponseHeader("link"_ns
, linkHeader
);
233 if (NS_SUCCEEDED(rv
) && !linkHeader
.IsEmpty()) {
234 mDocument
->SetHeaderData(nsGkAtoms::link
,
235 NS_ConvertASCIItoUTF16(linkHeader
));
237 NS_ASSERTION(!mProcessLinkHeaderEvent
.get(),
238 "Already dispatched an event?");
240 mProcessLinkHeaderEvent
=
241 NewNonOwningRunnableMethod("nsContentSink::DoProcessLinkHeader", this,
242 &nsContentSink::DoProcessLinkHeader
);
243 rv
= NS_DispatchToCurrentThread(mProcessLinkHeaderEvent
.get());
245 mProcessLinkHeaderEvent
.Forget();
252 void nsContentSink::DoProcessLinkHeader() {
254 mDocument
->GetHeaderData(nsGkAtoms::link
, value
);
255 ProcessLinkHeader(value
);
258 // check whether the Link header field applies to the context resource
259 // see <http://tools.ietf.org/html/rfc5988#section-5.2>
261 bool nsContentSink::LinkContextIsOurDocument(const nsAString
& aAnchor
) {
262 if (aAnchor
.IsEmpty()) {
263 // anchor parameter not present or empty -> same document reference
267 nsIURI
* docUri
= mDocument
->GetDocumentURI();
269 // the document URI might contain a fragment identifier ("#...')
270 // we want to ignore that because it's invisible to the server
271 // and just affects the local interpretation in the recipient
272 nsCOMPtr
<nsIURI
> contextUri
;
273 nsresult rv
= NS_GetURIWithoutRef(docUri
, getter_AddRefs(contextUri
));
280 // resolve anchor against context
281 nsCOMPtr
<nsIURI
> resolvedUri
;
282 rv
= NS_NewURI(getter_AddRefs(resolvedUri
), aAnchor
, nullptr, contextUri
);
290 rv
= contextUri
->Equals(resolvedUri
, &same
);
299 // Decode a parameter value using the encoding defined in RFC 5987 (in place)
301 // charset "'" [ language ] "'" value-chars
303 // returns true when decoding happened successfully (otherwise leaves
304 // passed value alone)
305 bool nsContentSink::Decode5987Format(nsAString
& aEncoded
) {
307 nsCOMPtr
<nsIMIMEHeaderParam
> mimehdrpar
=
308 do_GetService(NS_MIMEHEADERPARAM_CONTRACTID
, &rv
);
309 if (NS_FAILED(rv
)) return false;
311 nsAutoCString asciiValue
;
313 const char16_t
* encstart
= aEncoded
.BeginReading();
314 const char16_t
* encend
= aEncoded
.EndReading();
316 // create a plain ASCII string, aborting if we can't do that
317 // converted form is always shorter than input
318 while (encstart
!= encend
) {
319 if (*encstart
> 0 && *encstart
< 128) {
320 asciiValue
.Append((char)*encstart
);
327 nsAutoString decoded
;
328 nsAutoCString language
;
330 rv
= mimehdrpar
->DecodeRFC5987Param(asciiValue
, language
, decoded
);
331 if (NS_FAILED(rv
)) return false;
337 nsresult
nsContentSink::ProcessLinkHeader(const nsAString
& aLinkData
) {
340 // keep track where we are within the header field
341 bool seenParameters
= false;
343 // parse link content and call process style link
347 nsAutoString titleStar
;
348 nsAutoString integrity
;
354 nsAutoString crossOrigin
;
355 nsAutoString referrerPolicy
;
358 crossOrigin
.SetIsVoid(true);
360 // copy to work buffer
361 nsAutoString
stringList(aLinkData
);
363 // put an extra null at the end
364 stringList
.Append(kNullCh
);
366 char16_t
* start
= stringList
.BeginWriting();
367 char16_t
* end
= start
;
368 char16_t
* last
= start
;
371 while (*start
!= kNullCh
) {
372 // skip leading space
373 while ((*start
!= kNullCh
) && nsCRT::IsAsciiSpace(*start
)) {
380 bool wasQuotedString
= false;
382 // look for semicolon or comma
383 while (*end
!= kNullCh
&& *end
!= kSemicolon
&& *end
!= kComma
) {
386 if (ch
== kQuote
|| ch
== kLessThan
) {
390 if (quote
== kLessThan
) {
391 quote
= kGreaterThan
;
394 wasQuotedString
= (ch
== kQuote
);
396 char16_t
* closeQuote
= (end
+ 1);
398 // seek closing quote
399 while (*closeQuote
!= kNullCh
&& quote
!= *closeQuote
) {
400 // in quoted-string, "\" is an escape character
401 if (wasQuotedString
&& *closeQuote
== kBackSlash
&&
402 *(closeQuote
+ 1) != kNullCh
) {
409 if (quote
== *closeQuote
) {
412 // skip to close quote
419 if (ch
!= kNullCh
&& ch
!= kSemicolon
&& ch
!= kComma
) {
425 // keep going until semi or comma
426 while (ch
!= kNullCh
&& ch
!= kSemicolon
&& ch
!= kComma
) {
445 if ((*start
== kLessThan
) && (*last
== kGreaterThan
)) {
448 // first instance of <...> wins
449 // also, do not allow hrefs after the first param was seen
450 if (href
.IsEmpty() && !seenParameters
) {
452 href
.StripWhitespace();
455 char16_t
* equals
= start
;
456 seenParameters
= true;
458 while ((*equals
!= kNullCh
) && (*equals
!= kEqual
)) {
462 if (*equals
!= kNullCh
) {
464 nsAutoString
attr(start
);
465 attr
.StripWhitespace();
467 char16_t
* value
= ++equals
;
468 while (nsCRT::IsAsciiSpace(*value
)) {
472 if ((*value
== kQuote
) && (*value
== *last
)) {
477 if (wasQuotedString
) {
479 char16_t
* unescaped
= value
;
480 char16_t
* src
= value
;
482 while (*src
!= kNullCh
) {
483 if (*src
== kBackSlash
&& *(src
+ 1) != kNullCh
) {
486 *unescaped
++ = *src
++;
489 *unescaped
= kNullCh
;
492 if (attr
.LowerCaseEqualsLiteral("rel")) {
495 rel
.CompressWhitespace();
497 } else if (attr
.LowerCaseEqualsLiteral("title")) {
498 if (title
.IsEmpty()) {
500 title
.CompressWhitespace();
502 } else if (attr
.LowerCaseEqualsLiteral("title*")) {
503 if (titleStar
.IsEmpty() && !wasQuotedString
) {
504 // RFC 5987 encoding; uses token format only, so skip if we get
505 // here with a quoted-string
508 if (Decode5987Format(tmp
)) {
510 titleStar
.CompressWhitespace();
512 // header value did not parse, throw it away
513 titleStar
.Truncate();
516 } else if (attr
.LowerCaseEqualsLiteral("type")) {
517 if (type
.IsEmpty()) {
519 type
.StripWhitespace();
521 } else if (attr
.LowerCaseEqualsLiteral("media")) {
522 if (media
.IsEmpty()) {
525 // The HTML5 spec is formulated in terms of the CSS3 spec,
526 // which specifies that media queries are case insensitive.
527 nsContentUtils::ASCIIToLower(media
);
529 } else if (attr
.LowerCaseEqualsLiteral("anchor")) {
530 if (anchor
.IsEmpty()) {
532 anchor
.StripWhitespace();
534 } else if (attr
.LowerCaseEqualsLiteral("crossorigin")) {
535 if (crossOrigin
.IsVoid()) {
536 crossOrigin
.SetIsVoid(false);
538 crossOrigin
.StripWhitespace();
540 } else if (attr
.LowerCaseEqualsLiteral("as")) {
543 as
.CompressWhitespace();
545 } else if (attr
.LowerCaseEqualsLiteral("referrerpolicy")) {
546 // https://html.spec.whatwg.org/multipage/urls-and-fetching.html#referrer-policy-attribute
547 // Specs says referrer policy attribute is an enumerated attribute,
548 // case insensitive and includes the empty string
549 // We will parse the value with AttributeReferrerPolicyFromString
550 // later, which will handle parsing it as an enumerated attribute.
551 if (referrerPolicy
.IsEmpty()) {
552 referrerPolicy
= value
;
554 } else if (attr
.LowerCaseEqualsLiteral("integrity")) {
555 if (integrity
.IsEmpty()) {
558 } else if (attr
.LowerCaseEqualsLiteral("imagesrcset")) {
559 if (srcset
.IsEmpty()) {
562 } else if (attr
.LowerCaseEqualsLiteral("imagesizes")) {
563 if (sizes
.IsEmpty()) {
571 if (endCh
== kComma
) {
572 // hit a comma, process what we've got so far
574 href
.Trim(" \t\n\r\f"); // trim HTML5 whitespace
575 if (!href
.IsEmpty() && !rel
.IsEmpty()) {
576 rv
= ProcessLinkFromHeader(
578 // prefer RFC 5987 variant over non-I18zed version
579 titleStar
.IsEmpty() ? title
: titleStar
, integrity
, srcset
, sizes
,
580 type
, media
, crossOrigin
, referrerPolicy
, as
);
587 integrity
.Truncate();
592 referrerPolicy
.Truncate();
593 crossOrigin
.SetIsVoid(true);
596 seenParameters
= false;
602 href
.Trim(" \t\n\r\f"); // trim HTML5 whitespace
603 if (!href
.IsEmpty() && !rel
.IsEmpty()) {
604 rv
= ProcessLinkFromHeader(
606 // prefer RFC 5987 variant over non-I18zed version
607 titleStar
.IsEmpty() ? title
: titleStar
, integrity
, srcset
, sizes
, type
,
608 media
, crossOrigin
, referrerPolicy
, as
);
614 nsresult
nsContentSink::ProcessLinkFromHeader(
615 const nsAString
& aAnchor
, const nsAString
& aHref
, const nsAString
& aRel
,
616 const nsAString
& aTitle
, const nsAString
& aIntegrity
,
617 const nsAString
& aSrcset
, const nsAString
& aSizes
, const nsAString
& aType
,
618 const nsAString
& aMedia
, const nsAString
& aCrossOrigin
,
619 const nsAString
& aReferrerPolicy
, const nsAString
& aAs
) {
620 uint32_t linkTypes
= LinkStyle::ParseLinkTypes(aRel
);
622 // The link relation may apply to a different resource, specified
623 // in the anchor parameter. For the link relations supported so far,
624 // we simply abort if the link applies to a resource different to the
626 if (!LinkContextIsOurDocument(aAnchor
)) {
630 if (nsContentUtils::PrefetchPreloadEnabled(mDocShell
)) {
631 // prefetch href if relation is "next" or "prefetch"
632 if ((linkTypes
& LinkStyle::eNEXT
) || (linkTypes
& LinkStyle::ePREFETCH
)) {
633 PrefetchHref(aHref
, aAs
, aType
, aMedia
);
636 if (!aHref
.IsEmpty() && (linkTypes
& LinkStyle::eDNS_PREFETCH
)) {
640 if (!aHref
.IsEmpty() && (linkTypes
& LinkStyle::ePRECONNECT
)) {
641 Preconnect(aHref
, aCrossOrigin
);
644 if (linkTypes
& LinkStyle::ePRELOAD
) {
645 PreloadHref(aHref
, aAs
, aType
, aMedia
, aIntegrity
, aSrcset
, aSizes
,
646 aCrossOrigin
, aReferrerPolicy
);
650 // is it a stylesheet link?
651 if (!(linkTypes
& LinkStyle::eSTYLESHEET
)) {
655 bool isAlternate
= linkTypes
& LinkStyle::eALTERNATE
;
656 return ProcessStyleLinkFromHeader(aHref
, isAlternate
, aTitle
, aIntegrity
,
657 aType
, aMedia
, aReferrerPolicy
);
660 nsresult
nsContentSink::ProcessStyleLinkFromHeader(
661 const nsAString
& aHref
, bool aAlternate
, const nsAString
& aTitle
,
662 const nsAString
& aIntegrity
, const nsAString
& aType
,
663 const nsAString
& aMedia
, const nsAString
& aReferrerPolicy
) {
664 if (aAlternate
&& aTitle
.IsEmpty()) {
665 // alternates must have title return without error, for now
669 nsAutoString mimeType
;
671 nsContentUtils::SplitMimeType(aType
, mimeType
, params
);
674 if (!mimeType
.IsEmpty() && !mimeType
.LowerCaseEqualsLiteral("text/css")) {
675 // Unknown stylesheet language
679 nsCOMPtr
<nsIURI
> url
;
680 nsresult rv
= NS_NewURI(getter_AddRefs(url
), aHref
, nullptr,
681 mDocument
->GetDocBaseURI());
684 // The URI is bad, move along, don't propagate the error (for now)
688 // Link header is working like a <link> node, so referrerPolicy attr should
689 // have higher priority than referrer policy from document.
690 ReferrerPolicy policy
=
691 ReferrerInfo::ReferrerPolicyAttributeFromString(aReferrerPolicy
);
692 nsCOMPtr
<nsIReferrerInfo
> referrerInfo
=
693 ReferrerInfo::CreateFromDocumentAndPolicyOverride(mDocument
, policy
);
695 Loader::SheetInfo info
{
700 referrerInfo
.forget(),
705 /* nonce = */ u
""_ns
,
706 aAlternate
? Loader::HasAlternateRel::Yes
: Loader::HasAlternateRel::No
,
707 Loader::IsInline::No
,
708 Loader::IsExplicitlyEnabled::No
,
711 auto loadResultOrErr
=
712 mCSSLoader
->LoadStyleLink(info
, mRunsToCompletion
? nullptr : this);
713 if (loadResultOrErr
.isErr()) {
714 return loadResultOrErr
.unwrapErr();
717 if (loadResultOrErr
.inspect().ShouldBlock() && !mRunsToCompletion
) {
718 ++mPendingSheetCount
;
719 mScriptLoader
->AddParserBlockingScriptExecutionBlocker();
725 void nsContentSink::PrefetchHref(const nsAString
& aHref
, const nsAString
& aAs
,
726 const nsAString
& aType
,
727 const nsAString
& aMedia
) {
728 nsCOMPtr
<nsIPrefetchService
> prefetchService(components::Prefetch::Service());
729 if (prefetchService
) {
730 // construct URI using document charset
731 auto encoding
= mDocument
->GetDocumentCharacterSet();
732 nsCOMPtr
<nsIURI
> uri
;
733 NS_NewURI(getter_AddRefs(uri
), aHref
, encoding
, mDocument
->GetDocBaseURI());
735 auto referrerInfo
= MakeRefPtr
<ReferrerInfo
>(*mDocument
);
736 referrerInfo
= referrerInfo
->CloneWithNewOriginalReferrer(mDocumentURI
);
738 prefetchService
->PrefetchURI(uri
, referrerInfo
, mDocument
, true);
743 void nsContentSink::PreloadHref(const nsAString
& aHref
, const nsAString
& aAs
,
744 const nsAString
& aType
, const nsAString
& aMedia
,
745 const nsAString
& aIntegrity
,
746 const nsAString
& aSrcset
,
747 const nsAString
& aSizes
, const nsAString
& aCORS
,
748 const nsAString
& aReferrerPolicy
) {
750 HTMLLinkElement::ParseAsValue(aAs
, asAttr
);
751 auto policyType
= HTMLLinkElement::AsValueToContentPolicy(asAttr
);
753 if (policyType
== nsIContentPolicy::TYPE_INVALID
) {
754 // Ignore preload with a wrong or empty as attribute.
758 nsAutoString mimeType
;
759 nsAutoString notUsed
;
760 nsContentUtils::SplitMimeType(aType
, mimeType
, notUsed
);
761 if (!HTMLLinkElement::CheckPreloadAttrs(asAttr
, mimeType
, aMedia
,
763 policyType
= nsIContentPolicy::TYPE_INVALID
;
766 auto encoding
= mDocument
->GetDocumentCharacterSet();
767 nsCOMPtr
<nsIURI
> uri
;
768 NS_NewURI(getter_AddRefs(uri
), aHref
, encoding
, mDocument
->GetDocBaseURI());
771 // URL parsing failed.
775 auto referrerInfo
= MakeRefPtr
<ReferrerInfo
>(*mDocument
);
776 referrerInfo
= referrerInfo
->CloneWithNewOriginalReferrer(mDocumentURI
);
778 mDocument
->Preloads().PreloadLinkHeader(uri
, aHref
, policyType
, aAs
, aType
,
779 aIntegrity
, aSrcset
, aSizes
, aCORS
,
780 aReferrerPolicy
, referrerInfo
);
783 void nsContentSink::PrefetchDNS(const nsAString
& aHref
) {
784 nsAutoString hostname
;
785 bool isHttps
= false;
787 if (StringBeginsWith(aHref
, u
"//"_ns
)) {
788 hostname
= Substring(aHref
, 2);
790 nsCOMPtr
<nsIURI
> uri
;
791 NS_NewURI(getter_AddRefs(uri
), aHref
);
796 bool isLocalResource
= false;
797 rv
= NS_URIChainHasFlags(uri
, nsIProtocolHandler::URI_IS_LOCAL_RESOURCE
,
799 if (NS_SUCCEEDED(rv
) && !isLocalResource
) {
802 CopyUTF8toUTF16(host
, hostname
);
804 isHttps
= uri
->SchemeIs("https");
807 if (!hostname
.IsEmpty() && nsHTMLDNSPrefetch::IsAllowed(mDocument
)) {
809 StoragePrincipalHelper::GetOriginAttributesForNetworkState(mDocument
, oa
);
811 nsHTMLDNSPrefetch::PrefetchLow(hostname
, isHttps
, oa
,
812 mDocument
->GetChannel()->GetTRRMode());
816 void nsContentSink::Preconnect(const nsAString
& aHref
,
817 const nsAString
& aCrossOrigin
) {
818 // construct URI using document charset
819 auto encoding
= mDocument
->GetDocumentCharacterSet();
820 nsCOMPtr
<nsIURI
> uri
;
821 NS_NewURI(getter_AddRefs(uri
), aHref
, encoding
, mDocument
->GetDocBaseURI());
823 if (uri
&& mDocument
) {
824 mDocument
->MaybePreconnect(uri
,
825 dom::Element::StringToCORSMode(aCrossOrigin
));
829 nsresult
nsContentSink::SelectDocAppCache(
830 nsIApplicationCache
* aLoadApplicationCache
, nsIURI
* aManifestURI
,
831 bool aFetchedWithHTTPGetOrEquiv
, CacheSelectionAction
* aAction
) {
834 *aAction
= CACHE_SELECTION_NONE
;
836 if (aLoadApplicationCache
) {
837 nsCOMPtr
<nsIURI
> groupURI
;
838 rv
= aLoadApplicationCache
->GetManifestURI(getter_AddRefs(groupURI
));
839 NS_ENSURE_SUCCESS(rv
, rv
);
842 rv
= groupURI
->Equals(aManifestURI
, &equal
);
843 NS_ENSURE_SUCCESS(rv
, rv
);
846 // This is a foreign entry, force a reload to avoid loading the foreign
847 // entry. The entry will be marked as foreign to avoid loading it again.
849 *aAction
= CACHE_SELECTION_RELOAD
;
851 // The http manifest attribute URI is equal to the manifest URI of
852 // the cache the document was loaded from - associate the document with
853 // that cache and invoke the cache update process.
855 nsAutoCString docURISpec
, clientID
;
856 mDocumentURI
->GetAsciiSpec(docURISpec
);
857 aLoadApplicationCache
->GetClientID(clientID
);
858 SINK_TRACE(static_cast<LogModule
*>(gContentSinkLogModuleInfo
),
860 ("Selection: assigning app cache %s to document %s",
861 clientID
.get(), docURISpec
.get()));
864 rv
= mDocument
->SetApplicationCache(aLoadApplicationCache
);
865 NS_ENSURE_SUCCESS(rv
, rv
);
867 // Document will be added as implicit entry to the cache as part of
868 // the update process.
869 *aAction
= CACHE_SELECTION_UPDATE
;
872 // The document was not loaded from an application cache
873 // Here we know the manifest has the same origin as the
874 // document. There is call to CheckMayLoadWithReporting() on it above.
876 if (!aFetchedWithHTTPGetOrEquiv
) {
877 // The document was not loaded using HTTP GET or equivalent
878 // method. The spec says to run the cache selection algorithm w/o
879 // the manifest specified.
880 *aAction
= CACHE_SELECTION_RESELECT_WITHOUT_MANIFEST
;
882 // Always do an update in this case
883 *aAction
= CACHE_SELECTION_UPDATE
;
890 nsresult
nsContentSink::SelectDocAppCacheNoManifest(
891 nsIApplicationCache
* aLoadApplicationCache
, nsIURI
** aManifestURI
,
892 CacheSelectionAction
* aAction
) {
893 *aManifestURI
= nullptr;
894 *aAction
= CACHE_SELECTION_NONE
;
898 if (aLoadApplicationCache
) {
899 // The document was loaded from an application cache, use that
900 // application cache as the document's application cache.
902 nsAutoCString docURISpec
, clientID
;
903 mDocumentURI
->GetAsciiSpec(docURISpec
);
904 aLoadApplicationCache
->GetClientID(clientID
);
905 SINK_TRACE(static_cast<LogModule
*>(gContentSinkLogModuleInfo
),
907 ("Selection, no manifest: assigning app cache %s to document %s",
908 clientID
.get(), docURISpec
.get()));
911 rv
= mDocument
->SetApplicationCache(aLoadApplicationCache
);
912 NS_ENSURE_SUCCESS(rv
, rv
);
914 // Return the uri and invoke the update process for the selected
915 // application cache.
916 rv
= aLoadApplicationCache
->GetManifestURI(aManifestURI
);
917 NS_ENSURE_SUCCESS(rv
, rv
);
919 *aAction
= CACHE_SELECTION_UPDATE
;
925 void nsContentSink::ProcessOfflineManifest(nsIContent
* aElement
) {
926 // Only check the manifest for root document nodes.
927 if (aElement
!= mDocument
->GetRootElement()) {
931 // Don't bother processing offline manifest for documents
932 // without a docshell
937 // Check for a manifest= attribute.
938 nsAutoString manifestSpec
;
939 aElement
->AsElement()->GetAttr(kNameSpaceID_None
, nsGkAtoms::manifest
,
941 ProcessOfflineManifest(manifestSpec
);
944 void nsContentSink::ProcessOfflineManifest(const nsAString
& aManifestSpec
) {
945 // Don't bother processing offline manifest for documents
946 // without a docshell
951 // If offline storage is disabled skip processing
952 if (!StaticPrefs::browser_cache_offline_storage_enable()) {
956 // If this document has been interecepted, let's skip the processing of the
958 if (mDocument
->GetController().isSome()) {
962 // If the docshell's in private browsing mode, we don't want to do any
963 // manifest processing.
964 nsCOMPtr
<nsILoadContext
> loadContext
= do_QueryInterface(mDocShell
);
965 if (loadContext
->UsePrivateBrowsing()) {
971 // Grab the application cache the document was loaded from, if any.
972 nsCOMPtr
<nsIApplicationCache
> applicationCache
;
974 nsCOMPtr
<nsIApplicationCacheChannel
> applicationCacheChannel
=
975 do_QueryInterface(mDocument
->GetChannel());
976 if (applicationCacheChannel
) {
977 bool loadedFromApplicationCache
;
978 rv
= applicationCacheChannel
->GetLoadedFromApplicationCache(
979 &loadedFromApplicationCache
);
984 if (loadedFromApplicationCache
) {
985 rv
= applicationCacheChannel
->GetApplicationCache(
986 getter_AddRefs(applicationCache
));
993 if (aManifestSpec
.IsEmpty() && !applicationCache
) {
994 // Not loaded from an application cache, and no manifest
995 // attribute. Nothing to do here.
999 CacheSelectionAction action
= CACHE_SELECTION_NONE
;
1000 nsCOMPtr
<nsIURI
> manifestURI
;
1002 if (aManifestSpec
.IsEmpty()) {
1003 action
= CACHE_SELECTION_RESELECT_WITHOUT_MANIFEST
;
1005 nsContentUtils::NewURIWithDocumentCharset(
1006 getter_AddRefs(manifestURI
), aManifestSpec
, mDocument
, mDocumentURI
);
1011 // Documents must list a manifest from the same origin
1012 rv
= mDocument
->NodePrincipal()->CheckMayLoadWithReporting(
1013 manifestURI
, false, mDocument
->InnerWindowID());
1014 if (NS_FAILED(rv
)) {
1015 action
= CACHE_SELECTION_RESELECT_WITHOUT_MANIFEST
;
1017 if (!nsContentUtils::OfflineAppAllowed(mDocument
->NodePrincipal())) {
1018 nsCOMPtr
<nsIOfflineCacheUpdateService
> updateService
=
1019 components::OfflineCacheUpdate::Service();
1020 if (!updateService
) {
1023 rv
= updateService
->AllowOfflineApp(mDocument
->NodePrincipal());
1024 if (NS_FAILED(rv
)) {
1029 bool fetchedWithHTTPGetOrEquiv
= false;
1030 nsCOMPtr
<nsIHttpChannel
> httpChannel(
1031 do_QueryInterface(mDocument
->GetChannel()));
1033 nsAutoCString method
;
1034 rv
= httpChannel
->GetRequestMethod(method
);
1035 if (NS_SUCCEEDED(rv
))
1036 fetchedWithHTTPGetOrEquiv
= method
.EqualsLiteral("GET");
1039 rv
= SelectDocAppCache(applicationCache
, manifestURI
,
1040 fetchedWithHTTPGetOrEquiv
, &action
);
1041 if (NS_FAILED(rv
)) {
1047 if (action
== CACHE_SELECTION_RESELECT_WITHOUT_MANIFEST
) {
1048 rv
= SelectDocAppCacheNoManifest(applicationCache
,
1049 getter_AddRefs(manifestURI
), &action
);
1050 if (NS_FAILED(rv
)) {
1056 case CACHE_SELECTION_NONE
:
1058 case CACHE_SELECTION_UPDATE
: {
1059 nsCOMPtr
<nsIOfflineCacheUpdateService
> updateService
=
1060 components::OfflineCacheUpdate::Service();
1062 if (updateService
) {
1063 updateService
->ScheduleOnDocumentStop(
1064 manifestURI
, mDocumentURI
, mDocument
->NodePrincipal(), mDocument
);
1068 case CACHE_SELECTION_RELOAD
: {
1069 // This situation occurs only for toplevel documents, see bottom
1070 // of SelectDocAppCache method.
1071 // The document has been loaded from a different offline cache group than
1072 // the manifest it refers to, i.e. this is a foreign entry, mark it as
1073 // such and force a reload to avoid loading it. The next attempt will not
1076 applicationCacheChannel
->MarkOfflineCacheEntryAsForeign();
1078 nsCOMPtr
<nsIWebNavigation
> webNav
= do_QueryInterface(mDocShell
);
1080 webNav
->Stop(nsIWebNavigation::STOP_ALL
);
1081 webNav
->Reload(nsIWebNavigation::LOAD_FLAGS_NONE
);
1086 "Cache selection algorithm didn't decide on proper action");
1091 void nsContentSink::ScrollToRef() {
1092 RefPtr
<Document
> document
= mDocument
;
1093 document
->ScrollToRef();
1096 void nsContentSink::StartLayout(bool aIgnorePendingSheets
) {
1097 AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING("nsContentSink::StartLayout", LAYOUT
,
1098 mDocumentURI
->GetSpecOrDefault());
1100 if (mLayoutStarted
) {
1101 // Nothing to do here
1105 mDeferredLayoutStart
= true;
1107 if (!aIgnorePendingSheets
&&
1108 (WaitForPendingSheets() || mDocument
->HasPendingInitialTranslation())) {
1109 // Bail out; we'll start layout when the sheets and l10n load
1113 mDeferredLayoutStart
= false;
1115 if (aIgnorePendingSheets
) {
1116 nsContentUtils::ReportToConsole(
1117 nsIScriptError::warningFlag
, "Layout"_ns
, mDocument
,
1118 nsContentUtils::eLAYOUT_PROPERTIES
, "ForcedLayoutStart");
1121 // Notify on all our content. If none of our presshells have started layout
1122 // yet it'll be a no-op except for updating our data structures, a la
1123 // UpdateChildCounts() (because we don't want to double-notify on whatever we
1124 // have right now). If some of them _have_ started layout, we want to make
1125 // sure to flush tags instead of just calling UpdateChildCounts() after we
1126 // loop over the shells.
1129 mLayoutStarted
= true;
1130 mLastNotificationTime
= PR_Now();
1132 mDocument
->SetMayStartLayout(true);
1133 RefPtr
<PresShell
> presShell
= mDocument
->GetPresShell();
1134 // Make sure we don't call Initialize() for a shell that has
1135 // already called it. This can happen when the layout frame for
1136 // an iframe is constructed *between* the Embed() call for the
1137 // docshell in the iframe, and the content sink's call to OpenBody().
1139 if (presShell
&& !presShell
->DidInitialize()) {
1140 nsresult rv
= presShell
->Initialize();
1141 if (NS_FAILED(rv
)) {
1146 // If the document we are loading has a reference or it is a
1147 // frameset document, disable the scroll bars on the views.
1149 mDocument
->SetScrollToRef(mDocument
->GetDocumentURI());
1152 void nsContentSink::NotifyAppend(nsIContent
* aContainer
, uint32_t aStartIndex
) {
1156 // Scope so we call EndUpdate before we decrease mInNotification
1158 // Note that aContainer->OwnerDoc() may not be mDocument.
1159 MOZ_AUTO_DOC_UPDATE(aContainer
->OwnerDoc(), true);
1160 MutationObservers::NotifyContentAppended(
1161 aContainer
, aContainer
->GetChildAt_Deprecated(aStartIndex
));
1162 mLastNotificationTime
= PR_Now();
1169 nsContentSink::Notify(nsITimer
* timer
) {
1171 // We shouldn't interfere with our normal DidProcessAToken logic
1172 mDroppedTimer
= true;
1176 if (WaitForPendingSheets()) {
1177 mDeferredFlushTags
= true;
1181 // Now try and scroll to the reference
1182 // XXX Should we scroll unconditionally for history loads??
1186 mNotificationTimer
= nullptr;
1190 bool nsContentSink::IsTimeToNotify() {
1191 if (!StaticPrefs::content_notify_ontimer() || !mLayoutStarted
||
1192 !mBackoffCount
|| mInMonolithicContainer
) {
1196 if (WaitForPendingSheets()) {
1197 mDeferredFlushTags
= true;
1201 PRTime now
= PR_Now();
1203 int64_t interval
= GetNotificationInterval();
1204 int64_t diff
= now
- mLastNotificationTime
;
1206 if (diff
> interval
) {
1214 nsresult
nsContentSink::WillInterruptImpl() {
1215 nsresult result
= NS_OK
;
1217 SINK_TRACE(static_cast<LogModule
*>(gContentSinkLogModuleInfo
),
1218 SINK_TRACE_CALLS
, ("nsContentSink::WillInterrupt: this=%p", this));
1219 #ifndef SINK_NO_INCREMENTAL
1220 if (WaitForPendingSheets()) {
1221 mDeferredFlushTags
= true;
1222 } else if (StaticPrefs::content_notify_ontimer() && mLayoutStarted
) {
1223 if (mBackoffCount
&& !mInMonolithicContainer
) {
1224 int64_t now
= PR_Now();
1225 int64_t interval
= GetNotificationInterval();
1226 int64_t diff
= now
- mLastNotificationTime
;
1228 // If it's already time for us to have a notification
1229 if (diff
> interval
|| mDroppedTimer
) {
1231 SINK_TRACE(static_cast<LogModule
*>(gContentSinkLogModuleInfo
),
1233 ("nsContentSink::WillInterrupt: flushing tags since we've "
1234 "run out time; backoff count: %d",
1236 result
= FlushTags();
1237 if (mDroppedTimer
) {
1239 mDroppedTimer
= false;
1241 } else if (!mNotificationTimer
) {
1243 int32_t delay
= interval
;
1245 // Convert to milliseconds
1246 delay
/= PR_USEC_PER_MSEC
;
1248 NS_NewTimerWithCallback(getter_AddRefs(mNotificationTimer
), this, delay
,
1249 nsITimer::TYPE_ONE_SHOT
);
1250 if (mNotificationTimer
) {
1251 SINK_TRACE(static_cast<LogModule
*>(gContentSinkLogModuleInfo
),
1253 ("nsContentSink::WillInterrupt: setting up timer with "
1260 SINK_TRACE(static_cast<LogModule
*>(gContentSinkLogModuleInfo
),
1262 ("nsContentSink::WillInterrupt: flushing tags "
1263 "unconditionally"));
1264 result
= FlushTags();
1273 nsresult
nsContentSink::WillResumeImpl() {
1274 SINK_TRACE(static_cast<LogModule
*>(gContentSinkLogModuleInfo
),
1275 SINK_TRACE_CALLS
, ("nsContentSink::WillResume: this=%p", this));
1282 nsresult
nsContentSink::DidProcessATokenImpl() {
1283 if (mRunsToCompletion
|| !mParser
) {
1287 // Get the current user event time
1288 PresShell
* presShell
= mDocument
->GetPresShell();
1290 // If there's no pres shell in the document, return early since
1291 // we're not laying anything out here.
1295 // Increase before comparing to gEventProbeRate
1298 // Check if there's a pending event
1299 if (StaticPrefs::content_sink_pending_event_mode() != 0 &&
1300 !mHasPendingEvent
&&
1301 (mDeflectedCount
% StaticPrefs::content_sink_event_probe_rate()) == 0) {
1302 nsViewManager
* vm
= presShell
->GetViewManager();
1303 NS_ENSURE_TRUE(vm
, NS_ERROR_FAILURE
);
1304 nsCOMPtr
<nsIWidget
> widget
;
1305 vm
->GetRootWidget(getter_AddRefs(widget
));
1306 mHasPendingEvent
= widget
&& widget
->HasPendingInputEvent();
1309 if (mHasPendingEvent
&& StaticPrefs::content_sink_pending_event_mode() == 2) {
1310 return NS_ERROR_HTMLPARSER_INTERRUPTED
;
1313 // Have we processed enough tokens to check time?
1314 if (!mHasPendingEvent
&&
1316 uint32_t(mDynamicLowerValue
1317 ? StaticPrefs::content_sink_interactive_deflect_count()
1318 : StaticPrefs::content_sink_perf_deflect_count())) {
1322 mDeflectedCount
= 0;
1324 // Check if it's time to return to the main event loop
1325 if (PR_IntervalToMicroseconds(PR_IntervalNow()) > mCurrentParseEndTime
) {
1326 return NS_ERROR_HTMLPARSER_INTERRUPTED
;
1332 //----------------------------------------------------------------------
1334 void nsContentSink::FavorPerformanceHint(bool perfOverStarvation
,
1335 uint32_t starvationDelay
) {
1336 static NS_DEFINE_CID(kAppShellCID
, NS_APPSHELL_CID
);
1337 nsCOMPtr
<nsIAppShell
> appShell
= do_GetService(kAppShellCID
);
1339 appShell
->FavorPerformanceHint(perfOverStarvation
, starvationDelay
);
1342 void nsContentSink::BeginUpdate(Document
* aDocument
) {
1343 // Remember nested updates from updates that we started.
1344 if (mInNotification
> 0 && mUpdatesInNotification
< 2) {
1345 ++mUpdatesInNotification
;
1348 // If we're in a script and we didn't do the notification,
1349 // something else in the script processing caused the
1350 // notification to occur. Since this could result in frame
1351 // creation, make sure we've flushed everything before we
1354 if (!mInNotification
++) {
1359 void nsContentSink::EndUpdate(Document
* aDocument
) {
1360 // If we're in a script and we didn't do the notification,
1361 // something else in the script processing caused the
1362 // notification to occur. Update our notion of how much
1363 // has been flushed to include any new content if ending
1364 // this update leaves us not inside a notification.
1365 if (!--mInNotification
) {
1366 UpdateChildCounts();
1370 void nsContentSink::DidBuildModelImpl(bool aTerminated
) {
1371 MOZ_ASSERT(aTerminated
||
1372 mDocument
->GetReadyStateEnum() == Document::READYSTATE_LOADING
,
1374 mDocument
->SetReadyStateInternal(Document::READYSTATE_INTERACTIVE
);
1376 if (mScriptLoader
) {
1377 mScriptLoader
->ParsingComplete(aTerminated
);
1378 if (!mPendingSheetCount
) {
1379 mScriptLoader
->DeferCheckpointReached();
1383 if (!mDocument
->HaveFiredDOMTitleChange()) {
1384 mDocument
->NotifyPossibleTitleChange(false);
1387 // Cancel a timer if we had one out there
1388 if (mNotificationTimer
) {
1389 SINK_TRACE(static_cast<LogModule
*>(gContentSinkLogModuleInfo
),
1391 ("nsContentSink::DidBuildModel: canceling notification "
1393 mNotificationTimer
->Cancel();
1394 mNotificationTimer
= nullptr;
1398 void nsContentSink::DropParserAndPerfHint(void) {
1400 // Make sure we don't unblock unload too many times
1405 // Do this hack to make sure that the parser
1406 // doesn't get destroyed, accidently, before
1407 // the circularity, between sink & parser, is
1409 // Drop our reference to the parser to get rid of a circular
1411 RefPtr
<nsParserBase
> kungFuDeathGrip
= std::move(mParser
);
1412 mozilla::Unused
<< kungFuDeathGrip
;
1414 if (mDynamicLowerValue
) {
1415 // Reset the performance hint which was set to FALSE
1416 // when mDynamicLowerValue was set.
1417 FavorPerformanceHint(true, 0);
1420 // Call UnblockOnload only if mRunsToComletion is false and if
1421 // we have already started loading because it's possible that this function
1422 // is called (i.e. the parser is terminated) before we start loading due to
1423 // destroying the window inside unload event callbacks for the previous
1425 if (!mRunsToCompletion
&& mIsBlockingOnload
) {
1426 mDocument
->UnblockOnload(true);
1427 mIsBlockingOnload
= false;
1431 bool nsContentSink::IsScriptExecutingImpl() {
1432 return !!mScriptLoader
->GetCurrentScript();
1435 nsresult
nsContentSink::WillParseImpl(void) {
1436 if (mRunsToCompletion
|| !mDocument
) {
1440 PresShell
* presShell
= mDocument
->GetPresShell();
1445 uint32_t currentTime
= PR_IntervalToMicroseconds(PR_IntervalNow());
1447 if (StaticPrefs::content_sink_enable_perf_mode() == 0) {
1448 nsViewManager
* vm
= presShell
->GetViewManager();
1449 NS_ENSURE_TRUE(vm
, NS_ERROR_FAILURE
);
1450 uint32_t lastEventTime
;
1451 vm
->GetLastUserEventTime(lastEventTime
);
1453 bool newDynLower
= mDocument
->IsInBackgroundWindow() ||
1454 ((currentTime
- mBeginLoadTime
) >
1455 StaticPrefs::content_sink_initial_perf_time() &&
1456 (currentTime
- lastEventTime
) <
1457 StaticPrefs::content_sink_interactive_time());
1459 if (mDynamicLowerValue
!= newDynLower
) {
1460 FavorPerformanceHint(!newDynLower
, 0);
1461 mDynamicLowerValue
= newDynLower
;
1465 mDeflectedCount
= 0;
1466 mHasPendingEvent
= false;
1468 mCurrentParseEndTime
=
1469 currentTime
+ (mDynamicLowerValue
1470 ? StaticPrefs::content_sink_interactive_parse_time()
1471 : StaticPrefs::content_sink_perf_parse_time());
1476 void nsContentSink::WillBuildModelImpl() {
1477 if (!mRunsToCompletion
) {
1478 mDocument
->BlockOnload();
1479 mIsBlockingOnload
= true;
1481 mBeginLoadTime
= PR_IntervalToMicroseconds(PR_IntervalNow());
1484 mDocument
->ResetScrolledToRefAlready();
1486 if (mProcessLinkHeaderEvent
.get()) {
1487 mProcessLinkHeaderEvent
.Revoke();
1489 DoProcessLinkHeader();
1494 void nsContentSink::NotifyDocElementCreated(Document
* aDoc
) {
1495 MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
1497 nsCOMPtr
<nsIObserverService
> observerService
=
1498 mozilla::services::GetObserverService();
1499 MOZ_ASSERT(observerService
);
1501 auto* win
= nsGlobalWindowInner::Cast(aDoc
->GetInnerWindow());
1502 bool fireInitialInsertion
= !win
|| !win
->DidFireDocElemInserted();
1504 win
->SetDidFireDocElemInserted();
1506 if (fireInitialInsertion
) {
1507 observerService
->NotifyObservers(ToSupports(aDoc
),
1508 "initial-document-element-inserted", u
"");
1510 observerService
->NotifyObservers(ToSupports(aDoc
),
1511 "document-element-inserted", u
"");
1513 nsContentUtils::DispatchChromeEvent(aDoc
, ToSupports(aDoc
),
1514 u
"DOMDocElementInserted"_ns
,
1515 CanBubble::eYes
, Cancelable::eNo
);
1519 nsContentSink::GetName(nsACString
& aName
) {
1520 aName
.AssignLiteral("nsContentSink_timer");