2009-02-25 David Levin <levin@chromium.org>
authorlevin@chromium.org <levin@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 25 Feb 2009 18:06:35 +0000 (18:06 +0000)
committerlevin@chromium.org <levin@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 25 Feb 2009 18:06:35 +0000 (18:06 +0000)
        Reviewed by Alexey Proskuryakov.

        Bug 23688: ThreadableLoader needs a sync implementation for Workers.
        <https://bugs.webkit.org/show_bug.cgi?id=23688>

        No observable change in behavior, so no test.

        * loader/ThreadableLoader.cpp:
        (WebCore::ThreadableLoader::loadResourceSynchronously):
        * loader/ThreadableLoaderClientWrapper.h:
        (WebCore::ThreadableLoaderClientWrapper::clearClient):
        (WebCore::ThreadableLoaderClientWrapper::done):
        (WebCore::ThreadableLoaderClientWrapper::didFinishLoading):
        (WebCore::ThreadableLoaderClientWrapper::didFail):
        (WebCore::ThreadableLoaderClientWrapper::didFailRedirectCheck):
        (WebCore::ThreadableLoaderClientWrapper::ThreadableLoaderClientWrapper):
        Expose whether the loader is done (based on what callbacks were done).

        * loader/WorkerThreadableLoader.cpp:
        (WebCore::WorkerThreadableLoader::WorkerThreadableLoader):
        (WebCore::WorkerThreadableLoader::loadResourceSynchronously):
        Each loader is given its own mode so that only its callbacks get through the run loop.

        The xhr spec says that the readystatechange events are synchronous, so in the case of a
        nested sync xhr no readystatechange events should be fired for the outer xhr.

        (WebCore::WorkerThreadableLoader::MainThreadBridge::MainThreadBridge):

        * loader/WorkerThreadableLoader.h:
        (WebCore::WorkerThreadableLoader::create):
        (WebCore::WorkerThreadableLoader::done):

        * workers/WorkerRunLoop.cpp:
        (WebCore::WorkerRunLoop::WorkerRunLoop):
        * workers/WorkerRunLoop.h:
        (WebCore::WorkerRunLoop::createUniqueId):
        Simple method to create a uniqueId on demand with respect to the run loop.

        * workers/WorkerThread.h:

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

WebCore/ChangeLog
WebCore/loader/ThreadableLoader.cpp
WebCore/loader/ThreadableLoaderClientWrapper.h
WebCore/loader/WorkerThreadableLoader.cpp
WebCore/loader/WorkerThreadableLoader.h
WebCore/workers/WorkerRunLoop.cpp
WebCore/workers/WorkerRunLoop.h
WebCore/workers/WorkerThread.h

index e9fad2ac921f83281073a21d4f61be76fd7e7d76..992c8fcfc755bdec9329d5229b491b690e115e81 100644 (file)
@@ -1,3 +1,45 @@
+2009-02-25  David Levin  <levin@chromium.org>
+
+        Reviewed by Alexey Proskuryakov.
+
+        Bug 23688: ThreadableLoader needs a sync implementation for Workers.
+        <https://bugs.webkit.org/show_bug.cgi?id=23688>
+
+        No observable change in behavior, so no test.
+
+        * loader/ThreadableLoader.cpp:
+        (WebCore::ThreadableLoader::loadResourceSynchronously):
+        * loader/ThreadableLoaderClientWrapper.h:
+        (WebCore::ThreadableLoaderClientWrapper::clearClient):
+        (WebCore::ThreadableLoaderClientWrapper::done):
+        (WebCore::ThreadableLoaderClientWrapper::didFinishLoading):
+        (WebCore::ThreadableLoaderClientWrapper::didFail):
+        (WebCore::ThreadableLoaderClientWrapper::didFailRedirectCheck):
+        (WebCore::ThreadableLoaderClientWrapper::ThreadableLoaderClientWrapper):
+        Expose whether the loader is done (based on what callbacks were done).
+
+        * loader/WorkerThreadableLoader.cpp:
+        (WebCore::WorkerThreadableLoader::WorkerThreadableLoader):
+        (WebCore::WorkerThreadableLoader::loadResourceSynchronously):
+        Each loader is given its own mode so that only its callbacks get through the run loop.
+
+        The xhr spec says that the readystatechange events are synchronous, so in the case of a
+        nested sync xhr no readystatechange events should be fired for the outer xhr.
+
+        (WebCore::WorkerThreadableLoader::MainThreadBridge::MainThreadBridge):
+
+        * loader/WorkerThreadableLoader.h:
+        (WebCore::WorkerThreadableLoader::create):
+        (WebCore::WorkerThreadableLoader::done):
+
+        * workers/WorkerRunLoop.cpp:
+        (WebCore::WorkerRunLoop::WorkerRunLoop):
+        * workers/WorkerRunLoop.h:
+        (WebCore::WorkerRunLoop::createUniqueId):
+        Simple method to create a uniqueId on demand with respect to the run loop.
+
+        * workers/WorkerThread.h:
+
 2009-02-25  David Levin  <levin@chromium.org>
 
         Reviewed by Alexey Proskuryakov.
index 2cdca7bdc85e836304794f92e7ac42937968ab19..1b2cc8827762e7e95715199d2cee2e290d700526 100644 (file)
@@ -57,6 +57,14 @@ PassRefPtr<ThreadableLoader> ThreadableLoader::create(ScriptExecutionContext* co
 void ThreadableLoader::loadResourceSynchronously(ScriptExecutionContext* context, const ResourceRequest& request, ThreadableLoaderClient& client)
 {
     ASSERT(context);
+
+#if ENABLE(WORKERS)
+    if (context->isWorkerContext()) {
+        WorkerThreadableLoader::loadResourceSynchronously(static_cast<WorkerContext*>(context), request, client);
+        return;
+    }
+#endif // ENABLE(WORKERS)
+
     ASSERT(context->isDocument());
     DocumentThreadableLoader::loadResourceSynchronously(static_cast<Document*>(context), request, client);
 }
index 4c6163f1b8039ad1e9b3ea4055100f887d1819b7..d3c1a9feea3e1a15de9b07238a3ff74f7ca7bac4 100644 (file)
@@ -47,9 +47,15 @@ namespace WebCore {
 
         void clearClient()
         {
+            m_done = true;
             m_client = 0;
         }
 
+        bool done() const
+        {
+            return m_done;
+        }
+
         void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
         {
             if (m_client)
@@ -70,18 +76,21 @@ namespace WebCore {
 
         void didFinishLoading(unsigned long identifier)
         {
+            m_done = true;
             if (m_client)
                 m_client->didFinishLoading(identifier);
         }
 
         void didFail(const ResourceError& error)
         {
+            m_done = true;
             if (m_client)
                 m_client->didFail(error);
         }
 
         void didFailRedirectCheck()
         {
+            m_done = true;
             if (m_client)
                 m_client->didFailRedirectCheck();
         }
@@ -95,10 +104,12 @@ namespace WebCore {
     protected:
         ThreadableLoaderClientWrapper(ThreadableLoaderClient* client)
             : m_client(client)
+            , m_done(false)
         {
         }
 
         ThreadableLoaderClient* m_client;
+        bool m_done;
     };
 
 } // namespace WebCore
index d801c2c5c21c9b84270cadbfec79e08b66ff2465..2fa3203cd5fcec2af8424838e0ac97bbcec03fed 100644 (file)
@@ -51,11 +51,15 @@ using namespace std;
 
 namespace WebCore {
 
+static const char loadResourceSynchronouslyMode[] = "loadResourceSynchronouslyMode";
+
 // FIXME: The assumption that we can upcast worker object proxy to WorkerMessagingProxy will not be true in multi-process implementation.
 WorkerThreadableLoader::WorkerThreadableLoader(WorkerContext* workerContext, ThreadableLoaderClient* client, const String& taskMode, const ResourceRequest& request, LoadCallbacks callbacksSetting,
                                                ContentSniff contentSniff)
     : m_workerContext(workerContext)
-    , m_bridge(*(new MainThreadBridge(client, *(static_cast<WorkerMessagingProxy*>(m_workerContext->thread()->workerObjectProxy())), taskMode, request, callbacksSetting, contentSniff)))
+    , m_workerClientWrapper(ThreadableLoaderClientWrapper::create(client))
+    , m_bridge(*(new MainThreadBridge(m_workerClientWrapper, *(static_cast<WorkerMessagingProxy*>(m_workerContext->thread()->workerObjectProxy())), taskMode, request, callbacksSetting,
+                                      contentSniff)))
 {
 }
 
@@ -64,18 +68,32 @@ WorkerThreadableLoader::~WorkerThreadableLoader()
     m_bridge.destroy();
 }
 
+void WorkerThreadableLoader::loadResourceSynchronously(WorkerContext* workerContext, const ResourceRequest& request, ThreadableLoaderClient& client)
+{
+    WorkerRunLoop& runLoop = workerContext->thread()->runLoop();
+
+    // Create a unique mode just for this synchronous resource load.
+    String mode = loadResourceSynchronouslyMode;
+    mode.append(String::number(runLoop.createUniqueId()));
+
+    ContentSniff contentSniff = request.url().isLocalFile() ? SniffContent : DoNotSniffContent;
+    RefPtr<WorkerThreadableLoader> loader = WorkerThreadableLoader::create(workerContext, &client, mode, request, DoNotSendLoadCallbacks, contentSniff);
+    while (!loader->done())
+        runLoop.runInMode(workerContext, mode);
+}
+
 void WorkerThreadableLoader::cancel()
 {
     m_bridge.cancel();
 }
 
-WorkerThreadableLoader::MainThreadBridge::MainThreadBridge(ThreadableLoaderClient* workerClient, WorkerMessagingProxy& messagingProxy, const String& taskMode, const ResourceRequest& request,
-                                                           LoadCallbacks callbacksSetting, ContentSniff contentSniff)
-    : m_workerClientWrapper(ThreadableLoaderClientWrapper::create(workerClient))
+WorkerThreadableLoader::MainThreadBridge::MainThreadBridge(PassRefPtr<ThreadableLoaderClientWrapper> workerClientWrapper, WorkerMessagingProxy& messagingProxy, const String& taskMode,
+                                                           const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff)
+    : m_workerClientWrapper(workerClientWrapper)
     , m_messagingProxy(messagingProxy)
     , m_taskMode(taskMode.copy())
 {
-    ASSERT(workerClient);
+    ASSERT(m_workerClientWrapper.get());
     m_messagingProxy.postTaskToWorkerObject(createCallbackTask(&MainThreadBridge::mainThreadCreateLoader, this, request, callbacksSetting, contentSniff));
 }
 
index f997e10c64ddb0b9321c8a150b604aee2f924552..cd7c51d09b06113410585fbb373cda92c177cda6 100644 (file)
@@ -55,15 +55,18 @@ namespace WebCore {
 
     class WorkerThreadableLoader : public RefCounted<WorkerThreadableLoader>, public ThreadableLoader {
     public:
-        static PassRefPtr<WorkerThreadableLoader> create(WorkerContext* worker, ThreadableLoaderClient* client, const String& taskMode, const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff)
+        static void loadResourceSynchronously(WorkerContext*, const ResourceRequest&, ThreadableLoaderClient&);
+        static PassRefPtr<WorkerThreadableLoader> create(WorkerContext* workerContext, ThreadableLoaderClient* client, const String& taskMode, const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff)
         {
-            return adoptRef(new WorkerThreadableLoader(worker, client, taskMode, request, callbacksSetting, contentSniff));
+            return adoptRef(new WorkerThreadableLoader(workerContext, client, taskMode, request, callbacksSetting, contentSniff));
         }
 
         ~WorkerThreadableLoader();
 
         virtual void cancel();
 
+        bool done() const { return m_workerClientWrapper->done(); }
+
         using RefCounted<WorkerThreadableLoader>::ref;
         using RefCounted<WorkerThreadableLoader>::deref;
 
@@ -94,7 +97,7 @@ namespace WebCore {
         class MainThreadBridge : ThreadableLoaderClient {
         public:
             // All executed on the worker context's thread.
-            MainThreadBridge(ThreadableLoaderClient*, WorkerMessagingProxy&, const String& taskMode, const ResourceRequest&, LoadCallbacks, ContentSniff);
+            MainThreadBridge(PassRefPtr<ThreadableLoaderClientWrapper>, WorkerMessagingProxy&, const String& taskMode, const ResourceRequest&, LoadCallbacks, ContentSniff);
             void cancel();
             void destroy();
 
@@ -133,6 +136,7 @@ namespace WebCore {
         WorkerThreadableLoader(WorkerContext*, ThreadableLoaderClient*, const String& taskMode, const ResourceRequest&, LoadCallbacks, ContentSniff);
 
         RefPtr<WorkerContext> m_workerContext;
+        RefPtr<ThreadableLoaderClientWrapper> m_workerClientWrapper;
         MainThreadBridge& m_bridge;
     };
 
index 65877f7618b605374996c16d8c18964ec2ebda49..1e5e510320c408b8fb6bf576f46c68124af3ce01 100644 (file)
@@ -111,6 +111,7 @@ private:
 WorkerRunLoop::WorkerRunLoop()
     : m_sharedTimer(new WorkerSharedTimer)
     , m_nestedCount(0)
+    , m_uniqueId(0)
 {
 }
 
index 4d1eaa33d3721a2519688f7d4bd07054617979e8..5f74f01aa7a5452f84889ed2106b91e1ac5d42f5 100644 (file)
@@ -61,6 +61,8 @@ namespace WebCore {
         void postTask(PassRefPtr<ScriptExecutionContext::Task>);
         void postTaskForMode(PassRefPtr<ScriptExecutionContext::Task>, const String& mode);
 
+        unsigned long createUniqueId() { return ++m_uniqueId; }
+
         static String defaultMode();
         class Task;
     private:
@@ -70,6 +72,7 @@ namespace WebCore {
         MessageQueue<RefPtr<Task> > m_messageQueue;
         OwnPtr<WorkerSharedTimer> m_sharedTimer;
         int m_nestedCount;
+        unsigned long m_uniqueId;
     };
 
 } // namespace WebCore
index b1ef5f515291637abf46117691b850abf0d034aa..f1a8a524a7fb7f513fb4a978867f6fce3882c510 100644 (file)
@@ -29,7 +29,7 @@
 
 #if ENABLE(WORKERS)
 
-#include <WorkerRunLoop.h>
+#include "WorkerRunLoop.h"
 #include <wtf/OwnPtr.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>