diff options
author | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-11 06:05:34 +0000 |
---|---|---|
committer | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-11 06:05:34 +0000 |
commit | 91239db318e4e637e0f1f325552ceedfcaf995cc (patch) | |
tree | 4dcaf7ccfd8f40a18e3cece62f6feb598d8a6dbc /content | |
parent | 6f865c86e6d88d0a955f4c261b8cdf5914643ecc (diff) | |
download | chromium_src-91239db318e4e637e0f1f325552ceedfcaf995cc.zip chromium_src-91239db318e4e637e0f1f325552ceedfcaf995cc.tar.gz chromium_src-91239db318e4e637e0f1f325552ceedfcaf995cc.tar.bz2 |
EmbeddedWorker, browser side code
Adding two new classes, EmbeddedWorkerRegistry and EmbeddedWorkerInstance.
Technically they can be implemented within ServiceWorkerContextCore and
ServiceWorkerVersion, but here I wrote them in separate classes for logical
separation.
* EmbeddedWorkerRegistry
-- Hangs off the ServiceWorkerContextCore
-- Acts as a stub between MessageFilter and each EmbeddedWorkerInstance
-- Sends/receives messages to/from each EmbeddedWorker in child process
-- Mostly talks only with MessageFilter and EmbeddedWorkerInstance
* EmbeddedWorkerInstance
-- ServiceWorkerVersion will own it (1:1 relation)
-- Provides an interface to interact (Start/Stop/Execute) with an EmbeddedWorker
BUG=313530
TBR=jochen
Review URL: https://codereview.chromium.org/85023003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@240030 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
13 files changed, 580 insertions, 14 deletions
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc new file mode 100644 index 0000000..0799884 --- /dev/null +++ b/content/browser/service_worker/embedded_worker_instance.cc @@ -0,0 +1,99 @@ +// Copyright 2013 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/browser/service_worker/embedded_worker_instance.h" + +#include "content/browser/service_worker/embedded_worker_registry.h" +#include "url/gurl.h" + +namespace content { + +EmbeddedWorkerInstance::~EmbeddedWorkerInstance() { + registry_->RemoveWorker(embedded_worker_id_); +} + +bool EmbeddedWorkerInstance::Start( + int64 service_worker_version_id, + const GURL& script_url) { + DCHECK(status_ == STOPPED); + if (!ChooseProcess()) + return false; + status_ = STARTING; + bool success = registry_->StartWorker( + process_id_, + embedded_worker_id_, + service_worker_version_id, + script_url); + if (!success) { + status_ = STOPPED; + process_id_ = -1; + } + return success; +} + +bool EmbeddedWorkerInstance::Stop() { + DCHECK(status_ == STARTING || status_ == RUNNING); + const bool success = registry_->StopWorker(process_id_, embedded_worker_id_); + if (success) + status_ = STOPPING; + return success; +} + +void EmbeddedWorkerInstance::AddProcessReference(int process_id) { + ProcessRefMap::iterator found = process_refs_.find(process_id); + if (found == process_refs_.end()) + found = process_refs_.insert(std::make_pair(process_id, 0)).first; + ++found->second; +} + +void EmbeddedWorkerInstance::ReleaseProcessReference(int process_id) { + ProcessRefMap::iterator found = process_refs_.find(process_id); + if (found == process_refs_.end()) { + NOTREACHED() << "Releasing unknown process ref " << process_id; + return; + } + if (--found->second == 0) + process_refs_.erase(found); +} + +EmbeddedWorkerInstance::EmbeddedWorkerInstance( + EmbeddedWorkerRegistry* registry, + int embedded_worker_id) + : registry_(registry), + embedded_worker_id_(embedded_worker_id), + status_(STOPPED), + process_id_(-1), + thread_id_(-1) { +} + +void EmbeddedWorkerInstance::OnStarted(int thread_id) { + DCHECK(status_ == STARTING); + status_ = RUNNING; + thread_id_ = thread_id; +} + +void EmbeddedWorkerInstance::OnStopped() { + status_ = STOPPED; + process_id_ = -1; + thread_id_ = -1; +} + +bool EmbeddedWorkerInstance::ChooseProcess() { + DCHECK_EQ(-1, process_id_); + // Naive implementation; chooses a process which has the biggest number of + // associated providers (so that hopefully likely live longer). + ProcessRefMap::iterator max_ref_iter = process_refs_.end(); + for (ProcessRefMap::iterator iter = process_refs_.begin(); + iter != process_refs_.end(); ++iter) { + if (max_ref_iter == process_refs_.end() || + max_ref_iter->second < iter->second) + max_ref_iter = iter; + } + if (max_ref_iter == process_refs_.end()) + return false; + process_id_ = max_ref_iter->first; + return true; +} + +} // namespace content diff --git a/content/browser/service_worker/embedded_worker_instance.h b/content/browser/service_worker/embedded_worker_instance.h new file mode 100644 index 0000000..fb0fe19 --- /dev/null +++ b/content/browser/service_worker/embedded_worker_instance.h @@ -0,0 +1,102 @@ +// Copyright 2013 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_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_INSTANCE_H_ +#define CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_INSTANCE_H_ + +#include <map> + +#include "base/basictypes.h" +#include "base/callback_forward.h" +#include "base/gtest_prod_util.h" +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "content/common/content_export.h" + +class GURL; + +namespace content { + +class EmbeddedWorkerRegistry; + +// This gives an interface to control one EmbeddedWorker instance, which +// may be 'in-waiting' or running in one of the child processes added by +// AddProcessReference(). +class CONTENT_EXPORT EmbeddedWorkerInstance { + public: + enum Status { + STOPPED, + STARTING, + RUNNING, + STOPPING, + }; + + ~EmbeddedWorkerInstance(); + + // Starts the worker. It is invalid to call this when the worker is + // not in STOPPED status. + // This returns false if starting a worker fails immediately, e.g. when + // IPC couldn't be sent to the worker or no process was available. + bool Start(int64 service_worker_version_id, + const GURL& script_url); + + // Stops the worker. It is invalid to call this when the worker is + // not in STARTING or RUNNING status. + // This returns false if stopping a worker fails immediately, e.g. when + // IPC couldn't be sent to the worker. + bool Stop(); + + // Add or remove |process_id| to the internal process set where this + // worker can be started. + void AddProcessReference(int process_id); + void ReleaseProcessReference(int process_id); + + int embedded_worker_id() const { return embedded_worker_id_; } + Status status() const { return status_; } + int process_id() const { return process_id_; } + int thread_id() const { return thread_id_; } + + private: + friend class EmbeddedWorkerRegistry; + FRIEND_TEST_ALL_PREFIXES(EmbeddedWorkerInstanceTest, StartAndStop); + + typedef std::map<int, int> ProcessRefMap; + + // Constructor is called via EmbeddedWorkerRegistry::CreateWorker(). + // This instance holds a ref of |registry|. + EmbeddedWorkerInstance(EmbeddedWorkerRegistry* registry, + int embedded_worker_id); + + // Called back from Registry when the worker instance has ack'ed that + // its WorkerGlobalScope is actually started on |thread_id| in the + // child process. + // This will change the internal status from STARTING to RUNNING. + void OnStarted(int thread_id); + + // Called back from Registry when the worker instance has ack'ed that + // its WorkerGlobalScope is actually stopped in the child process. + // This will change the internal status from STARTING or RUNNING to + // STOPPED. + void OnStopped(); + + // Chooses a process to start this worker and populate process_id_. + // Returns false when no process is available. + bool ChooseProcess(); + + scoped_refptr<EmbeddedWorkerRegistry> registry_; + const int embedded_worker_id_; + Status status_; + + // Current running information. -1 indicates the worker is not running. + int process_id_; + int thread_id_; + + ProcessRefMap process_refs_; + + DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstance); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_INSTANCE_H_ diff --git a/content/browser/service_worker/embedded_worker_instance_unittest.cc b/content/browser/service_worker/embedded_worker_instance_unittest.cc new file mode 100644 index 0000000..45b2f29 --- /dev/null +++ b/content/browser/service_worker/embedded_worker_instance_unittest.cc @@ -0,0 +1,137 @@ +// Copyright 2013 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/basictypes.h" +#include "base/stl_util.h" +#include "content/browser/service_worker/embedded_worker_instance.h" +#include "content/browser/service_worker/embedded_worker_registry.h" +#include "content/browser/service_worker/service_worker_context_core.h" +#include "content/common/service_worker_messages.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "ipc/ipc_message.h" +#include "ipc/ipc_sender.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace content { + +namespace { + +typedef std::vector<IPC::Message*> MessageList; + +class FakeSender : public IPC::Sender { + public: + FakeSender() {} + virtual ~FakeSender() { + STLDeleteContainerPointers(sent_messages_.begin(), sent_messages_.end()); + } + + // IPC::Sender implementation. + virtual bool Send(IPC::Message* message) OVERRIDE { + sent_messages_.push_back(message); + return true; + } + + const MessageList& sent_messages() { return sent_messages_; } + + private: + MessageList sent_messages_; + DISALLOW_COPY_AND_ASSIGN(FakeSender); +}; + +} // namespace + +class EmbeddedWorkerInstanceTest : public testing::Test { + protected: + EmbeddedWorkerInstanceTest() + : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {} + + virtual void SetUp() OVERRIDE { + context_.reset(new ServiceWorkerContextCore(base::FilePath(), NULL)); + } + + virtual void TearDown() OVERRIDE { + context_.reset(); + } + + EmbeddedWorkerRegistry* embedded_worker_registry() { + DCHECK(context_); + return context_->embedded_worker_registry(); + } + + TestBrowserThreadBundle thread_bundle_; + scoped_ptr<ServiceWorkerContextCore> context_; + + DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstanceTest); +}; + +TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) { + scoped_ptr<EmbeddedWorkerInstance> worker = + embedded_worker_registry()->CreateWorker(); + EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status()); + + FakeSender fake_sender; + const int process_id = 11; + const int thread_id = 33; + const int64 service_worker_version_id = 55L; + const GURL url("http://example.com/worker.js"); + + // This fails as we have no available process yet. + EXPECT_FALSE(worker->Start(service_worker_version_id, url)); + EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status()); + + // Simulate adding one process to the worker. + worker->AddProcessReference(process_id); + embedded_worker_registry()->AddChildProcessSender(process_id, &fake_sender); + + // Start should succeed. + EXPECT_TRUE(worker->Start(service_worker_version_id, url)); + EXPECT_EQ(EmbeddedWorkerInstance::STARTING, worker->status()); + + // Simulate an upcall from embedded worker to notify that it's started. + worker->OnStarted(thread_id); + EXPECT_EQ(EmbeddedWorkerInstance::RUNNING, worker->status()); + EXPECT_EQ(process_id, worker->process_id()); + EXPECT_EQ(thread_id, worker->thread_id()); + + // Stop the worker. + EXPECT_TRUE(worker->Stop()); + EXPECT_EQ(EmbeddedWorkerInstance::STOPPING, worker->status()); + + // Simulate an upcall from embedded worker to notify that it's stopped. + worker->OnStopped(); + EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status()); + + // Verify that we've sent two messages to start and terminate the worker. + const MessageList& messages = fake_sender.sent_messages(); + ASSERT_EQ(2U, messages.size()); + ASSERT_EQ(ServiceWorkerMsg_StartWorker::ID, messages[0]->type()); + ASSERT_EQ(ServiceWorkerMsg_TerminateWorker::ID, messages[1]->type()); +} + +TEST_F(EmbeddedWorkerInstanceTest, ChooseProcess) { + scoped_ptr<EmbeddedWorkerInstance> worker = + embedded_worker_registry()->CreateWorker(); + EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status()); + + FakeSender fake_sender; + + // Simulate adding processes to the worker. + // Process 1 has 1 ref, 2 has 2 refs and 3 has 3 refs. + worker->AddProcessReference(1); + worker->AddProcessReference(2); + worker->AddProcessReference(2); + worker->AddProcessReference(3); + worker->AddProcessReference(3); + worker->AddProcessReference(3); + embedded_worker_registry()->AddChildProcessSender(1, &fake_sender); + embedded_worker_registry()->AddChildProcessSender(2, &fake_sender); + embedded_worker_registry()->AddChildProcessSender(3, &fake_sender); + + // Process 3 has the biggest # of references and it should be chosen. + EXPECT_TRUE(worker->Start(1L, GURL("http://example.com/worker.js"))); + EXPECT_EQ(EmbeddedWorkerInstance::STARTING, worker->status()); + EXPECT_EQ(3, worker->process_id()); +} + +} // namespace content diff --git a/content/browser/service_worker/embedded_worker_registry.cc b/content/browser/service_worker/embedded_worker_registry.cc new file mode 100644 index 0000000..f8f0fbe --- /dev/null +++ b/content/browser/service_worker/embedded_worker_registry.cc @@ -0,0 +1,70 @@ +// Copyright 2013 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/browser/service_worker/embedded_worker_registry.h" + +#include "base/stl_util.h" +#include "content/browser/service_worker/embedded_worker_instance.h" +#include "content/browser/service_worker/service_worker_context_core.h" +#include "content/common/service_worker_messages.h" +#include "ipc/ipc_message.h" +#include "ipc/ipc_sender.h" + +namespace content { + +EmbeddedWorkerRegistry::EmbeddedWorkerRegistry( + base::WeakPtr<ServiceWorkerContextCore> context) + : context_(context), + next_embedded_worker_id_(0) {} + +scoped_ptr<EmbeddedWorkerInstance> EmbeddedWorkerRegistry::CreateWorker() { + scoped_ptr<EmbeddedWorkerInstance> worker( + new EmbeddedWorkerInstance(this, next_embedded_worker_id_)); + worker_map_[next_embedded_worker_id_++] = worker.get(); + return worker.Pass(); +} + +void EmbeddedWorkerRegistry::RemoveWorker(int embedded_worker_id) { + DCHECK(ContainsKey(worker_map_, embedded_worker_id)); + worker_map_.erase(embedded_worker_id); +} + +bool EmbeddedWorkerRegistry::StartWorker( + int process_id, + int embedded_worker_id, + int64 service_worker_version_id, + const GURL& script_url) { + return Send(process_id, + new ServiceWorkerMsg_StartWorker(embedded_worker_id, + service_worker_version_id, + script_url)); +} + +bool EmbeddedWorkerRegistry::StopWorker(int process_id, + int embedded_worker_id) { + return Send(process_id, + new ServiceWorkerMsg_TerminateWorker(embedded_worker_id)); +} + +void EmbeddedWorkerRegistry::AddChildProcessSender( + int process_id, IPC::Sender* sender) { + process_sender_map_[process_id] = sender; +} + +void EmbeddedWorkerRegistry::RemoveChildProcessSender(int process_id) { + process_sender_map_.erase(process_id); +} + +EmbeddedWorkerRegistry::~EmbeddedWorkerRegistry() {} + +bool EmbeddedWorkerRegistry::Send(int process_id, IPC::Message* message) { + if (!context_) + return false; + ProcessToSenderMap::iterator found = process_sender_map_.find(process_id); + if (found == process_sender_map_.end()) + return false; + return found->second->Send(message); +} + +} // namespace content diff --git a/content/browser/service_worker/embedded_worker_registry.h b/content/browser/service_worker/embedded_worker_registry.h new file mode 100644 index 0000000..8860e37 --- /dev/null +++ b/content/browser/service_worker/embedded_worker_registry.h @@ -0,0 +1,77 @@ +// Copyright 2013 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_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_REGISTRY_H_ +#define CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_REGISTRY_H_ + +#include <map> + +#include "base/basictypes.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "content/common/content_export.h" + +class GURL; + +namespace IPC { +class Message; +class Sender; +} + +namespace content { + +class EmbeddedWorkerInstance; +class ServiceWorkerContextCore; + +// Acts as a thin stub between MessageFilter and each EmbeddedWorkerInstance, +// which sends/receives messages to/from each EmbeddedWorker in child process. +// +// Hangs off ServiceWorkerContextCore (its reference is also held by each +// EmbeddedWorkerInstance). Operated only on IO thread. +class CONTENT_EXPORT EmbeddedWorkerRegistry + : public NON_EXPORTED_BASE(base::RefCounted<EmbeddedWorkerRegistry>) { + public: + explicit EmbeddedWorkerRegistry( + base::WeakPtr<ServiceWorkerContextCore> context); + + // Creates and removes a new worker instance entry for bookkeeping. + // This doesn't actually start or stop the worker. + scoped_ptr<EmbeddedWorkerInstance> CreateWorker(); + void RemoveWorker(int embedded_worker_id); + + // Called from EmbeddedWorkerInstance, relayed to the child process. + bool StartWorker(int process_id, + int embedded_worker_id, + int64 service_worker_version_id, + const GURL& script_url); + bool StopWorker(int process_id, + int embedded_worker_id); + + // Keeps a map from process_id to sender information. + void AddChildProcessSender(int process_id, IPC::Sender* sender); + void RemoveChildProcessSender(int process_id); + + private: + friend class base::RefCounted<EmbeddedWorkerRegistry>; + + ~EmbeddedWorkerRegistry(); + bool Send(int process_id, IPC::Message* message); + + typedef std::map<int, EmbeddedWorkerInstance*> WorkerInstanceMap; + typedef std::map<int, IPC::Sender*> ProcessToSenderMap; + + base::WeakPtr<ServiceWorkerContextCore> context_; + + WorkerInstanceMap worker_map_; + ProcessToSenderMap process_sender_map_; + + int next_embedded_worker_id_; + + DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerRegistry); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_REGISTRY_H_ diff --git a/content/browser/service_worker/service_worker_context_core.cc b/content/browser/service_worker/service_worker_context_core.cc index 19b6c7f..8d1e7a8 100644 --- a/content/browser/service_worker/service_worker_context_core.cc +++ b/content/browser/service_worker/service_worker_context_core.cc @@ -7,6 +7,7 @@ #include "base/command_line.h" #include "base/files/file_path.h" #include "base/strings/string_util.h" +#include "content/browser/service_worker/embedded_worker_registry.h" #include "content/browser/service_worker/service_worker_provider_host.h" #include "content/browser/service_worker/service_worker_register_job.h" #include "content/browser/service_worker/service_worker_registration.h" @@ -20,7 +21,8 @@ namespace content { ServiceWorkerContextCore::ServiceWorkerContextCore( const base::FilePath& path, quota::QuotaManagerProxy* quota_manager_proxy) - : storage_(new ServiceWorkerStorage(path, quota_manager_proxy)) {} + : storage_(new ServiceWorkerStorage(path, quota_manager_proxy)), + embedded_worker_registry_(new EmbeddedWorkerRegistry(AsWeakPtr())) {} ServiceWorkerContextCore::~ServiceWorkerContextCore() {} diff --git a/content/browser/service_worker/service_worker_context_core.h b/content/browser/service_worker/service_worker_context_core.h index 854e234..0351c2e 100644 --- a/content/browser/service_worker/service_worker_context_core.h +++ b/content/browser/service_worker/service_worker_context_core.h @@ -29,9 +29,10 @@ class QuotaManagerProxy; namespace content { -class ServiceWorkerStorage; -class ServiceWorkerRegistration; +class EmbeddedWorkerRegistry; class ServiceWorkerProviderHost; +class ServiceWorkerRegistration; +class ServiceWorkerStorage; // This class manages data associated with service workers. // The class is single threaded and should only be used on the IO thread. @@ -74,6 +75,10 @@ class CONTENT_EXPORT ServiceWorkerContextCore void UnregisterServiceWorker(const GURL& pattern, const UnregistrationCallback& callback); + EmbeddedWorkerRegistry* embedded_worker_registry() { + return embedded_worker_registry_.get(); + } + private: typedef IDMap<ServiceWorkerProviderHost, IDMapOwnPointer> ProviderMap; typedef IDMap<ProviderMap, IDMapOwnPointer> ProcessToProviderMap; @@ -91,6 +96,7 @@ class CONTENT_EXPORT ServiceWorkerContextCore ProcessToProviderMap providers_; scoped_ptr<ServiceWorkerStorage> storage_; + scoped_refptr<EmbeddedWorkerRegistry> embedded_worker_registry_; DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContextCore); }; diff --git a/content/browser/service_worker/service_worker_dispatcher_host.cc b/content/browser/service_worker/service_worker_dispatcher_host.cc index b6614fa..9f6b139 100644 --- a/content/browser/service_worker/service_worker_dispatcher_host.cc +++ b/content/browser/service_worker/service_worker_dispatcher_host.cc @@ -5,6 +5,7 @@ #include "content/browser/service_worker/service_worker_dispatcher_host.h" #include "base/strings/utf_string_conversions.h" +#include "content/browser/service_worker/embedded_worker_registry.h" #include "content/browser/service_worker/service_worker_context_core.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/service_worker/service_worker_provider_host.h" @@ -37,8 +38,11 @@ ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost( } ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() { - if (context_) + if (context_) { context_->RemoveAllProviderHostsForProcess(render_process_id_); + context_->embedded_worker_registry()->RemoveChildProcessSender( + render_process_id_); + } } void ServiceWorkerDispatcherHost::Init( @@ -51,6 +55,8 @@ void ServiceWorkerDispatcherHost::Init( return; } context_ = context_wrapper->context()->AsWeakPtr(); + context_->embedded_worker_registry()->AddChildProcessSender( + render_process_id_, this); } void ServiceWorkerDispatcherHost::OnDestruct() const { diff --git a/content/browser/service_worker/service_worker_registration_unittest.cc b/content/browser/service_worker/service_worker_registration_unittest.cc index 1ad7895..3fb6611 100644 --- a/content/browser/service_worker/service_worker_registration_unittest.cc +++ b/content/browser/service_worker/service_worker_registration_unittest.cc @@ -26,7 +26,8 @@ class ServiceWorkerRegistrationTest : public testing::Test { }; TEST_F(ServiceWorkerRegistrationTest, Shutdown) { - int64 registration_id = -1L; + const int64 registration_id = -1L; + const int64 version_id = -1L; scoped_refptr<ServiceWorkerRegistration> registration = new ServiceWorkerRegistration( GURL("http://www.example.com/*"), @@ -34,7 +35,7 @@ TEST_F(ServiceWorkerRegistrationTest, Shutdown) { registration_id); scoped_refptr<ServiceWorkerVersion> active_version = - new ServiceWorkerVersion(registration); + new ServiceWorkerVersion(registration, NULL, version_id); registration->set_active_version(active_version); registration->Shutdown(); @@ -54,12 +55,14 @@ TEST_F(ServiceWorkerRegistrationTest, ActivatePending) { GURL("http://www.example.com/service_worker.js"), registration_id); + const int64 version_1_id = 1L; + const int64 version_2_id = 2L; scoped_refptr<ServiceWorkerVersion> version_1 = - new ServiceWorkerVersion(registration); + new ServiceWorkerVersion(registration, NULL, version_1_id); registration->set_active_version(version_1); scoped_refptr<ServiceWorkerVersion> version_2 = - new ServiceWorkerVersion(registration); + new ServiceWorkerVersion(registration, NULL, version_2_id); registration->set_pending_version(version_2); registration->ActivatePendingVersion(); diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc index fa3ad3d..a91ac6e 100644 --- a/content/browser/service_worker/service_worker_version.cc +++ b/content/browser/service_worker/service_worker_version.cc @@ -4,19 +4,53 @@ #include "content/browser/service_worker/service_worker_version.h" +#include "base/stl_util.h" +#include "content/browser/service_worker/embedded_worker_instance.h" +#include "content/browser/service_worker/embedded_worker_registry.h" +#include "content/browser/service_worker/service_worker_context_core.h" #include "content/browser/service_worker/service_worker_registration.h" namespace content { ServiceWorkerVersion::ServiceWorkerVersion( - ServiceWorkerRegistration* registration) - : is_shutdown_(false), registration_(registration) {} + ServiceWorkerRegistration* registration, + EmbeddedWorkerRegistry* worker_registry, + int64 version_id) + : version_id_(version_id), + is_shutdown_(false), + registration_(registration) { + if (worker_registry) + embedded_worker_ = worker_registry->CreateWorker(); +} ServiceWorkerVersion::~ServiceWorkerVersion() { DCHECK(is_shutdown_); } void ServiceWorkerVersion::Shutdown() { is_shutdown_ = true; registration_ = NULL; + embedded_worker_.reset(); +} + +void ServiceWorkerVersion::StartWorker() { + DCHECK(!is_shutdown_); + DCHECK(registration_); + embedded_worker_->Start(version_id_, registration_->script_url()); +} + +void ServiceWorkerVersion::StopWorker() { + DCHECK(!is_shutdown_); + embedded_worker_->Stop(); +} + +void ServiceWorkerVersion::OnAssociateProvider( + ServiceWorkerProviderHost* provider_host) { + DCHECK(!is_shutdown_); + embedded_worker_->AddProcessReference(provider_host->process_id()); +} + +void ServiceWorkerVersion::OnUnassociateProvider( + ServiceWorkerProviderHost* provider_host) { + embedded_worker_->ReleaseProcessReference(provider_host->process_id()); } } // namespace content diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h index 93f4459..46b75bd 100644 --- a/content/browser/service_worker/service_worker_version.h +++ b/content/browser/service_worker/service_worker_version.h @@ -8,12 +8,16 @@ #include "base/basictypes.h" #include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" #include "content/common/content_export.h" class GURL; namespace content { +class EmbeddedWorkerInstance; +class EmbeddedWorkerRegistry; +class ServiceWorkerProviderHost; class ServiceWorkerRegistration; // This class corresponds to a specific version of a ServiceWorker @@ -51,19 +55,40 @@ class ServiceWorkerRegistration; class CONTENT_EXPORT ServiceWorkerVersion : NON_EXPORTED_BASE(public base::RefCounted<ServiceWorkerVersion>) { public: - explicit ServiceWorkerVersion(ServiceWorkerRegistration* registration); + ServiceWorkerVersion( + ServiceWorkerRegistration* registration, + EmbeddedWorkerRegistry* worker_registry, + int64 version_id); + + int64 version_id() const { return version_id_; } void Shutdown(); bool is_shutdown() const { return is_shutdown_; } + // Starts and stops an embedded worker for this version. + void StartWorker(); + void StopWorker(); + + // Called when this version is associated to a provider host. + // Non-null |provider_host| must be given. + void OnAssociateProvider(ServiceWorkerProviderHost* provider_host); + void OnUnassociateProvider(ServiceWorkerProviderHost* provider_host); + private: - ~ServiceWorkerVersion(); friend class base::RefCounted<ServiceWorkerVersion>; + ~ServiceWorkerVersion(); + + const int64 version_id_; + bool is_shutdown_; scoped_refptr<ServiceWorkerRegistration> registration_; + scoped_ptr<EmbeddedWorkerInstance> embedded_worker_; + DISALLOW_COPY_AND_ASSIGN(ServiceWorkerVersion); }; + } // namespace content + #endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_VERSION_H_ diff --git a/content/content_browser.gypi b/content/content_browser.gypi index 03fb24b..294782a 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -1084,6 +1084,10 @@ 'browser/resource_context_impl.h', 'browser/safe_util_win.cc', 'browser/safe_util_win.h', + 'browser/service_worker/embedded_worker_instance.cc', + 'browser/service_worker/embedded_worker_instance.h', + 'browser/service_worker/embedded_worker_registry.cc', + 'browser/service_worker/embedded_worker_registry.h', 'browser/service_worker/service_worker_context.h', 'browser/service_worker/service_worker_context_core.cc', 'browser/service_worker/service_worker_context_core.h', diff --git a/content/content_tests.gypi b/content/content_tests.gypi index c71dc3d..bf6cdeb 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi @@ -461,10 +461,11 @@ 'browser/renderer_host/input/web_input_event_builders_gtk_unittest.cc', 'browser/renderer_host/websocket_dispatcher_host_unittest.cc', 'browser/resolve_proxy_msg_helper_unittest.cc', - 'browser/service_worker/service_worker_dispatcher_host_unittest.cc', + 'browser/service_worker/embedded_worker_instance_unittest.cc', 'browser/service_worker/service_worker_context_unittest.cc', - 'browser/service_worker/service_worker_storage_unittest.cc', + 'browser/service_worker/service_worker_dispatcher_host_unittest.cc', 'browser/service_worker/service_worker_registration_unittest.cc', + 'browser/service_worker/service_worker_storage_unittest.cc', 'browser/site_instance_impl_unittest.cc', 'browser/speech/chunked_byte_buffer_unittest.cc', 'browser/speech/endpointer/endpointer_unittest.cc', |