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 #ifndef _nsContentSink_h_
13 #define _nsContentSink_h_
15 // Base class for contentsink implementations.
17 #include "mozilla/Attributes.h"
18 #include "nsICSSLoaderObserver.h"
19 #include "nsNetUtil.h"
20 #include "nsWeakReference.h"
23 #include "nsGkAtoms.h"
25 #include "nsStubDocumentObserver.h"
26 #include "nsIContentSink.h"
27 #include "mozilla/Logging.h"
28 #include "nsCycleCollectionParticipant.h"
29 #include "nsThreadUtils.h"
30 #include "mozilla/StaticPrefs_content.h"
38 class nsNodeInfoManager
;
49 } // namespace mozilla
53 extern mozilla::LazyLogModule gContentSinkLogModuleInfo
;
55 # define SINK_TRACE_CALLS 0x1
56 # define SINK_TRACE_REFLOW 0x2
57 # define SINK_ALWAYS_REFLOW 0x4
59 # define SINK_LOG_TEST(_lm, _bit) (int((_lm)->Level()) & (_bit))
61 # define SINK_TRACE(_lm, _bit, _args) \
63 if (SINK_LOG_TEST(_lm, _bit)) { \
64 printf_stderr _args; \
69 # define SINK_TRACE(_lm, _bit, _args)
72 #undef SINK_NO_INCREMENTAL
74 //----------------------------------------------------------------------
76 class nsContentSink
: public nsICSSLoaderObserver
,
77 public nsSupportsWeakReference
,
78 public nsStubDocumentObserver
,
79 public nsITimerCallback
,
82 using Document
= mozilla::dom::Document
;
85 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
86 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsContentSink
, nsICSSLoaderObserver
)
88 NS_DECL_NSITIMERCALLBACK
92 // nsICSSLoaderObserver
93 NS_IMETHOD
StyleSheetLoaded(mozilla::StyleSheet
* aSheet
, bool aWasDeferred
,
94 nsresult aStatus
) override
;
96 // nsIContentSink implementation helpers
97 nsresult
WillParseImpl(void);
98 nsresult
WillInterruptImpl(void);
99 nsresult
WillResumeImpl(void);
100 nsresult
DidProcessATokenImpl(void);
101 void WillBuildModelImpl(void);
102 void DidBuildModelImpl(bool aTerminated
);
103 void DropParserAndPerfHint(void);
104 bool IsScriptExecutingImpl();
106 void NotifyAppend(nsIContent
* aContent
, uint32_t aStartIndex
);
108 // nsIDocumentObserver
109 NS_DECL_NSIDOCUMENTOBSERVER_BEGINUPDATE
110 NS_DECL_NSIDOCUMENTOBSERVER_ENDUPDATE
112 virtual void UpdateChildCounts() = 0;
114 bool IsTimeToNotify();
115 bool LinkContextIsOurDocument(const nsAString
& aAnchor
);
119 virtual ~nsContentSink();
121 nsresult
Init(Document
* aDoc
, nsIURI
* aURI
, nsISupports
* aContainer
,
122 nsIChannel
* aChannel
);
124 nsresult
ProcessHTTPHeaders(nsIChannel
* aChannel
);
125 nsresult
ProcessLinkFromHeader(const LinkHeader
& aHeader
);
127 virtual nsresult
ProcessStyleLinkFromHeader(
128 const nsAString
& aHref
, bool aAlternate
, const nsAString
& aTitle
,
129 const nsAString
& aIntegrity
, const nsAString
& aType
,
130 const nsAString
& aMedia
, const nsAString
& aReferrerPolicy
);
132 void PrefetchHref(const nsAString
& aHref
, const nsAString
& aAs
,
133 const nsAString
& aType
, const nsAString
& aMedia
);
134 void PreloadHref(const nsAString
& aHref
, const nsAString
& aAs
,
135 const nsAString
& aType
, const nsAString
& aMedia
,
136 const nsAString
& aIntegrity
, const nsAString
& aSrcset
,
137 const nsAString
& aSizes
, const nsAString
& aCORS
,
138 const nsAString
& aReferrerPolicy
);
140 // For PrefetchDNS() aHref can either be the usual
141 // URI format or of the form "//www.hostname.com" without a scheme.
142 void PrefetchDNS(const nsAString
& aHref
);
144 // Gets the cache key (used to identify items in a cache) of the channel.
145 nsresult
GetChannelCacheKey(nsIChannel
* aChannel
, nsACString
& aCacheKey
);
148 // For Preconnect() aHref can either be the usual
149 // URI format or of the form "//www.hostname.com" without a scheme.
150 void Preconnect(const nsAString
& aHref
, const nsAString
& aCrossOrigin
);
153 // Tries to scroll to the URI's named anchor. Once we've successfully
154 // done that, further calls to this method will be ignored.
155 MOZ_CAN_RUN_SCRIPT_BOUNDARY
void ScrollToRef();
157 // Start layout. If aIgnorePendingSheets is true, this will happen even if
158 // we still have stylesheet loads pending. Otherwise, we'll wait until the
159 // stylesheets are all done loading.
161 void StartLayout(bool aIgnorePendingSheets
);
163 static void NotifyDocElementCreated(Document
* aDoc
);
165 Document
* GetDocument() { return mDocument
; }
168 void FavorPerformanceHint(bool perfOverStarvation
, uint32_t starvationDelay
);
170 inline int32_t GetNotificationInterval() {
171 if (mDynamicLowerValue
) {
175 return mozilla::StaticPrefs::content_notify_interval();
178 virtual nsresult
FlushTags() = 0;
180 // Later on we might want to make this more involved somehow
181 // (e.g. stop waiting after some timeout or whatnot).
182 bool WaitForPendingSheets() { return mPendingSheetCount
> 0; }
184 void DoProcessLinkHeader();
186 void StopDeflecting() {
187 mDeflectedCount
= mozilla::StaticPrefs::content_sink_perf_deflect_count();
191 RefPtr
<Document
> mDocument
;
192 RefPtr
<nsParserBase
> mParser
;
193 nsCOMPtr
<nsIURI
> mDocumentURI
;
194 nsCOMPtr
<nsIDocShell
> mDocShell
;
195 RefPtr
<mozilla::css::Loader
> mCSSLoader
;
196 RefPtr
<nsNodeInfoManager
> mNodeInfoManager
;
197 RefPtr
<mozilla::dom::ScriptLoader
> mScriptLoader
;
199 // back off timer notification after count
200 int32_t mBackoffCount
;
202 // Time of last notification
203 // Note: mLastNotificationTime is only valid once mLayoutStarted is true.
204 PRTime mLastNotificationTime
;
206 // Timer used for notification
207 nsCOMPtr
<nsITimer
> mNotificationTimer
;
209 uint8_t mLayoutStarted
: 1;
210 uint8_t mDynamicLowerValue
: 1;
211 uint8_t mParsing
: 1;
212 uint8_t mDroppedTimer
: 1;
213 // If true, we deferred starting layout until sheets load
214 uint8_t mDeferredLayoutStart
: 1;
215 // If true, we deferred notifications until sheets load
216 uint8_t mDeferredFlushTags
: 1;
217 // If false, we're not ourselves a document observer; that means we
218 // shouldn't be performing any more content model notifications,
219 // since we're not longer updating our child counts.
220 uint8_t mIsDocumentObserver
: 1;
221 // True if this is parser is a fragment parser or an HTML DOMParser.
222 // XML DOMParser leaves this to false for now!
223 uint8_t mRunsToCompletion
: 1;
224 // True if we are blocking load event.
225 bool mIsBlockingOnload
: 1;
228 // -- Can interrupt parsing members --
231 // The number of tokens that have been processed since we measured
232 // if it's time to return to the main event loop.
233 uint32_t mDeflectedCount
;
235 // Is there currently a pending event?
236 bool mHasPendingEvent
;
238 // When to return to the main event loop
239 uint32_t mCurrentParseEndTime
;
241 int32_t mBeginLoadTime
;
243 // Last mouse event or keyboard event time sampled by the content
245 uint32_t mLastSampledUserEventTime
;
247 int32_t mInMonolithicContainer
;
249 int32_t mInNotification
;
250 uint32_t mUpdatesInNotification
;
252 uint32_t mPendingSheetCount
;
254 nsRevocableEventPtr
<nsRunnableMethod
<nsContentSink
, void, false> >
255 mProcessLinkHeaderEvent
;
258 #endif // _nsContentSink_h_