summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-01 20:33:27 +0000
committerjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-01 20:33:27 +0000
commit982e781d80d395cd9749de92d2efd6a309168cd3 (patch)
tree74cb4e36be8cf047c25812649a4f3a2f5325520f
parent52049d5cfde95de013f8f333f940fef4ecd31533 (diff)
downloadchromium_src-982e781d80d395cd9749de92d2efd6a309168cd3.zip
chromium_src-982e781d80d395cd9749de92d2efd6a309168cd3.tar.gz
chromium_src-982e781d80d395cd9749de92d2efd6a309168cd3.tar.bz2
Call WebWorkerClient on the main thread. This makes it consistent with the rest of the WebKit API, which is single threaded. Also a bunch of small fixes to make layout tests pass: the dll was being unloaded while its functions were still queued to be dispatched, and a string allocated in the dll was being GC'd in test shell.
BUG=11011 Review URL: http://codereview.chromium.org/102005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15087 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/worker/webworkerclient_proxy.cc10
-rw-r--r--chrome/worker/webworkerclient_proxy.h5
-rw-r--r--webkit/glue/webworker_impl.cc100
-rw-r--r--webkit/glue/webworker_impl.h43
-rw-r--r--webkit/tools/test_shell/test_webworker_helper.cc31
-rw-r--r--webkit/tools/test_shell/test_webworker_helper.h11
-rw-r--r--webkit/tools/test_shell/test_worker/test_webworker.cc108
-rw-r--r--webkit/tools/test_shell/test_worker/test_worker_main.cc12
8 files changed, 200 insertions, 120 deletions
diff --git a/chrome/worker/webworkerclient_proxy.cc b/chrome/worker/webworkerclient_proxy.cc
index fa2bd39..4e154e2 100644
--- a/chrome/worker/webworkerclient_proxy.cc
+++ b/chrome/worker/webworkerclient_proxy.cc
@@ -20,7 +20,6 @@ WebWorkerClientProxy::WebWorkerClientProxy(const GURL& url, int route_id)
: url_(url),
route_id_(route_id),
ALLOW_THIS_IN_INITIALIZER_LIST(impl_(WebWorker::create(this))) {
- AddRef();
WorkerThread::current()->AddRoute(route_id_, this);
ChildProcess::current()->AddRefProcess();
}
@@ -67,18 +66,11 @@ void WebWorkerClientProxy::reportPendingActivity(bool has_pending_activity) {
void WebWorkerClientProxy::workerContextDestroyed() {
Send(new WorkerHostMsg_WorkerContextDestroyed(route_id_));
- impl_ = NULL;
- WorkerThread::current()->message_loop()->ReleaseSoon(FROM_HERE, this);
+ delete this;
}
bool WebWorkerClientProxy::Send(IPC::Message* message) {
- if (MessageLoop::current() != WorkerThread::current()->message_loop()) {
- WorkerThread::current()->message_loop()->PostTask(FROM_HERE,
- NewRunnableMethod(this, &WebWorkerClientProxy::Send, message));
- return true;
- }
-
return WorkerThread::current()->Send(message);
}
diff --git a/chrome/worker/webworkerclient_proxy.h b/chrome/worker/webworkerclient_proxy.h
index f650d58..ccf9557 100644
--- a/chrome/worker/webworkerclient_proxy.h
+++ b/chrome/worker/webworkerclient_proxy.h
@@ -6,7 +6,6 @@
#define CHROME_WORKER_WEBWORKERCLIENT_PROXY_H_
#include "base/basictypes.h"
-#include "base/ref_counted.h"
#include "chrome/common/ipc_channel.h"
#include "googleurl/src/gurl.h"
#include "third_party/WebKit/WebKit/chromium/public/WebWorkerClient.h"
@@ -21,8 +20,7 @@ class WebWorker;
// IPCs that are sent to the renderer, where they're converted back to function
// calls by WebWorkerProxy.
class WebWorkerClientProxy : public WebKit::WebWorkerClient,
- public IPC::Channel::Listener,
- public base::RefCounted<WebWorkerClientProxy> {
+ public IPC::Channel::Listener {
public:
WebWorkerClientProxy(const GURL& url, int route_id);
@@ -47,7 +45,6 @@ class WebWorkerClientProxy : public WebKit::WebWorkerClient,
virtual void OnMessageReceived(const IPC::Message& message);
private:
- friend class base::RefCounted<WebWorkerClientProxy>;
~WebWorkerClientProxy ();
bool Send(IPC::Message* message);
diff --git a/webkit/glue/webworker_impl.cc b/webkit/glue/webworker_impl.cc
index a8e461d..ba78c7d 100644
--- a/webkit/glue/webworker_impl.cc
+++ b/webkit/glue/webworker_impl.cc
@@ -12,6 +12,7 @@
#include "SecurityOrigin.h"
#include "WorkerContext.h"
#include "WorkerThread.h"
+#include <wtf/MainThread.h>
#include <wtf/Threading.h>
#undef LOG
@@ -106,17 +107,54 @@ void WebWorkerImpl::postMessageToWorkerContext(const WebString& message) {
void WebWorkerImpl::workerObjectDestroyed() {
}
+void WebWorkerImpl::DispatchTaskToMainThread(
+ PassRefPtr<WebCore::ScriptExecutionContext::Task> task) {
+ return WTF::callOnMainThread(InvokeTaskMethod, task.releaseRef());
+}
+
+void WebWorkerImpl::InvokeTaskMethod(void* param) {
+ WebCore::ScriptExecutionContext::Task* task =
+ static_cast<WebCore::ScriptExecutionContext::Task*>(param);
+ task->performTask(NULL);
+ task->deref();
+}
+
// WorkerObjectProxy -----------------------------------------------------------
void WebWorkerImpl::postMessageToWorkerObject(const WebCore::String& message) {
- client_->postMessageToWorkerObject(webkit_glue::StringToWebString(message));
+ DispatchTaskToMainThread(WebCore::createCallbackTask(
+ &PostMessageTask,
+ this,
+ message));
+}
+
+void WebWorkerImpl::PostMessageTask(
+ WebCore::ScriptExecutionContext* context,
+ WebWorkerImpl* this_ptr,
+ WebCore::String message) {
+ this_ptr->client_->postMessageToWorkerObject(
+ webkit_glue::StringToWebString(message));
}
void WebWorkerImpl::postExceptionToWorkerObject(
const WebCore::String& error_message,
int line_number,
const WebCore::String& source_url) {
- client_->postExceptionToWorkerObject(
+ DispatchTaskToMainThread(WebCore::createCallbackTask(
+ &PostExceptionTask,
+ this,
+ error_message,
+ line_number,
+ source_url));
+}
+
+void WebWorkerImpl::PostExceptionTask(
+ WebCore::ScriptExecutionContext* context,
+ WebWorkerImpl* this_ptr,
+ const WebCore::String& error_message,
+ int line_number,
+ const WebCore::String& source_url) {
+ this_ptr->client_->postExceptionToWorkerObject(
webkit_glue::StringToWebString(error_message),
line_number,
webkit_glue::StringToWebString(source_url));
@@ -129,28 +167,76 @@ void WebWorkerImpl::postConsoleMessageToWorkerObject(
const WebCore::String& message,
int line_number,
const WebCore::String& source_url) {
- client_->postConsoleMessageToWorkerObject(
+ DispatchTaskToMainThread(WebCore::createCallbackTask(
+ &PostConsoleMessageTask,
+ this,
static_cast<int>(destination),
static_cast<int>(source),
static_cast<int>(level),
+ message,
+ line_number,
+ source_url));
+}
+
+void WebWorkerImpl::PostConsoleMessageTask(
+ WebCore::ScriptExecutionContext* context,
+ WebWorkerImpl* this_ptr,
+ int destination,
+ int source,
+ int level,
+ const WebCore::String& message,
+ int line_number,
+ const WebCore::String& source_url) {
+ this_ptr->client_->postConsoleMessageToWorkerObject(
+ destination,
+ source,
+ level,
webkit_glue::StringToWebString(message),
line_number,
webkit_glue::StringToWebString(source_url));
}
void WebWorkerImpl::confirmMessageFromWorkerObject(bool has_pending_activity) {
- client_->confirmMessageFromWorkerObject(has_pending_activity);
+ DispatchTaskToMainThread(WebCore::createCallbackTask(
+ &ConfirmMessageTask,
+ this,
+ has_pending_activity));
+}
+
+void WebWorkerImpl::ConfirmMessageTask(
+ WebCore::ScriptExecutionContext* context,
+ WebWorkerImpl* this_ptr,
+ bool has_pending_activity) {
+ this_ptr->client_->confirmMessageFromWorkerObject(has_pending_activity);
}
void WebWorkerImpl::reportPendingActivity(bool has_pending_activity) {
- client_->reportPendingActivity(has_pending_activity);
+ DispatchTaskToMainThread(WebCore::createCallbackTask(
+ &ReportPendingActivityTask,
+ this,
+ has_pending_activity));
+}
+
+void WebWorkerImpl::ReportPendingActivityTask(
+ WebCore::ScriptExecutionContext* context,
+ WebWorkerImpl* this_ptr,
+ bool has_pending_activity) {
+ this_ptr->client_->reportPendingActivity(has_pending_activity);
}
void WebWorkerImpl::workerContextDestroyed() {
- client_->workerContextDestroyed();
+ DispatchTaskToMainThread(WebCore::createCallbackTask(
+ &WorkerContextDestroyedTask,
+ this));
+}
+
+void WebWorkerImpl::WorkerContextDestroyedTask(
+ WebCore::ScriptExecutionContext* context,
+ WebWorkerImpl* this_ptr) {
+ this_ptr->client_->workerContextDestroyed();
// The lifetime of this proxy is controlled by the worker context.
- delete this;
+ delete this_ptr;
}
#else
diff --git a/webkit/glue/webworker_impl.h b/webkit/glue/webworker_impl.h
index 8ae78c6..bfdd26a 100644
--- a/webkit/glue/webworker_impl.h
+++ b/webkit/glue/webworker_impl.h
@@ -29,7 +29,6 @@ class WebWorkerImpl: public WebCore::WorkerObjectProxy,
public WebKit::WebWorker {
public:
explicit WebWorkerImpl(WebKit::WebWorkerClient* client);
- virtual ~WebWorkerImpl();
// WebCore::WorkerObjectProxy methods:
virtual void postMessageToWorkerObject(const WebCore::String& message);
@@ -56,12 +55,54 @@ class WebWorkerImpl: public WebCore::WorkerObjectProxy,
virtual void postMessageToWorkerContext(const WebKit::WebString& message);
virtual void workerObjectDestroyed();
+ // Executes the given task on the main thread.
+ static void DispatchTaskToMainThread(
+ PassRefPtr<WebCore::ScriptExecutionContext::Task> task);
+
private:
+ virtual ~WebWorkerImpl();
+
+ // Tasks that are run on the worker thread.
static void PostMessageToWorkerContextTask(
WebCore::ScriptExecutionContext* context,
WebWorkerImpl* this_ptr,
const WebCore::String& message);
+ // Function used to invoke tasks on the main thread.
+ static void InvokeTaskMethod(void* param);
+
+ // Tasks that are run on the main thread.
+ static void PostMessageTask(
+ WebCore::ScriptExecutionContext* context,
+ WebWorkerImpl* this_ptr,
+ WebCore::String message);
+ static void PostExceptionTask(
+ WebCore::ScriptExecutionContext* context,
+ WebWorkerImpl* this_ptr,
+ const WebCore::String& error_message,
+ int line_number,
+ const WebCore::String& source_url);
+ static void PostConsoleMessageTask(
+ WebCore::ScriptExecutionContext* context,
+ WebWorkerImpl* this_ptr,
+ int destination,
+ int source,
+ int level,
+ const WebCore::String& message,
+ int line_number,
+ const WebCore::String& source_url);
+ static void ConfirmMessageTask(
+ WebCore::ScriptExecutionContext* context,
+ WebWorkerImpl* this_ptr,
+ bool has_pending_activity);
+ static void ReportPendingActivityTask(
+ WebCore::ScriptExecutionContext* context,
+ WebWorkerImpl* this_ptr,
+ bool has_pending_activity);
+ static void WorkerContextDestroyedTask(
+ WebCore::ScriptExecutionContext* context,
+ WebWorkerImpl* this_ptr);
+
WebKit::WebWorkerClient* client_;
WTF::RefPtr<WebCore::WorkerThread> worker_thread_;
diff --git a/webkit/tools/test_shell/test_webworker_helper.cc b/webkit/tools/test_shell/test_webworker_helper.cc
index 6cf309c..20a8d4e 100644
--- a/webkit/tools/test_shell/test_webworker_helper.cc
+++ b/webkit/tools/test_shell/test_webworker_helper.cc
@@ -19,33 +19,34 @@
#include "base/file_util.h"
#include "base/path_service.h"
#include "third_party/WebKit/WebKit/chromium/public/WebKit.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebKitClient.h"
using WebKit::WebWorker;
using WebKit::WebWorkerClient;
+static TestWebWorkerHelper* g_helper;
+
WebWorker* TestWebWorkerHelper::CreateWebWorker(WebWorkerClient* client) {
- TestWebWorkerHelper* loader = new TestWebWorkerHelper();
- return loader->CreateWebWorker_(client, loader);
+ if (!g_helper)
+ g_helper = new TestWebWorkerHelper();
+ g_helper->worker_count_++;
+ return g_helper->CreateWebWorker_(client, g_helper);
}
TestWebWorkerHelper::TestWebWorkerHelper() :
#if defined(OS_WIN)
module_(NULL),
#endif
- CreateWebWorker_(NULL) {
+ CreateWebWorker_(NULL),
+ worker_count_(0) {
Load();
}
TestWebWorkerHelper::~TestWebWorkerHelper() {
}
-bool TestWebWorkerHelper::IsMainThread() const {
- return WTF::isMainThread();
-}
-
-void TestWebWorkerHelper::DispatchToMainThread(WTF::MainThreadFunction* func,
- void* context) {
- return WTF::callOnMainThread(func, context);
+void TestWebWorkerHelper::DispatchToMainThread(void (*func)()) {
+ WebKit::webKitClient()->callOnMainThread(func);
}
void TestWebWorkerHelper::Load() {
@@ -84,13 +85,22 @@ void TestWebWorkerHelper::Load() {
}
void TestWebWorkerHelper::Unload() {
+ DCHECK(worker_count_);
+ worker_count_--;
// Since this is called from DLL, delay the unloading until it can be
// invoked from EXE.
return WTF::callOnMainThread(UnloadHelper, this);
}
+WebKit::WebString TestWebWorkerHelper::DuplicateString(
+ const WebKit::WebString& string) {
+ return WebKit::WebString(string.data(), string.length());
+}
+
void TestWebWorkerHelper::UnloadHelper(void* param) {
TestWebWorkerHelper* this_ptr = static_cast<TestWebWorkerHelper*>(param);
+ if (this_ptr->worker_count_)
+ return;
#if defined(OS_WIN)
if (this_ptr->module_) {
@@ -108,4 +118,5 @@ void TestWebWorkerHelper::UnloadHelper(void* param) {
#endif
delete this_ptr;
+ g_helper = NULL;
}
diff --git a/webkit/tools/test_shell/test_webworker_helper.h b/webkit/tools/test_shell/test_webworker_helper.h
index 6770678..951950b 100644
--- a/webkit/tools/test_shell/test_webworker_helper.h
+++ b/webkit/tools/test_shell/test_webworker_helper.h
@@ -12,12 +12,14 @@
#include "base/basictypes.h"
#include "base/port.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
#include <wtf/MainThread.h>
class TestWebWorkerHelper;
namespace WebKit {
+class WebKitClient;
class WebWorker;
class WebWorkerClient;
}
@@ -32,14 +34,14 @@ class TestWebWorkerHelper {
static WebKit::WebWorker* CreateWebWorker(WebKit::WebWorkerClient* client);
TestWebWorkerHelper();
- ~TestWebWorkerHelper();
- virtual bool IsMainThread() const;
- virtual void DispatchToMainThread(WTF::MainThreadFunction* func,
- void* context);
+ virtual void DispatchToMainThread(void (*func)());
virtual void Unload();
+ virtual WebKit::WebString DuplicateString(const WebKit::WebString& string);
+
private:
+ ~TestWebWorkerHelper();
void Load();
static void UnloadHelper(void* param);
@@ -51,6 +53,7 @@ class TestWebWorkerHelper {
#endif
CreateWebWorkerFunc CreateWebWorker_;
+ int worker_count_;
DISALLOW_COPY_AND_ASSIGN(TestWebWorkerHelper);
};
diff --git a/webkit/tools/test_shell/test_worker/test_webworker.cc b/webkit/tools/test_shell/test_worker/test_webworker.cc
index 6b073b5..29733b4 100644
--- a/webkit/tools/test_shell/test_worker/test_webworker.cc
+++ b/webkit/tools/test_shell/test_worker/test_webworker.cc
@@ -19,21 +19,6 @@ using WebKit::WebURL;
using WebKit::WebWorker;
using WebKit::WebWorkerClient;
-// We use this class to pass a WebString between threads. This works by
-// copying to a string16 which is itself safe to pass between threads.
-// TODO(jam): Remove this once all worker callbacks happen on the main thread.
-class ThreadSafeWebString {
- public:
- explicit ThreadSafeWebString(const WebString& str)
- : str_(str) {
- }
- operator WebString() const {
- return str_;
- }
- private:
- string16 str_;
-};
-
TestWebWorker::TestWebWorker(WebWorkerClient* client,
TestWebWorkerHelper* webworker_helper)
: webworkerclient_delegate_(client),
@@ -81,32 +66,22 @@ void TestWebWorker::workerObjectDestroyed() {
}
void TestWebWorker::postMessageToWorkerObject(const WebString& message) {
- if (webworker_helper_->IsMainThread()) {
- if (webworkerclient_delegate_)
- webworkerclient_delegate_->postMessageToWorkerObject(message);
- } else {
- webworker_helper_->DispatchToMainThread(
- InvokeMainThreadMethod, NewRunnableMethod(
- this, &TestWebWorker::postMessageToWorkerObject,
- ThreadSafeWebString(message)));
- }
+ if (!webworkerclient_delegate_)
+ return;
+ // The string was created in the dll's memory space as a result of a postTask.
+ // If we pass it to test shell's memory space, it'll cause problems when GC
+ // occurs. So duplicate it from the test shell's memory space first.
+ webworkerclient_delegate_->postMessageToWorkerObject(
+ webworker_helper_->DuplicateString(message));
}
void TestWebWorker::postExceptionToWorkerObject(const WebString& error_message,
int line_number,
const WebString& source_url) {
- if (webworker_helper_->IsMainThread()) {
- if (webworkerclient_delegate_)
- webworkerclient_delegate_->postExceptionToWorkerObject(error_message,
- line_number,
- source_url);
- } else {
- webworker_helper_->DispatchToMainThread(
- InvokeMainThreadMethod, NewRunnableMethod(
- this, &TestWebWorker::postExceptionToWorkerObject,
- ThreadSafeWebString(error_message), line_number,
- ThreadSafeWebString(source_url)));
- }
+ if (webworkerclient_delegate_)
+ webworkerclient_delegate_->postExceptionToWorkerObject(error_message,
+ line_number,
+ source_url);
}
void TestWebWorker::postConsoleMessageToWorkerObject(
@@ -116,63 +91,28 @@ void TestWebWorker::postConsoleMessageToWorkerObject(
const WebString& message,
int line_number,
const WebString& source_url) {
- if (webworker_helper_->IsMainThread()) {
- if (webworkerclient_delegate_)
- webworkerclient_delegate_->postConsoleMessageToWorkerObject(
- destination_id, source_id, message_level, message, line_number,
- source_url);
- } else {
- webworker_helper_->DispatchToMainThread(
- InvokeMainThreadMethod, NewRunnableMethod(
- this, &TestWebWorker::postConsoleMessageToWorkerObject,
- destination_id, source_id, message_level,
- ThreadSafeWebString(message), line_number,
- ThreadSafeWebString(source_url)));
- }
+ if (webworkerclient_delegate_)
+ webworkerclient_delegate_->postConsoleMessageToWorkerObject(
+ destination_id, source_id, message_level, message, line_number,
+ source_url);
}
void TestWebWorker::confirmMessageFromWorkerObject(bool has_pending_activity) {
- if (webworker_helper_->IsMainThread()) {
- if (webworkerclient_delegate_)
- webworkerclient_delegate_->confirmMessageFromWorkerObject(
- has_pending_activity);
- } else {
- webworker_helper_->DispatchToMainThread(
- InvokeMainThreadMethod, NewRunnableMethod(
- this, &TestWebWorker::confirmMessageFromWorkerObject,
- has_pending_activity));
- }
+ if (webworkerclient_delegate_)
+ webworkerclient_delegate_->confirmMessageFromWorkerObject(
+ has_pending_activity);
}
void TestWebWorker::reportPendingActivity(bool has_pending_activity) {
- if (webworker_helper_->IsMainThread()) {
- if (webworkerclient_delegate_)
- webworkerclient_delegate_->reportPendingActivity(has_pending_activity);
- } else {
- webworker_helper_->DispatchToMainThread(
- InvokeMainThreadMethod, NewRunnableMethod(
- this, &TestWebWorker::reportPendingActivity,
- has_pending_activity));
- }
+ if (webworkerclient_delegate_)
+ webworkerclient_delegate_->reportPendingActivity(has_pending_activity);
}
void TestWebWorker::workerContextDestroyed() {
- if (webworker_helper_->IsMainThread()) {
- if (webworkerclient_delegate_)
- webworkerclient_delegate_->workerContextDestroyed();
- Release(); // Releases the reference held for worker context object.
- } else {
- webworker_impl_ = NULL;
- webworker_helper_->DispatchToMainThread(
- InvokeMainThreadMethod, NewRunnableMethod(
- this, &TestWebWorker::workerContextDestroyed));
- }
-}
-
-void TestWebWorker::InvokeMainThreadMethod(void* param) {
- Task* task = static_cast<Task*>(param);
- task->Run();
- delete task;
+ webworker_impl_ = NULL;
+ if (webworkerclient_delegate_)
+ webworkerclient_delegate_->workerContextDestroyed();
+ Release(); // Releases the reference held for worker context object.
}
#endif
diff --git a/webkit/tools/test_shell/test_worker/test_worker_main.cc b/webkit/tools/test_shell/test_worker/test_worker_main.cc
index 6695a11..9273d35 100644
--- a/webkit/tools/test_shell/test_worker/test_worker_main.cc
+++ b/webkit/tools/test_shell/test_worker/test_worker_main.cc
@@ -29,6 +29,9 @@ static base::AtExitManager global_at_exit_manager;
// Stub WebKit Client.
class WorkerWebKitClientImpl : public webkit_glue::WebKitClientImpl {
public:
+ explicit WorkerWebKitClientImpl(TestWebWorkerHelper* helper)
+ : helper_(helper) { }
+
// WebKitClient methods:
virtual WebKit::WebClipboard* clipboard() {
NOTREACHED();
@@ -76,6 +79,13 @@ class WorkerWebKitClientImpl : public webkit_glue::WebKitClientImpl {
NOTREACHED();
return WebKit::WebString();
}
+
+ virtual void callOnMainThread(void (*func)()) {
+ helper_->DispatchToMainThread(func);
+ }
+
+ private:
+ TestWebWorkerHelper* helper_;
};
// WebKit client used in DLL.
@@ -89,7 +99,7 @@ extern "C" {
WebWorker* API_CALL CreateWebWorker(WebWorkerClient* webworker_client,
TestWebWorkerHelper* webworker_helper) {
if (!WebKit::webKitClient()) {
- webkit_client.reset(new WorkerWebKitClientImpl());
+ webkit_client.reset(new WorkerWebKitClientImpl(webworker_helper));
WebKit::initialize(webkit_client.get());
}