2011-01-05 Yong Li <yoli@rim.com>
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 5 Jan 2011 15:51:37 +0000 (15:51 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 5 Jan 2011 15:51:37 +0000 (15:51 +0000)
        Reviewed by Adam Barth.

        Suspend HTMLParserScheduler when page load is deferred to
        avoid potential JS re-entrancy. Otherwise, when JS execution is triggered
        from an external script or by events, and is blocked by a modal dialog,
        WebKit can parse more HTML source and also start another JS execution.

        https://bugs.webkit.org/show_bug.cgi?id=48077

        Test case: WebCore/manual-tests/bugzilla-48077.html.

        * dom/DocumentParser.cpp:
        (WebCore::DocumentParser::suspendScheduledTasks):
        (WebCore::DocumentParser::resumeScheduledTasks):
        * dom/DocumentParser.h:
        * html/parser/HTMLDocumentParser.cpp:
        (WebCore::HTMLDocumentParser::suspendScheduledTasks):
        (WebCore::HTMLDocumentParser::resumeScheduledTasks):
        * html/parser/HTMLParserScheduler.cpp:
        (WebCore::HTMLParserScheduler::HTMLParserScheduler):
        (WebCore::HTMLParserScheduler::suspend):
        (WebCore::HTMLParserScheduler::resume):
        * html/parser/HTMLParserScheduler.h:
        (WebCore::HTMLParserScheduler::isScheduledForResume):
        * page/PageGroupLoadDeferrer.cpp:
        (WebCore::PageGroupLoadDeferrer::PageGroupLoadDeferrer):
        (WebCore::PageGroupLoadDeferrer::~PageGroupLoadDeferrer):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@75066 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/dom/DocumentParser.cpp
WebCore/dom/DocumentParser.h
WebCore/html/parser/HTMLDocumentParser.cpp
WebCore/html/parser/HTMLDocumentParser.h
WebCore/html/parser/HTMLParserScheduler.cpp
WebCore/html/parser/HTMLParserScheduler.h
WebCore/page/PageGroupLoadDeferrer.cpp

index e149f69..8368b1f 100644 (file)
@@ -1,3 +1,33 @@
+2011-01-05  Yong Li  <yoli@rim.com>
+
+        Reviewed by Adam Barth.
+
+        Suspend HTMLParserScheduler when page load is deferred to
+        avoid potential JS re-entrancy. Otherwise, when JS execution is triggered
+        from an external script or by events, and is blocked by a modal dialog,
+        WebKit can parse more HTML source and also start another JS execution.
+        
+        https://bugs.webkit.org/show_bug.cgi?id=48077
+
+        Test case: WebCore/manual-tests/bugzilla-48077.html.
+
+        * dom/DocumentParser.cpp:
+        (WebCore::DocumentParser::suspendScheduledTasks):
+        (WebCore::DocumentParser::resumeScheduledTasks):
+        * dom/DocumentParser.h:
+        * html/parser/HTMLDocumentParser.cpp:
+        (WebCore::HTMLDocumentParser::suspendScheduledTasks):
+        (WebCore::HTMLDocumentParser::resumeScheduledTasks):
+        * html/parser/HTMLParserScheduler.cpp:
+        (WebCore::HTMLParserScheduler::HTMLParserScheduler):
+        (WebCore::HTMLParserScheduler::suspend):
+        (WebCore::HTMLParserScheduler::resume):
+        * html/parser/HTMLParserScheduler.h:
+        (WebCore::HTMLParserScheduler::isScheduledForResume):
+        * page/PageGroupLoadDeferrer.cpp:
+        (WebCore::PageGroupLoadDeferrer::PageGroupLoadDeferrer):
+        (WebCore::PageGroupLoadDeferrer::~PageGroupLoadDeferrer):
+
 2011-01-05  Simon Hausmann  <simon.hausmann@nokia.com>
 
         Reviewed by Kenneth Rohde Christiansen, Gustavo Noronha Silva
index 5f8e04f..355b1cf 100644 (file)
@@ -68,5 +68,13 @@ void DocumentParser::detach()
     m_document = 0;
 }
 
+void DocumentParser::suspendScheduledTasks()
+{
+}
+
+void DocumentParser::resumeScheduledTasks()
+{
+}
+
 };
 
index aa18a64..6f78a38 100644 (file)
@@ -91,6 +91,10 @@ public:
     void setDocumentWasLoadedAsPartOfNavigation() { m_documentWasLoadedAsPartOfNavigation = true; }
     bool documentWasLoadedAsPartOfNavigation() const { return m_documentWasLoadedAsPartOfNavigation; }
 
+    // FIXME: The names are not very accurate :(
+    virtual void suspendScheduledTasks();
+    virtual void resumeScheduledTasks();
+
 protected:
     DocumentParser(Document*);
 
index 0e3a10b..c9d5e10 100644 (file)
@@ -520,4 +520,16 @@ bool HTMLDocumentParser::usePreHTML5ParserQuirks(Document* document)
     return document->settings() && document->settings()->usePreHTML5ParserQuirks();
 }
 
+void HTMLDocumentParser::suspendScheduledTasks()
+{
+    if (m_parserScheduler)
+        m_parserScheduler->suspend();
+}
+
+void HTMLDocumentParser::resumeScheduledTasks()
+{
+    if (m_parserScheduler)
+        m_parserScheduler->resume();
+}
+
 }
index fca269a..80ca727 100644 (file)
@@ -72,6 +72,8 @@ public:
     HTMLTokenizer* tokenizer() const { return m_tokenizer.get(); }
 
     virtual TextPosition0 textPosition() const;
+    virtual void suspendScheduledTasks();
+    virtual void resumeScheduledTasks();
 
 protected:
     virtual void insert(const SegmentedString&);
index 6e67697..56db1aa 100644 (file)
@@ -65,6 +65,7 @@ HTMLParserScheduler::HTMLParserScheduler(HTMLDocumentParser* parser)
     , m_parserTimeLimit(parserTimeLimit(m_parser->document()->page()))
     , m_parserChunkSize(parserChunkSize(m_parser->document()->page()))
     , m_continueNextChunkTimer(this, &HTMLParserScheduler::continueNextChunkTimerFired)
+    , m_isSuspendedWithActiveTimer(false)
 {
 }
 
@@ -92,4 +93,22 @@ void HTMLParserScheduler::continueNextChunkTimerFired(Timer<HTMLParserScheduler>
     m_parser->resumeParsingAfterYield();
 }
 
+void HTMLParserScheduler::suspend()
+{
+    ASSERT(!m_isSuspendedWithActiveTimer);
+    if (!m_continueNextChunkTimer.isActive())
+        return;
+    m_isSuspendedWithActiveTimer = true;
+    m_continueNextChunkTimer.stop();
+}
+
+void HTMLParserScheduler::resume()
+{
+    ASSERT(!m_continueNextChunkTimer.isActive());
+    if (!m_isSuspendedWithActiveTimer)
+        return;
+    m_isSuspendedWithActiveTimer = false;
+    m_continueNextChunkTimer.startOneShot(0);
+}
+
 }
index 5be33b0..3a20b2b 100644 (file)
@@ -71,7 +71,10 @@ public:
         return true;
     }
 
-    bool isScheduledForResume() const { return m_continueNextChunkTimer.isActive(); }
+    bool isScheduledForResume() const { return m_isSuspendedWithActiveTimer || m_continueNextChunkTimer.isActive(); }
+
+    void suspend();
+    void resume();
 
 private:
     HTMLParserScheduler(HTMLDocumentParser*);
@@ -83,6 +86,7 @@ private:
     double m_parserTimeLimit;
     int m_parserChunkSize;
     Timer<HTMLParserScheduler> m_continueNextChunkTimer;
+    bool m_isSuspendedWithActiveTimer;
 };
 
 }
index 98a4720..781bc34 100644 (file)
@@ -22,6 +22,7 @@
 #include "PageGroupLoadDeferrer.h"
 
 #include "AsyncScriptRunner.h"
+#include "DocumentParser.h"
 #include "Frame.h"
 #include "Page.h"
 #include "PageGroup.h"
@@ -49,6 +50,8 @@ PageGroupLoadDeferrer::PageGroupLoadDeferrer(Page* page, bool deferSelf)
                 for (Frame* frame = otherPage->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
                     frame->document()->suspendActiveDOMObjects(ActiveDOMObject::WillShowDialog);
                     frame->document()->asyncScriptRunner()->suspend();
+                    if (DocumentParser* parser = frame->document()->parser())
+                        parser->suspendScheduledTasks();
                 }
             }
         }
@@ -69,6 +72,8 @@ PageGroupLoadDeferrer::~PageGroupLoadDeferrer()
             for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
                 frame->document()->resumeActiveDOMObjects();
                 frame->document()->asyncScriptRunner()->resume();
+                if (DocumentParser* parser = frame->document()->parser())
+                    parser->resumeScheduledTasks();
             }
         }
     }