summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-14 16:21:05 +0000
committerjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-14 16:21:05 +0000
commit6e07d8b7d3b054975a2e717a5d0a6e60bc0c9444 (patch)
treecf8cb65ab8ffa28c7165b1e9400f9918bdb4c712 /content
parent5558fffd6a542a5eb0260ff4866ed9388438704b (diff)
downloadchromium_src-6e07d8b7d3b054975a2e717a5d0a6e60bc0c9444.zip
chromium_src-6e07d8b7d3b054975a2e717a5d0a6e60bc0c9444.tar.gz
chromium_src-6e07d8b7d3b054975a2e717a5d0a6e60bc0c9444.tar.bz2
Move worker code from chrome\worker to content\worker.
TBR=atwilson Review URL: http://codereview.chromium.org/6691004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@78039 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/content.gyp1
-rw-r--r--content/content_worker.gypi39
-rw-r--r--content/worker/DEPS8
-rw-r--r--content/worker/websharedworker_stub.cc90
-rw-r--r--content/worker/websharedworker_stub.h50
-rw-r--r--content/worker/webworker_stub.cc73
-rw-r--r--content/worker/webworker_stub.h44
-rw-r--r--content/worker/webworker_stub_base.cc40
-rw-r--r--content/worker/webworker_stub_base.h48
-rw-r--r--content/worker/webworkerclient_proxy.cc200
-rw-r--r--content/worker/webworkerclient_proxy.h100
-rw-r--r--content/worker/worker_main.cc55
-rw-r--r--content/worker/worker_thread.cc127
-rw-r--r--content/worker/worker_thread.h54
-rw-r--r--content/worker/worker_uitest.cc772
-rw-r--r--content/worker/worker_webapplicationcachehost_impl.cc27
-rw-r--r--content/worker/worker_webapplicationcachehost_impl.h51
-rw-r--r--content/worker/worker_webkitclient_impl.cc258
-rw-r--r--content/worker/worker_webkitclient_impl.h89
19 files changed, 2126 insertions, 0 deletions
diff --git a/content/content.gyp b/content/content.gyp
index 936469f..cc3fe6a 100644
--- a/content/content.gyp
+++ b/content/content.gyp
@@ -10,5 +10,6 @@
'content_browser.gypi',
'content_common.gypi',
'content_gpu.gypi',
+ 'content_worker.gypi',
],
}
diff --git a/content/content_worker.gypi b/content/content_worker.gypi
new file mode 100644
index 0000000..fa1d504
--- /dev/null
+++ b/content/content_worker.gypi
@@ -0,0 +1,39 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'content_worker',
+ 'type': '<(library)',
+ 'msvs_guid': 'C78D02D0-A366-4EC6-A248-AA8E64C4BA18',
+ 'dependencies': [
+ 'content_common',
+ '../base/base.gyp:base',
+ '../skia/skia.gyp:skia',
+ '../third_party/WebKit/Source/WebKit/chromium/WebKit.gyp:webkit',
+ ],
+ 'sources': [
+ 'worker/websharedworker_stub.cc',
+ 'worker/websharedworker_stub.h',
+ 'worker/webworker_stub_base.cc',
+ 'worker/webworker_stub_base.h',
+ 'worker/webworker_stub.cc',
+ 'worker/webworker_stub.h',
+ 'worker/webworkerclient_proxy.cc',
+ 'worker/webworkerclient_proxy.h',
+ 'worker/worker_main.cc',
+ 'worker/worker_thread.cc',
+ 'worker/worker_thread.h',
+ 'worker/worker_webapplicationcachehost_impl.cc',
+ 'worker/worker_webapplicationcachehost_impl.h',
+ 'worker/worker_webkitclient_impl.cc',
+ 'worker/worker_webkitclient_impl.h',
+ ],
+ 'include_dirs': [
+ '..',
+ ],
+ },
+ ],
+}
diff --git a/content/worker/DEPS b/content/worker/DEPS
new file mode 100644
index 0000000..31730d3
--- /dev/null
+++ b/content/worker/DEPS
@@ -0,0 +1,8 @@
+include_rules = [
+ "+chrome/app", # For UI test
+ "+chrome/browser/worker_host", # For UI test.
+ "+sandbox/src",
+ "+webkit/appcache",
+ "+webkit/glue",
+]
+
diff --git a/content/worker/websharedworker_stub.cc b/content/worker/websharedworker_stub.cc
new file mode 100644
index 0000000..3ecf598
--- /dev/null
+++ b/content/worker/websharedworker_stub.cc
@@ -0,0 +1,90 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/worker/websharedworker_stub.h"
+
+#include "content/common/child_thread.h"
+#include "content/common/file_system/file_system_dispatcher.h"
+#include "content/common/webmessageportchannel_impl.h"
+#include "content/common/worker_messages.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSharedWorker.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
+
+WebSharedWorkerStub::WebSharedWorkerStub(
+ const string16& name, int route_id,
+ const WorkerAppCacheInitInfo& appcache_init_info)
+ : WebWorkerStubBase(route_id, appcache_init_info),
+ name_(name),
+ started_(false) {
+ // TODO(atwilson): Add support for NaCl when they support MessagePorts.
+ impl_ = WebKit::WebSharedWorker::create(client());
+}
+
+WebSharedWorkerStub::~WebSharedWorkerStub() {
+ impl_->clientDestroyed();
+}
+
+bool WebSharedWorkerStub::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(WebSharedWorkerStub, message)
+ IPC_MESSAGE_HANDLER(WorkerMsg_StartWorkerContext, OnStartWorkerContext)
+ IPC_MESSAGE_HANDLER(WorkerMsg_TerminateWorkerContext,
+ OnTerminateWorkerContext)
+ IPC_MESSAGE_HANDLER(WorkerMsg_Connect, OnConnect)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void WebSharedWorkerStub::OnChannelError() {
+ OnTerminateWorkerContext();
+}
+
+const GURL& WebSharedWorkerStub::url() const {
+ return url_;
+}
+
+void WebSharedWorkerStub::OnStartWorkerContext(
+ const GURL& url, const string16& user_agent, const string16& source_code) {
+ // Ignore multiple attempts to start this worker (can happen if two pages
+ // try to start it simultaneously).
+ if (started_)
+ return;
+
+ impl_->startWorkerContext(url, name_, user_agent, source_code, 0);
+ started_ = true;
+ url_ = url;
+
+ // Process any pending connections.
+ for (PendingConnectInfoList::const_iterator iter = pending_connects_.begin();
+ iter != pending_connects_.end();
+ ++iter) {
+ OnConnect(iter->first, iter->second);
+ }
+ pending_connects_.clear();
+}
+
+void WebSharedWorkerStub::OnConnect(int sent_message_port_id, int routing_id) {
+ if (started_) {
+ WebKit::WebMessagePortChannel* channel =
+ new WebMessagePortChannelImpl(routing_id, sent_message_port_id);
+ impl_->connect(channel, NULL);
+ } else {
+ // If two documents try to load a SharedWorker at the same time, the
+ // WorkerMsg_Connect for one of the documents can come in before the
+ // worker is started. Just queue up the connect and deliver it once the
+ // worker starts.
+ PendingConnectInfo pending_connect(sent_message_port_id, routing_id);
+ pending_connects_.push_back(pending_connect);
+ }
+}
+
+void WebSharedWorkerStub::OnTerminateWorkerContext() {
+ impl_->terminateWorkerContext();
+
+ // Call the client to make sure context exits.
+ EnsureWorkerContextTerminates();
+ started_ = false;
+}
diff --git a/content/worker/websharedworker_stub.h b/content/worker/websharedworker_stub.h
new file mode 100644
index 0000000..6083460
--- /dev/null
+++ b/content/worker/websharedworker_stub.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_WORKER_WEBSHAREDWORKER_STUB_H_
+#define CONTENT_WORKER_WEBSHAREDWORKER_STUB_H_
+#pragma once
+
+#include "content/worker/webworker_stub_base.h"
+#include "content/worker/webworkerclient_proxy.h"
+#include "googleurl/src/gurl.h"
+
+namespace WebKit {
+class WebSharedWorker;
+}
+
+// This class creates a WebSharedWorker, and translates incoming IPCs to the
+// appropriate WebSharedWorker APIs.
+class WebSharedWorkerStub : public WebWorkerStubBase {
+ public:
+ WebSharedWorkerStub(const string16& name, int route_id,
+ const WorkerAppCacheInitInfo& appcache_init_info);
+
+ // IPC::Channel::Listener implementation.
+ virtual bool OnMessageReceived(const IPC::Message& message);
+ virtual void OnChannelError();
+
+ virtual const GURL& url() const;
+
+ private:
+ virtual ~WebSharedWorkerStub();
+
+ void OnConnect(int sent_message_port_id, int routing_id);
+ void OnStartWorkerContext(
+ const GURL& url, const string16& user_agent, const string16& source_code);
+ void OnTerminateWorkerContext();
+
+ WebKit::WebSharedWorker* impl_;
+ string16 name_;
+ bool started_;
+ GURL url_;
+
+ typedef std::pair<int, int> PendingConnectInfo;
+ typedef std::vector<PendingConnectInfo> PendingConnectInfoList;
+ PendingConnectInfoList pending_connects_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebSharedWorkerStub);
+};
+
+#endif // CONTENT_WORKER_WEBSHAREDWORKER_STUB_H_
diff --git a/content/worker/webworker_stub.cc b/content/worker/webworker_stub.cc
new file mode 100644
index 0000000..1cf7fdb
--- /dev/null
+++ b/content/worker/webworker_stub.cc
@@ -0,0 +1,73 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/worker/webworker_stub.h"
+
+#include "base/command_line.h"
+#include "content/common/child_thread.h"
+#include "content/common/file_system/file_system_dispatcher.h"
+#include "content/common/webmessageportchannel_impl.h"
+#include "content/common/worker_messages.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebWorker.h"
+
+using WebKit::WebWorker;
+
+WebWorkerStub::WebWorkerStub(const GURL& url, int route_id,
+ const WorkerAppCacheInitInfo& appcache_init_info)
+ : WebWorkerStubBase(route_id, appcache_init_info),
+ ALLOW_THIS_IN_INITIALIZER_LIST(impl_(WebWorker::create(client()))),
+ url_(url) {
+}
+
+WebWorkerStub::~WebWorkerStub() {
+ impl_->clientDestroyed();
+}
+
+void WebWorkerStub::OnChannelError() {
+ OnTerminateWorkerContext();
+}
+
+const GURL& WebWorkerStub::url() const {
+ return url_;
+}
+
+bool WebWorkerStub::OnMessageReceived(const IPC::Message& message) {
+ if (!impl_)
+ return false;
+
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(WebWorkerStub, message)
+ IPC_MESSAGE_FORWARD(WorkerMsg_StartWorkerContext, impl_,
+ WebWorker::startWorkerContext)
+ IPC_MESSAGE_HANDLER(WorkerMsg_TerminateWorkerContext,
+ OnTerminateWorkerContext)
+ IPC_MESSAGE_HANDLER(WorkerMsg_PostMessage, OnPostMessage)
+ IPC_MESSAGE_FORWARD(WorkerMsg_WorkerObjectDestroyed, impl_,
+ WebWorker::workerObjectDestroyed)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void WebWorkerStub::OnTerminateWorkerContext() {
+ impl_->terminateWorkerContext();
+
+ // Call the client to make sure context exits.
+ EnsureWorkerContextTerminates();
+}
+
+void WebWorkerStub::OnPostMessage(
+ const string16& message,
+ const std::vector<int>& sent_message_port_ids,
+ const std::vector<int>& new_routing_ids) {
+ WebKit::WebMessagePortChannelArray channels(sent_message_port_ids.size());
+ for (size_t i = 0; i < sent_message_port_ids.size(); i++) {
+ channels[i] = new WebMessagePortChannelImpl(
+ new_routing_ids[i], sent_message_port_ids[i]);
+ }
+
+ impl_->postMessageToWorkerContext(message, channels);
+}
diff --git a/content/worker/webworker_stub.h b/content/worker/webworker_stub.h
new file mode 100644
index 0000000..ff93cdd
--- /dev/null
+++ b/content/worker/webworker_stub.h
@@ -0,0 +1,44 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_WORKER_WEBWORKER_STUB_H_
+#define CONTENT_WORKER_WEBWORKER_STUB_H_
+#pragma once
+
+#include "content/worker/webworker_stub_base.h"
+#include "content/worker/webworkerclient_proxy.h"
+#include "googleurl/src/gurl.h"
+
+namespace WebKit {
+class WebWorker;
+}
+
+// This class creates a WebWorker, and translates incoming IPCs to the
+// appropriate WebWorker APIs.
+class WebWorkerStub : public WebWorkerStubBase {
+ public:
+ WebWorkerStub(const GURL& url, int route_id,
+ const WorkerAppCacheInitInfo& appcache_init_info);
+
+ // IPC::Channel::Listener implementation.
+ virtual bool OnMessageReceived(const IPC::Message& message);
+ virtual void OnChannelError();
+
+ virtual const GURL& url() const;
+
+ private:
+ virtual ~WebWorkerStub();
+
+ void OnTerminateWorkerContext();
+ void OnPostMessage(const string16& message,
+ const std::vector<int>& sent_message_port_ids,
+ const std::vector<int>& new_routing_ids);
+
+ WebKit::WebWorker* impl_;
+ GURL url_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebWorkerStub);
+};
+
+#endif // CONTENT_WORKER_WEBWORKER_STUB_H_
diff --git a/content/worker/webworker_stub_base.cc b/content/worker/webworker_stub_base.cc
new file mode 100644
index 0000000..c5232a3
--- /dev/null
+++ b/content/worker/webworker_stub_base.cc
@@ -0,0 +1,40 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/worker/webworker_stub_base.h"
+
+#include "base/compiler_specific.h"
+#include "content/common/child_process.h"
+#include "content/worker/worker_thread.h"
+
+WebWorkerStubBase::WebWorkerStubBase(
+ int route_id, const WorkerAppCacheInitInfo& appcache_init_info)
+ : route_id_(route_id),
+ appcache_init_info_(appcache_init_info),
+ ALLOW_THIS_IN_INITIALIZER_LIST(client_(route_id, this)) {
+
+ WorkerThread* workerThread = WorkerThread::current();
+ DCHECK(workerThread);
+ workerThread->AddWorkerStub(this);
+ // Start processing incoming IPCs for this worker.
+ workerThread->AddRoute(route_id_, this);
+ ChildProcess::current()->AddRefProcess();
+}
+
+WebWorkerStubBase::~WebWorkerStubBase() {
+ WorkerThread* workerThread = WorkerThread::current();
+ DCHECK(workerThread);
+ workerThread->RemoveWorkerStub(this);
+ workerThread->RemoveRoute(route_id_);
+ ChildProcess::current()->ReleaseProcess();
+}
+
+void WebWorkerStubBase::Shutdown() {
+ // The worker has exited - free ourselves and the client.
+ delete this;
+}
+
+void WebWorkerStubBase::EnsureWorkerContextTerminates() {
+ client_.EnsureWorkerContextTerminates();
+}
diff --git a/content/worker/webworker_stub_base.h b/content/worker/webworker_stub_base.h
new file mode 100644
index 0000000..a57e3ff
--- /dev/null
+++ b/content/worker/webworker_stub_base.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_WORKER_WEBWORKER_STUB_BASE_H_
+#define CONTENT_WORKER_WEBWORKER_STUB_BASE_H_
+#pragma once
+
+#include "base/scoped_ptr.h"
+#include "content/worker/webworkerclient_proxy.h"
+#include "content/worker/worker_webapplicationcachehost_impl.h"
+#include "ipc/ipc_channel.h"
+
+// This class is the common base class for both WebWorkerStub and
+// WebSharedWorkerStub and contains common setup/teardown functionality.
+class WebWorkerStubBase : public IPC::Channel::Listener {
+ public:
+ WebWorkerStubBase(int route_id,
+ const WorkerAppCacheInitInfo& appcache_init_info);
+ virtual ~WebWorkerStubBase();
+
+ // Invoked when the WebWorkerClientProxy is shutting down.
+ void Shutdown();
+
+ // Called after terminating the worker context to make sure that the worker
+ // actually terminates (is not stuck in an infinite loop).
+ void EnsureWorkerContextTerminates();
+
+ WebWorkerClientProxy* client() { return &client_; }
+
+ const WorkerAppCacheInitInfo& appcache_init_info() const {
+ return appcache_init_info_;
+ }
+
+ // Returns the script url of this worker.
+ virtual const GURL& url() const = 0;
+
+ private:
+ int route_id_;
+ WorkerAppCacheInitInfo appcache_init_info_;
+
+ // WebWorkerClient that responds to outgoing API calls from the worker object.
+ WebWorkerClientProxy client_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebWorkerStubBase);
+};
+
+#endif // CONTENT_WORKER_WEBWORKER_STUB_BASE_H_
diff --git a/content/worker/webworkerclient_proxy.cc b/content/worker/webworkerclient_proxy.cc
new file mode 100644
index 0000000..d3c7334
--- /dev/null
+++ b/content/worker/webworkerclient_proxy.cc
@@ -0,0 +1,200 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/worker/webworkerclient_proxy.h"
+
+#include "base/command_line.h"
+#include "base/message_loop.h"
+#include "content/common/content_switches.h"
+#include "content/common/file_system/file_system_dispatcher.h"
+#include "content/common/file_system/webfilesystem_callback_dispatcher.h"
+#include "content/common/webmessageportchannel_impl.h"
+#include "content/common/worker_messages.h"
+// TODO(jam): uncomment this and WebWorkerClientProxy::createWorker when the
+// renderer worker code moves to content. This code isn't used now since we
+// don't support nested workers anyways.
+//#include "content/renderer/webworker_proxy.h"
+#include "content/worker/webworker_stub_base.h"
+#include "content/worker/worker_thread.h"
+#include "content/worker/worker_webapplicationcachehost_impl.h"
+#include "ipc/ipc_logging.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileSystemCallbacks.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebWorker.h"
+
+using WebKit::WebApplicationCacheHost;
+using WebKit::WebFrame;
+using WebKit::WebMessagePortChannel;
+using WebKit::WebMessagePortChannelArray;
+using WebKit::WebSecurityOrigin;
+using WebKit::WebString;
+using WebKit::WebWorker;
+using WebKit::WebWorkerClient;
+
+// How long to wait for worker to finish after it's been told to terminate.
+#define kMaxTimeForRunawayWorkerMs 3000
+
+WebWorkerClientProxy::WebWorkerClientProxy(int route_id,
+ WebWorkerStubBase* stub)
+ : route_id_(route_id),
+ appcache_host_id_(0),
+ stub_(stub),
+ ALLOW_THIS_IN_INITIALIZER_LIST(kill_process_factory_(this)) {
+}
+
+WebWorkerClientProxy::~WebWorkerClientProxy() {
+}
+
+void WebWorkerClientProxy::postMessageToWorkerObject(
+ const WebString& message,
+ const WebMessagePortChannelArray& channels) {
+ std::vector<int> message_port_ids(channels.size());
+ std::vector<int> routing_ids(channels.size());
+ for (size_t i = 0; i < channels.size(); ++i) {
+ WebMessagePortChannelImpl* webchannel =
+ static_cast<WebMessagePortChannelImpl*>(channels[i]);
+ message_port_ids[i] = webchannel->message_port_id();
+ webchannel->QueueMessages();
+ DCHECK(message_port_ids[i] != MSG_ROUTING_NONE);
+ routing_ids[i] = MSG_ROUTING_NONE;
+ }
+
+ Send(new WorkerMsg_PostMessage(
+ route_id_, message, message_port_ids, routing_ids));
+}
+
+void WebWorkerClientProxy::postExceptionToWorkerObject(
+ const WebString& error_message,
+ int line_number,
+ const WebString& source_url) {
+ Send(new WorkerHostMsg_PostExceptionToWorkerObject(
+ route_id_, error_message, line_number, source_url));
+}
+
+void WebWorkerClientProxy::postConsoleMessageToWorkerObject(
+ int source,
+ int type,
+ int level,
+ const WebString& message,
+ int line_number,
+ const WebString& source_url) {
+ WorkerHostMsg_PostConsoleMessageToWorkerObject_Params params;
+ params.source_identifier = source;
+ params.message_type = type;
+ params.message_level = level;
+ params.message = message;
+ params.line_number = line_number;
+ params.source_url = source_url;
+ Send(new WorkerHostMsg_PostConsoleMessageToWorkerObject(route_id_, params));
+}
+
+void WebWorkerClientProxy::confirmMessageFromWorkerObject(
+ bool has_pending_activity) {
+ Send(new WorkerHostMsg_ConfirmMessageFromWorkerObject(
+ route_id_, has_pending_activity));
+}
+
+void WebWorkerClientProxy::reportPendingActivity(bool has_pending_activity) {
+ Send(new WorkerHostMsg_ReportPendingActivity(
+ route_id_, has_pending_activity));
+}
+
+void WebWorkerClientProxy::workerContextClosed() {
+ Send(new WorkerHostMsg_WorkerContextClosed(route_id_));
+}
+
+void WebWorkerClientProxy::workerContextDestroyed() {
+ Send(new WorkerHostMsg_WorkerContextDestroyed(route_id_));
+ // Tell the stub that the worker has shutdown - frees this object.
+ if (stub_)
+ stub_->Shutdown();
+}
+
+WebKit::WebWorker* WebWorkerClientProxy::createWorker(
+ WebKit::WebWorkerClient* client) {
+ // TODO(jam): see comment at top of file
+ //return new WebWorkerProxy(client, WorkerThread::current(),
+ // 0, appcache_host_id_);
+ return NULL;
+}
+
+WebKit::WebNotificationPresenter*
+WebWorkerClientProxy::notificationPresenter() {
+ // TODO(johnnyg): Notifications are not yet hooked up to workers.
+ // Coming soon.
+ NOTREACHED();
+ return NULL;
+}
+
+WebApplicationCacheHost* WebWorkerClientProxy::createApplicationCacheHost(
+ WebKit::WebApplicationCacheHostClient* client) {
+ WorkerWebApplicationCacheHostImpl* host =
+ new WorkerWebApplicationCacheHostImpl(stub_->appcache_init_info(),
+ client);
+ // Remember the id of the instance we create so we have access to that
+ // value when creating nested dedicated workers in createWorker.
+ appcache_host_id_ = host->host_id();
+ return host;
+}
+
+bool WebWorkerClientProxy::allowDatabase(WebFrame* frame,
+ const WebString& name,
+ const WebString& display_name,
+ unsigned long estimated_size) {
+ WebSecurityOrigin origin = frame->securityOrigin();
+ if (origin.isEmpty())
+ return false;
+
+ bool result;
+ if (!Send(new WorkerProcessHostMsg_AllowDatabase(route_id_,
+ GURL(origin.toString().utf8()), name, display_name, estimated_size,
+ &result)))
+ return false;
+
+ return result;
+}
+
+void WebWorkerClientProxy::openFileSystem(
+ WebKit::WebFileSystem::Type type,
+ long long size,
+ bool create,
+ WebKit::WebFileSystemCallbacks* callbacks) {
+ ChildThread::current()->file_system_dispatcher()->OpenFileSystem(
+ stub_->url().GetOrigin(), static_cast<fileapi::FileSystemType>(type),
+ size, create, new WebFileSystemCallbackDispatcher(callbacks));
+}
+
+void WebWorkerClientProxy::openFileSystem(
+ WebKit::WebFileSystem::Type type,
+ long long size,
+ WebKit::WebFileSystemCallbacks* callbacks) {
+ openFileSystem(type, size, true, callbacks);
+}
+
+bool WebWorkerClientProxy::Send(IPC::Message* message) {
+ return WorkerThread::current()->Send(message);
+}
+
+void WebWorkerClientProxy::EnsureWorkerContextTerminates() {
+ // Avoid a worker doing a while(1) from never exiting.
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kWebWorkerShareProcesses)) {
+ // Can't kill the process since there could be workers from other
+ // renderer process.
+ NOTIMPLEMENTED();
+ return;
+ }
+
+ // This shuts down the process cleanly from the perspective of the browser
+ // process, and avoids the crashed worker infobar from appearing to the new
+ // page. It's ok to post several of theese, because the first executed task
+ // will exit the message loop and subsequent ones won't be executed.
+ MessageLoop::current()->PostDelayedTask(FROM_HERE,
+ kill_process_factory_.NewRunnableMethod(
+ &WebWorkerClientProxy::workerContextDestroyed),
+ kMaxTimeForRunawayWorkerMs);
+}
diff --git a/content/worker/webworkerclient_proxy.h b/content/worker/webworkerclient_proxy.h
new file mode 100644
index 0000000..f85caa58
--- /dev/null
+++ b/content/worker/webworkerclient_proxy.h
@@ -0,0 +1,100 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_WORKER_WEBWORKERCLIENT_PROXY_H_
+#define CONTENT_WORKER_WEBWORKERCLIENT_PROXY_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/task.h"
+#include "ipc/ipc_channel.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileSystem.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebWorkerClient.h"
+
+namespace WebKit {
+class WebApplicationCacheHost;
+class WebApplicationCacheHostClient;
+class WebFrame;
+class WebWorker;
+}
+
+class WebWorkerStubBase;
+
+// This class receives IPCs from the renderer and calls the WebCore::Worker
+// implementation (after the data types have been converted by glue code). It
+// is also called by the worker code and converts these function calls into
+// IPCs that are sent to the renderer, where they're converted back to function
+// calls by WebWorkerProxy.
+class WebWorkerClientProxy : public WebKit::WebWorkerClient {
+ public:
+ WebWorkerClientProxy(int route_id, WebWorkerStubBase* stub);
+ virtual ~WebWorkerClientProxy();
+
+ // WebWorkerClient implementation.
+ virtual void postMessageToWorkerObject(
+ const WebKit::WebString& message,
+ const WebKit::WebMessagePortChannelArray& channel);
+ virtual void postExceptionToWorkerObject(
+ const WebKit::WebString& error_message,
+ int line_number,
+ const WebKit::WebString& source_url);
+ // TODO(caseq): The overload before is obsolete and is preserved for
+ // WebKit/chromium compatibility only (pure virtual is base class).
+ // Should be removed once WebKit part is updated.
+ virtual void postConsoleMessageToWorkerObject(
+ int destination,
+ int source,
+ int type,
+ int level,
+ const WebKit::WebString& message,
+ int line_number,
+ const WebKit::WebString& source_url) {
+ }
+ virtual void postConsoleMessageToWorkerObject(
+ int source,
+ int type,
+ int level,
+ const WebKit::WebString& message,
+ int line_number,
+ const WebKit::WebString& source_url);
+ virtual void confirmMessageFromWorkerObject(bool has_pending_activity);
+ virtual void reportPendingActivity(bool has_pending_activity);
+ virtual void workerContextClosed();
+ virtual void workerContextDestroyed();
+ virtual WebKit::WebWorker* createWorker(WebKit::WebWorkerClient* client);
+
+ virtual WebKit::WebNotificationPresenter* notificationPresenter();
+
+ virtual WebKit::WebApplicationCacheHost* createApplicationCacheHost(
+ WebKit::WebApplicationCacheHostClient* client);
+
+ virtual bool allowDatabase(WebKit::WebFrame* frame,
+ const WebKit::WebString& name,
+ const WebKit::WebString& display_name,
+ unsigned long estimated_size);
+
+ virtual void openFileSystem(WebKit::WebFileSystem::Type type,
+ long long size,
+ bool create,
+ WebKit::WebFileSystemCallbacks* callbacks);
+
+ // TODO(adamk): Remove this method once it's gone from WebKit.
+ virtual void openFileSystem(WebKit::WebFileSystem::Type type,
+ long long size,
+ WebKit::WebFileSystemCallbacks* callbacks);
+
+ void EnsureWorkerContextTerminates();
+
+ private:
+ bool Send(IPC::Message* message);
+
+ int route_id_;
+ int appcache_host_id_;
+ WebWorkerStubBase* stub_;
+ ScopedRunnableMethodFactory<WebWorkerClientProxy> kill_process_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebWorkerClientProxy);
+};
+
+#endif // CONTENT_WORKER_WEBWORKERCLIENT_PROXY_H_
diff --git a/content/worker/worker_main.cc b/content/worker/worker_main.cc
new file mode 100644
index 0000000..6ec0263
--- /dev/null
+++ b/content/worker/worker_main.cc
@@ -0,0 +1,55 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/base_switches.h"
+#include "base/command_line.h"
+#include "base/message_loop.h"
+#include "base/string_util.h"
+#include "base/threading/platform_thread.h"
+#include "content/common/child_process.h"
+#include "content/common/hi_res_timer_manager.h"
+#include "content/common/main_function_params.h"
+#include "content/worker/worker_thread.h"
+#include "ui/base/system_monitor/system_monitor.h"
+
+#if defined(OS_WIN)
+#include "content/common/sandbox_init_wrapper.h"
+#include "sandbox/src/sandbox.h"
+#endif
+
+// Mainline routine for running as the worker process.
+int WorkerMain(const MainFunctionParams& parameters) {
+ // The main message loop of the worker process.
+ MessageLoop main_message_loop;
+ base::PlatformThread::SetName("CrWorkerMain");
+
+ ui::SystemMonitor system_monitor;
+ HighResolutionTimerManager hi_res_timer_manager;
+
+ ChildProcess worker_process;
+ worker_process.set_main_thread(new WorkerThread());
+#if defined(OS_WIN)
+ sandbox::TargetServices* target_services =
+ parameters.sandbox_info_.TargetServices();
+ if (!target_services)
+ return false;
+
+ // Cause advapi32 to load before the sandbox is turned on.
+ unsigned int dummy_rand;
+ rand_s(&dummy_rand);
+
+ target_services->LowerToken();
+#endif
+
+ const CommandLine& parsed_command_line = parameters.command_line_;
+ if (parsed_command_line.HasSwitch(switches::kWaitForDebugger)) {
+ ChildProcess::WaitForDebugger("Worker");
+ }
+
+ // Load the accelerator table from the browser executable and tell the
+ // message loop to use it when translating messages.
+ MessageLoop::current()->Run();
+
+ return 0;
+}
diff --git a/content/worker/worker_thread.cc b/content/worker/worker_thread.cc
new file mode 100644
index 0000000..f53ad94
--- /dev/null
+++ b/content/worker/worker_thread.cc
@@ -0,0 +1,127 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/worker/worker_thread.h"
+
+#include "base/command_line.h"
+#include "base/lazy_instance.h"
+#include "base/threading/thread_local.h"
+#include "content/common/appcache/appcache_dispatcher.h"
+#include "content/common/content_switches.h"
+#include "content/common/db_message_filter.h"
+#include "content/common/web_database_observer_impl.h"
+#include "content/common/worker_messages.h"
+#include "content/worker/webworker_stub.h"
+#include "content/worker/websharedworker_stub.h"
+#include "content/worker/worker_webkitclient_impl.h"
+#include "ipc/ipc_sync_channel.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebBlobRegistry.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDatabase.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebRuntimeFeatures.h"
+#include "webkit/glue/webkit_glue.h"
+
+using WebKit::WebRuntimeFeatures;
+
+static base::LazyInstance<base::ThreadLocalPointer<WorkerThread> > lazy_tls(
+ base::LINKER_INITIALIZED);
+
+
+WorkerThread::WorkerThread() {
+ lazy_tls.Pointer()->Set(this);
+ webkit_client_.reset(new WorkerWebKitClientImpl);
+ WebKit::initialize(webkit_client_.get());
+
+ appcache_dispatcher_.reset(new AppCacheDispatcher(this));
+
+ web_database_observer_impl_.reset(new WebDatabaseObserverImpl(this));
+ WebKit::WebDatabase::setObserver(web_database_observer_impl_.get());
+ db_message_filter_ = new DBMessageFilter();
+ channel()->AddFilter(db_message_filter_.get());
+
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+
+ webkit_glue::EnableWebCoreLogChannels(
+ command_line.GetSwitchValueASCII(switches::kWebCoreLogChannels));
+
+ WebKit::WebRuntimeFeatures::enableDatabase(
+ !command_line.HasSwitch(switches::kDisableDatabases));
+
+ WebKit::WebRuntimeFeatures::enableApplicationCache(
+ !command_line.HasSwitch(switches::kDisableApplicationCache));
+
+#if defined(OS_WIN)
+ // We don't yet support notifications on non-Windows, so hide it from pages.
+ WebRuntimeFeatures::enableNotifications(
+ !command_line.HasSwitch(switches::kDisableDesktopNotifications));
+#endif
+
+ WebRuntimeFeatures::enableSockets(
+ !command_line.HasSwitch(switches::kDisableWebSockets));
+
+ WebRuntimeFeatures::enableFileSystem(
+ !command_line.HasSwitch(switches::kDisableFileSystem));
+
+ WebRuntimeFeatures::enableWebGL(
+ !command_line.HasSwitch(switches::kDisable3DAPIs) &&
+ !command_line.HasSwitch(switches::kDisableExperimentalWebGL));
+}
+
+WorkerThread::~WorkerThread() {
+ // Shutdown in reverse of the initialization order.
+ channel()->RemoveFilter(db_message_filter_.get());
+ db_message_filter_ = NULL;
+
+ WebKit::shutdown();
+ lazy_tls.Pointer()->Set(NULL);
+}
+
+WorkerThread* WorkerThread::current() {
+ return lazy_tls.Pointer()->Get();
+}
+
+bool WorkerThread::OnControlMessageReceived(const IPC::Message& msg) {
+ // Appcache messages are handled by a delegate.
+ if (appcache_dispatcher_->OnMessageReceived(msg))
+ return true;
+
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(WorkerThread, msg)
+ IPC_MESSAGE_HANDLER(WorkerProcessMsg_CreateWorker, OnCreateWorker)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void WorkerThread::OnCreateWorker(
+ const WorkerProcessMsg_CreateWorker_Params& params) {
+ WorkerAppCacheInitInfo appcache_init_info(
+ params.is_shared, params.creator_process_id,
+ params.creator_appcache_host_id,
+ params.shared_worker_appcache_id);
+
+ // WebWorkerStub and WebSharedWorkerStub own themselves.
+ if (params.is_shared)
+ new WebSharedWorkerStub(params.name, params.route_id, appcache_init_info);
+ else
+ new WebWorkerStub(params.url, params.route_id, appcache_init_info);
+}
+
+// The browser process is likely dead. Terminate all workers.
+void WorkerThread::OnChannelError() {
+ set_on_channel_error_called(true);
+
+ for (WorkerStubsList::iterator it = worker_stubs_.begin();
+ it != worker_stubs_.end(); ++it) {
+ (*it)->OnChannelError();
+ }
+}
+
+void WorkerThread::RemoveWorkerStub(WebWorkerStubBase* stub) {
+ worker_stubs_.erase(stub);
+}
+
+void WorkerThread::AddWorkerStub(WebWorkerStubBase* stub) {
+ worker_stubs_.insert(stub);
+}
diff --git a/content/worker/worker_thread.h b/content/worker/worker_thread.h
new file mode 100644
index 0000000..25995a6
--- /dev/null
+++ b/content/worker/worker_thread.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_WORKER_WORKER_THREAD_H_
+#define CONTENT_WORKER_WORKER_THREAD_H_
+#pragma once
+
+#include <set>
+
+#include "content/common/child_thread.h"
+
+class GURL;
+class AppCacheDispatcher;
+class DBMessageFilter;
+class WebDatabaseObserverImpl;
+class WebWorkerStubBase;
+class WorkerWebKitClientImpl;
+struct WorkerProcessMsg_CreateWorker_Params;
+
+class WorkerThread : public ChildThread {
+ public:
+ WorkerThread();
+ ~WorkerThread();
+
+ // Returns the one worker thread.
+ static WorkerThread* current();
+
+ // Invoked from stub constructors/destructors. Stubs own themselves.
+ void AddWorkerStub(WebWorkerStubBase* stub);
+ void RemoveWorkerStub(WebWorkerStubBase* stub);
+
+ AppCacheDispatcher* appcache_dispatcher() {
+ return appcache_dispatcher_.get();
+ }
+
+ private:
+ virtual bool OnControlMessageReceived(const IPC::Message& msg);
+ virtual void OnChannelError();
+
+ void OnCreateWorker(const WorkerProcessMsg_CreateWorker_Params& params);
+
+ scoped_ptr<WorkerWebKitClientImpl> webkit_client_;
+ scoped_ptr<AppCacheDispatcher> appcache_dispatcher_;
+ scoped_ptr<WebDatabaseObserverImpl> web_database_observer_impl_;
+ scoped_refptr<DBMessageFilter> db_message_filter_;
+
+ typedef std::set<WebWorkerStubBase*> WorkerStubsList;
+ WorkerStubsList worker_stubs_;
+
+ DISALLOW_COPY_AND_ASSIGN(WorkerThread);
+};
+
+#endif // CONTENT_WORKER_WORKER_THREAD_H_
diff --git a/content/worker/worker_uitest.cc b/content/worker/worker_uitest.cc
new file mode 100644
index 0000000..6cfbb47
--- /dev/null
+++ b/content/worker/worker_uitest.cc
@@ -0,0 +1,772 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/file_path.h"
+#include "base/string_util.h"
+#include "base/test/test_timeouts.h"
+#include "base/threading/platform_thread.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/test/automation/browser_proxy.h"
+#include "chrome/test/automation/tab_proxy.h"
+#include "chrome/test/ui/ui_layout_test.h"
+#include "chrome/test/ui_test_utils.h"
+#include "content/browser/worker_host/worker_service.h"
+#include "net/test/test_server.h"
+
+namespace {
+
+const char kTestCompleteCookie[] = "status";
+const char kTestCompleteSuccess[] = "OK";
+const FilePath::CharType* kTestDir =
+ FILE_PATH_LITERAL("workers");
+const FilePath::CharType* kManySharedWorkersFile =
+ FILE_PATH_LITERAL("many_shared_workers.html");
+const FilePath::CharType* kManyWorkersFile =
+ FILE_PATH_LITERAL("many_workers.html");
+const FilePath::CharType* kQuerySharedWorkerShutdownFile =
+ FILE_PATH_LITERAL("queued_shared_worker_shutdown.html");
+const FilePath::CharType* kShutdownSharedWorkerFile =
+ FILE_PATH_LITERAL("shutdown_shared_worker.html");
+const FilePath::CharType* kSingleSharedWorkersFile =
+ FILE_PATH_LITERAL("single_shared_worker.html");
+const FilePath::CharType* kWorkerClose =
+ FILE_PATH_LITERAL("worker_close.html");
+
+} // anonymous namespace
+
+class WorkerTest : public UILayoutTest {
+ protected:
+ virtual ~WorkerTest() { }
+
+ void RunTest(const FilePath& test_case) {
+ scoped_refptr<TabProxy> tab(GetActiveTab());
+ ASSERT_TRUE(tab.get());
+
+ GURL url = ui_test_utils::GetTestUrl(FilePath(kTestDir), test_case);
+ ASSERT_TRUE(tab->NavigateToURL(url));
+
+ std::string value = WaitUntilCookieNonEmpty(tab.get(), url,
+ kTestCompleteCookie, TestTimeouts::action_max_timeout_ms());
+ ASSERT_STREQ(kTestCompleteSuccess, value.c_str());
+ }
+
+ void RunIncognitoTest(const FilePath& test_case) {
+ scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(browser.get());
+
+ // Open an Incognito window.
+ ASSERT_TRUE(browser->RunCommand(IDC_NEW_INCOGNITO_WINDOW));
+ scoped_refptr<BrowserProxy> incognito(automation()->GetBrowserWindow(1));
+ ASSERT_TRUE(incognito.get());
+ int window_count;
+ ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
+ ASSERT_EQ(2, window_count);
+
+ scoped_refptr<TabProxy> tab(incognito->GetTab(0));
+ ASSERT_TRUE(tab.get());
+
+ GURL url = ui_test_utils::GetTestUrl(FilePath(kTestDir), test_case);
+ ASSERT_TRUE(tab->NavigateToURL(url));
+
+ std::string value = WaitUntilCookieNonEmpty(tab.get(), url,
+ kTestCompleteCookie, TestTimeouts::action_max_timeout_ms());
+
+ // Close the incognito window
+ ASSERT_TRUE(incognito->RunCommand(IDC_CLOSE_WINDOW));
+ ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
+ ASSERT_EQ(1, window_count);
+
+ ASSERT_STREQ(kTestCompleteSuccess, value.c_str());
+ }
+
+ bool WaitForProcessCountToBe(int tabs, int workers) {
+ // The 1 is for the browser process.
+ int number_of_processes = 1 + workers +
+ (ProxyLauncher::in_process_renderer() ? 0 : tabs);
+#if defined(OS_LINUX)
+ // On Linux, we also have a zygote process and a sandbox host process.
+ number_of_processes += 2;
+#endif
+
+ int cur_process_count;
+ for (int i = 0; i < 100; ++i) {
+ cur_process_count = 0;
+ if (!GetBrowserProcessCount(&cur_process_count))
+ return false;
+ if (cur_process_count == number_of_processes)
+ return true;
+
+ // Sometimes the worker processes can take a while to shut down on the
+ // bots, so use a longer timeout period to avoid spurious failures.
+ base::PlatformThread::Sleep(TestTimeouts::action_max_timeout_ms() / 100);
+ }
+
+ EXPECT_EQ(number_of_processes, cur_process_count);
+ return false;
+ }
+
+ void RunWorkerFastLayoutTest(const std::string& test_case_file_name) {
+ FilePath fast_test_dir;
+ fast_test_dir = fast_test_dir.AppendASCII("fast");
+
+ FilePath worker_test_dir;
+ worker_test_dir = worker_test_dir.AppendASCII("workers");
+ InitializeForLayoutTest(fast_test_dir, worker_test_dir, kNoHttpPort);
+
+ // Worker tests also rely on common files in js/resources.
+ FilePath js_dir = fast_test_dir.AppendASCII("js");
+ FilePath resource_dir;
+ resource_dir = resource_dir.AppendASCII("resources");
+ AddResourceForLayoutTest(js_dir, resource_dir);
+
+ printf("Test: %s\n", test_case_file_name.c_str());
+ RunLayoutTest(test_case_file_name, kNoHttpPort);
+
+ // Navigate to a blank page so that any workers are cleaned up.
+ // This helps leaks trackers do a better job of reporting.
+ scoped_refptr<TabProxy> tab(GetActiveTab());
+ GURL about_url(chrome::kAboutBlankURL);
+ EXPECT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS, tab->NavigateToURL(about_url));
+ }
+
+ void RunWorkerStorageLayoutTest(const std::string& test_case_file_name) {
+ FilePath worker_test_dir;
+ worker_test_dir = worker_test_dir.AppendASCII("fast");
+ worker_test_dir = worker_test_dir.AppendASCII("workers");
+
+ FilePath storage_test_dir;
+ storage_test_dir = storage_test_dir.AppendASCII("storage");
+ InitializeForLayoutTest(worker_test_dir, storage_test_dir, kNoHttpPort);
+
+ // Storage worker tests also rely on common files in 'resources'.
+ FilePath resource_dir;
+ resource_dir = resource_dir.AppendASCII("resources");
+ AddResourceForLayoutTest(worker_test_dir.Append(storage_test_dir),
+ resource_dir);
+
+ printf("Test: %s\n", test_case_file_name.c_str());
+ RunLayoutTest(test_case_file_name, kNoHttpPort);
+
+ // Navigate to a blank page so that any workers are cleaned up.
+ // This helps leaks trackers do a better job of reporting.
+ scoped_refptr<TabProxy> tab(GetActiveTab());
+ GURL about_url(chrome::kAboutBlankURL);
+ EXPECT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS, tab->NavigateToURL(about_url));
+ }
+
+ bool NavigateAndWaitForAuth(TabProxy* tab, const GURL& url) {
+ // Pass a large number of navigations to tell the tab to block until an auth
+ // dialog pops up.
+ EXPECT_EQ(AUTOMATION_MSG_NAVIGATION_AUTH_NEEDED,
+ tab->NavigateToURLBlockUntilNavigationsComplete(url, 100));
+ return tab->NeedsAuth();
+ }
+};
+
+
+TEST_F(WorkerTest, SingleWorker) {
+ RunTest(FilePath(FILE_PATH_LITERAL("single_worker.html")));
+}
+
+TEST_F(WorkerTest, MultipleWorkers) {
+ RunTest(FilePath(FILE_PATH_LITERAL("multi_worker.html")));
+}
+
+TEST_F(WorkerTest, SingleSharedWorker) {
+ RunTest(FilePath(FILE_PATH_LITERAL("single_worker.html?shared=true")));
+}
+
+TEST_F(WorkerTest, MultipleSharedWorkers) {
+ RunTest(FilePath(FILE_PATH_LITERAL("multi_worker.html?shared=true")));
+}
+
+TEST_F(WorkerTest, TerminateQueuedWorkers) {
+ ASSERT_TRUE(WaitForProcessCountToBe(1, 0));
+ RunTest(FilePath(FILE_PATH_LITERAL("terminate_queued_workers.html")));
+ // Make sure all workers exit.
+ ASSERT_TRUE(WaitForProcessCountToBe(1, 0));
+}
+
+#if defined(OS_LINUX)
+// http://crbug.com/30021
+#define IncognitoSharedWorkers FLAKY_IncognitoSharedWorkers
+#endif
+
+// Incognito windows should not share workers with non-incognito windows
+TEST_F(WorkerTest, IncognitoSharedWorkers) {
+ // Load a non-incognito tab and have it create a shared worker
+ RunTest(FilePath(FILE_PATH_LITERAL("incognito_worker.html")));
+ // Incognito worker should not share with non-incognito
+ RunIncognitoTest(FilePath(FILE_PATH_LITERAL("incognito_worker.html")));
+}
+
+const FilePath::CharType kDocRoot[] =
+ FILE_PATH_LITERAL("chrome/test/data/workers");
+
+#if defined(OS_WIN)
+// http://crbug.com/33344 - NavigateAndWaitForAuth times out on the Windows
+// build bots.
+#define WorkerHttpAuth DISABLED_WorkerHttpAuth
+#endif
+// Make sure that auth dialog is displayed from worker context.
+TEST_F(WorkerTest, WorkerHttpAuth) {
+ net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot));
+ ASSERT_TRUE(test_server.Start());
+
+ scoped_refptr<TabProxy> tab(GetActiveTab());
+ ASSERT_TRUE(tab.get());
+
+ GURL url = test_server.GetURL("files/worker_auth.html");
+ EXPECT_TRUE(NavigateAndWaitForAuth(tab, url));
+}
+
+#if defined(OS_WIN)
+// http://crbug.com/33344 - NavigateAndWaitForAuth times out on the Windows
+// build bots.
+#define SharedWorkerHttpAuth DISABLED_SharedWorkerHttpAuth
+#endif
+// Make sure that auth dialog is displayed from shared worker context.
+TEST_F(WorkerTest, SharedWorkerHttpAuth) {
+ net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot));
+ ASSERT_TRUE(test_server.Start());
+
+ scoped_refptr<TabProxy> tab(GetActiveTab());
+ ASSERT_TRUE(tab.get());
+
+ GURL url = test_server.GetURL("files/shared_worker_auth.html");
+ EXPECT_TRUE(NavigateAndWaitForAuth(tab, url));
+ // TODO(atwilson): Add support to automation framework to test for auth
+ // dialogs displayed by non-navigating tabs.
+}
+
+TEST_F(WorkerTest, StressJSExecution) {
+ RunWorkerFastLayoutTest("stress-js-execution.html");
+}
+
+TEST_F(WorkerTest, UseMachineStack) {
+ RunWorkerFastLayoutTest("use-machine-stack.html");
+}
+
+TEST_F(WorkerTest, WorkerCall) {
+ RunWorkerFastLayoutTest("worker-call.html");
+}
+
+// Crashy, http://crbug.com/35965.
+// Flaky, http://crbug.com/36555.
+TEST_F(WorkerTest, DISABLED_WorkerClonePort) {
+ RunWorkerFastLayoutTest("worker-cloneport.html");
+}
+
+// Flaky, http://crbug.com/59780.
+TEST_F(WorkerTest, FLAKY_WorkerCloseFast) {
+ RunWorkerFastLayoutTest("worker-close.html");
+}
+
+TEST_F(WorkerTest, WorkerConstructor) {
+ RunWorkerFastLayoutTest("worker-constructor.html");
+}
+
+TEST_F(WorkerTest, WorkerContextGc) {
+ RunWorkerFastLayoutTest("worker-context-gc.html");
+}
+
+TEST_F(WorkerTest, WorkerContextMultiPort) {
+ RunWorkerFastLayoutTest("worker-context-multi-port.html");
+}
+
+TEST_F(WorkerTest, WorkerEventListener) {
+ RunWorkerFastLayoutTest("worker-event-listener.html");
+}
+
+TEST_F(WorkerTest, WorkerGC) {
+ RunWorkerFastLayoutTest("worker-gc.html");
+}
+
+// worker-lifecycle.html relies on layoutTestController.workerThreadCount
+// which is not currently implemented. http://crbug.com/45168
+TEST_F(WorkerTest, DISABLED_WorkerLifecycle) {
+ RunWorkerFastLayoutTest("worker-lifecycle.html");
+}
+
+TEST_F(WorkerTest, WorkerLocation) {
+ RunWorkerFastLayoutTest("worker-location.html");
+}
+
+// Flaky, http://crbug.com/71518.
+TEST_F(WorkerTest, FLAKY_WorkerMapGc) {
+ RunWorkerFastLayoutTest("wrapper-map-gc.html");
+}
+
+TEST_F(WorkerTest, WorkerMessagePort) {
+ RunWorkerFastLayoutTest("worker-messageport.html");
+}
+
+TEST_F(WorkerTest, WorkerMessagePortGC) {
+ RunWorkerFastLayoutTest("worker-messageport-gc.html");
+}
+
+TEST_F(WorkerTest, WorkerMultiPort) {
+ RunWorkerFastLayoutTest("worker-multi-port.html");
+}
+
+TEST_F(WorkerTest, WorkerNavigator) {
+ RunWorkerFastLayoutTest("worker-navigator.html");
+}
+
+TEST_F(WorkerTest, WorkerReplaceGlobalConstructor) {
+ RunWorkerFastLayoutTest("worker-replace-global-constructor.html");
+}
+
+TEST_F(WorkerTest, WorkerReplaceSelf) {
+ RunWorkerFastLayoutTest("worker-replace-self.html");
+}
+
+// See bug 44457.
+#if defined(OS_MACOSX)
+#define WorkerScriptError FLAKY_WorkerScriptError
+#endif
+
+TEST_F(WorkerTest, WorkerScriptError) {
+ RunWorkerFastLayoutTest("worker-script-error.html");
+}
+
+TEST_F(WorkerTest, WorkerTerminate) {
+ RunWorkerFastLayoutTest("worker-terminate.html");
+}
+
+TEST_F(WorkerTest, WorkerTimeout) {
+ RunWorkerFastLayoutTest("worker-timeout.html");
+}
+
+//
+// SharedWorkerFastLayoutTests
+//
+// http://crbug.com/27636 - incorrect URL_MISMATCH exceptions sometimes get
+// generated on the windows try bots. FLAKY on Win.
+// http://crbug.com/28445 - flakiness on mac
+TEST_F(WorkerTest, FLAKY_SharedWorkerFastConstructor) {
+ RunWorkerFastLayoutTest("shared-worker-constructor.html");
+}
+
+TEST_F(WorkerTest, FLAKY_SharedWorkerFastContextGC) {
+ RunWorkerFastLayoutTest("shared-worker-context-gc.html");
+}
+
+TEST_F(WorkerTest, FLAKY_SharedWorkerFastEventListener) {
+ RunWorkerFastLayoutTest("shared-worker-event-listener.html");
+}
+
+TEST_F(WorkerTest, FLAKY_SharedWorkerFastException) {
+ RunWorkerFastLayoutTest("shared-worker-exception.html");
+}
+
+TEST_F(WorkerTest, FLAKY_SharedWorkerFastGC) {
+ RunWorkerFastLayoutTest("shared-worker-gc.html");
+}
+
+TEST_F(WorkerTest, FLAKY_SharedWorkerFastInIframe) {
+ RunWorkerFastLayoutTest("shared-worker-in-iframe.html");
+}
+
+TEST_F(WorkerTest, FLAKY_SharedWorkerFastLoadError) {
+ RunWorkerFastLayoutTest("shared-worker-load-error.html");
+}
+
+TEST_F(WorkerTest, FLAKY_SharedWorkerFastLocation) {
+ RunWorkerFastLayoutTest("shared-worker-location.html");
+}
+
+TEST_F(WorkerTest, FLAKY_SharedWorkerFastName) {
+ RunWorkerFastLayoutTest("shared-worker-name.html");
+}
+
+TEST_F(WorkerTest, FLAKY_SharedWorkerFastNavigator) {
+ RunWorkerFastLayoutTest("shared-worker-navigator.html");
+}
+
+TEST_F(WorkerTest, FLAKY_SharedWorkerFastReplaceGlobalConstructor) {
+ RunWorkerFastLayoutTest("shared-worker-replace-global-constructor.html");
+}
+
+TEST_F(WorkerTest, FLAKY_SharedWorkerFastReplaceSelf) {
+ RunWorkerFastLayoutTest("shared-worker-replace-self.html");
+}
+
+TEST_F(WorkerTest, FLAKY_SharedWorkerFastScriptError) {
+ RunWorkerFastLayoutTest("shared-worker-script-error.html");
+}
+
+TEST_F(WorkerTest, FLAKY_SharedWorkerFastShared) {
+ RunWorkerFastLayoutTest("shared-worker-shared.html");
+}
+
+TEST_F(WorkerTest, FLAKY_SharedWorkerFastSimple) {
+ RunWorkerFastLayoutTest("shared-worker-simple.html");
+}
+
+// http://crbug.com/16934
+TEST_F(WorkerTest, DISABLED_WorkerHttpLayoutTests) {
+ static const char* kLayoutTestFiles[] = {
+ "shared-worker-importScripts.html",
+ "shared-worker-redirect.html",
+ // flakey? BUG 16934 "text-encoding.html",
+#if defined(OS_WIN)
+ // Fails on the mac (and linux?):
+ // http://code.google.com/p/chromium/issues/detail?id=22599
+ "worker-importScripts.html",
+#endif
+ "worker-redirect.html",
+ };
+
+ FilePath http_test_dir;
+ http_test_dir = http_test_dir.AppendASCII("http");
+ http_test_dir = http_test_dir.AppendASCII("tests");
+
+ FilePath worker_test_dir;
+ worker_test_dir = worker_test_dir.AppendASCII("workers");
+ InitializeForLayoutTest(http_test_dir, worker_test_dir, kHttpPort);
+
+ StartHttpServer(new_http_root_dir_);
+ for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i)
+ RunLayoutTest(kLayoutTestFiles[i], kHttpPort);
+ StopHttpServer();
+}
+
+TEST_F(WorkerTest, WorkerWebSocketLayoutTests) {
+ static const char* kLayoutTestFiles[] = {
+ "close-in-onmessage-crash.html",
+ "close-in-shared-worker.html",
+ "close-in-worker.html",
+ "shared-worker-simple.html",
+ "worker-handshake-challenge-randomness.html",
+ "worker-simple.html"
+ };
+
+ FilePath websocket_test_dir;
+ websocket_test_dir = websocket_test_dir.AppendASCII("http");
+ websocket_test_dir = websocket_test_dir.AppendASCII("tests");
+
+ FilePath worker_test_dir;
+ worker_test_dir = worker_test_dir.AppendASCII("websocket");
+ worker_test_dir = worker_test_dir.AppendASCII("tests");
+ worker_test_dir = worker_test_dir.AppendASCII("workers");
+ InitializeForLayoutTest(websocket_test_dir, worker_test_dir, kHttpPort);
+
+ FilePath websocket_root_dir(temp_test_dir_);
+ websocket_root_dir = websocket_root_dir.AppendASCII("LayoutTests");
+ ui_test_utils::TestWebSocketServer websocket_server;
+ ASSERT_TRUE(websocket_server.Start(websocket_root_dir));
+
+ StartHttpServer(new_http_root_dir_);
+ for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i)
+ RunLayoutTest(kLayoutTestFiles[i], kHttpPort);
+ StopHttpServer();
+}
+
+TEST_F(WorkerTest, DISABLED_WorkerXhrHttpLayoutTests) {
+ static const char* kLayoutTestFiles[] = {
+ "abort-exception-assert.html",
+#if defined(OS_WIN)
+ // Fails on the mac (and linux?):
+ // http://code.google.com/p/chromium/issues/detail?id=22599
+ "close.html",
+#endif
+ // These tests (and the shared-worker versions below) are disabled due to
+ // limitations in lighttpd (doesn't handle all of the HTTP methods).
+ // "methods-async.html",
+ // "methods.html",
+
+ "shared-worker-close.html",
+ // Disabled due to limitations in lighttpd (does not handle methods other
+ // than GET/PUT/POST).
+ // "shared-worker-methods-async.html",
+ // "shared-worker-methods.html",
+ "shared-worker-xhr-file-not-found.html",
+
+ "xmlhttprequest-file-not-found.html"
+ };
+
+ FilePath http_test_dir;
+ http_test_dir = http_test_dir.AppendASCII("http");
+ http_test_dir = http_test_dir.AppendASCII("tests");
+
+ FilePath worker_test_dir;
+ worker_test_dir = worker_test_dir.AppendASCII("xmlhttprequest");
+ worker_test_dir = worker_test_dir.AppendASCII("workers");
+ InitializeForLayoutTest(http_test_dir, worker_test_dir, kHttpPort);
+
+ StartHttpServer(new_http_root_dir_);
+ for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i)
+ RunLayoutTest(kLayoutTestFiles[i], kHttpPort);
+ StopHttpServer();
+}
+
+// Flaky, http://crbug.com/34996.
+TEST_F(WorkerTest, FLAKY_MessagePorts) {
+ static const char* kLayoutTestFiles[] = {
+ "message-channel-gc.html",
+ "message-channel-gc-2.html",
+ "message-channel-gc-3.html",
+ "message-channel-gc-4.html",
+ "message-port.html",
+ "message-port-clone.html",
+ "message-port-constructor-for-deleted-document.html",
+ "message-port-deleted-document.html",
+ "message-port-deleted-frame.html",
+ "message-port-inactive-document.html",
+ "message-port-multi.html",
+ "message-port-no-wrapper.html",
+ // Only works with run-webkit-tests --leaks.
+ // "message-channel-listener-circular-ownership.html",
+ };
+
+ FilePath fast_test_dir;
+ fast_test_dir = fast_test_dir.AppendASCII("fast");
+
+ FilePath worker_test_dir;
+ worker_test_dir = worker_test_dir.AppendASCII("events");
+ InitializeForLayoutTest(fast_test_dir, worker_test_dir, kNoHttpPort);
+
+ // MessagePort tests also rely on common files in js/resources.
+ FilePath js_dir = fast_test_dir.AppendASCII("js");
+ FilePath resource_dir;
+ resource_dir = resource_dir.AppendASCII("resources");
+ AddResourceForLayoutTest(js_dir, resource_dir);
+
+ for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i)
+ RunLayoutTest(kLayoutTestFiles[i], kNoHttpPort);
+}
+
+// This has been flaky on Windows since r39931. http://crbug.com/36800
+// And on Mac since r51935. http://crbug.com/48664
+TEST_F(WorkerTest, FLAKY_LimitPerPage) {
+ int max_workers_per_tab = WorkerService::kMaxWorkersPerTabWhenSeparate;
+ GURL url = ui_test_utils::GetTestUrl(FilePath(kTestDir),
+ FilePath(kManyWorkersFile));
+ url = GURL(url.spec() + StringPrintf("?count=%d", max_workers_per_tab + 1));
+
+ NavigateToURL(url);
+ ASSERT_TRUE(WaitForProcessCountToBe(1, max_workers_per_tab));
+}
+
+// Doesn't crash, but on all platforms, it sometimes fails.
+// Flaky on all platforms: http://crbug.com/28445
+#if defined(OS_LINUX)
+// Hangs on Linux: http://30332
+#define FLAKY_LimitTotal DISABLED_LimitTotal
+#endif
+TEST_F(WorkerTest, FLAKY_LimitTotal) {
+ int max_workers_per_tab = WorkerService::kMaxWorkersPerTabWhenSeparate;
+ int total_workers = WorkerService::kMaxWorkersWhenSeparate;
+
+ int tab_count = (total_workers / max_workers_per_tab) + 1;
+ GURL url = ui_test_utils::GetTestUrl(FilePath(kTestDir),
+ FilePath(kManyWorkersFile));
+ url = GURL(url.spec() + StringPrintf("?count=%d", max_workers_per_tab));
+
+ scoped_refptr<TabProxy> tab(GetActiveTab());
+ ASSERT_TRUE(tab.get());
+ ASSERT_TRUE(tab->NavigateToURL(url));
+ scoped_refptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+ for (int i = 1; i < tab_count; ++i)
+ ASSERT_TRUE(window->AppendTab(url));
+
+ // Check that we didn't create more than the max number of workers.
+ ASSERT_TRUE(WaitForProcessCountToBe(tab_count, total_workers));
+
+ // Now close a page and check that the queued workers were started.
+ const FilePath::CharType* kGoogleDir = FILE_PATH_LITERAL("google");
+ const FilePath::CharType* kGoogleFile = FILE_PATH_LITERAL("google.html");
+ ASSERT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS,
+ tab->NavigateToURL(ui_test_utils::GetTestUrl(FilePath(kGoogleDir),
+ FilePath(kGoogleFile))));
+
+ ASSERT_TRUE(WaitForProcessCountToBe(tab_count, total_workers));
+}
+
+// Flaky, http://crbug.com/59786.
+TEST_F(WorkerTest, FLAKY_WorkerClose) {
+ scoped_refptr<TabProxy> tab(GetActiveTab());
+ ASSERT_TRUE(tab.get());
+ GURL url = ui_test_utils::GetTestUrl(FilePath(kTestDir),
+ FilePath(kWorkerClose));
+ ASSERT_TRUE(tab->NavigateToURL(url));
+ std::string value = WaitUntilCookieNonEmpty(tab.get(), url,
+ kTestCompleteCookie, TestTimeouts::action_max_timeout_ms());
+ ASSERT_STREQ(kTestCompleteSuccess, value.c_str());
+ ASSERT_TRUE(WaitForProcessCountToBe(1, 0));
+}
+
+// Flaky, http://crbug.com/70861.
+TEST_F(WorkerTest, FLAKY_QueuedSharedWorkerShutdown) {
+ // Tests to make sure that queued shared workers are started up when
+ // shared workers shut down.
+ int max_workers_per_tab = WorkerService::kMaxWorkersPerTabWhenSeparate;
+ GURL url = ui_test_utils::GetTestUrl(FilePath(kTestDir),
+ FilePath(kQuerySharedWorkerShutdownFile));
+ url = GURL(url.spec() + StringPrintf("?count=%d", max_workers_per_tab));
+
+ scoped_refptr<TabProxy> tab(GetActiveTab());
+ ASSERT_TRUE(tab.get());
+ ASSERT_TRUE(tab->NavigateToURL(url));
+ std::string value = WaitUntilCookieNonEmpty(tab.get(), url,
+ kTestCompleteCookie, TestTimeouts::action_max_timeout_ms());
+ ASSERT_STREQ(kTestCompleteSuccess, value.c_str());
+ ASSERT_TRUE(WaitForProcessCountToBe(1, max_workers_per_tab));
+}
+
+// Flaky, http://crbug.com/69881.
+TEST_F(WorkerTest, FLAKY_MultipleTabsQueuedSharedWorker) {
+ // Tests to make sure that only one instance of queued shared workers are
+ // started up even when those instances are on multiple tabs.
+ int max_workers_per_tab = WorkerService::kMaxWorkersPerTabWhenSeparate;
+ GURL url = ui_test_utils::GetTestUrl(FilePath(kTestDir),
+ FilePath(kManySharedWorkersFile));
+ url = GURL(url.spec() + StringPrintf("?count=%d", max_workers_per_tab+1));
+
+ scoped_refptr<TabProxy> tab(GetActiveTab());
+ ASSERT_TRUE(tab.get());
+ ASSERT_TRUE(tab->NavigateToURL(url));
+ ASSERT_TRUE(WaitForProcessCountToBe(1, max_workers_per_tab));
+
+ // Create same set of workers in new tab (leaves one worker queued from this
+ // tab).
+ scoped_refptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+ ASSERT_TRUE(window->AppendTab(url));
+ ASSERT_TRUE(WaitForProcessCountToBe(2, max_workers_per_tab));
+
+ // Now shutdown one of the shared workers - this will fire both queued
+ // workers, but only one instance should be started
+ GURL url2 = ui_test_utils::GetTestUrl(FilePath(kTestDir),
+ FilePath(kShutdownSharedWorkerFile));
+ url2 = GURL(url2.spec() + "?id=0");
+ ASSERT_TRUE(window->AppendTab(url2));
+
+ std::string value = WaitUntilCookieNonEmpty(tab.get(), url,
+ kTestCompleteCookie, TestTimeouts::action_max_timeout_ms());
+ ASSERT_STREQ(kTestCompleteSuccess, value.c_str());
+ ASSERT_TRUE(WaitForProcessCountToBe(3, max_workers_per_tab));
+}
+
+// Flaky: http://crbug.com/48148
+TEST_F(WorkerTest, FLAKY_QueuedSharedWorkerStartedFromOtherTab) {
+ // Tests to make sure that queued shared workers are started up when
+ // an instance is launched from another tab.
+ int max_workers_per_tab = WorkerService::kMaxWorkersPerTabWhenSeparate;
+ GURL url = ui_test_utils::GetTestUrl(FilePath(kTestDir),
+ FilePath(kManySharedWorkersFile));
+ url = GURL(url.spec() + StringPrintf("?count=%d", max_workers_per_tab+1));
+
+ scoped_refptr<TabProxy> tab(GetActiveTab());
+ ASSERT_TRUE(tab.get());
+ ASSERT_TRUE(tab->NavigateToURL(url));
+ ASSERT_TRUE(WaitForProcessCountToBe(1, max_workers_per_tab));
+ // First window has hit its limit. Now launch second window which creates
+ // the same worker that was queued in the first window, to ensure it gets
+ // connected to the first window too.
+ scoped_refptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(window.get());
+ GURL url2 = ui_test_utils::GetTestUrl(FilePath(kTestDir),
+ FilePath(kSingleSharedWorkersFile));
+ url2 = GURL(url2.spec() + StringPrintf("?id=%d", max_workers_per_tab));
+ ASSERT_TRUE(window->AppendTab(url2));
+
+ std::string value = WaitUntilCookieNonEmpty(tab.get(), url,
+ kTestCompleteCookie, TestTimeouts::action_max_timeout_ms());
+ ASSERT_STREQ(kTestCompleteSuccess, value.c_str());
+ ASSERT_TRUE(WaitForProcessCountToBe(2, max_workers_per_tab+1));
+}
+
+class WorkerFileSystemTest : public WorkerTest {
+ protected:
+ void RunWorkerFileSystemLayoutTest(const std::string& test_case_file_name) {
+ FilePath worker_test_dir;
+ worker_test_dir = worker_test_dir.AppendASCII("fast");
+
+ FilePath filesystem_test_dir;
+ filesystem_test_dir = filesystem_test_dir.AppendASCII("filesystem");
+ filesystem_test_dir = filesystem_test_dir.AppendASCII("workers");
+ InitializeForLayoutTest(worker_test_dir, filesystem_test_dir, kNoHttpPort);
+
+ FilePath resource_dir;
+ resource_dir = resource_dir.AppendASCII("resources");
+ AddResourceForLayoutTest(worker_test_dir.AppendASCII("filesystem"),
+ resource_dir);
+
+ // FS tests also rely on common files in js/resources.
+ FilePath js_dir = worker_test_dir.AppendASCII("js");
+ FilePath js_resource_dir;
+ js_resource_dir = js_resource_dir.AppendASCII("resources");
+ AddResourceForLayoutTest(js_dir, js_resource_dir);
+
+ RunLayoutTest(test_case_file_name, kNoHttpPort);
+
+ // Navigate to a blank page so that any workers are cleaned up.
+ // This helps leaks trackers do a better job of reporting.
+ scoped_refptr<TabProxy> tab(GetActiveTab());
+ ASSERT_TRUE(tab.get());
+ GURL about_url(chrome::kAboutBlankURL);
+ EXPECT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS, tab->NavigateToURL(about_url));
+ }
+};
+
+TEST_F(WorkerFileSystemTest, Temporary) {
+ RunWorkerFileSystemLayoutTest("simple-temporary.html");
+}
+
+TEST_F(WorkerFileSystemTest, Persistent) {
+ RunWorkerFileSystemLayoutTest("simple-persistent.html");
+}
+
+TEST_F(WorkerFileSystemTest, SyncTemporary) {
+ RunWorkerFileSystemLayoutTest("simple-temporary-sync.html");
+}
+
+TEST_F(WorkerFileSystemTest, SyncPersistent) {
+ RunWorkerFileSystemLayoutTest("simple-persistent-sync.html");
+}
+
+TEST_F(WorkerFileSystemTest, AsyncOperations) {
+ RunWorkerFileSystemLayoutTest("async-operations.html");
+}
+
+TEST_F(WorkerFileSystemTest, SyncOperations) {
+ RunWorkerFileSystemLayoutTest("sync-operations.html");
+}
+
+TEST_F(WorkerFileSystemTest, FileEntryToURISync) {
+ RunWorkerFileSystemLayoutTest("file-entry-to-uri-sync.html");
+}
+
+#if defined(OS_LINUX)
+// These tests fail on Linux due to an assert in WebKit's RNG.
+// See http://webkit.org/b/55728.
+#define FileFromFileEntry DISABLED_FileFromFileEntry
+#define FileFromFileEntrySync DISABLED_FileFromFileEntrySync
+#define FileWriterTruncateExtend DISABLED_FileWriterTruncateExtend
+#define FileWriterSyncTruncateExtend DISABLED_FileWriterSyncTruncateExtend
+#define FileWriterSyncWriteOverlapped DISABLED_FileWriterSyncWriteOverlapped
+#endif
+TEST_F(WorkerFileSystemTest, FileFromFileEntry) {
+ RunWorkerFileSystemLayoutTest("file-from-file-entry.html");
+}
+
+TEST_F(WorkerFileSystemTest, FileFromFileEntrySync) {
+ RunWorkerFileSystemLayoutTest("file-from-file-entry-sync.html");
+}
+
+TEST_F(WorkerFileSystemTest, FileWriterTruncateExtend) {
+ RunWorkerFileSystemLayoutTest("file-writer-truncate-extend.html");
+}
+
+TEST_F(WorkerFileSystemTest, FileWriterSyncTruncateExtend) {
+ RunWorkerFileSystemLayoutTest("file-writer-sync-truncate-extend.html");
+}
+
+TEST_F(WorkerFileSystemTest, FileWriterSyncWriteOverlapped) {
+ RunWorkerFileSystemLayoutTest("file-writer-sync-write-overlapped.html");
+}
diff --git a/content/worker/worker_webapplicationcachehost_impl.cc b/content/worker/worker_webapplicationcachehost_impl.cc
new file mode 100644
index 0000000..45c75ed
--- /dev/null
+++ b/content/worker/worker_webapplicationcachehost_impl.cc
@@ -0,0 +1,27 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/worker/worker_webapplicationcachehost_impl.h"
+
+#include "content/common/appcache/appcache_dispatcher.h"
+#include "content/worker/worker_thread.h"
+
+WorkerWebApplicationCacheHostImpl::WorkerWebApplicationCacheHostImpl(
+ const WorkerAppCacheInitInfo& init_info,
+ WebKit::WebApplicationCacheHostClient* client)
+ : WebApplicationCacheHostImpl(client,
+ WorkerThread::current()->appcache_dispatcher()->backend_proxy()) {
+ if (init_info.is_shared_worker)
+ backend()->SelectCacheForSharedWorker(host_id(),
+ init_info.main_resource_appcache_id);
+ else
+ backend()->SelectCacheForWorker(host_id(),
+ init_info.parent_process_id,
+ init_info.parent_appcache_host_id);
+}
+
+bool WorkerWebApplicationCacheHostImpl::selectCacheWithManifest(
+ const WebKit::WebURL& manifestURL) {
+ return true;
+}
diff --git a/content/worker/worker_webapplicationcachehost_impl.h b/content/worker/worker_webapplicationcachehost_impl.h
new file mode 100644
index 0000000..db6dc8a
--- /dev/null
+++ b/content/worker/worker_webapplicationcachehost_impl.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_WORKER_WORKER_WEBAPPLICATIONCACHEHOST_IMPL_H_
+#define CHROME_WORKER_WORKER_WEBAPPLICATIONCACHEHOST_IMPL_H_
+#pragma once
+
+#include "webkit/appcache/web_application_cache_host_impl.h"
+
+// Information used to construct and initialize an appcache host
+// for a worker.
+struct WorkerAppCacheInitInfo {
+ bool is_shared_worker;
+ int parent_process_id;
+ int parent_appcache_host_id; // Only valid for dedicated workers.
+ int64 main_resource_appcache_id; // Only valid for shared workers.
+
+ WorkerAppCacheInitInfo()
+ : is_shared_worker(false), parent_process_id(0),
+ parent_appcache_host_id(0), main_resource_appcache_id(0) {
+ }
+ WorkerAppCacheInitInfo(
+ bool is_shared, int process_id, int host_id, int64 cache_id)
+ : is_shared_worker(is_shared), parent_process_id(process_id),
+ parent_appcache_host_id(host_id), main_resource_appcache_id(cache_id) {
+ }
+};
+
+class WorkerWebApplicationCacheHostImpl
+ : public appcache::WebApplicationCacheHostImpl {
+ public:
+ WorkerWebApplicationCacheHostImpl(
+ const WorkerAppCacheInitInfo& init_info,
+ WebKit::WebApplicationCacheHostClient* client);
+
+ // Main resource loading is different for workers. The resource is
+ // loaded by the creator of the worker rather than the worker itself.
+ virtual void willStartMainResourceRequest(WebKit::WebURLRequest&) {}
+ virtual void didReceiveResponseForMainResource(
+ const WebKit::WebURLResponse&) {}
+ virtual void didReceiveDataForMainResource(const char* data, int len) {}
+ virtual void didFinishLoadingMainResource(bool success) {}
+
+ // Cache selection is also different for workers. We know at construction
+ // time what cache to select and do so then.
+ virtual void selectCacheWithoutManifest() {}
+ virtual bool selectCacheWithManifest(const WebKit::WebURL& manifestURL);
+};
+
+#endif // CHROME_WORKER_WORKER_WEBAPPLICATIONCACHEHOST_IMPL_H_
diff --git a/content/worker/worker_webkitclient_impl.cc b/content/worker/worker_webkitclient_impl.cc
new file mode 100644
index 0000000..0da3322
--- /dev/null
+++ b/content/worker/worker_webkitclient_impl.cc
@@ -0,0 +1,258 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/worker/worker_webkitclient_impl.h"
+
+#include "base/logging.h"
+#include "base/utf_string_conversions.h"
+#include "content/common/database_util.h"
+#include "content/common/file_system/webfilesystem_impl.h"
+#include "content/common/file_utilities_messages.h"
+#include "content/common/mime_registry_messages.h"
+#include "content/common/webblobregistry_impl.h"
+#include "content/common/webmessageportchannel_impl.h"
+#include "content/worker/worker_thread.h"
+#include "ipc/ipc_sync_message_filter.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebBlobRegistry.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
+#include "webkit/glue/webfileutilities_impl.h"
+#include "webkit/glue/webkit_glue.h"
+
+using WebKit::WebBlobRegistry;
+using WebKit::WebClipboard;
+using WebKit::WebFileSystem;
+using WebKit::WebFileUtilities;
+using WebKit::WebKitClient;
+using WebKit::WebMessagePortChannel;
+using WebKit::WebMimeRegistry;
+using WebKit::WebSandboxSupport;
+using WebKit::WebSharedWorkerRepository;
+using WebKit::WebStorageNamespace;
+using WebKit::WebString;
+using WebKit::WebURL;
+
+// TODO(kinuko): Probably this could be consolidated into
+// RendererWebKitClientImpl::FileUtilities.
+class WorkerWebKitClientImpl::FileUtilities
+ : public webkit_glue::WebFileUtilitiesImpl {
+ public:
+ virtual bool getFileSize(const WebKit::WebString& path, long long& result);
+ virtual bool getFileModificationTime(const WebKit::WebString& path,
+ double& result);
+};
+
+static bool SendSyncMessageFromAnyThread(IPC::SyncMessage* msg) {
+ WorkerThread* worker_thread = WorkerThread::current();
+ if (worker_thread)
+ return worker_thread->Send(msg);
+
+ scoped_refptr<IPC::SyncMessageFilter> sync_msg_filter(
+ ChildThread::current()->sync_message_filter());
+ return sync_msg_filter->Send(msg);
+}
+
+bool WorkerWebKitClientImpl::FileUtilities::getFileSize(const WebString& path,
+ long long& result) {
+ if (SendSyncMessageFromAnyThread(new FileUtilitiesMsg_GetFileSize(
+ webkit_glue::WebStringToFilePath(path),
+ reinterpret_cast<int64*>(&result)))) {
+ return result >= 0;
+ }
+
+ result = -1;
+ return false;
+}
+
+bool WorkerWebKitClientImpl::FileUtilities::getFileModificationTime(
+ const WebString& path,
+ double& result) {
+ base::Time time;
+ if (SendSyncMessageFromAnyThread(new FileUtilitiesMsg_GetFileModificationTime(
+ webkit_glue::WebStringToFilePath(path), &time))) {
+ result = time.ToDoubleT();
+ return !time.is_null();
+ }
+
+ result = 0;
+ return false;
+}
+
+//------------------------------------------------------------------------------
+
+WorkerWebKitClientImpl::WorkerWebKitClientImpl() {
+}
+
+WorkerWebKitClientImpl::~WorkerWebKitClientImpl() {
+}
+
+WebClipboard* WorkerWebKitClientImpl::clipboard() {
+ NOTREACHED();
+ return NULL;
+}
+
+WebMimeRegistry* WorkerWebKitClientImpl::mimeRegistry() {
+ return this;
+}
+
+WebFileSystem* WorkerWebKitClientImpl::fileSystem() {
+ if (!web_file_system_.get())
+ web_file_system_.reset(new WebFileSystemImpl());
+ return web_file_system_.get();
+}
+
+WebFileUtilities* WorkerWebKitClientImpl::fileUtilities() {
+ if (!file_utilities_.get()) {
+ file_utilities_.reset(new FileUtilities);
+ file_utilities_->set_sandbox_enabled(sandboxEnabled());
+ }
+ return file_utilities_.get();
+}
+
+WebSandboxSupport* WorkerWebKitClientImpl::sandboxSupport() {
+ NOTREACHED();
+ return NULL;
+}
+
+bool WorkerWebKitClientImpl::sandboxEnabled() {
+ // Always return true because WebKit should always act as though the Sandbox
+ // is enabled for workers. See the comment in WebKitClient for more info.
+ return true;
+}
+
+unsigned long long WorkerWebKitClientImpl::visitedLinkHash(
+ const char* canonical_url,
+ size_t length) {
+ NOTREACHED();
+ return 0;
+}
+
+bool WorkerWebKitClientImpl::isLinkVisited(unsigned long long link_hash) {
+ NOTREACHED();
+ return false;
+}
+
+WebMessagePortChannel*
+WorkerWebKitClientImpl::createMessagePortChannel() {
+ return new WebMessagePortChannelImpl();
+}
+
+void WorkerWebKitClientImpl::setCookies(const WebURL& url,
+ const WebURL& first_party_for_cookies,
+ const WebString& value) {
+ NOTREACHED();
+}
+
+WebString WorkerWebKitClientImpl::cookies(
+ const WebURL& url, const WebURL& first_party_for_cookies) {
+ // WebSocketHandshake may access cookies in worker process.
+ return WebString();
+}
+
+void WorkerWebKitClientImpl::prefetchHostName(const WebString&) {
+ NOTREACHED();
+}
+
+WebString WorkerWebKitClientImpl::defaultLocale() {
+ NOTREACHED();
+ return WebString();
+}
+
+WebStorageNamespace* WorkerWebKitClientImpl::createLocalStorageNamespace(
+ const WebString& path, unsigned quota) {
+ NOTREACHED();
+ return 0;
+}
+
+void WorkerWebKitClientImpl::dispatchStorageEvent(
+ const WebString& key, const WebString& old_value,
+ const WebString& new_value, const WebString& origin,
+ const WebKit::WebURL& url, bool is_local_storage) {
+ NOTREACHED();
+}
+
+WebSharedWorkerRepository* WorkerWebKitClientImpl::sharedWorkerRepository() {
+ return 0;
+}
+
+WebKitClient::FileHandle WorkerWebKitClientImpl::databaseOpenFile(
+ const WebString& vfs_file_name, int desired_flags) {
+ return DatabaseUtil::databaseOpenFile(vfs_file_name, desired_flags);
+}
+
+int WorkerWebKitClientImpl::databaseDeleteFile(
+ const WebString& vfs_file_name, bool sync_dir) {
+ return DatabaseUtil::databaseDeleteFile(vfs_file_name, sync_dir);
+}
+
+long WorkerWebKitClientImpl::databaseGetFileAttributes(
+ const WebString& vfs_file_name) {
+ return DatabaseUtil::databaseGetFileAttributes(vfs_file_name);
+}
+
+long long WorkerWebKitClientImpl::databaseGetFileSize(
+ const WebString& vfs_file_name) {
+ return DatabaseUtil::databaseGetFileSize(vfs_file_name);
+}
+
+WebMimeRegistry::SupportsType WorkerWebKitClientImpl::supportsMIMEType(
+ const WebString&) {
+ return WebMimeRegistry::IsSupported;
+}
+
+WebMimeRegistry::SupportsType WorkerWebKitClientImpl::supportsImageMIMEType(
+ const WebString&) {
+ NOTREACHED();
+ return WebMimeRegistry::IsSupported;
+}
+
+WebMimeRegistry::SupportsType
+WorkerWebKitClientImpl::supportsJavaScriptMIMEType(const WebString&) {
+ NOTREACHED();
+ return WebMimeRegistry::IsSupported;
+}
+
+WebMimeRegistry::SupportsType WorkerWebKitClientImpl::supportsMediaMIMEType(
+ const WebString&, const WebString&) {
+ NOTREACHED();
+ return WebMimeRegistry::IsSupported;
+}
+
+WebMimeRegistry::SupportsType WorkerWebKitClientImpl::supportsNonImageMIMEType(
+ const WebString&) {
+ NOTREACHED();
+ return WebMimeRegistry::IsSupported;
+}
+
+WebString WorkerWebKitClientImpl::mimeTypeForExtension(
+ const WebString& file_extension) {
+ std::string mime_type;
+ SendSyncMessageFromAnyThread(new MimeRegistryMsg_GetMimeTypeFromExtension(
+ webkit_glue::WebStringToFilePathString(file_extension), &mime_type));
+ return ASCIIToUTF16(mime_type);
+}
+
+WebString WorkerWebKitClientImpl::mimeTypeFromFile(
+ const WebString& file_path) {
+ std::string mime_type;
+ SendSyncMessageFromAnyThread(new MimeRegistryMsg_GetMimeTypeFromFile(
+ FilePath(webkit_glue::WebStringToFilePathString(file_path)),
+ &mime_type));
+ return ASCIIToUTF16(mime_type);
+}
+
+WebString WorkerWebKitClientImpl::preferredExtensionForMIMEType(
+ const WebString& mime_type) {
+ FilePath::StringType file_extension;
+ SendSyncMessageFromAnyThread(
+ new MimeRegistryMsg_GetPreferredExtensionForMimeType(
+ UTF16ToASCII(mime_type), &file_extension));
+ return webkit_glue::FilePathStringToWebString(file_extension);
+}
+
+WebBlobRegistry* WorkerWebKitClientImpl::blobRegistry() {
+ if (!blob_registry_.get())
+ blob_registry_.reset(new WebBlobRegistryImpl(WorkerThread::current()));
+ return blob_registry_.get();
+}
diff --git a/content/worker/worker_webkitclient_impl.h b/content/worker/worker_webkitclient_impl.h
new file mode 100644
index 0000000..7a628c3
--- /dev/null
+++ b/content/worker/worker_webkitclient_impl.h
@@ -0,0 +1,89 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_WORKER_WORKER_WEBKITCLIENT_IMPL_H_
+#define CONTENT_WORKER_WORKER_WEBKITCLIENT_IMPL_H_
+#pragma once
+
+#include "base/scoped_ptr.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebMimeRegistry.h"
+#include "webkit/glue/webkitclient_impl.h"
+
+class WebFileSystemImpl;
+
+namespace WebKit {
+class WebFileUtilities;
+}
+
+class WorkerWebKitClientImpl : public webkit_glue::WebKitClientImpl,
+ public WebKit::WebMimeRegistry {
+ public:
+ WorkerWebKitClientImpl();
+ virtual ~WorkerWebKitClientImpl();
+
+ // WebKitClient methods:
+ virtual WebKit::WebClipboard* clipboard();
+ virtual WebKit::WebMimeRegistry* mimeRegistry();
+ virtual WebKit::WebFileSystem* fileSystem();
+ virtual WebKit::WebFileUtilities* fileUtilities();
+ virtual WebKit::WebSandboxSupport* sandboxSupport();
+ virtual bool sandboxEnabled();
+ virtual unsigned long long visitedLinkHash(const char* canonicalURL,
+ size_t length);
+ virtual bool isLinkVisited(unsigned long long linkHash);
+ virtual WebKit::WebMessagePortChannel* createMessagePortChannel();
+ virtual void setCookies(const WebKit::WebURL& url,
+ const WebKit::WebURL& first_party_for_cookies,
+ const WebKit::WebString& value);
+ virtual WebKit::WebString cookies(
+ const WebKit::WebURL& url,
+ const WebKit::WebURL& first_party_for_cookies);
+ virtual void prefetchHostName(const WebKit::WebString&);
+ virtual WebKit::WebString defaultLocale();
+ virtual WebKit::WebStorageNamespace* createLocalStorageNamespace(
+ const WebKit::WebString& path, unsigned quota);
+ virtual void dispatchStorageEvent(
+ const WebKit::WebString& key, const WebKit::WebString& old_value,
+ const WebKit::WebString& new_value, const WebKit::WebString& origin,
+ const WebKit::WebURL& url, bool is_local_storage);
+ virtual WebKit::WebSharedWorkerRepository* sharedWorkerRepository();
+
+ virtual WebKit::WebKitClient::FileHandle databaseOpenFile(
+ const WebKit::WebString& vfs_file_name, int desired_flags);
+ virtual int databaseDeleteFile(const WebKit::WebString& vfs_file_name,
+ bool sync_dir);
+ virtual long databaseGetFileAttributes(
+ const WebKit::WebString& vfs_file_name);
+ virtual long long databaseGetFileSize(
+ const WebKit::WebString& vfs_file_name);
+
+ virtual WebKit::WebBlobRegistry* blobRegistry();
+
+ // WebMimeRegistry methods:
+ virtual WebKit::WebMimeRegistry::SupportsType supportsMIMEType(
+ const WebKit::WebString&);
+ virtual WebKit::WebMimeRegistry::SupportsType supportsImageMIMEType(
+ const WebKit::WebString&);
+ virtual WebKit::WebMimeRegistry::SupportsType supportsJavaScriptMIMEType(
+ const WebKit::WebString&);
+ virtual WebKit::WebMimeRegistry::SupportsType supportsMediaMIMEType(
+ const WebKit::WebString&, const WebKit::WebString&);
+ virtual WebKit::WebMimeRegistry::SupportsType supportsNonImageMIMEType(
+ const WebKit::WebString&);
+ virtual WebKit::WebString mimeTypeForExtension(const WebKit::WebString&);
+ virtual WebKit::WebString mimeTypeFromFile(const WebKit::WebString&);
+ virtual WebKit::WebString preferredExtensionForMIMEType(
+ const WebKit::WebString&);
+
+ private:
+
+ class FileUtilities;
+ scoped_ptr<FileUtilities> file_utilities_;
+
+ scoped_ptr<WebKit::WebBlobRegistry> blob_registry_;
+
+ scoped_ptr<WebFileSystemImpl> web_file_system_;
+};
+
+#endif // CONTENT_WORKER_WORKER_WEBKITCLIENT_IMPL_H_