diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-14 16:21:05 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-14 16:21:05 +0000 |
commit | 6e07d8b7d3b054975a2e717a5d0a6e60bc0c9444 (patch) | |
tree | cf8cb65ab8ffa28c7165b1e9400f9918bdb4c712 /content | |
parent | 5558fffd6a542a5eb0260ff4866ed9388438704b (diff) | |
download | chromium_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.gyp | 1 | ||||
-rw-r--r-- | content/content_worker.gypi | 39 | ||||
-rw-r--r-- | content/worker/DEPS | 8 | ||||
-rw-r--r-- | content/worker/websharedworker_stub.cc | 90 | ||||
-rw-r--r-- | content/worker/websharedworker_stub.h | 50 | ||||
-rw-r--r-- | content/worker/webworker_stub.cc | 73 | ||||
-rw-r--r-- | content/worker/webworker_stub.h | 44 | ||||
-rw-r--r-- | content/worker/webworker_stub_base.cc | 40 | ||||
-rw-r--r-- | content/worker/webworker_stub_base.h | 48 | ||||
-rw-r--r-- | content/worker/webworkerclient_proxy.cc | 200 | ||||
-rw-r--r-- | content/worker/webworkerclient_proxy.h | 100 | ||||
-rw-r--r-- | content/worker/worker_main.cc | 55 | ||||
-rw-r--r-- | content/worker/worker_thread.cc | 127 | ||||
-rw-r--r-- | content/worker/worker_thread.h | 54 | ||||
-rw-r--r-- | content/worker/worker_uitest.cc | 772 | ||||
-rw-r--r-- | content/worker/worker_webapplicationcachehost_impl.cc | 27 | ||||
-rw-r--r-- | content/worker/worker_webapplicationcachehost_impl.h | 51 | ||||
-rw-r--r-- | content/worker/worker_webkitclient_impl.cc | 258 | ||||
-rw-r--r-- | content/worker/worker_webkitclient_impl.h | 89 |
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_ |