2010-07-11 Maciej Stachowiak <mjs@apple.com>
authormjs@apple.com <mjs@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 12 Jul 2010 03:41:11 +0000 (03:41 +0000)
committermjs@apple.com <mjs@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 12 Jul 2010 03:41:11 +0000 (03:41 +0000)
        Reviewed by Dan Bernstein.

        Implement waitUntilDone and notifyDone for WebKitTestRunner
        https://bugs.webkit.org/show_bug.cgi?id=42049

        With this fix, most of the DOM tests pass.

        * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
        (WTR::InjectedBundle::didCreatePage): Track the main page. Not
        a great way to do it in the future case where we may get multiple
        pages - we really need a way to send it over from the ui process.
        * WebKitTestRunner/InjectedBundle/InjectedBundle.h:
        (WTR::InjectedBundle::page): A way to get the main page.
        * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp:
        (WTR::InjectedBundlePage::InjectedBundlePage): Initialize m_isLoading to false.
        (WTR::InjectedBundlePage::didStartProvisionalLoadForFrame): Track that we
        are loading.
        (WTR::InjectedBundlePage::dump): Factor into a method so this can be
        called by the layout test controller. Also, cancel any pending watchdogs.
        (WTR::InjectedBundlePage::didFinishLoadForFrame): Note that we are done loading.
        (WTR::InjectedBundlePage::didFailLoadWithErrorForFrame): Ditto.
        * WebKitTestRunner/InjectedBundle/InjectedBundlePage.h:
        (WTR::InjectedBundlePage::isLoading): A way to track if we are loading.
        * WebKitTestRunner/InjectedBundle/LayoutTestController.cpp:
        (WTR::LayoutTestController::LayoutTestController): Initialize m_waitToDump
        to false.
        (WTR::LayoutTestController::invalidateWaitToDumpWatchdog): Invalidate
        the watchdog.
        (WTR::waitUntilDoneWatchdogFired): Static helper for the watchdog timer.
        (WTR::LayoutTestController::setWaitToDump): Set the flag.
        (WTR::LayoutTestController::waitToDumpWatchdogTimerFired): Handle the case
        where waitUntilDone times out.
        (WTR::LayoutTestController::notifyDone): Dump, if loading is done.
        (WTR::waitUntilDoneCallback): JS glue for waitUntilDone.
        (WTR::notifyDoneCallback): JS glue for notifyDone.
        (WTR::LayoutTestController::staticFunctions): Add waitUntilDone and notifyDone
        to the layoutController.
        * WebKitTestRunner/InjectedBundle/LayoutTestController.h:
        (WTR::LayoutTestController::waitToDump): Inline method to get the wait state.

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

WebKitTools/ChangeLog
WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp
WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundle.h
WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp
WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.h
WebKitTools/WebKitTestRunner/InjectedBundle/LayoutTestController.cpp
WebKitTools/WebKitTestRunner/InjectedBundle/LayoutTestController.h

index 7bd2c27be7289ba4418c7a4625105d15bfab1036..165c6b3f89f7f4f2b25f0f93f6defc1cb2fc8f65 100644 (file)
@@ -1,3 +1,45 @@
+2010-07-11  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Dan Bernstein.
+
+        Implement waitUntilDone and notifyDone for WebKitTestRunner
+        https://bugs.webkit.org/show_bug.cgi?id=42049
+
+        With this fix, most of the DOM tests pass.
+        
+        * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
+        (WTR::InjectedBundle::didCreatePage): Track the main page. Not
+        a great way to do it in the future case where we may get multiple
+        pages - we really need a way to send it over from the ui process.
+        * WebKitTestRunner/InjectedBundle/InjectedBundle.h:
+        (WTR::InjectedBundle::page): A way to get the main page.
+        * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp:
+        (WTR::InjectedBundlePage::InjectedBundlePage): Initialize m_isLoading to false.
+        (WTR::InjectedBundlePage::didStartProvisionalLoadForFrame): Track that we
+        are loading.
+        (WTR::InjectedBundlePage::dump): Factor into a method so this can be
+        called by the layout test controller. Also, cancel any pending watchdogs.
+        (WTR::InjectedBundlePage::didFinishLoadForFrame): Note that we are done loading.
+        (WTR::InjectedBundlePage::didFailLoadWithErrorForFrame): Ditto.
+        * WebKitTestRunner/InjectedBundle/InjectedBundlePage.h:
+        (WTR::InjectedBundlePage::isLoading): A way to track if we are loading.
+        * WebKitTestRunner/InjectedBundle/LayoutTestController.cpp:
+        (WTR::LayoutTestController::LayoutTestController): Initialize m_waitToDump
+        to false.
+        (WTR::LayoutTestController::invalidateWaitToDumpWatchdog): Invalidate 
+        the watchdog.
+        (WTR::waitUntilDoneWatchdogFired): Static helper for the watchdog timer.
+        (WTR::LayoutTestController::setWaitToDump): Set the flag.
+        (WTR::LayoutTestController::waitToDumpWatchdogTimerFired): Handle the case
+        where waitUntilDone times out.
+        (WTR::LayoutTestController::notifyDone): Dump, if loading is done.
+        (WTR::waitUntilDoneCallback): JS glue for waitUntilDone.
+        (WTR::notifyDoneCallback): JS glue for notifyDone.
+        (WTR::LayoutTestController::staticFunctions): Add waitUntilDone and notifyDone
+        to the layoutController.
+        * WebKitTestRunner/InjectedBundle/LayoutTestController.h:
+        (WTR::LayoutTestController::waitToDump): Inline method to get the wait state.
+
 2010-07-09  Brian Weinstein  <bweinstein@apple.com>
 
         Rubber-stamped by Dan Bernstein.
index 7733c7f4f614b7bc778044fd16e647737f1ca890..9eea3e26a6e8f5a0cc1770d351fa755e812c74fc 100644 (file)
@@ -85,7 +85,9 @@ void InjectedBundle::done()
 
 void InjectedBundle::didCreatePage(WKBundlePageRef page)
 {
-    m_pages.add(page, new InjectedBundlePage(page));
+    // FIXME: we really need the main page ref to be sent over from the ui process
+    m_mainPage = new InjectedBundlePage(page);
+    m_pages.add(page, m_mainPage);
 }
 
 void InjectedBundle::willDestroyPage(WKBundlePageRef page)
index 33934cf4fe55645d484af9911c23a83629c5f007..1581ebc459971245c8b81846efb79c8e60813a42 100644 (file)
@@ -48,6 +48,7 @@ public:
     void done();
 
     LayoutTestController* layoutTestController() { return m_layoutTestController.get(); }
+    InjectedBundlePage* page() { return m_mainPage; }
 
     std::ostringstream& os() { return m_outputStream; }
 
@@ -67,6 +68,7 @@ private:
 
     WKBundleRef m_bundle;
     HashMap<WKBundlePageRef, InjectedBundlePage*> m_pages;
+    InjectedBundlePage* m_mainPage;
 
     RefPtr<LayoutTestController> m_layoutTestController;
 
index 248f99d7e09dada45f4d0391274a46caeed53080..c0060c37964d143654d0cd5c3449f593d13f9253 100644 (file)
@@ -38,6 +38,7 @@ namespace WTR {
 
 InjectedBundlePage::InjectedBundlePage(WKBundlePageRef page)
     : m_page(page)
+    , m_isLoading(false)
 {
     WKBundlePageLoaderClient loaderClient = {
         0,
@@ -110,6 +111,8 @@ void InjectedBundlePage::_didClearWindowForFrame(WKBundlePageRef page, WKBundleF
 
 void InjectedBundlePage::didStartProvisionalLoadForFrame(WKBundleFrameRef frame)
 {
+    if (frame == WKBundlePageGetMainFrame(m_page))
+        m_isLoading = true;
 }
 
 void InjectedBundlePage::didReceiveServerRedirectForProvisionalLoadForFrame(WKBundleFrameRef frame)
@@ -137,14 +140,13 @@ static std::auto_ptr<Vector<char> > WKStringToUTF8(WKStringRef wkStringRef)
     return buffer;
 }
 
-void InjectedBundlePage::didFinishLoadForFrame(WKBundleFrameRef frame)
+void InjectedBundlePage::dump()
 {
-    if (!WKBundleFrameIsMainFrame(frame))
-        return;
+    InjectedBundle::shared().layoutTestController()->invalidateWaitToDumpWatchdog();
 
     if (InjectedBundle::shared().layoutTestController()->dumpAsText()) {
         // FIXME: Support dumping subframes when layoutTestController()->dumpChildFramesAsText() is true.
-        WKRetainPtr<WKStringRef> innerText(AdoptWK, WKBundleFrameCopyInnerText(frame));
+        WKRetainPtr<WKStringRef> innerText(AdoptWK, WKBundleFrameCopyInnerText(WKBundlePageGetMainFrame(m_page)));
         std::auto_ptr<Vector<char> > utf8InnerText = WKStringToUTF8(innerText.get());
         InjectedBundle::shared().os() << utf8InnerText->data() << "\n";
     } else {
@@ -155,11 +157,26 @@ void InjectedBundlePage::didFinishLoadForFrame(WKBundleFrameRef frame)
     InjectedBundle::shared().done();
 }
 
+void InjectedBundlePage::didFinishLoadForFrame(WKBundleFrameRef frame)
+{
+    if (!WKBundleFrameIsMainFrame(frame))
+        return;
+
+    m_isLoading = false;
+
+    if (InjectedBundle::shared().layoutTestController()->waitToDump())
+        return;
+
+    dump();
+}
+
 void InjectedBundlePage::didFailLoadWithErrorForFrame(WKBundleFrameRef frame)
 {
     if (!WKBundleFrameIsMainFrame(frame))
         return;
 
+    m_isLoading = false;
+
     InjectedBundle::shared().done();
 }
 
index fddc3662e08c89836964d8283f5dc72b6d9423f4..79aebb7b27f40a920e9e5ae68aa26d5051d87aa5 100644 (file)
@@ -36,6 +36,9 @@ public:
     ~InjectedBundlePage();
 
     WKBundlePageRef page() const { return m_page; }
+    void dump();
+
+    bool isLoading() { return m_isLoading; }
 
 private:
     // Loader Client
@@ -61,6 +64,7 @@ private:
     void addMessageToConsole(WKStringRef message, uint32_t lineNumber);
 
     WKBundlePageRef m_page;
+    bool m_isLoading;
 };
 
 } // namespace WTR
index 014851cf1651e32b6596fe78a1186f13ec87f8db..88308a4df09324f852e699e718793151fcb3c429 100644 (file)
@@ -24,6 +24,8 @@
  */
 
 #include "LayoutTestController.h"
+#include "InjectedBundle.h"
+#include "InjectedBundlePage.h"
 
 #include <JavaScriptCore/JSRetainPtr.h>
 
@@ -36,6 +38,7 @@ PassRefPtr<LayoutTestController> LayoutTestController::create(const std::string&
 
 LayoutTestController::LayoutTestController(const std::string& testPathOrURL)
     : m_dumpAsText(false)
+    , m_waitToDump(false)
     , m_testPathOrURL(testPathOrURL)
 {
 }
@@ -44,6 +47,47 @@ LayoutTestController::~LayoutTestController()
 {
 }
 
+static const CFTimeInterval waitToDumpWatchdogInterval = 30.0;
+
+
+void LayoutTestController::invalidateWaitToDumpWatchdog()
+{
+    if (m_waitToDumpWatchdog) {
+        CFRunLoopTimerInvalidate(m_waitToDumpWatchdog.get());
+        m_waitToDumpWatchdog = 0;
+    }
+}
+
+static void waitUntilDoneWatchdogFired(CFRunLoopTimerRef timer, void* info)
+{
+    InjectedBundle::shared().layoutTestController()->waitToDumpWatchdogTimerFired();
+}
+
+void LayoutTestController::setWaitToDump()
+{
+    m_waitToDump = true;
+    if (!m_waitToDumpWatchdog) {
+        m_waitToDumpWatchdog.adoptCF(CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + waitToDumpWatchdogInterval, 
+                                                      0, 0, 0, waitUntilDoneWatchdogFired, NULL));
+        CFRunLoopAddTimer(CFRunLoopGetCurrent(), m_waitToDumpWatchdog.get(), kCFRunLoopCommonModes);
+    }
+}
+
+void LayoutTestController::waitToDumpWatchdogTimerFired()
+{
+    invalidateWaitToDumpWatchdog();
+    const char* message = "FAIL: Timed out waiting for notifyDone to be called\n";
+    InjectedBundle::shared().os() << message << "\n";
+    InjectedBundle::shared().done();
+}
+
+void LayoutTestController::notifyDone()
+{
+    if (m_waitToDump && !InjectedBundle::shared().page()->isLoading())
+        InjectedBundle::shared().page()->dump();
+    m_waitToDump = false;
+}
+
 static JSValueRef dumpAsTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
 {
     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
@@ -51,6 +95,20 @@ static JSValueRef dumpAsTextCallback(JSContextRef context, JSObjectRef function,
     return JSValueMakeUndefined(context);
 }
 
+static JSValueRef waitUntilDoneCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
+    controller->setWaitToDump();
+    return JSValueMakeUndefined(context);
+}
+
+static JSValueRef notifyDoneCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
+    controller->notifyDone();
+    return JSValueMakeUndefined(context);
+}
+
 // Object Finalization
 
 static void layoutTestControllerObjectFinalize(JSObjectRef object)
@@ -88,6 +146,8 @@ JSStaticFunction* LayoutTestController::staticFunctions()
 {
     static JSStaticFunction staticFunctions[] = {
         { "dumpAsText", dumpAsTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+        { "notifyDone", notifyDoneCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+        { "waitUntilDone", waitUntilDoneCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { 0, 0, 0 }
     };
 
index 56717c1864c9f6fa970684a01fd59de95cfda906..12bd94a53b838f2fcc71a7953f5a0fe2e8b64d96 100644 (file)
@@ -29,6 +29,7 @@
 #include <JavaScriptCore/JavaScriptCore.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
+#include <wtf/RetainPtr.h>
 #include <string>
 
 namespace WTR {
@@ -43,13 +44,22 @@ public:
     bool dumpAsText() const { return m_dumpAsText; }
     void setDumpAsText(bool dumpAsText) { m_dumpAsText = dumpAsText; }
 
+    bool waitToDump() const { return m_waitToDump; }
+    void setWaitToDump();
+    void waitToDumpWatchdogTimerFired();
+    void invalidateWaitToDumpWatchdog();
+    void notifyDone();
+
 private:
     LayoutTestController(const std::string& testPathOrURL);
 
     bool m_dumpAsText;
+    bool m_waitToDump; // True if waitUntilDone() has been called, but notifyDone() has not yet been called.
 
     std::string m_testPathOrURL;
     
+    RetainPtr<CFRunLoopTimerRef> m_waitToDumpWatchdog;
+
     static JSClassRef getJSClass();
     static JSStaticValue* staticValues();
     static JSStaticFunction* staticFunctions();