2009-06-08  Dmitry Titov  <dimich@chromium.org>

        Reviewed by David Levin.

        https://bugs.webkit.org/show_bug.cgi?id=26126
        Refactor methods of WorkerMessagingProxy used to talk to main-thread loader into new interface.

        Split a couple of methods used to schedule cross-thread tasks between worker thread and loader thread
        implemented on WorkerMessagingProxy into a separate interface so the loading can be implemented in
        Chromium's workers.

        No changes in functionality so no tests added.

        * GNUmakefile.am:
        * WebCore.vcproj/WebCore.vcproj:
        * WebCore.xcodeproj/project.pbxproj:
        Added WorkerLoaderProxy.h to the bulid.

        * bindings/js/WorkerScriptController.cpp:
        (WebCore::WorkerScriptController::evaluate): WorkerThread::workerObjectProxy() now returns & instead of *
        * bindings/v8/WorkerScriptController.cpp:
        (WebCore::WorkerScriptController::evaluate): same.
        * workers/WorkerContext.cpp:
        (WebCore::WorkerContext::~WorkerContext): same.
        (WebCore::WorkerContext::reportException): same.
        (WebCore::WorkerContext::addMessage): same.
        (WebCore::WorkerContext::postMessage): same.

        * loader/WorkerThreadableLoader.cpp:
        (WebCore::WorkerThreadableLoader::WorkerThreadableLoader):
        (WebCore::WorkerThreadableLoader::MainThreadBridge::MainThreadBridge):
        (WebCore::WorkerThreadableLoader::MainThreadBridge::destroy):
        (WebCore::WorkerThreadableLoader::MainThreadBridge::cancel):
        (WebCore::WorkerThreadableLoader::MainThreadBridge::didSendData):
        (WebCore::WorkerThreadableLoader::MainThreadBridge::didReceiveResponse):
        (WebCore::WorkerThreadableLoader::MainThreadBridge::didReceiveData):
        (WebCore::WorkerThreadableLoader::MainThreadBridge::didFinishLoading):
        (WebCore::WorkerThreadableLoader::MainThreadBridge::didFail):
        (WebCore::WorkerThreadableLoader::MainThreadBridge::didFailRedirectCheck):
        (WebCore::WorkerThreadableLoader::MainThreadBridge::didReceiveAuthenticationCancellation):
        Use WorkerLoaderProxy instead of WorkerMessagingProxy for the MainThreadBridge.
        Mostly rename.

        (WebCore::WorkerThreadableLoader::MainThreadBridge::mainThreadCreateLoader):
        In addition to using WorkerLoaderProxy instead of WorkerMessagingProxy, the check for
        AskedToTerminate is removed. It seems to be an optimization for a very small number of cases
        when worker termination is requested a very short time before the request to load something
        (XHR or importScript) was dispatched on the main thread.

        * loader/WorkerThreadableLoader.h:
        Now keeps a pointer to WorkerLoaderProxy rather then to a WorkerMessagingProxy. This allows
        to implement WorkerThreadableLoader for Chromium.

        * workers/WorkerLoaderProxy.h: Added.
        (WebCore::WorkerLoaderProxy::~WorkerLoaderProxy):

        * workers/WorkerMessagingProxy.cpp:
        (WebCore::WorkerMessagingProxy::startWorkerContext):
        (WebCore::WorkerMessagingProxy::postTaskToLoader): Added ASSERT since this needs to be implemented for nested workers.
        * workers/WorkerMessagingProxy.h:
        Derived from WorkerLoaderProxy, the methods for posting tasks cross-thread are now virtual.
        Removed unused postTaskToWorkerContext() method.

        * workers/WorkerThread.cpp:
        (WebCore::WorkerThread::create):
        (WebCore::WorkerThread::WorkerThread):
        * workers/WorkerThread.h:
        (WebCore::WorkerThread::workerLoaderProxy):
        * workers/WorkerThread.cpp:
        (WebCore::WorkerThread::create):
        (WebCore::WorkerThread::WorkerThread):
        (WebCore::WorkerThread::workerThread):
        * workers/WorkerThread.h:
        (WebCore::WorkerThread::workerLoaderProxy):
        (WebCore::WorkerThread::workerObjectProxy):
        WorkerThread gets a new member of type WorkerLoaderProxy&, and accessor.
        Also, existing WorkerObjectProxy* member is now WorkerObjectProxy& because it can't be null.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@44515 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index a799e8e..4c1e50b 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,81 @@
+2009-06-08  Dmitry Titov  <dimich@chromium.org>
+
+        Reviewed by David Levin.
+
+        https://bugs.webkit.org/show_bug.cgi?id=26126
+        Refactor methods of WorkerMessagingProxy used to talk to main-thread loader into new interface.
+
+        Split a couple of methods used to schedule cross-thread tasks between worker thread and loader thread
+        implemented on WorkerMessagingProxy into a separate interface so the loading can be implemented in
+        Chromium's workers.
+
+        No changes in functionality so no tests added.
+
+        * GNUmakefile.am:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        Added WorkerLoaderProxy.h to the bulid.
+
+        * bindings/js/WorkerScriptController.cpp:
+        (WebCore::WorkerScriptController::evaluate): WorkerThread::workerObjectProxy() now returns & instead of *
+        * bindings/v8/WorkerScriptController.cpp:
+        (WebCore::WorkerScriptController::evaluate): same.
+        * workers/WorkerContext.cpp:
+        (WebCore::WorkerContext::~WorkerContext): same.
+        (WebCore::WorkerContext::reportException): same.
+        (WebCore::WorkerContext::addMessage): same.
+        (WebCore::WorkerContext::postMessage): same.
+
+        * loader/WorkerThreadableLoader.cpp:
+        (WebCore::WorkerThreadableLoader::WorkerThreadableLoader):
+        (WebCore::WorkerThreadableLoader::MainThreadBridge::MainThreadBridge):
+        (WebCore::WorkerThreadableLoader::MainThreadBridge::destroy):
+        (WebCore::WorkerThreadableLoader::MainThreadBridge::cancel):
+        (WebCore::WorkerThreadableLoader::MainThreadBridge::didSendData):
+        (WebCore::WorkerThreadableLoader::MainThreadBridge::didReceiveResponse):
+        (WebCore::WorkerThreadableLoader::MainThreadBridge::didReceiveData):
+        (WebCore::WorkerThreadableLoader::MainThreadBridge::didFinishLoading):
+        (WebCore::WorkerThreadableLoader::MainThreadBridge::didFail):
+        (WebCore::WorkerThreadableLoader::MainThreadBridge::didFailRedirectCheck):
+        (WebCore::WorkerThreadableLoader::MainThreadBridge::didReceiveAuthenticationCancellation):
+        Use WorkerLoaderProxy instead of WorkerMessagingProxy for the MainThreadBridge.
+        Mostly rename.
+
+        (WebCore::WorkerThreadableLoader::MainThreadBridge::mainThreadCreateLoader):
+        In addition to using WorkerLoaderProxy instead of WorkerMessagingProxy, the check for
+        AskedToTerminate is removed. It seems to be an optimization for a very small number of cases
+        when worker termination is requested a very short time before the request to load something
+        (XHR or importScript) was dispatched on the main thread.
+
+        * loader/WorkerThreadableLoader.h:
+        Now keeps a pointer to WorkerLoaderProxy rather then to a WorkerMessagingProxy. This allows
+        to implement WorkerThreadableLoader for Chromium.
+
+        * workers/WorkerLoaderProxy.h: Added.
+        (WebCore::WorkerLoaderProxy::~WorkerLoaderProxy):
+
+        * workers/WorkerMessagingProxy.cpp:
+        (WebCore::WorkerMessagingProxy::startWorkerContext):
+        (WebCore::WorkerMessagingProxy::postTaskToLoader): Added ASSERT since this needs to be implemented for nested workers.
+        * workers/WorkerMessagingProxy.h:
+        Derived from WorkerLoaderProxy, the methods for posting tasks cross-thread are now virtual.
+        Removed unused postTaskToWorkerContext() method.
+
+        * workers/WorkerThread.cpp:
+        (WebCore::WorkerThread::create):
+        (WebCore::WorkerThread::WorkerThread):
+        * workers/WorkerThread.h:
+        (WebCore::WorkerThread::workerLoaderProxy):
+        * workers/WorkerThread.cpp:
+        (WebCore::WorkerThread::create):
+        (WebCore::WorkerThread::WorkerThread):
+        (WebCore::WorkerThread::workerThread):
+        * workers/WorkerThread.h:
+        (WebCore::WorkerThread::workerLoaderProxy):
+        (WebCore::WorkerThread::workerObjectProxy):
+        WorkerThread gets a new member of type WorkerLoaderProxy&, and accessor.
+        Also, existing WorkerObjectProxy* member is now WorkerObjectProxy& because it can't be null.
+
 2009-06-08  Dimitri Glazkov  <dglazkov@chromium.org>
 
         Reviewed by Eric Seidel.
diff --git a/WebCore/GNUmakefile.am b/WebCore/GNUmakefile.am
index 5fd1422..151c01a 100644
--- a/WebCore/GNUmakefile.am
+++ b/WebCore/GNUmakefile.am
@@ -2271,6 +2271,7 @@
 	WebCore/workers/WorkerContext.cpp \
 	WebCore/workers/WorkerContext.h \
 	WebCore/workers/WorkerContextProxy.h \
+	WebCore/workers/WorkerLoaderProxy.h \
 	WebCore/workers/WorkerLocation.cpp \
 	WebCore/workers/WorkerLocation.h \
 	WebCore/workers/WorkerMessagingProxy.cpp \
diff --git a/WebCore/WebCore.vcproj/WebCore.vcproj b/WebCore/WebCore.vcproj/WebCore.vcproj
index 584beaa..6052ce4 100644
--- a/WebCore/WebCore.vcproj/WebCore.vcproj
+++ b/WebCore/WebCore.vcproj/WebCore.vcproj
@@ -9367,6 +9367,10 @@
 				>

 			</File>

 			<File

+				RelativePath="..\workers\WorkerLoaderProxy.h"

+				>

+			</File>

+			<File

 				RelativePath="..\workers\WorkerLocation.cpp"

 				>

 			</File>

diff --git a/WebCore/WebCore.xcodeproj/project.pbxproj b/WebCore/WebCore.xcodeproj/project.pbxproj
index b14b051..c7b27ee 100644
--- a/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -208,6 +208,7 @@
 		185BCF290F3279CE000EA262 /* ThreadTimers.h in Headers */ = {isa = PBXBuildFile; fileRef = 185BCF270F3279CE000EA262 /* ThreadTimers.h */; };
 		188604B30F2E654A000B6443 /* DOMTimer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 188604B10F2E654A000B6443 /* DOMTimer.cpp */; };
 		188604B40F2E654A000B6443 /* DOMTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 188604B20F2E654A000B6443 /* DOMTimer.h */; };
+		18F831B80FD48C7800D8C56B /* WorkerLoaderProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 18F831B70FD48C7800D8C56B /* WorkerLoaderProxy.h */; };
 		1A0D57360A5C77FE007EDD4C /* OverflowEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A0D57340A5C77FE007EDD4C /* OverflowEvent.cpp */; };
 		1A0D57370A5C77FE007EDD4C /* OverflowEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A0D57350A5C77FE007EDD4C /* OverflowEvent.h */; };
 		1A0D57400A5C7867007EDD4C /* JSOverflowEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A0D573E0A5C7867007EDD4C /* JSOverflowEvent.cpp */; };
@@ -5060,6 +5061,7 @@
 		185BCF270F3279CE000EA262 /* ThreadTimers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadTimers.h; sourceTree = "<group>"; };
 		188604B10F2E654A000B6443 /* DOMTimer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DOMTimer.cpp; sourceTree = "<group>"; };
 		188604B20F2E654A000B6443 /* DOMTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMTimer.h; sourceTree = "<group>"; };
+		18F831B70FD48C7800D8C56B /* WorkerLoaderProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WorkerLoaderProxy.h; path = workers/WorkerLoaderProxy.h; sourceTree = "<group>"; };
 		1A0D57340A5C77FE007EDD4C /* OverflowEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = OverflowEvent.cpp; sourceTree = "<group>"; };
 		1A0D57350A5C77FE007EDD4C /* OverflowEvent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = OverflowEvent.h; sourceTree = "<group>"; };
 		1A0D57380A5C7812007EDD4C /* OverflowEvent.idl */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = OverflowEvent.idl; sourceTree = "<group>"; };
@@ -9763,6 +9765,7 @@
 		2E4346310F546A6800B0F1BA /* workers */ = {
 			isa = PBXGroup;
 			children = (
+				18F831B70FD48C7800D8C56B /* WorkerLoaderProxy.h */,
 				2E4346320F546A8200B0F1BA /* GenericWorkerTask.h */,
 				2E4346330F546A8200B0F1BA /* Worker.cpp */,
 				2E4346340F546A8200B0F1BA /* Worker.h */,
@@ -16787,6 +16790,7 @@
 				845E72F80FD261EE00A87D79 /* Filter.h in Headers */,
 				845E72FC0FD2623900A87D79 /* SVGFilter.h in Headers */,
 				081EBF3B0FD34F4100DA7559 /* SVGFilterBuilder.h in Headers */,
+				18F831B80FD48C7800D8C56B /* WorkerLoaderProxy.h in Headers */,
 				A89CCC530F44E98100B5DA10 /* ReplaceNodeWithSpanCommand.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
diff --git a/WebCore/bindings/js/WorkerScriptController.cpp b/WebCore/bindings/js/WorkerScriptController.cpp
index dd391bc..bcf107b 100644
--- a/WebCore/bindings/js/WorkerScriptController.cpp
+++ b/WebCore/bindings/js/WorkerScriptController.cpp
@@ -110,7 +110,7 @@
     Completion comp = JSC::evaluate(exec, exec->dynamicGlobalObject()->globalScopeChain(), sourceCode.jsSourceCode(), m_workerContextWrapper);
     m_workerContextWrapper->globalData()->timeoutChecker.stop();
 
-    m_workerContext->thread()->workerObjectProxy()->reportPendingActivity(m_workerContext->hasPendingActivity());
+    m_workerContext->thread()->workerObjectProxy().reportPendingActivity(m_workerContext->hasPendingActivity());
 
     if (comp.complType() == Normal || comp.complType() == ReturnValue)
         return comp.value();
diff --git a/WebCore/bindings/v8/WorkerScriptController.cpp b/WebCore/bindings/v8/WorkerScriptController.cpp
index cf2a186..b3ede11 100644
--- a/WebCore/bindings/v8/WorkerScriptController.cpp
+++ b/WebCore/bindings/v8/WorkerScriptController.cpp
@@ -68,7 +68,7 @@
     }
 
     v8::Local<v8::Value> result = m_proxy->evaluate(sourceCode.source(), sourceCode.url().string(), sourceCode.startLine() - 1);
-    m_workerContext->thread()->workerObjectProxy()->reportPendingActivity(m_workerContext->hasPendingActivity());
+    m_workerContext->thread()->workerObjectProxy().reportPendingActivity(m_workerContext->hasPendingActivity());
     return ScriptValue();
 }
 
diff --git a/WebCore/loader/WorkerThreadableLoader.cpp b/WebCore/loader/WorkerThreadableLoader.cpp
index beaf061..47402c1 100644
--- a/WebCore/loader/WorkerThreadableLoader.cpp
+++ b/WebCore/loader/WorkerThreadableLoader.cpp
@@ -40,7 +40,7 @@
 #include "ResourceResponse.h"
 #include "ThreadableLoader.h"
 #include "WorkerContext.h"
-#include "WorkerMessagingProxy.h"
+#include "WorkerLoaderProxy.h"
 #include "WorkerThread.h"
 #include <memory>
 #include <wtf/OwnPtr.h>
@@ -53,13 +53,11 @@
 
 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, StoredCredentials storedCredentials)
     : m_workerContext(workerContext)
     , m_workerClientWrapper(ThreadableLoaderClientWrapper::create(client))
-    , m_bridge(*(new MainThreadBridge(m_workerClientWrapper, *(static_cast<WorkerMessagingProxy*>(m_workerContext->thread()->workerObjectProxy())), taskMode, request, callbacksSetting,
-                                      contentSniff, storedCredentials)))
+    , m_bridge(*(new MainThreadBridge(m_workerClientWrapper, m_workerContext->thread()->workerLoaderProxy(), taskMode, request, callbacksSetting, contentSniff, storedCredentials)))
 {
 }
 
@@ -92,14 +90,14 @@
     m_bridge.cancel();
 }
 
-WorkerThreadableLoader::MainThreadBridge::MainThreadBridge(PassRefPtr<ThreadableLoaderClientWrapper> workerClientWrapper, WorkerMessagingProxy& messagingProxy, const String& taskMode,
+WorkerThreadableLoader::MainThreadBridge::MainThreadBridge(PassRefPtr<ThreadableLoaderClientWrapper> workerClientWrapper, WorkerLoaderProxy& loaderProxy, const String& taskMode,
                                                            const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials)
     : m_workerClientWrapper(workerClientWrapper)
-    , m_messagingProxy(messagingProxy)
+    , m_loaderProxy(loaderProxy)
     , m_taskMode(taskMode.copy())
 {
     ASSERT(m_workerClientWrapper.get());
-    m_messagingProxy.postTaskToWorkerObject(createCallbackTask(&MainThreadBridge::mainThreadCreateLoader, this, request, callbacksSetting, contentSniff, storedCredentials));
+    m_loaderProxy.postTaskToLoader(createCallbackTask(&MainThreadBridge::mainThreadCreateLoader, this, request, callbacksSetting, contentSniff, storedCredentials));
 }
 
 WorkerThreadableLoader::MainThreadBridge::~MainThreadBridge()
@@ -108,16 +106,9 @@
 
 void WorkerThreadableLoader::MainThreadBridge::mainThreadCreateLoader(ScriptExecutionContext* context, MainThreadBridge* thisPtr, auto_ptr<CrossThreadResourceRequestData> requestData, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials)
 {
-    // FIXME: This assert fails for nested workers.  Removing the assert would allow it to work,
-    // but then there would be one WorkerThreadableLoader in every intermediate worker simply
-    // chaining the requests, which is not very good. Instead, the postTaskToWorkerObject should be a
-    // postTaskToDocumentContext.
     ASSERT(isMainThread());
     ASSERT(context->isDocument());
 
-    if (thisPtr->m_messagingProxy.askedToTerminate())
-        return;
-
     // FIXME: the created loader has no knowledge of the origin of the worker doing the load request.
     // Basically every setting done in SubresourceLoader::create (including the contents of addExtraFieldsToRequest)
     // needs to be examined for how it should take into account a different originator.
@@ -142,7 +133,7 @@
     clearClientWrapper();
 
     // "delete this" and m_mainThreadLoader::deref() on the worker object's thread.
-    m_messagingProxy.postTaskToWorkerObject(createCallbackTask(&MainThreadBridge::mainThreadDestroy, this));
+    m_loaderProxy.postTaskToLoader(createCallbackTask(&MainThreadBridge::mainThreadDestroy, this));
 }
 
 void WorkerThreadableLoader::MainThreadBridge::mainThreadCancel(ScriptExecutionContext* context, MainThreadBridge* thisPtr)
@@ -158,7 +149,7 @@
 
 void WorkerThreadableLoader::MainThreadBridge::cancel()
 {
-    m_messagingProxy.postTaskToWorkerObject(createCallbackTask(&MainThreadBridge::mainThreadCancel, this));
+    m_loaderProxy.postTaskToLoader(createCallbackTask(&MainThreadBridge::mainThreadCancel, this));
     ThreadableLoaderClientWrapper* clientWrapper = static_cast<ThreadableLoaderClientWrapper*>(m_workerClientWrapper.get());
     if (!clientWrapper->done()) {
         // If the client hasn't reached a termination state, then transition it by sending a cancellation error.
@@ -183,7 +174,7 @@
 
 void WorkerThreadableLoader::MainThreadBridge::didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
 {
-    m_messagingProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidSendData, m_workerClientWrapper, bytesSent, totalBytesToBeSent), m_taskMode);
+    m_loaderProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidSendData, m_workerClientWrapper, bytesSent, totalBytesToBeSent), m_taskMode);
 }
 
 static void workerContextDidReceiveResponse(ScriptExecutionContext* context, RefPtr<ThreadableLoaderClientWrapper> workerClientWrapper, auto_ptr<CrossThreadResourceResponseData> responseData)
@@ -195,7 +186,7 @@
 
 void WorkerThreadableLoader::MainThreadBridge::didReceiveResponse(const ResourceResponse& response)
 {
-    m_messagingProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidReceiveResponse, m_workerClientWrapper, response), m_taskMode);
+    m_loaderProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidReceiveResponse, m_workerClientWrapper, response), m_taskMode);
 }
 
 static void workerContextDidReceiveData(ScriptExecutionContext* context, RefPtr<ThreadableLoaderClientWrapper> workerClientWrapper, auto_ptr<Vector<char> > vectorData)
@@ -208,7 +199,7 @@
 {
     auto_ptr<Vector<char> > vector(new Vector<char>(lengthReceived)); // needs to be an auto_ptr for usage with createCallbackTask.
     memcpy(vector->data(), data, lengthReceived);
-    m_messagingProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidReceiveData, m_workerClientWrapper, vector), m_taskMode);
+    m_loaderProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidReceiveData, m_workerClientWrapper, vector), m_taskMode);
 }
 
 static void workerContextDidFinishLoading(ScriptExecutionContext* context, RefPtr<ThreadableLoaderClientWrapper> workerClientWrapper, unsigned long identifier)
@@ -219,7 +210,7 @@
 
 void WorkerThreadableLoader::MainThreadBridge::didFinishLoading(unsigned long identifier)
 {
-    m_messagingProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidFinishLoading, m_workerClientWrapper, identifier), m_taskMode);
+    m_loaderProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidFinishLoading, m_workerClientWrapper, identifier), m_taskMode);
 }
 
 static void workerContextDidFail(ScriptExecutionContext* context, RefPtr<ThreadableLoaderClientWrapper> workerClientWrapper, const ResourceError& error)
@@ -230,7 +221,7 @@
 
 void WorkerThreadableLoader::MainThreadBridge::didFail(const ResourceError& error)
 {
-    m_messagingProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidFail, m_workerClientWrapper, error), m_taskMode);
+    m_loaderProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidFail, m_workerClientWrapper, error), m_taskMode);
 }
 
 static void workerContextDidFailRedirectCheck(ScriptExecutionContext* context, RefPtr<ThreadableLoaderClientWrapper> workerClientWrapper)
@@ -241,7 +232,7 @@
 
 void WorkerThreadableLoader::MainThreadBridge::didFailRedirectCheck()
 {
-    m_messagingProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidFailRedirectCheck, m_workerClientWrapper), m_taskMode);
+    m_loaderProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidFailRedirectCheck, m_workerClientWrapper), m_taskMode);
 }
 
 static void workerContextDidReceiveAuthenticationCancellation(ScriptExecutionContext* context, RefPtr<ThreadableLoaderClientWrapper> workerClientWrapper, auto_ptr<CrossThreadResourceResponseData> responseData)
@@ -253,7 +244,7 @@
 
 void WorkerThreadableLoader::MainThreadBridge::didReceiveAuthenticationCancellation(const ResourceResponse& response)
 {
-    m_messagingProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidReceiveAuthenticationCancellation, m_workerClientWrapper, response), m_taskMode);
+    m_loaderProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidReceiveAuthenticationCancellation, m_workerClientWrapper, response), m_taskMode);
 }
 
 } // namespace WebCore
diff --git a/WebCore/loader/WorkerThreadableLoader.h b/WebCore/loader/WorkerThreadableLoader.h
index 9817fea..e584954 100644
--- a/WebCore/loader/WorkerThreadableLoader.h
+++ b/WebCore/loader/WorkerThreadableLoader.h
@@ -49,7 +49,7 @@
     class ResourceError;
     struct ResourceRequest;
     class WorkerContext;
-    class WorkerMessagingProxy;
+    class WorkerLoaderProxy;
     struct CrossThreadResourceResponseData;
     struct CrossThreadResourceRequestData;
 
@@ -86,7 +86,7 @@
         //
         // case 1. worker.terminate is called.
         //    In this case, no more tasks are posted from the worker object's thread to the worker
-        //    context's thread -- WorkerMessagingProxy enforces this.
+        //    context's thread -- WorkerContextProxy implementation enforces this.
         //
         // case 2. xhr gets aborted and the worker context continues running.
         //    The ThreadableLoaderClientWrapper has the underlying client cleared, so no more calls
@@ -97,7 +97,7 @@
         class MainThreadBridge : ThreadableLoaderClient {
         public:
             // All executed on the worker context's thread.
-            MainThreadBridge(PassRefPtr<ThreadableLoaderClientWrapper>, WorkerMessagingProxy&, const String& taskMode, const ResourceRequest&, LoadCallbacks, ContentSniff, StoredCredentials);
+            MainThreadBridge(PassRefPtr<ThreadableLoaderClientWrapper>, WorkerLoaderProxy&, const String& taskMode, const ResourceRequest&, LoadCallbacks, ContentSniff, StoredCredentials);
             void cancel();
             void destroy();
 
@@ -127,7 +127,7 @@
             RefPtr<ThreadSafeShared<ThreadableLoaderClientWrapper> > m_workerClientWrapper;
 
             // May be used on either thread.
-            WorkerMessagingProxy& m_messagingProxy;
+            WorkerLoaderProxy& m_loaderProxy;
 
             // For use on the main thread.
             String m_taskMode;
diff --git a/WebCore/workers/WorkerContext.cpp b/WebCore/workers/WorkerContext.cpp
index 59168c7..989efcd 100644
--- a/WebCore/workers/WorkerContext.cpp
+++ b/WebCore/workers/WorkerContext.cpp
@@ -67,7 +67,7 @@
 {
     ASSERT(currentThread() == m_thread->threadID());
 
-    m_thread->workerObjectProxy()->workerContextDestroyed();
+    m_thread->workerObjectProxy().workerContextDestroyed();
 }
 
 ScriptExecutionContext* WorkerContext::scriptExecutionContext() const
@@ -136,12 +136,12 @@
 
 void WorkerContext::reportException(const String& errorMessage, int lineNumber, const String& sourceURL)
 {
-    m_thread->workerObjectProxy()->postExceptionToWorkerObject(errorMessage, lineNumber, sourceURL);
+    m_thread->workerObjectProxy().postExceptionToWorkerObject(errorMessage, lineNumber, sourceURL);
 }
 
 void WorkerContext::addMessage(MessageDestination destination, MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceURL)
 {
-    m_thread->workerObjectProxy()->postConsoleMessageToWorkerObject(destination, source, level, message, lineNumber, sourceURL);
+    m_thread->workerObjectProxy().postConsoleMessageToWorkerObject(destination, source, level, message, lineNumber, sourceURL);
 }
 
 void WorkerContext::resourceRetrievedByXMLHttpRequest(unsigned long, const ScriptString&)
@@ -161,7 +161,7 @@
     if (m_closing)
         return;
 
-    m_thread->workerObjectProxy()->postMessageToWorkerObject(message);
+    m_thread->workerObjectProxy().postMessageToWorkerObject(message);
 }
 
 void WorkerContext::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> eventListener, bool)
diff --git a/WebCore/workers/WorkerLoaderProxy.h b/WebCore/workers/WorkerLoaderProxy.h
new file mode 100644
index 0000000..b51f480
--- /dev/null
+++ b/WebCore/workers/WorkerLoaderProxy.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WorkerLoaderProxy_h
+#define WorkerLoaderProxy_h
+
+#if ENABLE(WORKERS)
+
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+    class ScriptExecutionContext::Task;
+    class String;
+
+    // A proxy to talk to the loader context. Normally, the document on the main thread
+    // provides loading services for the subordinate workers. This interface provides 2-way
+    // communications to the Document context and back to the worker.
+    // Note that in multi-process browsers, the Worker object context and the Document
+    // context can be distinct.
+    class WorkerLoaderProxy {
+    public:
+        virtual ~WorkerLoaderProxy() { }
+
+        // Posts a task to the thread which runs the loading code (normally, the main thread).
+        virtual void postTaskToLoader(PassRefPtr<ScriptExecutionContext::Task>) = 0;
+
+        // Posts callbacks from loading code to the WorkerContext. The 'mode' is used to differentiate
+        // specific synchronous loading requests so they can be 'nested', per spec.
+        virtual void postTaskForModeToWorkerContext(PassRefPtr<ScriptExecutionContext::Task>, const String& mode) = 0;
+    };
+
+} // namespace WebCore
+
+#endif // ENABLE(WORKERS)
+
+#endif // WorkerLoaderProxy_h
diff --git a/WebCore/workers/WorkerMessagingProxy.cpp b/WebCore/workers/WorkerMessagingProxy.cpp
index 07ee4f9..a6d0d5d 100644
--- a/WebCore/workers/WorkerMessagingProxy.cpp
+++ b/WebCore/workers/WorkerMessagingProxy.cpp
@@ -62,7 +62,7 @@
 
         context->dispatchMessage(m_message);
 
-        context->thread()->workerObjectProxy()->confirmMessageFromWorkerObject(context->hasPendingActivity());
+        context->thread()->workerObjectProxy().confirmMessageFromWorkerObject(context->hasPendingActivity());
     }
 
 private:
@@ -200,7 +200,7 @@
 
 void WorkerMessagingProxy::startWorkerContext(const KURL& scriptURL, const String& userAgent, const String& sourceCode)
 {
-    RefPtr<WorkerThread> thread = WorkerThread::create(scriptURL, userAgent, sourceCode, this);
+    RefPtr<WorkerThread> thread = WorkerThread::create(scriptURL, userAgent, sourceCode, *this, *this);
     workerThreadCreated(thread);
     thread->start();
 }
@@ -222,11 +222,6 @@
         m_queuedEarlyTasks.append(MessageWorkerContextTask::create(message));
 }
 
-void WorkerMessagingProxy::postTaskToWorkerContext(PassRefPtr<ScriptExecutionContext::Task> task)
-{
-    postTaskForModeToWorkerContext(task, WorkerRunLoop::defaultMode());
-}
-
 void WorkerMessagingProxy::postTaskForModeToWorkerContext(PassRefPtr<ScriptExecutionContext::Task> task, const String& mode)
 {
     if (m_askedToTerminate)
@@ -236,8 +231,10 @@
     m_workerThread->runLoop().postTaskForMode(task, mode);
 }
 
-void WorkerMessagingProxy::postTaskToWorkerObject(PassRefPtr<ScriptExecutionContext::Task> task)
+void WorkerMessagingProxy::postTaskToLoader(PassRefPtr<ScriptExecutionContext::Task> task)
 {
+    // FIXME: In case of nested workers, this should go directly to the root Document context.
+    ASSERT(m_scriptExecutionContext->isDocument());
     m_scriptExecutionContext->postTask(task);
 }
 
diff --git a/WebCore/workers/WorkerMessagingProxy.h b/WebCore/workers/WorkerMessagingProxy.h
index 8d81deb..7fc9797 100644
--- a/WebCore/workers/WorkerMessagingProxy.h
+++ b/WebCore/workers/WorkerMessagingProxy.h
@@ -31,6 +31,7 @@
 
 #include "ScriptExecutionContext.h"
 #include "WorkerContextProxy.h"
+#include "WorkerLoaderProxy.h"
 #include "WorkerObjectProxy.h"
 #include <wtf/Noncopyable.h>
 #include <wtf/PassRefPtr.h>
@@ -44,7 +45,7 @@
     class Worker;
     class WorkerThread;
 
-    class WorkerMessagingProxy : public WorkerContextProxy, public WorkerObjectProxy, Noncopyable {
+    class WorkerMessagingProxy : public WorkerContextProxy, public WorkerObjectProxy, public WorkerLoaderProxy, Noncopyable {
     public:
         WorkerMessagingProxy(Worker*);
 
@@ -65,9 +66,11 @@
         virtual void reportPendingActivity(bool hasPendingActivity);
         virtual void workerContextDestroyed();
 
-        void postTaskToWorkerObject(PassRefPtr<ScriptExecutionContext::Task>);
-        void postTaskToWorkerContext(PassRefPtr<ScriptExecutionContext::Task>);
-        void postTaskForModeToWorkerContext(PassRefPtr<ScriptExecutionContext::Task>, const String& mode);
+        // Implementation of WorkerLoaderProxy.
+        // These methods are called on different threads to schedule loading
+        // requests and to send callbacks back to WorkerContext.
+        virtual void postTaskToLoader(PassRefPtr<ScriptExecutionContext::Task>);
+        virtual void postTaskForModeToWorkerContext(PassRefPtr<ScriptExecutionContext::Task>, const String& mode);
 
         void workerThreadCreated(PassRefPtr<WorkerThread>);
 
diff --git a/WebCore/workers/WorkerThread.cpp b/WebCore/workers/WorkerThread.cpp
index d1026b1..0745226 100644
--- a/WebCore/workers/WorkerThread.cpp
+++ b/WebCore/workers/WorkerThread.cpp
@@ -62,13 +62,14 @@
 {
 }
 
-PassRefPtr<WorkerThread> WorkerThread::create(const KURL& scriptURL, const String& userAgent, const String& sourceCode, WorkerObjectProxy* workerObjectProxy)
+PassRefPtr<WorkerThread> WorkerThread::create(const KURL& scriptURL, const String& userAgent, const String& sourceCode, WorkerLoaderProxy& workerLoaderProxy, WorkerObjectProxy& workerObjectProxy)
 {
-    return adoptRef(new WorkerThread(scriptURL, userAgent, sourceCode, workerObjectProxy));
+    return adoptRef(new WorkerThread(scriptURL, userAgent, sourceCode, workerLoaderProxy, workerObjectProxy));
 }
 
-WorkerThread::WorkerThread(const KURL& scriptURL, const String& userAgent, const String& sourceCode, WorkerObjectProxy* workerObjectProxy)
+WorkerThread::WorkerThread(const KURL& scriptURL, const String& userAgent, const String& sourceCode, WorkerLoaderProxy& workerLoaderProxy, WorkerObjectProxy& workerObjectProxy)
     : m_threadID(0)
+    , m_workerLoaderProxy(workerLoaderProxy)
     , m_workerObjectProxy(workerObjectProxy)
     , m_startupData(WorkerThreadStartupData::create(scriptURL, userAgent, sourceCode))
 {
@@ -115,7 +116,7 @@
     // WorkerThread::~WorkerThread happens on a different thread where it was created.
     m_startupData.clear();
 
-    m_workerObjectProxy->reportPendingActivity(m_workerContext->hasPendingActivity());
+    m_workerObjectProxy.reportPendingActivity(m_workerContext->hasPendingActivity());
 
     // Blocks until terminated.
     m_runLoop.run(m_workerContext.get());
diff --git a/WebCore/workers/WorkerThread.h b/WebCore/workers/WorkerThread.h
index f1a8a52..8a1ce6c 100644
--- a/WebCore/workers/WorkerThread.h
+++ b/WebCore/workers/WorkerThread.h
@@ -39,12 +39,13 @@
     class KURL;
     class String;
     class WorkerContext;
+    class WorkerLoaderProxy;
     class WorkerObjectProxy;
     struct WorkerThreadStartupData;
 
     class WorkerThread : public RefCounted<WorkerThread> {
     public:
-        static PassRefPtr<WorkerThread> create(const KURL& scriptURL, const String& userAgent, const String& sourceCode, WorkerObjectProxy*);
+        static PassRefPtr<WorkerThread> create(const KURL& scriptURL, const String& userAgent, const String& sourceCode, WorkerLoaderProxy&, WorkerObjectProxy&);
         ~WorkerThread();
 
         bool start();
@@ -52,17 +53,19 @@
 
         ThreadIdentifier threadID() const { return m_threadID; }
         WorkerRunLoop& runLoop() { return m_runLoop; }
-        WorkerObjectProxy* workerObjectProxy() const { return m_workerObjectProxy; }
+        WorkerLoaderProxy& workerLoaderProxy() const { return m_workerLoaderProxy; }
+        WorkerObjectProxy& workerObjectProxy() const { return m_workerObjectProxy; }
 
     private:
-        WorkerThread(const KURL&, const String& userAgent, const String& sourceCode, WorkerObjectProxy*);
+        WorkerThread(const KURL&, const String& userAgent, const String& sourceCode, WorkerLoaderProxy&, WorkerObjectProxy&);
 
         static void* workerThreadStart(void*);
         void* workerThread();
 
         ThreadIdentifier m_threadID;
         WorkerRunLoop m_runLoop;
-        WorkerObjectProxy* m_workerObjectProxy;
+        WorkerLoaderProxy& m_workerLoaderProxy;
+        WorkerObjectProxy& m_workerObjectProxy;
 
         RefPtr<WorkerContext> m_workerContext;
         Mutex m_threadCreationMutex;