content/base/src/nsContentSink.h

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

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

mercurial