tor-browser

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

PrototypeDocumentContentSink.h (8119B)


      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 https://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef mozilla_dom_PrototypeDocumentContentSink_h__
      8 #define mozilla_dom_PrototypeDocumentContentSink_h__
      9 
     10 #include "js/experimental/JSStencil.h"
     11 #include "mozilla/Logging.h"
     12 #include "mozilla/RefPtr.h"
     13 #include "mozilla/dom/FromParser.h"
     14 #include "nsCOMPtr.h"
     15 #include "nsCRT.h"
     16 #include "nsCycleCollectionNoteChild.h"
     17 #include "nsCycleCollectionParticipant.h"
     18 #include "nsICSSLoaderObserver.h"
     19 #include "nsIContentSink.h"
     20 #include "nsIScriptContext.h"
     21 #include "nsIStreamLoader.h"
     22 #include "nsTArray.h"
     23 #include "nsXULPrototypeDocument.h"
     24 
     25 class nsIURI;
     26 class nsIChannel;
     27 class nsIContent;
     28 class nsIParser;
     29 class nsTextNode;
     30 class nsINode;
     31 class nsXULPrototypeElement;
     32 class nsXULPrototypePI;
     33 class nsXULPrototypeScript;
     34 
     35 namespace mozilla::dom {
     36 class Element;
     37 class ScriptLoader;
     38 class Document;
     39 class XMLStylesheetProcessingInstruction;
     40 }  // namespace mozilla::dom
     41 
     42 nsresult NS_NewPrototypeDocumentContentSink(nsIContentSink** aResult,
     43                                            mozilla::dom::Document* aDoc,
     44                                            nsIURI* aURI,
     45                                            nsISupports* aContainer,
     46                                            nsIChannel* aChannel);
     47 
     48 namespace mozilla::dom {
     49 
     50 class PrototypeDocumentContentSink final : public nsIStreamLoaderObserver,
     51                                           public nsIContentSink,
     52                                           public nsICSSLoaderObserver,
     53                                           public nsIOffThreadScriptReceiver {
     54 public:
     55  PrototypeDocumentContentSink();
     56 
     57  nsresult Init(Document* aDoc, nsIURI* aURL, nsISupports* aContainer,
     58                nsIChannel* aChannel);
     59 
     60  // nsISupports
     61  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     62  NS_DECL_NSISTREAMLOADEROBSERVER
     63 
     64  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(PrototypeDocumentContentSink,
     65                                           nsIContentSink)
     66 
     67  // nsIContentSink
     68  NS_IMETHOD WillParse(void) override { return NS_OK; };
     69  NS_IMETHOD WillInterrupt(void) override { return NS_OK; };
     70  void WillResume() override {};
     71  NS_IMETHOD SetParser(nsParserBase* aParser) override;
     72  virtual void InitialTranslationCompleted() override;
     73  virtual void FlushPendingNotifications(FlushType aType) override {};
     74  virtual void SetDocumentCharset(NotNull<const Encoding*> aEncoding) override;
     75  virtual nsISupports* GetTarget() override;
     76  virtual bool IsScriptExecuting() override;
     77  virtual void ContinueInterruptedParsingAsync() override;
     78 
     79  // nsICSSLoaderObserver
     80  NS_IMETHOD StyleSheetLoaded(StyleSheet* aSheet, bool aWasDeferred,
     81                              nsresult aStatus) override;
     82 
     83  // nsIOffThreadScriptReceiver
     84  NS_IMETHOD OnScriptCompileComplete(JS::Stencil* aStencil,
     85                                     nsresult aStatus) override;
     86 
     87  nsresult OnPrototypeLoadDone(nsXULPrototypeDocument* aPrototype);
     88 
     89 protected:
     90  virtual ~PrototypeDocumentContentSink();
     91 
     92  static LazyLogModule gLog;
     93 
     94  nsIParser* GetParser();
     95 
     96  void ContinueInterruptedParsingIfEnabled();
     97  void StartLayout();
     98 
     99  virtual nsresult AddAttributes(nsXULPrototypeElement* aPrototype,
    100                                 Element* aElement);
    101 
    102  RefPtr<nsParserBase> mParser;
    103  nsCOMPtr<nsIURI> mDocumentURI;
    104  RefPtr<Document> mDocument;
    105  RefPtr<ScriptLoader> mScriptLoader;
    106 
    107  PrototypeDocumentContentSink* mNextSrcLoadWaiter;  // [OWNER] but not COMPtr
    108 
    109  /**
    110   * The prototype-script of the current transcluded script that is being
    111   * loaded.  For document.write('<script src="nestedwrite.js"><\/script>')
    112   * to work, these need to be in a stack element type, and we need to hold
    113   * the top of stack here.
    114   */
    115  nsXULPrototypeScript* mCurrentScriptProto;
    116 
    117  /**
    118   * Whether the current transcluded script is being compiled off thread.
    119   * The load event is blocked while this is in progress.
    120   */
    121  bool mOffThreadCompiling;
    122 
    123  /**
    124   * Wether the prototype document is still be traversed to create the DOM.
    125   * Layout will not be started until false.
    126   */
    127  bool mStillWalking;
    128 
    129  /**
    130   * Number of style sheets still loading. Layout will not start until zero.
    131   */
    132  uint32_t mPendingSheets;
    133 
    134  /**
    135   * Context stack, which maintains the state of the Builder and allows
    136   * it to be interrupted.
    137   */
    138  class ContextStack {
    139   protected:
    140    struct Entry {
    141      nsXULPrototypeElement* mPrototype;
    142      nsIContent* mElement;
    143      int32_t mIndex;
    144      Entry* mNext;
    145    };
    146 
    147    Entry* mTop;
    148    int32_t mDepth;
    149 
    150   public:
    151    ContextStack();
    152    ~ContextStack();
    153 
    154    int32_t Depth() { return mDepth; }
    155 
    156    nsresult Push(nsXULPrototypeElement* aPrototype, nsIContent* aElement);
    157    nsresult Pop();
    158    nsresult Peek(nsXULPrototypeElement** aPrototype, nsIContent** aElement,
    159                  int32_t* aIndex);
    160 
    161    nsresult SetTopIndex(int32_t aIndex);
    162 
    163    void Traverse(nsCycleCollectionTraversalCallback& aCallback,
    164                  const char* aName, uint32_t aFlags = 0);
    165    void Clear();
    166 
    167    // Cycle collector helpers for ContextStack.
    168    friend void ImplCycleCollectionUnlink(
    169        PrototypeDocumentContentSink::ContextStack& aField) {
    170      aField.Clear();
    171    }
    172 
    173    friend void ImplCycleCollectionTraverse(
    174        nsCycleCollectionTraversalCallback& aCallback,
    175        PrototypeDocumentContentSink::ContextStack& aField, const char* aName,
    176        uint32_t aFlags = 0) {
    177      aField.Traverse(aCallback, aName, aFlags);
    178    }
    179  };
    180 
    181  friend class ContextStack;
    182  ContextStack mContextStack;
    183 
    184  /**
    185   * The current prototype that we are walking to construct the
    186   * content model.
    187   */
    188  RefPtr<nsXULPrototypeDocument> mCurrentPrototype;
    189  nsresult CreateAndInsertPI(const nsXULPrototypePI* aProtoPI);
    190  nsresult ExecuteScript(nsXULPrototypeScript* aScript);
    191  nsresult LoadScript(nsXULPrototypeScript* aScriptProto, bool* aBlock);
    192 
    193  /**
    194   * A wrapper around ResumeWalkInternal to report walking errors.
    195   */
    196  nsresult ResumeWalk();
    197 
    198  /**
    199   * Resume (or initiate) an interrupted (or newly prepared)
    200   * prototype walk.
    201   */
    202  nsresult ResumeWalkInternal();
    203 
    204  /**
    205   * Called at the end of ResumeWalk(), from StyleSheetLoaded(),
    206   * and from DocumentL10n.
    207   * If walking, stylesheets and l10n are not blocking, it
    208   * will trigger `DoneWalking()`.
    209   */
    210  nsresult MaybeDoneWalking();
    211 
    212  /**
    213   * Called from `MaybeDoneWalking()`.
    214   * Expects that both the prototype document walk is complete and
    215   * all referenced stylesheets finished loading.
    216   */
    217  nsresult DoneWalking();
    218 
    219  /**
    220   * Create a delegate content model element from a prototype.
    221   * Note that the resulting content node is not bound to any tree
    222   */
    223  nsresult CreateElementFromPrototype(nsXULPrototypeElement* aPrototype,
    224                                      Element** aResult, nsIContent* aParent);
    225  /**
    226   * Prepare to walk the current prototype.
    227   */
    228  nsresult PrepareToWalk();
    229  /**
    230   * Creates a processing instruction based on aProtoPI and inserts
    231   * it to the DOM.
    232   */
    233  nsresult CreateAndInsertPI(const nsXULPrototypePI* aProtoPI, nsINode* aParent,
    234                             bool aInProlog);
    235 
    236  /**
    237   * Inserts the passed <?xml-stylesheet ?> PI at the specified
    238   * index. Loads and applies the associated stylesheet
    239   * asynchronously.
    240   * The prototype document walk can happen before the stylesheets
    241   * are loaded, but the final steps in the load process (see
    242   * DoneWalking()) are not run before all the stylesheets are done
    243   * loading.
    244   */
    245  nsresult InsertXMLStylesheetPI(const nsXULPrototypePI* aProtoPI,
    246                                 nsINode* aParent,
    247                                 XMLStylesheetProcessingInstruction* aPINode);
    248  void CloseElement(Element* aElement, bool aHadChildren);
    249 };
    250 
    251 }  // namespace mozilla::dom
    252 
    253 #endif  // mozilla_dom_PrototypeDocumentContentSink_h__