parser/html/nsHtml5DocumentBuilder.h

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ts=2 sw=2 et tw=78: */
     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/. */
     7 #ifndef nsHtml5DocumentBuilder_h
     8 #define nsHtml5DocumentBuilder_h
    10 #include "nsHtml5PendingNotification.h"
    11 #include "nsContentSink.h"
    12 #include "nsHtml5DocumentMode.h"
    13 #include "nsIDocument.h"
    15 typedef nsIContent* nsIContentPtr;
    17 enum eHtml5FlushState {
    18   eNotFlushing = 0,  // not flushing
    19   eInFlush = 1,      // the Flush() method is on the call stack
    20   eInDocUpdate = 2,  // inside an update batch on the document
    21   eNotifying = 3     // flushing pending append notifications
    22 };
    24 class nsHtml5DocumentBuilder : public nsContentSink
    25 {
    26 public:
    27   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHtml5DocumentBuilder,
    28                                            nsContentSink)
    30   NS_DECL_ISUPPORTS_INHERITED
    32   inline void HoldElement(nsIContent* aContent)
    33   {
    34     mOwnedElements.AppendElement(aContent);
    35   }
    37   inline bool HaveNotified(nsIContent* aNode)
    38   {
    39     NS_PRECONDITION(aNode, "HaveNotified called with null argument.");
    40     const nsHtml5PendingNotification* start = mPendingNotifications.Elements();
    41     const nsHtml5PendingNotification* end = start + mPendingNotifications.Length();
    42     for (;;) {
    43       nsIContent* parent = aNode->GetParent();
    44       if (!parent) {
    45         return true;
    46       }
    47       for (nsHtml5PendingNotification* iter = (nsHtml5PendingNotification*)start; iter < end; ++iter) {
    48         if (iter->Contains(parent)) {
    49           return iter->HaveNotifiedIndex(parent->IndexOf(aNode));
    50         }
    51       }
    52       aNode = parent;
    53     }
    54   }
    56   void PostPendingAppendNotification(nsIContent* aParent, nsIContent* aChild)
    57   {
    58     bool newParent = true;
    59     const nsIContentPtr* first = mElementsSeenInThisAppendBatch.Elements();
    60     const nsIContentPtr* last = first + mElementsSeenInThisAppendBatch.Length() - 1;
    61     for (const nsIContentPtr* iter = last; iter >= first; --iter) {
    62 #ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
    63       sAppendBatchSlotsExamined++;
    64 #endif
    65       if (*iter == aParent) {
    66         newParent = false;
    67         break;
    68       }
    69     }
    70     if (aChild->IsElement()) {
    71       mElementsSeenInThisAppendBatch.AppendElement(aChild);
    72     }
    73     mElementsSeenInThisAppendBatch.AppendElement(aParent);
    74     if (newParent) {
    75       mPendingNotifications.AppendElement(aParent);
    76     }
    77 #ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
    78     sAppendBatchExaminations++;
    79 #endif
    80   }
    82   void FlushPendingAppendNotifications()
    83   {
    84     NS_PRECONDITION(mFlushState == eInDocUpdate, "Notifications flushed outside update");
    85     mFlushState = eNotifying;
    86     const nsHtml5PendingNotification* start = mPendingNotifications.Elements();
    87     const nsHtml5PendingNotification* end = start + mPendingNotifications.Length();
    88     for (nsHtml5PendingNotification* iter = (nsHtml5PendingNotification*)start; iter < end; ++iter) {
    89       iter->Fire();
    90     }
    91     mPendingNotifications.Clear();
    92 #ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
    93     if (mElementsSeenInThisAppendBatch.Length() > sAppendBatchMaxSize) {
    94       sAppendBatchMaxSize = mElementsSeenInThisAppendBatch.Length();
    95     }
    96 #endif
    97     mElementsSeenInThisAppendBatch.Clear();
    98     NS_ASSERTION(mFlushState == eNotifying, "mFlushState out of sync");
    99     mFlushState = eInDocUpdate;
   100   }
   102   nsresult Init(nsIDocument* aDoc, nsIURI* aURI,
   103                 nsISupports* aContainer, nsIChannel* aChannel);
   105   // Getters and setters for fields from nsContentSink
   106   nsIDocument* GetDocument()
   107   {
   108     return mDocument;
   109   }
   111   nsNodeInfoManager* GetNodeInfoManager()
   112   {
   113     return mNodeInfoManager;
   114   }
   116   /**
   117    * Marks this parser as broken and tells the stream parser (if any) to
   118    * terminate.
   119    *
   120    * @return aReason for convenience
   121    */
   122   virtual nsresult MarkAsBroken(nsresult aReason);
   124   /**
   125    * Checks if this parser is broken. Returns a non-NS_OK (i.e. non-0)
   126    * value if broken.
   127    */
   128   inline nsresult IsBroken()
   129   {
   130     return mBroken;
   131   }
   133   inline void BeginDocUpdate()
   134   {
   135     NS_PRECONDITION(mFlushState == eInFlush, "Tried to double-open update.");
   136     NS_PRECONDITION(mParser, "Started update without parser.");
   137     mFlushState = eInDocUpdate;
   138     mDocument->BeginUpdate(UPDATE_CONTENT_MODEL);
   139   }
   141   inline void EndDocUpdate()
   142   {
   143     NS_PRECONDITION(mFlushState != eNotifying, "mFlushState out of sync");
   144     if (mFlushState == eInDocUpdate) {
   145       FlushPendingAppendNotifications();
   146       mFlushState = eInFlush;
   147       mDocument->EndUpdate(UPDATE_CONTENT_MODEL);
   148     }
   149   }
   151   void SetDocumentCharsetAndSource(nsACString& aCharset, int32_t aCharsetSource);
   153   /**
   154    * Sets up style sheet load / parse
   155    */
   156   void UpdateStyleSheet(nsIContent* aElement);
   158   void SetDocumentMode(nsHtml5DocumentMode m);
   160   void SetNodeInfoManager(nsNodeInfoManager* aManager)
   161   {
   162     mNodeInfoManager = aManager;
   163   }
   165   // nsContentSink methods
   166   virtual void UpdateChildCounts();
   167   virtual nsresult FlushTags();
   169 protected:
   170   inline void SetAppendBatchCapacity(uint32_t aCapacity)
   171   {
   172     mElementsSeenInThisAppendBatch.SetCapacity(aCapacity);
   173   }
   175   nsHtml5DocumentBuilder(bool aRunsToCompletion);
   176   virtual ~nsHtml5DocumentBuilder();
   178 private:
   179   nsTArray<nsHtml5PendingNotification> mPendingNotifications;
   180   nsTArray<nsIContentPtr>              mElementsSeenInThisAppendBatch;
   181 protected:
   182   nsTArray<nsCOMPtr<nsIContent> >      mOwnedElements;
   183   /**
   184    * Non-NS_OK if this parser should refuse to process any more input.
   185    * For example, the parser needs to be marked as broken if it drops some
   186    * input due to a memory allocation failure. In such a case, the whole
   187    * parser needs to be marked as broken, because some input has been lost
   188    * and parsing more input could lead to a DOM where pieces of HTML source
   189    * that weren't supposed to become scripts become scripts.
   190    *
   191    * Since NS_OK is actually 0, zeroing operator new takes care of
   192    * initializing this.
   193    */
   194   nsresult                             mBroken;
   195   eHtml5FlushState                     mFlushState;
   196 };
   198 #endif // nsHtml5DocumentBuilder_h

mercurial