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
+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.
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);
}
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)
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();
}
protected:
ThreadableLoaderClientWrapper(ThreadableLoaderClient* client)
: m_client(client)
+ , m_done(false)
{
}
ThreadableLoaderClient* m_client;
+ bool m_done;
};
} // namespace WebCore
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)))
{
}
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));
}
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;
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();
WorkerThreadableLoader(WorkerContext*, ThreadableLoaderClient*, const String& taskMode, const ResourceRequest&, LoadCallbacks, ContentSniff);
RefPtr<WorkerContext> m_workerContext;
+ RefPtr<ThreadableLoaderClientWrapper> m_workerClientWrapper;
MainThreadBridge& m_bridge;
};
WorkerRunLoop::WorkerRunLoop()
: m_sharedTimer(new WorkerSharedTimer)
, m_nestedCount(0)
+ , m_uniqueId(0)
{
}
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:
MessageQueue<RefPtr<Task> > m_messageQueue;
OwnPtr<WorkerSharedTimer> m_sharedTimer;
int m_nestedCount;
+ unsigned long m_uniqueId;
};
} // namespace WebCore
#if ENABLE(WORKERS)
-#include <WorkerRunLoop.h>
+#include "WorkerRunLoop.h"
#include <wtf/OwnPtr.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>