Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /*
7 * Base class for the XML and HTML content sinks, which construct a
8 * DOM based on information from the parser.
9 */
11 #ifndef _nsContentSink_h_
12 #define _nsContentSink_h_
14 // Base class for contentsink implementations.
16 #include "mozilla/Attributes.h"
17 #include "nsICSSLoaderObserver.h"
18 #include "nsWeakReference.h"
19 #include "nsCOMPtr.h"
20 #include "nsString.h"
21 #include "nsAutoPtr.h"
22 #include "nsGkAtoms.h"
23 #include "nsITimer.h"
24 #include "nsStubDocumentObserver.h"
25 #include "nsIContentSink.h"
26 #include "prlog.h"
27 #include "nsCycleCollectionParticipant.h"
28 #include "nsThreadUtils.h"
30 class nsIDocument;
31 class nsIURI;
32 class nsIChannel;
33 class nsIDocShell;
34 class nsIParser;
35 class nsIAtom;
36 class nsIChannel;
37 class nsIContent;
38 class nsViewManager;
39 class nsNodeInfoManager;
40 class nsScriptLoader;
41 class nsIApplicationCache;
43 namespace mozilla {
44 namespace css {
45 class Loader;
46 }
47 }
49 #ifdef DEBUG
51 extern PRLogModuleInfo* gContentSinkLogModuleInfo;
53 #define SINK_TRACE_CALLS 0x1
54 #define SINK_TRACE_REFLOW 0x2
55 #define SINK_ALWAYS_REFLOW 0x4
57 #define SINK_LOG_TEST(_lm, _bit) (int((_lm)->level) & (_bit))
59 #define SINK_TRACE(_lm, _bit, _args) \
60 PR_BEGIN_MACRO \
61 if (SINK_LOG_TEST(_lm, _bit)) { \
62 PR_LogPrint _args; \
63 } \
64 PR_END_MACRO
66 #else
67 #define SINK_TRACE(_lm, _bit, _args)
68 #endif
70 #undef SINK_NO_INCREMENTAL
72 //----------------------------------------------------------------------
74 // 1/2 second fudge factor for window creation
75 #define NS_DELAY_FOR_WINDOW_CREATION 500000
77 class nsContentSink : public nsICSSLoaderObserver,
78 public nsSupportsWeakReference,
79 public nsStubDocumentObserver,
80 public nsITimerCallback
81 {
82 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
83 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsContentSink,
84 nsICSSLoaderObserver)
85 // nsITimerCallback
86 NS_DECL_NSITIMERCALLBACK
88 // nsICSSLoaderObserver
89 NS_IMETHOD StyleSheetLoaded(nsCSSStyleSheet* aSheet, bool aWasAlternate,
90 nsresult aStatus) MOZ_OVERRIDE;
92 virtual nsresult ProcessMETATag(nsIContent* aContent);
94 // nsIContentSink implementation helpers
95 NS_HIDDEN_(nsresult) WillParseImpl(void);
96 NS_HIDDEN_(nsresult) WillInterruptImpl(void);
97 NS_HIDDEN_(nsresult) WillResumeImpl(void);
98 NS_HIDDEN_(nsresult) DidProcessATokenImpl(void);
99 NS_HIDDEN_(void) WillBuildModelImpl(void);
100 NS_HIDDEN_(void) DidBuildModelImpl(bool aTerminated);
101 NS_HIDDEN_(void) DropParserAndPerfHint(void);
102 bool IsScriptExecutingImpl();
104 void NotifyAppend(nsIContent* aContent, uint32_t aStartIndex);
106 // nsIDocumentObserver
107 NS_DECL_NSIDOCUMENTOBSERVER_BEGINUPDATE
108 NS_DECL_NSIDOCUMENTOBSERVER_ENDUPDATE
110 virtual void UpdateChildCounts() = 0;
112 bool IsTimeToNotify();
113 bool LinkContextIsOurDocument(const nsSubstring& aAnchor);
114 bool Decode5987Format(nsAString& aEncoded);
116 static void InitializeStatics();
118 protected:
119 nsContentSink();
120 virtual ~nsContentSink();
122 enum CacheSelectionAction {
123 // There is no offline cache manifest specified by the document,
124 // or the document was loaded from a cache other than the one it
125 // specifies via its manifest attribute and IS NOT a top-level
126 // document, or an error occurred during the cache selection
127 // algorithm.
128 CACHE_SELECTION_NONE = 0,
130 // The offline cache manifest must be updated.
131 CACHE_SELECTION_UPDATE = 1,
133 // The document was loaded from a cache other than the one it
134 // specifies via its manifest attribute and IS a top-level
135 // document. In this case, the document is marked as foreign in
136 // the cache it was loaded from and must be reloaded from the
137 // correct cache (the one it specifies).
138 CACHE_SELECTION_RELOAD = 2,
140 // Some conditions require we must reselect the cache without the manifest
141 CACHE_SELECTION_RESELECT_WITHOUT_MANIFEST = 3
142 };
144 nsresult Init(nsIDocument* aDoc, nsIURI* aURI,
145 nsISupports* aContainer, nsIChannel* aChannel);
147 nsresult ProcessHTTPHeaders(nsIChannel* aChannel);
148 nsresult ProcessHeaderData(nsIAtom* aHeader, const nsAString& aValue,
149 nsIContent* aContent = nullptr);
150 nsresult ProcessLinkHeader(const nsAString& aLinkData);
151 nsresult ProcessLink(const nsSubstring& aAnchor,
152 const nsSubstring& aHref, const nsSubstring& aRel,
153 const nsSubstring& aTitle, const nsSubstring& aType,
154 const nsSubstring& aMedia);
156 virtual nsresult ProcessStyleLink(nsIContent* aElement,
157 const nsSubstring& aHref,
158 bool aAlternate,
159 const nsSubstring& aTitle,
160 const nsSubstring& aType,
161 const nsSubstring& aMedia);
163 void PrefetchHref(const nsAString &aHref, nsINode *aSource,
164 bool aExplicit);
166 // aHref can either be the usual URI format or of the form "//www.hostname.com"
167 // without a scheme.
168 void PrefetchDNS(const nsAString &aHref);
170 // Gets the cache key (used to identify items in a cache) of the channel.
171 nsresult GetChannelCacheKey(nsIChannel* aChannel, nsACString& aCacheKey);
173 // There is an offline cache manifest attribute specified and the
174 // document is allowed to use the offline cache. Process the cache
175 // selection algorithm for this document and the manifest. Result is
176 // an action that must be taken on the manifest, see
177 // CacheSelectionAction enum above.
178 //
179 // @param aLoadApplicationCache
180 // The application cache from which the load originated, if
181 // any.
182 // @param aManifestURI
183 // The manifest URI listed in the document.
184 // @param aFetchedWithHTTPGetOrEquiv
185 // TRUE if this was fetched using the HTTP GET method.
186 // @param aAction
187 // Out parameter, returns the action that should be performed
188 // by the calling function.
189 nsresult SelectDocAppCache(nsIApplicationCache *aLoadApplicationCache,
190 nsIURI *aManifestURI,
191 bool aFetchedWithHTTPGetOrEquiv,
192 CacheSelectionAction *aAction);
194 // There is no offline cache manifest attribute specified. Process
195 // the cache selection algorithm w/o the manifest. Result is an
196 // action that must be taken, see CacheSelectionAction enum
197 // above. In case the offline cache manifest has to be updated the
198 // manifest URI is returned in aManifestURI.
199 //
200 // @param aLoadApplicationCache
201 // The application cache from which the load originated, if
202 // any.
203 // @param aManifestURI
204 // Out parameter, returns the manifest URI of the cache that
205 // was selected.
206 // @param aAction
207 // Out parameter, returns the action that should be performed
208 // by the calling function.
209 nsresult SelectDocAppCacheNoManifest(nsIApplicationCache *aLoadApplicationCache,
210 nsIURI **aManifestURI,
211 CacheSelectionAction *aAction);
213 public:
214 // Searches for the offline cache manifest attribute and calls one
215 // of the above defined methods to select the document's application
216 // cache, let it be associated with the document and eventually
217 // schedule the cache update process.
218 // This method MUST be called with the empty string as the argument
219 // when there is no manifest attribute!
220 void ProcessOfflineManifest(const nsAString& aManifestSpec);
222 // Extracts the manifest attribute from the element if it is the root
223 // element and calls the above method.
224 void ProcessOfflineManifest(nsIContent *aElement);
226 protected:
227 // Tries to scroll to the URI's named anchor. Once we've successfully
228 // done that, further calls to this method will be ignored.
229 void ScrollToRef();
231 // Start layout. If aIgnorePendingSheets is true, this will happen even if
232 // we still have stylesheet loads pending. Otherwise, we'll wait until the
233 // stylesheets are all done loading.
234 public:
235 void StartLayout(bool aIgnorePendingSheets);
237 static void NotifyDocElementCreated(nsIDocument* aDoc);
239 protected:
240 void
241 FavorPerformanceHint(bool perfOverStarvation, uint32_t starvationDelay);
243 inline int32_t GetNotificationInterval()
244 {
245 if (mDynamicLowerValue) {
246 return 1000;
247 }
249 return sNotificationInterval;
250 }
252 virtual nsresult FlushTags() = 0;
254 // Later on we might want to make this more involved somehow
255 // (e.g. stop waiting after some timeout or whatnot).
256 bool WaitForPendingSheets() { return mPendingSheetCount > 0; }
258 void DoProcessLinkHeader();
260 void StopDeflecting() {
261 mDeflectedCount = sPerfDeflectCount;
262 }
264 private:
265 // People shouldn't be allocating this class directly. All subclasses should
266 // be allocated using a zeroing operator new.
267 void* operator new(size_t sz) CPP_THROW_NEW; // Not to be implemented
269 protected:
271 nsCOMPtr<nsIDocument> mDocument;
272 nsRefPtr<nsParserBase> mParser;
273 nsCOMPtr<nsIURI> mDocumentURI;
274 nsCOMPtr<nsIDocShell> mDocShell;
275 nsRefPtr<mozilla::css::Loader> mCSSLoader;
276 nsRefPtr<nsNodeInfoManager> mNodeInfoManager;
277 nsRefPtr<nsScriptLoader> mScriptLoader;
279 // back off timer notification after count
280 int32_t mBackoffCount;
282 // Time of last notification
283 // Note: mLastNotificationTime is only valid once mLayoutStarted is true.
284 PRTime mLastNotificationTime;
286 // Timer used for notification
287 nsCOMPtr<nsITimer> mNotificationTimer;
289 // Have we already called BeginUpdate for this set of content changes?
290 uint8_t mBeganUpdate : 1;
291 uint8_t mLayoutStarted : 1;
292 uint8_t mDynamicLowerValue : 1;
293 uint8_t mParsing : 1;
294 uint8_t mDroppedTimer : 1;
295 // If true, we deferred starting layout until sheets load
296 uint8_t mDeferredLayoutStart : 1;
297 // If true, we deferred notifications until sheets load
298 uint8_t mDeferredFlushTags : 1;
299 // If false, we're not ourselves a document observer; that means we
300 // shouldn't be performing any more content model notifications,
301 // since we're not longer updating our child counts.
302 uint8_t mIsDocumentObserver : 1;
303 // True if this is parser is a fragment parser or an HTML DOMParser.
304 // XML DOMParser leaves this to false for now!
305 uint8_t mRunsToCompletion : 1;
307 //
308 // -- Can interrupt parsing members --
309 //
311 // The number of tokens that have been processed since we measured
312 // if it's time to return to the main event loop.
313 uint32_t mDeflectedCount;
315 // Is there currently a pending event?
316 bool mHasPendingEvent;
318 // When to return to the main event loop
319 uint32_t mCurrentParseEndTime;
321 int32_t mBeginLoadTime;
323 // Last mouse event or keyboard event time sampled by the content
324 // sink
325 uint32_t mLastSampledUserEventTime;
327 int32_t mInMonolithicContainer;
329 int32_t mInNotification;
330 uint32_t mUpdatesInNotification;
332 uint32_t mPendingSheetCount;
334 nsRevocableEventPtr<nsRunnableMethod<nsContentSink, void, false> >
335 mProcessLinkHeaderEvent;
337 // Do we notify based on time?
338 static bool sNotifyOnTimer;
339 // Back off timer notification after count.
340 static int32_t sBackoffCount;
341 // Notification interval in microseconds
342 static int32_t sNotificationInterval;
343 // How many times to deflect in interactive/perf modes
344 static int32_t sInteractiveDeflectCount;
345 static int32_t sPerfDeflectCount;
346 // 0 = don't check for pending events
347 // 1 = don't deflect if there are pending events
348 // 2 = bail if there are pending events
349 static int32_t sPendingEventMode;
350 // How often to probe for pending events. 1=every token
351 static int32_t sEventProbeRate;
352 // How long to stay off the event loop in interactive/perf modes
353 static int32_t sInteractiveParseTime;
354 static int32_t sPerfParseTime;
355 // How long to be in interactive mode after an event
356 static int32_t sInteractiveTime;
357 // How long to stay in perf mode after initial loading
358 static int32_t sInitialPerfTime;
359 // Should we switch between perf-mode and interactive-mode
360 static int32_t sEnablePerfMode;
361 };
363 #endif // _nsContentSink_h_