LCOV - code coverage report
Current view: top level - dom/base - nsContentSink.h (source / functions) Hit Total Coverage
Test: output.info Lines: 9 9 100.0 %
Date: 2017-07-14 16:53:18 Functions: 4 10 40.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13