Title: [102278] trunk
Revision
102278
Author
[email protected]
Date
2011-12-07 15:41:21 -0800 (Wed, 07 Dec 2011)

Log Message

Defer ScriptExecutionContext::Task's in Document when page loading is deferred.
Schedule them with timer when page loading is resumed. The tasks will be performed
in the original order. This fixes the problem that database callbacks could be missed
when page loading was deferred.
https://bugs.webkit.org/show_bug.cgi?id=49401

Patch by Yong Li <[email protected]> on 2011-12-07
Reviewed by Darin Adler.

Manual test added: ManualTests/database-callback-deferred.html.

* dom/Document.cpp:
(WebCore::Document::Document):
(WebCore::Document::didReceiveTask):
(WebCore::Document::postTask):
(WebCore::Document::pendingTasksTimerFired):
(WebCore::Document::suspendScheduledTasks):
(WebCore::Document::resumeScheduledTasks):
* dom/Document.h:
* page/PageGroupLoadDeferrer.cpp:
(WebCore::PageGroupLoadDeferrer::PageGroupLoadDeferrer):
(WebCore::PageGroupLoadDeferrer::~PageGroupLoadDeferrer):

Modified Paths

Added Paths

Diff

Added: trunk/ManualTests/database-callback-deferred.html (0 => 102278)


--- trunk/ManualTests/database-callback-deferred.html	                        (rev 0)
+++ trunk/ManualTests/database-callback-deferred.html	2011-12-07 23:41:21 UTC (rev 102278)
@@ -0,0 +1,17 @@
+<html>
+<script>
+function test() {
+    function transactionCallback()
+    {
+        document.getElementById("result").innerHTML = "Callback was called. Test passed";
+    }
+    var db = openDatabase("DatabaseCallbackDeferred", "1.0", "", 1);
+    db.transaction(function(tx) { tx.executeSql("CREATE TABLE IF NOT EXISTS CallbackDeferredTest (randomData)", []); }, transactionCallback, transactionCallback);
+
+    alert("Wait for a few seconds and close it");
+}
+</script>
+<body _onload_="test()">
+<p id="result">Wait...</p>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (102277 => 102278)


--- trunk/Source/WebCore/ChangeLog	2011-12-07 22:48:49 UTC (rev 102277)
+++ trunk/Source/WebCore/ChangeLog	2011-12-07 23:41:21 UTC (rev 102278)
@@ -1,3 +1,28 @@
+2011-12-07  Yong Li  <[email protected]>
+
+        Defer ScriptExecutionContext::Task's in Document when page loading is deferred.
+        Schedule them with timer when page loading is resumed. The tasks will be performed
+        in the original order. This fixes the problem that database callbacks could be missed
+        when page loading was deferred.
+        https://bugs.webkit.org/show_bug.cgi?id=49401
+ 
+
+        Reviewed by Darin Adler.
+
+        Manual test added: ManualTests/database-callback-deferred.html. 
+
+        * dom/Document.cpp:
+        (WebCore::Document::Document):
+        (WebCore::Document::didReceiveTask):
+        (WebCore::Document::postTask):
+        (WebCore::Document::pendingTasksTimerFired):
+        (WebCore::Document::suspendScheduledTasks):
+        (WebCore::Document::resumeScheduledTasks):
+        * dom/Document.h:
+        * page/PageGroupLoadDeferrer.cpp:
+        (WebCore::PageGroupLoadDeferrer::PageGroupLoadDeferrer):
+        (WebCore::PageGroupLoadDeferrer::~PageGroupLoadDeferrer):
+
 2011-12-07  Andreas Kling  <[email protected]>
 
         RenderObject::style(): Inline early-return condition.

Modified: trunk/Source/WebCore/dom/Document.cpp (102277 => 102278)


--- trunk/Source/WebCore/dom/Document.cpp	2011-12-07 22:48:49 UTC (rev 102277)
+++ trunk/Source/WebCore/dom/Document.cpp	2011-12-07 23:41:21 UTC (rev 102278)
@@ -7,6 +7,7 @@
  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
  * Copyright (C) 2008, 2009, 2011 Google Inc. All rights reserved.
  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) Research In Motion Limited 2010-2011. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -429,6 +430,7 @@
     , m_writeRecursionIsTooDeep(false)
     , m_writeRecursionDepth(0)
     , m_wheelEventHandlerCount(0)
+    , m_pendingTasksTimer(this, &Document::pendingTasksTimerFired)
 {
     m_document = this;
 
@@ -4704,24 +4706,61 @@
     OwnPtr<ScriptExecutionContext::Task> task;
 };
 
-static void performTask(void* ctx)
+void Document::didReceiveTask(void* untypedContext)
 {
     ASSERT(isMainThread());
 
-    PerformTaskContext* context = reinterpret_cast<PerformTaskContext*>(ctx);
+    OwnPtr<PerformTaskContext> context = adoptPtr(static_cast<PerformTaskContext*>(untypedContext));
     ASSERT(context);
 
-    if (Document* document = context->documentReference->document())
-        context->task->performTask(document);
+    Document* document = context->documentReference->document();
+    if (!document)
+        return;
 
-    delete context;
+    Page* page = document->page();
+    if ((page && page->defersLoading()) || !document->m_pendingTasks.isEmpty()) {
+        document->m_pendingTasks.append(context->task.release());
+        return;
+    }
+
+    context->task->performTask(document);
 }
 
 void Document::postTask(PassOwnPtr<Task> task)
 {
-    callOnMainThread(performTask, new PerformTaskContext(m_weakReference, task));
+    callOnMainThread(didReceiveTask, new PerformTaskContext(m_weakReference, task));
 }
 
+void Document::pendingTasksTimerFired(Timer<Document>*)
+{
+    while (!m_pendingTasks.isEmpty()) {
+        OwnPtr<Task> task = m_pendingTasks[0].release();
+        m_pendingTasks.remove(0);
+        task->performTask(this);
+    }
+}
+
+void Document::suspendScheduledTasks()
+{
+    suspendScriptedAnimationControllerCallbacks();
+    suspendActiveDOMObjects(ActiveDOMObject::WillShowDialog);
+    scriptRunner()->suspend();
+    m_pendingTasksTimer.stop();
+    if (m_parser)
+        m_parser->suspendScheduledTasks();
+}
+
+void Document::resumeScheduledTasks()
+{
+    if (m_parser)
+        m_parser->resumeScheduledTasks();
+    if (!m_pendingTasks.isEmpty())
+        m_pendingTasksTimer.startOneShot(0);
+    scriptRunner()->resume();
+    resumeActiveDOMObjects();
+    resumeScriptedAnimationControllerCallbacks();
+}
+
 void Document::suspendScriptedAnimationControllerCallbacks()
 {
 #if ENABLE(REQUEST_ANIMATION_FRAME)

Modified: trunk/Source/WebCore/dom/Document.h (102277 => 102278)


--- trunk/Source/WebCore/dom/Document.h	2011-12-07 22:48:49 UTC (rev 102277)
+++ trunk/Source/WebCore/dom/Document.h	2011-12-07 23:41:21 UTC (rev 102278)
@@ -1114,7 +1114,7 @@
     unsigned wheelEventHandlerCount() const { return m_wheelEventHandlerCount; }
     void didAddWheelEventHandler();
     void didRemoveWheelEventHandler();
-    
+
     bool visualUpdatesAllowed() const;
 
 #if ENABLE(MICRODATA)
@@ -1124,6 +1124,9 @@
     
     bool isInDocumentWrite() { return m_writeRecursionDepth > 0; }
 
+    void suspendScheduledTasks();
+    void resumeScheduledTasks();
+
 protected:
     Document(Frame*, const KURL&, bool isXHTML, bool isHTML);
 
@@ -1171,6 +1174,10 @@
 
     void loadEventDelayTimerFired(Timer<Document>*);
 
+    void pendingTasksTimerFired(Timer<Document>*);
+
+    static void didReceiveTask(void*);
+
 #if ENABLE(PAGE_VISIBILITY_API)
     PageVisibilityState visibilityState() const;
 #endif
@@ -1433,6 +1440,9 @@
 #if ENABLE(REQUEST_ANIMATION_FRAME)
     OwnPtr<ScriptedAnimationController> m_scriptedAnimationController;
 #endif
+
+    Timer<Document> m_pendingTasksTimer;
+    Vector<OwnPtr<Task> > m_pendingTasks;
 };
 
 // Put these methods here, because they require the Document definition, but we really want to inline them.

Modified: trunk/Source/WebCore/page/PageGroupLoadDeferrer.cpp (102277 => 102278)


--- trunk/Source/WebCore/page/PageGroupLoadDeferrer.cpp	2011-12-07 22:48:49 UTC (rev 102277)
+++ trunk/Source/WebCore/page/PageGroupLoadDeferrer.cpp	2011-12-07 23:41:21 UTC (rev 102278)
@@ -48,13 +48,8 @@
                 // windows or sheets, which is exactly when PageGroupLoadDeferrer is used.
                 // NOTE: if PageGroupLoadDeferrer is ever used for tasks other than showing a modal window or sheet,
                 // the constructor will need to take a ActiveDOMObject::ReasonForSuspension.
-                for (Frame* frame = otherPage->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
-                    frame->document()->suspendScriptedAnimationControllerCallbacks();
-                    frame->document()->suspendActiveDOMObjects(ActiveDOMObject::WillShowDialog);
-                    frame->document()->scriptRunner()->suspend();
-                    if (DocumentParser* parser = frame->document()->parser())
-                        parser->suspendScheduledTasks();
-                }
+                for (Frame* frame = otherPage->mainFrame(); frame; frame = frame->tree()->traverseNext())
+                    frame->document()->suspendScheduledTasks();
             }
         }
     }
@@ -71,13 +66,8 @@
         if (Page* page = m_deferredFrames[i]->page()) {
             page->setDefersLoading(false);
 
-            for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
-                frame->document()->resumeActiveDOMObjects();
-                frame->document()->resumeScriptedAnimationControllerCallbacks();
-                frame->document()->scriptRunner()->resume();
-                if (DocumentParser* parser = frame->document()->parser())
-                    parser->resumeScheduledTasks();
-            }
+            for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext())
+                frame->document()->resumeScheduledTasks();
         }
     }
 }
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to