tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsContentSink.h (8774B)


      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 "mozilla/Logging.h"
     19 #include "mozilla/StaticPrefs_content.h"
     20 #include "nsCOMPtr.h"
     21 #include "nsCycleCollectionParticipant.h"
     22 #include "nsGkAtoms.h"
     23 #include "nsICSSLoaderObserver.h"
     24 #include "nsIContentSink.h"
     25 #include "nsITimer.h"
     26 #include "nsString.h"
     27 #include "nsStubDocumentObserver.h"
     28 #include "nsThreadUtils.h"
     29 #include "nsWeakReference.h"
     30 
     31 class nsIURI;
     32 class nsIChannel;
     33 class nsIDocShell;
     34 class nsAtom;
     35 class nsIChannel;
     36 class nsIContent;
     37 class nsNodeInfoManager;
     38 
     39 namespace mozilla {
     40 namespace css {
     41 class Loader;
     42 }  // namespace css
     43 
     44 namespace dom {
     45 class Document;
     46 class ScriptLoader;
     47 }  // namespace dom
     48 
     49 namespace net {
     50 struct LinkHeader;
     51 };
     52 }  // namespace mozilla
     53 
     54 #ifdef DEBUG
     55 
     56 extern mozilla::LazyLogModule gContentSinkLogModuleInfo;
     57 
     58 #  define SINK_TRACE_CALLS 0x1
     59 #  define SINK_TRACE_REFLOW 0x2
     60 #  define SINK_ALWAYS_REFLOW 0x4
     61 
     62 #  define SINK_LOG_TEST(_lm, _bit) (int((_lm)->Level()) & (_bit))
     63 
     64 #  define SINK_TRACE(_lm, _bit, _args) \
     65    do {                               \
     66      if (SINK_LOG_TEST(_lm, _bit)) {  \
     67        printf_stderr _args;           \
     68      }                                \
     69    } while (0)
     70 
     71 #else
     72 #  define SINK_TRACE(_lm, _bit, _args)
     73 #endif
     74 
     75 #undef SINK_NO_INCREMENTAL
     76 
     77 //----------------------------------------------------------------------
     78 
     79 class nsContentSink : public nsICSSLoaderObserver,
     80                      public nsSupportsWeakReference,
     81                      public nsStubDocumentObserver,
     82                      public nsITimerCallback,
     83                      public nsINamed {
     84 protected:
     85  using Document = mozilla::dom::Document;
     86 
     87 private:
     88  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     89  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsContentSink, nsICSSLoaderObserver)
     90  // nsITimerCallback
     91  NS_DECL_NSITIMERCALLBACK
     92 
     93  NS_DECL_NSINAMED
     94 
     95  // nsICSSLoaderObserver
     96  NS_IMETHOD StyleSheetLoaded(mozilla::StyleSheet* aSheet, bool aWasDeferred,
     97                              nsresult aStatus) override;
     98 
     99  // nsIContentSink implementation helpers
    100  nsresult WillParseImpl(void);
    101  nsresult WillInterruptImpl(void);
    102  void WillResumeImpl();
    103  nsresult DidProcessATokenImpl(void);
    104  void WillBuildModelImpl(void);
    105  void DidBuildModelImpl(bool aTerminated);
    106  void DropParserAndPerfHint(void);
    107  bool IsScriptExecutingImpl();
    108  void ContinueParsingDocumentAfterCurrentScriptImpl();
    109 
    110  void NotifyAppend(nsIContent* aContent, uint32_t aStartIndex);
    111 
    112  // nsIDocumentObserver
    113  NS_DECL_NSIDOCUMENTOBSERVER_BEGINUPDATE
    114  NS_DECL_NSIDOCUMENTOBSERVER_ENDUPDATE
    115 
    116  virtual void UpdateChildCounts() = 0;
    117 
    118  bool IsTimeToNotify();
    119 
    120 protected:
    121  nsContentSink();
    122  virtual ~nsContentSink();
    123 
    124  nsresult Init(Document* aDoc, nsIURI* aURI, nsISupports* aContainer,
    125                nsIChannel* aChannel);
    126 
    127  nsresult ProcessHTTPHeaders(nsIChannel* aChannel);
    128  // aEarlyHintPreloaderId zero means no early hint channel to connect back
    129  nsresult ProcessLinkFromHeader(const mozilla::net::LinkHeader& aHeader,
    130                                 uint64_t aEarlyHintPreloaderId);
    131 
    132  // @param aFetchPriority Accepts a case-insensitive fetch priority keyword and
    133  //                       other values too, see
    134  //                       <https://html.spec.whatwg.org/#fetch-priority-attribute>.
    135  virtual nsresult ProcessStyleLinkFromHeader(
    136      const nsAString& aHref, bool aAlternate, const nsAString& aTitle,
    137      const nsAString& aIntegrity, const nsAString& aType,
    138      const nsAString& aMedia, const nsAString& aReferrerPolicy,
    139      const nsAString& aFetchPriority);
    140 
    141  void PrefetchHref(const nsAString& aHref, const nsAString& aAs,
    142                    const nsAString& aType, const nsAString& aMedia);
    143  void PreloadHref(const nsAString& aHref, const nsAString& aAs,
    144                   const nsAString& aRel, const nsAString& aType,
    145                   const nsAString& aMedia, const nsAString& aNonce,
    146                   const nsAString& aIntegrity, const nsAString& aSrcset,
    147                   const nsAString& aSizes, const nsAString& aCORS,
    148                   const nsAString& aReferrerPolicy,
    149                   uint64_t aEarlyHintPreloaderId,
    150                   const nsAString& aFetchPriority);
    151 
    152  void PreloadModule(const nsAString& aHref, const nsAString& aAs,
    153                     const nsAString& aMedia, const nsAString& aNonce,
    154                     const nsAString& aIntegrity, const nsAString& aCORS,
    155                     const nsAString& aReferrerPolicy,
    156                     uint64_t aEarlyHintPreloaderId,
    157                     const nsAString& aFetchPriority);
    158 
    159  // For PrefetchDNS() aHref can either be the usual
    160  // URI format or of the form "//www.hostname.com" without a scheme.
    161  void PrefetchDNS(const nsAString& aHref);
    162 
    163  // Gets the cache key (used to identify items in a cache) of the channel.
    164  nsresult GetChannelCacheKey(nsIChannel* aChannel, nsACString& aCacheKey);
    165 
    166 public:
    167  // For Preconnect() aHref can either be the usual
    168  // URI format or of the form "//www.hostname.com" without a scheme.
    169  void Preconnect(const nsAString& aHref, const nsAString& aCrossOrigin);
    170 
    171 protected:
    172  // Tries to scroll to the URI's named anchor. Once we've successfully
    173  // done that, further calls to this method will be ignored.
    174  MOZ_CAN_RUN_SCRIPT_BOUNDARY void ScrollToRef();
    175 
    176  // Start layout.  If aIgnorePendingSheets is true, this will happen even if
    177  // we still have stylesheet loads pending.  Otherwise, we'll wait until the
    178  // stylesheets are all done loading.
    179 public:
    180  void StartLayout(bool aIgnorePendingSheets);
    181 
    182  static void NotifyDocElementCreated(Document* aDoc);
    183 
    184  Document* GetDocument() { return mDocument; }
    185 
    186  // Later on we might want to make this more involved somehow
    187  // (e.g. stop waiting after some timeout or whatnot).
    188  bool WaitForPendingSheets() { return mPendingSheetCount > 0; }
    189 
    190 protected:
    191  inline int32_t GetNotificationInterval() {
    192    if (mDynamicLowerValue) {
    193      return 1000;
    194    }
    195 
    196    return mozilla::StaticPrefs::content_notify_interval();
    197  }
    198 
    199  virtual nsresult FlushTags() = 0;
    200 
    201  void DoProcessLinkHeader();
    202 
    203  void StopDeflecting() {
    204    mDeflectedCount = mozilla::StaticPrefs::content_sink_perf_deflect_count();
    205  }
    206 
    207 protected:
    208  RefPtr<Document> mDocument;
    209  RefPtr<nsParserBase> mParser;
    210  nsCOMPtr<nsIURI> mDocumentURI;
    211  nsCOMPtr<nsIDocShell> mDocShell;
    212  RefPtr<nsNodeInfoManager> mNodeInfoManager;
    213  RefPtr<mozilla::dom::ScriptLoader> mScriptLoader;
    214 
    215  // back off timer notification after count
    216  int32_t mBackoffCount;
    217 
    218  // Time of last notification
    219  // Note: mLastNotificationTime is only valid once mLayoutStarted is true.
    220  PRTime mLastNotificationTime;
    221 
    222  // Timer used for notification
    223  nsCOMPtr<nsITimer> mNotificationTimer;
    224 
    225  uint8_t mLayoutStarted : 1;
    226  uint8_t mDynamicLowerValue : 1;
    227  uint8_t mParsing : 1;
    228  uint8_t mDroppedTimer : 1;
    229  // If true, we deferred starting layout until sheets load
    230  uint8_t mDeferredLayoutStart : 1;
    231  // If true, we deferred notifications until sheets load
    232  uint8_t mDeferredFlushTags : 1;
    233  // If false, we're not ourselves a document observer; that means we
    234  // shouldn't be performing any more content model notifications,
    235  // since we're not longer updating our child counts.
    236  uint8_t mIsDocumentObserver : 1;
    237  // True if this is parser is a fragment parser or an HTML DOMParser.
    238  // XML DOMParser leaves this to false for now!
    239  uint8_t mRunsToCompletion : 1;
    240  // True if we are blocking load event.
    241  bool mIsBlockingOnload : 1;
    242 
    243  //
    244  // -- Can interrupt parsing members --
    245  //
    246 
    247  // The number of tokens that have been processed since we measured
    248  // if it's time to return to the main event loop.
    249  uint32_t mDeflectedCount;
    250 
    251  // Is there currently a pending event?
    252  bool mHasPendingEvent;
    253 
    254  // When to return to the main event loop
    255  uint32_t mCurrentParseEndTime;
    256 
    257  int32_t mBeginLoadTime;
    258 
    259  // Last mouse event or keyboard event time sampled by the content
    260  // sink
    261  uint32_t mLastSampledUserEventTime;
    262 
    263  int32_t mInMonolithicContainer;
    264 
    265  int32_t mInNotification;
    266  uint32_t mUpdatesInNotification;
    267 
    268  uint32_t mPendingSheetCount;
    269 
    270  nsRevocableEventPtr<nsRunnableMethod<nsContentSink, void, false> >
    271      mProcessLinkHeaderEvent;
    272 };
    273 
    274 #endif  // _nsContentSink_h_