content/base/src/nsContentSink.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/content/base/src/nsContentSink.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,363 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +/*
    1.10 + * Base class for the XML and HTML content sinks, which construct a
    1.11 + * DOM based on information from the parser.
    1.12 + */
    1.13 +
    1.14 +#ifndef _nsContentSink_h_
    1.15 +#define _nsContentSink_h_
    1.16 +
    1.17 +// Base class for contentsink implementations.
    1.18 +
    1.19 +#include "mozilla/Attributes.h"
    1.20 +#include "nsICSSLoaderObserver.h"
    1.21 +#include "nsWeakReference.h"
    1.22 +#include "nsCOMPtr.h"
    1.23 +#include "nsString.h"
    1.24 +#include "nsAutoPtr.h"
    1.25 +#include "nsGkAtoms.h"
    1.26 +#include "nsITimer.h"
    1.27 +#include "nsStubDocumentObserver.h"
    1.28 +#include "nsIContentSink.h"
    1.29 +#include "prlog.h"
    1.30 +#include "nsCycleCollectionParticipant.h"
    1.31 +#include "nsThreadUtils.h"
    1.32 +
    1.33 +class nsIDocument;
    1.34 +class nsIURI;
    1.35 +class nsIChannel;
    1.36 +class nsIDocShell;
    1.37 +class nsIParser;
    1.38 +class nsIAtom;
    1.39 +class nsIChannel;
    1.40 +class nsIContent;
    1.41 +class nsViewManager;
    1.42 +class nsNodeInfoManager;
    1.43 +class nsScriptLoader;
    1.44 +class nsIApplicationCache;
    1.45 +
    1.46 +namespace mozilla {
    1.47 +namespace css {
    1.48 +class Loader;
    1.49 +}
    1.50 +}
    1.51 +
    1.52 +#ifdef DEBUG
    1.53 +
    1.54 +extern PRLogModuleInfo* gContentSinkLogModuleInfo;
    1.55 +
    1.56 +#define SINK_TRACE_CALLS              0x1
    1.57 +#define SINK_TRACE_REFLOW             0x2
    1.58 +#define SINK_ALWAYS_REFLOW            0x4
    1.59 +
    1.60 +#define SINK_LOG_TEST(_lm, _bit) (int((_lm)->level) & (_bit))
    1.61 +
    1.62 +#define SINK_TRACE(_lm, _bit, _args) \
    1.63 +  PR_BEGIN_MACRO                     \
    1.64 +    if (SINK_LOG_TEST(_lm, _bit)) {  \
    1.65 +      PR_LogPrint _args;             \
    1.66 +    }                                \
    1.67 +  PR_END_MACRO
    1.68 +
    1.69 +#else
    1.70 +#define SINK_TRACE(_lm, _bit, _args)
    1.71 +#endif
    1.72 +
    1.73 +#undef SINK_NO_INCREMENTAL
    1.74 +
    1.75 +//----------------------------------------------------------------------
    1.76 +
    1.77 +// 1/2 second fudge factor for window creation
    1.78 +#define NS_DELAY_FOR_WINDOW_CREATION  500000
    1.79 +
    1.80 +class nsContentSink : public nsICSSLoaderObserver,
    1.81 +                      public nsSupportsWeakReference,
    1.82 +                      public nsStubDocumentObserver,
    1.83 +                      public nsITimerCallback
    1.84 +{
    1.85 +  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
    1.86 +  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsContentSink,
    1.87 +                                           nsICSSLoaderObserver)
    1.88 +    // nsITimerCallback
    1.89 +  NS_DECL_NSITIMERCALLBACK
    1.90 +
    1.91 +  // nsICSSLoaderObserver
    1.92 +  NS_IMETHOD StyleSheetLoaded(nsCSSStyleSheet* aSheet, bool aWasAlternate,
    1.93 +                              nsresult aStatus) MOZ_OVERRIDE;
    1.94 +
    1.95 +  virtual nsresult ProcessMETATag(nsIContent* aContent);
    1.96 +
    1.97 +  // nsIContentSink implementation helpers
    1.98 +  NS_HIDDEN_(nsresult) WillParseImpl(void);
    1.99 +  NS_HIDDEN_(nsresult) WillInterruptImpl(void);
   1.100 +  NS_HIDDEN_(nsresult) WillResumeImpl(void);
   1.101 +  NS_HIDDEN_(nsresult) DidProcessATokenImpl(void);
   1.102 +  NS_HIDDEN_(void) WillBuildModelImpl(void);
   1.103 +  NS_HIDDEN_(void) DidBuildModelImpl(bool aTerminated);
   1.104 +  NS_HIDDEN_(void) DropParserAndPerfHint(void);
   1.105 +  bool IsScriptExecutingImpl();
   1.106 +
   1.107 +  void NotifyAppend(nsIContent* aContent, uint32_t aStartIndex);
   1.108 +
   1.109 +  // nsIDocumentObserver
   1.110 +  NS_DECL_NSIDOCUMENTOBSERVER_BEGINUPDATE
   1.111 +  NS_DECL_NSIDOCUMENTOBSERVER_ENDUPDATE
   1.112 +
   1.113 +  virtual void UpdateChildCounts() = 0;
   1.114 +
   1.115 +  bool IsTimeToNotify();
   1.116 +  bool LinkContextIsOurDocument(const nsSubstring& aAnchor);
   1.117 +  bool Decode5987Format(nsAString& aEncoded);
   1.118 +
   1.119 +  static void InitializeStatics();
   1.120 +
   1.121 +protected:
   1.122 +  nsContentSink();
   1.123 +  virtual ~nsContentSink();
   1.124 +
   1.125 +  enum CacheSelectionAction {
   1.126 +    // There is no offline cache manifest specified by the document,
   1.127 +    // or the document was loaded from a cache other than the one it
   1.128 +    // specifies via its manifest attribute and IS NOT a top-level
   1.129 +    // document, or an error occurred during the cache selection
   1.130 +    // algorithm.
   1.131 +    CACHE_SELECTION_NONE = 0,
   1.132 +
   1.133 +    // The offline cache manifest must be updated.
   1.134 +    CACHE_SELECTION_UPDATE = 1,
   1.135 +
   1.136 +    // The document was loaded from a cache other than the one it
   1.137 +    // specifies via its manifest attribute and IS a top-level
   1.138 +    // document.  In this case, the document is marked as foreign in
   1.139 +    // the cache it was loaded from and must be reloaded from the
   1.140 +    // correct cache (the one it specifies).
   1.141 +    CACHE_SELECTION_RELOAD = 2,
   1.142 +
   1.143 +    // Some conditions require we must reselect the cache without the manifest
   1.144 +    CACHE_SELECTION_RESELECT_WITHOUT_MANIFEST = 3
   1.145 +  };
   1.146 +
   1.147 +  nsresult Init(nsIDocument* aDoc, nsIURI* aURI,
   1.148 +                nsISupports* aContainer, nsIChannel* aChannel);
   1.149 +
   1.150 +  nsresult ProcessHTTPHeaders(nsIChannel* aChannel);
   1.151 +  nsresult ProcessHeaderData(nsIAtom* aHeader, const nsAString& aValue,
   1.152 +                             nsIContent* aContent = nullptr);
   1.153 +  nsresult ProcessLinkHeader(const nsAString& aLinkData);
   1.154 +  nsresult ProcessLink(const nsSubstring& aAnchor,
   1.155 +                       const nsSubstring& aHref, const nsSubstring& aRel,
   1.156 +                       const nsSubstring& aTitle, const nsSubstring& aType,
   1.157 +                       const nsSubstring& aMedia);
   1.158 +
   1.159 +  virtual nsresult ProcessStyleLink(nsIContent* aElement,
   1.160 +                                    const nsSubstring& aHref,
   1.161 +                                    bool aAlternate,
   1.162 +                                    const nsSubstring& aTitle,
   1.163 +                                    const nsSubstring& aType,
   1.164 +                                    const nsSubstring& aMedia);
   1.165 +
   1.166 +  void PrefetchHref(const nsAString &aHref, nsINode *aSource,
   1.167 +                    bool aExplicit);
   1.168 +
   1.169 +  // aHref can either be the usual URI format or of the form "//www.hostname.com"
   1.170 +  // without a scheme.
   1.171 +  void PrefetchDNS(const nsAString &aHref);
   1.172 +
   1.173 +  // Gets the cache key (used to identify items in a cache) of the channel.
   1.174 +  nsresult GetChannelCacheKey(nsIChannel* aChannel, nsACString& aCacheKey);
   1.175 +
   1.176 +  // There is an offline cache manifest attribute specified and the
   1.177 +  // document is allowed to use the offline cache.  Process the cache
   1.178 +  // selection algorithm for this document and the manifest. Result is
   1.179 +  // an action that must be taken on the manifest, see
   1.180 +  // CacheSelectionAction enum above.
   1.181 +  //
   1.182 +  // @param aLoadApplicationCache
   1.183 +  //        The application cache from which the load originated, if
   1.184 +  //        any.
   1.185 +  // @param aManifestURI
   1.186 +  //        The manifest URI listed in the document.
   1.187 +  // @param aFetchedWithHTTPGetOrEquiv
   1.188 +  //        TRUE if this was fetched using the HTTP GET method.
   1.189 +  // @param aAction
   1.190 +  //        Out parameter, returns the action that should be performed
   1.191 +  //        by the calling function.
   1.192 +  nsresult SelectDocAppCache(nsIApplicationCache *aLoadApplicationCache,
   1.193 +                             nsIURI *aManifestURI,
   1.194 +                             bool aFetchedWithHTTPGetOrEquiv,
   1.195 +                             CacheSelectionAction *aAction);
   1.196 +
   1.197 +  // There is no offline cache manifest attribute specified.  Process
   1.198 +  // the cache selection algorithm w/o the manifest. Result is an
   1.199 +  // action that must be taken, see CacheSelectionAction enum
   1.200 +  // above. In case the offline cache manifest has to be updated the
   1.201 +  // manifest URI is returned in aManifestURI.
   1.202 +  //
   1.203 +  // @param aLoadApplicationCache
   1.204 +  //        The application cache from which the load originated, if
   1.205 +  //        any.
   1.206 +  // @param aManifestURI
   1.207 +  //        Out parameter, returns the manifest URI of the cache that
   1.208 +  //        was selected.
   1.209 +  // @param aAction
   1.210 +  //        Out parameter, returns the action that should be performed
   1.211 +  //        by the calling function.
   1.212 +  nsresult SelectDocAppCacheNoManifest(nsIApplicationCache *aLoadApplicationCache,
   1.213 +                                       nsIURI **aManifestURI,
   1.214 +                                       CacheSelectionAction *aAction);
   1.215 +
   1.216 +public:
   1.217 +  // Searches for the offline cache manifest attribute and calls one
   1.218 +  // of the above defined methods to select the document's application
   1.219 +  // cache, let it be associated with the document and eventually
   1.220 +  // schedule the cache update process.
   1.221 +  // This method MUST be called with the empty string as the argument
   1.222 +  // when there is no manifest attribute!
   1.223 +  void ProcessOfflineManifest(const nsAString& aManifestSpec);
   1.224 +
   1.225 +  // Extracts the manifest attribute from the element if it is the root 
   1.226 +  // element and calls the above method.
   1.227 +  void ProcessOfflineManifest(nsIContent *aElement);
   1.228 +
   1.229 +protected:
   1.230 +  // Tries to scroll to the URI's named anchor. Once we've successfully
   1.231 +  // done that, further calls to this method will be ignored.
   1.232 +  void ScrollToRef();
   1.233 +
   1.234 +  // Start layout.  If aIgnorePendingSheets is true, this will happen even if
   1.235 +  // we still have stylesheet loads pending.  Otherwise, we'll wait until the
   1.236 +  // stylesheets are all done loading.
   1.237 +public:
   1.238 +  void StartLayout(bool aIgnorePendingSheets);
   1.239 +
   1.240 +  static void NotifyDocElementCreated(nsIDocument* aDoc);
   1.241 +
   1.242 +protected:
   1.243 +  void
   1.244 +  FavorPerformanceHint(bool perfOverStarvation, uint32_t starvationDelay);
   1.245 +
   1.246 +  inline int32_t GetNotificationInterval()
   1.247 +  {
   1.248 +    if (mDynamicLowerValue) {
   1.249 +      return 1000;
   1.250 +    }
   1.251 +
   1.252 +    return sNotificationInterval;
   1.253 +  }
   1.254 +
   1.255 +  virtual nsresult FlushTags() = 0;
   1.256 +
   1.257 +  // Later on we might want to make this more involved somehow
   1.258 +  // (e.g. stop waiting after some timeout or whatnot).
   1.259 +  bool WaitForPendingSheets() { return mPendingSheetCount > 0; }
   1.260 +
   1.261 +  void DoProcessLinkHeader();
   1.262 +
   1.263 +  void StopDeflecting() {
   1.264 +    mDeflectedCount = sPerfDeflectCount;
   1.265 +  }
   1.266 +
   1.267 +private:
   1.268 +  // People shouldn't be allocating this class directly.  All subclasses should
   1.269 +  // be allocated using a zeroing operator new.
   1.270 +  void* operator new(size_t sz) CPP_THROW_NEW;  // Not to be implemented
   1.271 +
   1.272 +protected:
   1.273 +
   1.274 +  nsCOMPtr<nsIDocument>         mDocument;
   1.275 +  nsRefPtr<nsParserBase>        mParser;
   1.276 +  nsCOMPtr<nsIURI>              mDocumentURI;
   1.277 +  nsCOMPtr<nsIDocShell>         mDocShell;
   1.278 +  nsRefPtr<mozilla::css::Loader> mCSSLoader;
   1.279 +  nsRefPtr<nsNodeInfoManager>   mNodeInfoManager;
   1.280 +  nsRefPtr<nsScriptLoader>      mScriptLoader;
   1.281 +
   1.282 +  // back off timer notification after count
   1.283 +  int32_t mBackoffCount;
   1.284 +
   1.285 +  // Time of last notification
   1.286 +  // Note: mLastNotificationTime is only valid once mLayoutStarted is true.
   1.287 +  PRTime mLastNotificationTime;
   1.288 +
   1.289 +  // Timer used for notification
   1.290 +  nsCOMPtr<nsITimer> mNotificationTimer;
   1.291 +
   1.292 +  // Have we already called BeginUpdate for this set of content changes?
   1.293 +  uint8_t mBeganUpdate : 1;
   1.294 +  uint8_t mLayoutStarted : 1;
   1.295 +  uint8_t mDynamicLowerValue : 1;
   1.296 +  uint8_t mParsing : 1;
   1.297 +  uint8_t mDroppedTimer : 1;
   1.298 +  // If true, we deferred starting layout until sheets load
   1.299 +  uint8_t mDeferredLayoutStart : 1;
   1.300 +  // If true, we deferred notifications until sheets load
   1.301 +  uint8_t mDeferredFlushTags : 1;
   1.302 +  // If false, we're not ourselves a document observer; that means we
   1.303 +  // shouldn't be performing any more content model notifications,
   1.304 +  // since we're not longer updating our child counts.
   1.305 +  uint8_t mIsDocumentObserver : 1;
   1.306 +  // True if this is parser is a fragment parser or an HTML DOMParser.
   1.307 +  // XML DOMParser leaves this to false for now!
   1.308 +  uint8_t mRunsToCompletion : 1;
   1.309 +  
   1.310 +  //
   1.311 +  // -- Can interrupt parsing members --
   1.312 +  //
   1.313 +
   1.314 +  // The number of tokens that have been processed since we measured
   1.315 +  // if it's time to return to the main event loop.
   1.316 +  uint32_t mDeflectedCount;
   1.317 +
   1.318 +  // Is there currently a pending event?
   1.319 +  bool mHasPendingEvent;
   1.320 +
   1.321 +  // When to return to the main event loop
   1.322 +  uint32_t mCurrentParseEndTime;
   1.323 +
   1.324 +  int32_t mBeginLoadTime;
   1.325 +
   1.326 +  // Last mouse event or keyboard event time sampled by the content
   1.327 +  // sink
   1.328 +  uint32_t mLastSampledUserEventTime;
   1.329 +
   1.330 +  int32_t mInMonolithicContainer;
   1.331 +
   1.332 +  int32_t mInNotification;
   1.333 +  uint32_t mUpdatesInNotification;
   1.334 +
   1.335 +  uint32_t mPendingSheetCount;
   1.336 +
   1.337 +  nsRevocableEventPtr<nsRunnableMethod<nsContentSink, void, false> >
   1.338 +    mProcessLinkHeaderEvent;
   1.339 +
   1.340 +  // Do we notify based on time?
   1.341 +  static bool sNotifyOnTimer;
   1.342 +  // Back off timer notification after count.
   1.343 +  static int32_t sBackoffCount;
   1.344 +  // Notification interval in microseconds
   1.345 +  static int32_t sNotificationInterval;
   1.346 +  // How many times to deflect in interactive/perf modes
   1.347 +  static int32_t sInteractiveDeflectCount;
   1.348 +  static int32_t sPerfDeflectCount;
   1.349 +  // 0 = don't check for pending events
   1.350 +  // 1 = don't deflect if there are pending events
   1.351 +  // 2 = bail if there are pending events
   1.352 +  static int32_t sPendingEventMode;
   1.353 +  // How often to probe for pending events. 1=every token
   1.354 +  static int32_t sEventProbeRate;
   1.355 +  // How long to stay off the event loop in interactive/perf modes
   1.356 +  static int32_t sInteractiveParseTime;
   1.357 +  static int32_t sPerfParseTime;
   1.358 +  // How long to be in interactive mode after an event
   1.359 +  static int32_t sInteractiveTime;
   1.360 +  // How long to stay in perf mode after initial loading
   1.361 +  static int32_t sInitialPerfTime;
   1.362 +  // Should we switch between perf-mode and interactive-mode
   1.363 +  static int32_t sEnablePerfMode;
   1.364 +};
   1.365 +
   1.366 +#endif // _nsContentSink_h_

mercurial