LCOV - code coverage report
Current view: directory - parser/html - nsHtml5TreeOpExecutor.h (source / functions) Found Hit Coverage
Test: app.info Lines: 104 69 66.3 %
Date: 2012-06-02 Functions: 28 16 57.1 %

       1                 : /* ***** BEGIN LICENSE BLOCK *****
       2                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       3                 :  *
       4                 :  * The contents of this file are subject to the Mozilla Public License Version
       5                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       6                 :  * the License. You may obtain a copy of the License at
       7                 :  * http://www.mozilla.org/MPL/
       8                 :  *
       9                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      10                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      11                 :  * for the specific language governing rights and limitations under the
      12                 :  * License.
      13                 :  *
      14                 :  * The Original Code is HTML Parser Gecko integration code.
      15                 :  *
      16                 :  * The Initial Developer of the Original Code is
      17                 :  * Mozilla Foundation.
      18                 :  * Portions created by the Initial Developer are Copyright (C) 2009
      19                 :  * the Initial Developer. All Rights Reserved.
      20                 :  *
      21                 :  * Contributor(s):
      22                 :  *   Henri Sivonen <hsivonen@iki.fi>
      23                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      26                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK ***** */
      37                 : 
      38                 : #ifndef nsHtml5TreeOpExecutor_h__
      39                 : #define nsHtml5TreeOpExecutor_h__
      40                 : 
      41                 : #include "prtypes.h"
      42                 : #include "nsIAtom.h"
      43                 : #include "nsINameSpaceManager.h"
      44                 : #include "nsIContent.h"
      45                 : #include "nsIDocument.h"
      46                 : #include "nsTraceRefcnt.h"
      47                 : #include "nsHtml5TreeOperation.h"
      48                 : #include "nsHtml5SpeculativeLoad.h"
      49                 : #include "nsHtml5PendingNotification.h"
      50                 : #include "nsTArray.h"
      51                 : #include "nsContentSink.h"
      52                 : #include "nsNodeInfoManager.h"
      53                 : #include "nsHtml5DocumentMode.h"
      54                 : #include "nsIScriptElement.h"
      55                 : #include "nsIParser.h"
      56                 : #include "nsAHtml5TreeOpSink.h"
      57                 : #include "nsHtml5TreeOpStage.h"
      58                 : #include "nsIURI.h"
      59                 : #include "nsTHashtable.h"
      60                 : #include "nsHashKeys.h"
      61                 : 
      62                 : class nsHtml5Parser;
      63                 : class nsHtml5TreeBuilder;
      64                 : class nsHtml5Tokenizer;
      65                 : class nsHtml5StreamParser;
      66                 : 
      67                 : typedef nsIContent* nsIContentPtr;
      68                 : 
      69                 : enum eHtml5FlushState {
      70                 :   eNotFlushing = 0,  // not flushing
      71                 :   eInFlush = 1,      // the Flush() method is on the call stack
      72                 :   eInDocUpdate = 2,  // inside an update batch on the document
      73                 :   eNotifying = 3     // flushing pending append notifications
      74                 : };
      75                 : 
      76                 : class nsHtml5TreeOpExecutor : public nsContentSink,
      77                 :                               public nsIContentSink,
      78                 :                               public nsAHtml5TreeOpSink
      79                 : {
      80                 :   friend class nsHtml5FlushLoopGuard;
      81                 : 
      82                 :   public:
      83              48 :     NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
      84                 :     NS_DECL_ISUPPORTS_INHERITED
      85            1466 :     NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHtml5TreeOpExecutor, nsContentSink)
      86                 : 
      87                 :   private:
      88                 : #ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
      89                 :     static PRUint32    sAppendBatchMaxSize;
      90                 :     static PRUint32    sAppendBatchSlotsExamined;
      91                 :     static PRUint32    sAppendBatchExaminations;
      92                 :     static PRUint32    sLongestTimeOffTheEventLoop;
      93                 :     static PRUint32    sTimesFlushLoopInterrupted;
      94                 : #endif
      95                 : 
      96                 :     /**
      97                 :      * Whether EOF needs to be suppressed
      98                 :      */
      99                 :     bool                                 mSuppressEOF;
     100                 :     
     101                 :     bool                                 mReadingFromStage;
     102                 :     nsTArray<nsHtml5TreeOperation>       mOpQueue;
     103                 :     nsTArray<nsIContentPtr>              mElementsSeenInThisAppendBatch;
     104                 :     nsTArray<nsHtml5PendingNotification> mPendingNotifications;
     105                 :     nsHtml5StreamParser*                 mStreamParser;
     106                 :     nsTArray<nsCOMPtr<nsIContent> >      mOwnedElements;
     107                 :     
     108                 :     /**
     109                 :      * URLs already preloaded/preloading.
     110                 :      */
     111                 :     nsTHashtable<nsCStringHashKey> mPreloadedURLs;
     112                 : 
     113                 :     nsCOMPtr<nsIURI> mSpeculationBaseURI;
     114                 : 
     115                 :     nsCOMPtr<nsIURI> mViewSourceBaseURI;
     116                 : 
     117                 :     /**
     118                 :      * Whether the parser has started
     119                 :      */
     120                 :     bool                          mStarted;
     121                 : 
     122                 :     nsHtml5TreeOpStage            mStage;
     123                 : 
     124                 :     eHtml5FlushState              mFlushState;
     125                 : 
     126                 :     bool                          mRunFlushLoopOnStack;
     127                 : 
     128                 :     bool                          mCallContinueInterruptedParsingIfEnabled;
     129                 : 
     130                 :     /**
     131                 :      * True if this parser should refuse to process any more input.
     132                 :      * Currently, the only way a parser can break is if it drops some input
     133                 :      * due to a memory allocation failure. In such a case, the whole parser
     134                 :      * needs to be marked as broken, because some input has been lost and
     135                 :      * parsing more input could lead to a DOM where pieces of HTML source
     136                 :      * that weren't supposed to become scripts become scripts.
     137                 :      */
     138                 :     bool                          mBroken;
     139                 : 
     140                 :   public:
     141                 :   
     142                 :     nsHtml5TreeOpExecutor(bool aRunsToCompletion = false);
     143                 :     virtual ~nsHtml5TreeOpExecutor();
     144                 :   
     145                 :     // nsIContentSink
     146                 : 
     147                 :     /**
     148                 :      * Unimplemented. For interface compat only.
     149                 :      */
     150                 :     NS_IMETHOD WillParse();
     151                 : 
     152                 :     /**
     153                 :      * 
     154                 :      */
     155               0 :     NS_IMETHOD WillBuildModel(nsDTDMode aDTDMode) {
     156               0 :       NS_ASSERTION(!mDocShell || GetDocument()->GetScriptGlobalObject(),
     157                 :                    "Script global object not ready");
     158               0 :       mDocument->AddObserver(this);
     159               0 :       WillBuildModelImpl();
     160               0 :       GetDocument()->BeginLoad();
     161               0 :       return NS_OK;
     162                 :     }
     163                 : 
     164                 :     /**
     165                 :      * Emits EOF.
     166                 :      */
     167                 :     NS_IMETHOD DidBuildModel(bool aTerminated);
     168                 : 
     169                 :     /**
     170                 :      * Forwards to nsContentSink
     171                 :      */
     172                 :     NS_IMETHOD WillInterrupt();
     173                 : 
     174                 :     /**
     175                 :      * Unimplemented. For interface compat only.
     176                 :      */
     177                 :     NS_IMETHOD WillResume();
     178                 : 
     179                 :     /**
     180                 :      * Sets the parser.
     181                 :      */
     182                 :     NS_IMETHOD SetParser(nsParserBase* aParser);
     183                 : 
     184                 :     /**
     185                 :      * No-op for backwards compat.
     186                 :      */
     187                 :     virtual void FlushPendingNotifications(mozFlushType aType);
     188                 : 
     189                 :     /**
     190                 :      * Don't call. For interface compat only.
     191                 :      */
     192               0 :     NS_IMETHOD SetDocumentCharset(nsACString& aCharset) {
     193               0 :         NS_NOTREACHED("No one should call this.");
     194               0 :         return NS_ERROR_NOT_IMPLEMENTED;
     195                 :     }
     196                 : 
     197                 :     /**
     198                 :      * Returns the document.
     199                 :      */
     200                 :     virtual nsISupports *GetTarget();
     201                 :   
     202                 :     // nsContentSink methods
     203                 :     virtual void UpdateChildCounts();
     204                 :     virtual nsresult FlushTags();
     205                 :     virtual void ContinueInterruptedParsingAsync();
     206                 :  
     207                 :     /**
     208                 :      * Sets up style sheet load / parse
     209                 :      */
     210                 :     void UpdateStyleSheet(nsIContent* aElement);
     211                 : 
     212                 :     // Getters and setters for fields from nsContentSink
     213            1067 :     nsIDocument* GetDocument() {
     214            1067 :       return mDocument;
     215                 :     }
     216            1066 :     nsNodeInfoManager* GetNodeInfoManager() {
     217            1066 :       return mNodeInfoManager;
     218                 :     }
     219                 :     nsIDocShell* GetDocShell() {
     220                 :       return mDocShell;
     221                 :     }
     222                 : 
     223               0 :     bool IsScriptExecuting() {
     224               0 :       return IsScriptExecutingImpl();
     225                 :     }
     226                 :     
     227             234 :     void SetNodeInfoManager(nsNodeInfoManager* aManager) {
     228             234 :       mNodeInfoManager = aManager;
     229             234 :     }
     230                 :     
     231                 :     // Not from interface
     232                 : 
     233                 :     void SetDocumentCharsetAndSource(nsACString& aCharset, PRInt32 aCharsetSource);
     234                 : 
     235               0 :     void SetStreamParser(nsHtml5StreamParser* aStreamParser) {
     236               0 :       mStreamParser = aStreamParser;
     237               0 :     }
     238                 :     
     239                 :     void InitializeDocWriteParserState(nsAHtml5TreeBuilderState* aState, PRInt32 aLine);
     240                 : 
     241                 :     bool IsScriptEnabled();
     242                 : 
     243                 :     /**
     244                 :      * Enables the fragment mode.
     245                 :      *
     246                 :      * @param aPreventScriptExecution if true, scripts are prevented from
     247                 :      * executing; don't set to false when parsing a fragment directly into
     248                 :      * a document--only when parsing to an actual DOM fragment
     249                 :      */
     250               0 :     void EnableFragmentMode(bool aPreventScriptExecution) {
     251               0 :       mPreventScriptExecution = aPreventScriptExecution;
     252               0 :     }
     253                 :     
     254             234 :     void PreventScriptExecution() {
     255             234 :       mPreventScriptExecution = true;
     256             234 :     }
     257                 : 
     258             780 :     bool BelongsToStringParser() {
     259             780 :       return mRunsToCompletion;
     260                 :     }
     261                 : 
     262                 :     /**
     263                 :      * Marks this parser as broken and tells the stream parser (if any) to
     264                 :      * terminate.
     265                 :      */
     266                 :     void MarkAsBroken();
     267                 : 
     268                 :     /**
     269                 :      * Checks if this parser is broken.
     270                 :      */
     271               0 :     inline bool IsBroken() {
     272               0 :       NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     273               0 :       return mBroken;
     274                 :     }
     275                 : 
     276             246 :     inline void BeginDocUpdate() {
     277             246 :       NS_PRECONDITION(mFlushState == eInFlush, "Tried to double-open update.");
     278             246 :       NS_PRECONDITION(mParser, "Started update without parser.");
     279             246 :       mFlushState = eInDocUpdate;
     280             246 :       mDocument->BeginUpdate(UPDATE_CONTENT_MODEL);
     281             246 :     }
     282                 : 
     283             480 :     inline void EndDocUpdate() {
     284             480 :       NS_PRECONDITION(mFlushState != eNotifying, "mFlushState out of sync");
     285             480 :       if (mFlushState == eInDocUpdate) {
     286             246 :         FlushPendingAppendNotifications();
     287             246 :         mFlushState = eInFlush;
     288             246 :         mDocument->EndUpdate(UPDATE_CONTENT_MODEL);
     289                 :       }
     290             480 :     }
     291                 : 
     292             832 :     void PostPendingAppendNotification(nsIContent* aParent, nsIContent* aChild) {
     293             832 :       bool newParent = true;
     294             832 :       const nsIContentPtr* first = mElementsSeenInThisAppendBatch.Elements();
     295             832 :       const nsIContentPtr* last = first + mElementsSeenInThisAppendBatch.Length() - 1;
     296            1101 :       for (const nsIContentPtr* iter = last; iter >= first; --iter) {
     297                 : #ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
     298                 :         sAppendBatchSlotsExamined++;
     299                 : #endif
     300             855 :         if (*iter == aParent) {
     301             586 :           newParent = false;
     302             586 :           break;
     303                 :         }
     304                 :       }
     305             832 :       if (aChild->IsElement()) {
     306             546 :         mElementsSeenInThisAppendBatch.AppendElement(aChild);
     307                 :       }
     308             832 :       mElementsSeenInThisAppendBatch.AppendElement(aParent);
     309             832 :       if (newParent) {
     310             246 :         mPendingNotifications.AppendElement(aParent);
     311                 :       }
     312                 : #ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
     313                 :       sAppendBatchExaminations++;
     314                 : #endif
     315             832 :     }
     316                 : 
     317             480 :     void FlushPendingAppendNotifications() {
     318             480 :       NS_PRECONDITION(mFlushState == eInDocUpdate, "Notifications flushed outside update");
     319             480 :       mFlushState = eNotifying;
     320             480 :       const nsHtml5PendingNotification* start = mPendingNotifications.Elements();
     321             480 :       const nsHtml5PendingNotification* end = start + mPendingNotifications.Length();
     322             726 :       for (nsHtml5PendingNotification* iter = (nsHtml5PendingNotification*)start; iter < end; ++iter) {
     323             246 :         iter->Fire();
     324                 :       }
     325             480 :       mPendingNotifications.Clear();
     326                 : #ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
     327                 :       if (mElementsSeenInThisAppendBatch.Length() > sAppendBatchMaxSize) {
     328                 :         sAppendBatchMaxSize = mElementsSeenInThisAppendBatch.Length();
     329                 :       }
     330                 : #endif
     331             480 :       mElementsSeenInThisAppendBatch.Clear();
     332             480 :       NS_ASSERTION(mFlushState == eNotifying, "mFlushState out of sync");
     333             480 :       mFlushState = eInDocUpdate;
     334             480 :     }
     335                 :     
     336               1 :     inline bool HaveNotified(nsIContent* aNode) {
     337               1 :       NS_PRECONDITION(aNode, "HaveNotified called with null argument.");
     338               1 :       const nsHtml5PendingNotification* start = mPendingNotifications.Elements();
     339               1 :       const nsHtml5PendingNotification* end = start + mPendingNotifications.Length();
     340               1 :       for (;;) {
     341               2 :         nsIContent* parent = aNode->GetParent();
     342               2 :         if (!parent) {
     343               0 :           return true;
     344                 :         }
     345               3 :         for (nsHtml5PendingNotification* iter = (nsHtml5PendingNotification*)start; iter < end; ++iter) {
     346               2 :           if (iter->Contains(parent)) {
     347               1 :             return iter->HaveNotifiedIndex(parent->IndexOf(aNode));
     348                 :           }
     349                 :         }
     350               1 :         aNode = parent;
     351                 :       }
     352                 :     }
     353                 : 
     354                 :     void StartLayout();
     355                 :     
     356                 :     void SetDocumentMode(nsHtml5DocumentMode m);
     357                 : 
     358                 :     nsresult Init(nsIDocument* aDoc, nsIURI* aURI,
     359                 :                   nsISupports* aContainer, nsIChannel* aChannel);
     360                 : 
     361                 :     void FlushSpeculativeLoads();
     362                 :                   
     363                 :     void RunFlushLoop();
     364                 : 
     365                 :     void FlushDocumentWrite();
     366                 : 
     367                 :     void MaybeSuspend();
     368                 : 
     369                 :     void Start();
     370                 : 
     371                 :     void NeedsCharsetSwitchTo(const char* aEncoding, PRInt32 aSource);
     372                 :     
     373               0 :     bool IsComplete() {
     374               0 :       return !mParser;
     375                 :     }
     376                 :     
     377             234 :     bool HasStarted() {
     378             234 :       return mStarted;
     379                 :     }
     380                 :     
     381               0 :     bool IsFlushing() {
     382               0 :       return mFlushState >= eInFlush;
     383                 :     }
     384                 : 
     385                 : #ifdef DEBUG
     386               0 :     bool IsInFlushLoop() {
     387               0 :       return mRunFlushLoopOnStack;
     388                 :     }
     389                 : #endif
     390                 :     
     391                 :     void RunScript(nsIContent* aScriptElement);
     392                 :     
     393                 :     void Reset();
     394                 :     
     395             780 :     inline void HoldElement(nsIContent* aContent) {
     396             780 :       mOwnedElements.AppendElement(aContent);
     397             780 :     }
     398                 : 
     399                 :     void DropHeldElements();
     400                 : 
     401                 :     /**
     402                 :      * Flush the operations from the tree operations from the argument
     403                 :      * queue unconditionally. (This is for the main thread case.)
     404                 :      */
     405                 :     virtual void MoveOpsFrom(nsTArray<nsHtml5TreeOperation>& aOpQueue);
     406                 :     
     407               0 :     nsHtml5TreeOpStage* GetStage() {
     408               0 :       return &mStage;
     409                 :     }
     410                 :     
     411               0 :     void StartReadingFromStage() {
     412               0 :       mReadingFromStage = true;
     413               0 :     }
     414                 : 
     415                 :     void StreamEnded();
     416                 :     
     417                 : #ifdef DEBUG
     418               0 :     void AssertStageEmpty() {
     419               0 :       mStage.AssertEmpty();
     420               0 :     }
     421                 : #endif
     422                 : 
     423                 :     nsIURI* GetViewSourceBaseURI();
     424                 : 
     425                 :     void PreloadScript(const nsAString& aURL,
     426                 :                        const nsAString& aCharset,
     427                 :                        const nsAString& aType,
     428                 :                        const nsAString& aCrossOrigin);
     429                 : 
     430                 :     void PreloadStyle(const nsAString& aURL, const nsAString& aCharset);
     431                 : 
     432                 :     void PreloadImage(const nsAString& aURL, const nsAString& aCrossOrigin);
     433                 : 
     434                 :     void SetSpeculationBase(const nsAString& aURL);
     435                 : 
     436                 :   private:
     437                 :     nsHtml5Parser* GetParser();
     438                 : 
     439                 :     /**
     440                 :      * Get a nsIURI for an nsString if the URL hasn't been preloaded yet.
     441                 :      */
     442                 :     already_AddRefed<nsIURI> ConvertIfNotPreloadedYet(const nsAString& aURL);
     443                 : 
     444                 : };
     445                 : 
     446                 : #endif // nsHtml5TreeOpExecutor_h__

Generated by: LCOV version 1.7