Commit 76981022 authored by jyasskin@chromium.org's avatar jyasskin@chromium.org

Reparent SWProcessManager onto SWContextWrapper.

This will allow Wrapper::Shutdown to drop all process references synchronously
in a future change, which will make it possible to shutdown Chrome with service
workers running and without hitting the DCHECK in
ProfileDestroyer::DestroyProfileWhenAppropriate().

BUG=368570

Review URL: https://codereview.chromium.org/292973003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@272839 0039d316-1c4b-4281-b951-d872f2087c98
parent ba97e73f
...@@ -23,10 +23,7 @@ EmbeddedWorkerTestHelper::EmbeddedWorkerTestHelper(int mock_render_process_id) ...@@ -23,10 +23,7 @@ EmbeddedWorkerTestHelper::EmbeddedWorkerTestHelper(int mock_render_process_id)
base::MessageLoopProxy::current(), base::MessageLoopProxy::current(),
base::MessageLoopProxy::current(), base::MessageLoopProxy::current(),
NULL); NULL);
scoped_ptr<ServiceWorkerProcessManager> process_manager( wrapper_->process_manager()->SetProcessIdForTest(mock_render_process_id);
new ServiceWorkerProcessManager(wrapper_));
process_manager->SetProcessIdForTest(mock_render_process_id);
wrapper_->context()->SetProcessManagerForTest(process_manager.Pass());
registry()->AddChildProcessSender(mock_render_process_id, this); registry()->AddChildProcessSender(mock_render_process_id, this);
} }
......
...@@ -82,14 +82,16 @@ ServiceWorkerContextCore::ServiceWorkerContextCore( ...@@ -82,14 +82,16 @@ ServiceWorkerContextCore::ServiceWorkerContextCore(
base::MessageLoopProxy* disk_cache_thread, base::MessageLoopProxy* disk_cache_thread,
quota::QuotaManagerProxy* quota_manager_proxy, quota::QuotaManagerProxy* quota_manager_proxy,
ObserverListThreadSafe<ServiceWorkerContextObserver>* observer_list, ObserverListThreadSafe<ServiceWorkerContextObserver>* observer_list,
scoped_ptr<ServiceWorkerProcessManager> process_manager) ServiceWorkerContextWrapper* wrapper)
: weak_factory_(this), : weak_factory_(this),
storage_(new ServiceWorkerStorage( wrapper_(wrapper),
path, AsWeakPtr(), database_task_runner, disk_cache_thread, storage_(new ServiceWorkerStorage(path,
quota_manager_proxy)), AsWeakPtr(),
database_task_runner,
disk_cache_thread,
quota_manager_proxy)),
embedded_worker_registry_(new EmbeddedWorkerRegistry(AsWeakPtr())), embedded_worker_registry_(new EmbeddedWorkerRegistry(AsWeakPtr())),
job_coordinator_(new ServiceWorkerJobCoordinator(AsWeakPtr())), job_coordinator_(new ServiceWorkerJobCoordinator(AsWeakPtr())),
process_manager_(process_manager.Pass()),
next_handle_id_(0), next_handle_id_(0),
observer_list_(observer_list) { observer_list_(observer_list) {
} }
...@@ -307,4 +309,8 @@ void ServiceWorkerContextCore::OnReportConsoleMessage( ...@@ -307,4 +309,8 @@ void ServiceWorkerContextCore::OnReportConsoleMessage(
source_identifier, message_level, message, line_number, source_url)); source_identifier, message_level, message, line_number, source_url));
} }
ServiceWorkerProcessManager* ServiceWorkerContextCore::process_manager() {
return wrapper_->process_manager();
}
} // namespace content } // namespace content
...@@ -37,6 +37,7 @@ namespace content { ...@@ -37,6 +37,7 @@ namespace content {
class EmbeddedWorkerRegistry; class EmbeddedWorkerRegistry;
class ServiceWorkerContextObserver; class ServiceWorkerContextObserver;
class ServiceWorkerContextWrapper;
class ServiceWorkerHandle; class ServiceWorkerHandle;
class ServiceWorkerJobCoordinator; class ServiceWorkerJobCoordinator;
class ServiceWorkerProviderHost; class ServiceWorkerProviderHost;
...@@ -91,7 +92,7 @@ class CONTENT_EXPORT ServiceWorkerContextCore ...@@ -91,7 +92,7 @@ class CONTENT_EXPORT ServiceWorkerContextCore
base::MessageLoopProxy* disk_cache_thread, base::MessageLoopProxy* disk_cache_thread,
quota::QuotaManagerProxy* quota_manager_proxy, quota::QuotaManagerProxy* quota_manager_proxy,
ObserverListThreadSafe<ServiceWorkerContextObserver>* observer_list, ObserverListThreadSafe<ServiceWorkerContextObserver>* observer_list,
scoped_ptr<ServiceWorkerProcessManager> process_manager); ServiceWorkerContextWrapper* wrapper);
virtual ~ServiceWorkerContextCore(); virtual ~ServiceWorkerContextCore();
// ServiceWorkerVersion::Listener overrides. // ServiceWorkerVersion::Listener overrides.
...@@ -111,9 +112,7 @@ class CONTENT_EXPORT ServiceWorkerContextCore ...@@ -111,9 +112,7 @@ class CONTENT_EXPORT ServiceWorkerContextCore
const GURL& source_url) OVERRIDE; const GURL& source_url) OVERRIDE;
ServiceWorkerStorage* storage() { return storage_.get(); } ServiceWorkerStorage* storage() { return storage_.get(); }
ServiceWorkerProcessManager* process_manager() { ServiceWorkerProcessManager* process_manager();
return process_manager_.get();
}
EmbeddedWorkerRegistry* embedded_worker_registry() { EmbeddedWorkerRegistry* embedded_worker_registry() {
return embedded_worker_registry_.get(); return embedded_worker_registry_.get();
} }
...@@ -159,12 +158,6 @@ class CONTENT_EXPORT ServiceWorkerContextCore ...@@ -159,12 +158,6 @@ class CONTENT_EXPORT ServiceWorkerContextCore
return weak_factory_.GetWeakPtr(); return weak_factory_.GetWeakPtr();
} }
// Allows tests to change how processes are created.
void SetProcessManagerForTest(
scoped_ptr<ServiceWorkerProcessManager> new_process_manager) {
process_manager_ = new_process_manager.Pass();
}
private: private:
typedef std::map<int64, ServiceWorkerRegistration*> RegistrationsMap; typedef std::map<int64, ServiceWorkerRegistration*> RegistrationsMap;
typedef std::map<int64, ServiceWorkerVersion*> VersionMap; typedef std::map<int64, ServiceWorkerVersion*> VersionMap;
...@@ -184,11 +177,14 @@ class CONTENT_EXPORT ServiceWorkerContextCore ...@@ -184,11 +177,14 @@ class CONTENT_EXPORT ServiceWorkerContextCore
ServiceWorkerStatusCode status); ServiceWorkerStatusCode status);
base::WeakPtrFactory<ServiceWorkerContextCore> weak_factory_; base::WeakPtrFactory<ServiceWorkerContextCore> weak_factory_;
// It's safe to store a raw pointer instead of a scoped_refptr to |wrapper_|
// because the Wrapper::Shutdown call that hops threads to destroy |this| uses
// Bind() to hold a reference to |wrapper_| until |this| is fully destroyed.
ServiceWorkerContextWrapper* wrapper_;
ProcessToProviderMap providers_; ProcessToProviderMap providers_;
scoped_ptr<ServiceWorkerStorage> storage_; scoped_ptr<ServiceWorkerStorage> storage_;
scoped_refptr<EmbeddedWorkerRegistry> embedded_worker_registry_; scoped_refptr<EmbeddedWorkerRegistry> embedded_worker_registry_;
scoped_ptr<ServiceWorkerJobCoordinator> job_coordinator_; scoped_ptr<ServiceWorkerJobCoordinator> job_coordinator_;
scoped_ptr<ServiceWorkerProcessManager> process_manager_;
std::map<int64, ServiceWorkerRegistration*> live_registrations_; std::map<int64, ServiceWorkerRegistration*> live_registrations_;
std::map<int64, ServiceWorkerVersion*> live_versions_; std::map<int64, ServiceWorkerVersion*> live_versions_;
int next_handle_id_; int next_handle_id_;
......
...@@ -18,7 +18,7 @@ ServiceWorkerContextWrapper::ServiceWorkerContextWrapper( ...@@ -18,7 +18,7 @@ ServiceWorkerContextWrapper::ServiceWorkerContextWrapper(
BrowserContext* browser_context) BrowserContext* browser_context)
: observer_list_( : observer_list_(
new ObserverListThreadSafe<ServiceWorkerContextObserver>()), new ObserverListThreadSafe<ServiceWorkerContextObserver>()),
browser_context_(browser_context) { process_manager_(new ServiceWorkerProcessManager(browser_context)) {
} }
ServiceWorkerContextWrapper::~ServiceWorkerContextWrapper() { ServiceWorkerContextWrapper::~ServiceWorkerContextWrapper() {
...@@ -39,16 +39,12 @@ void ServiceWorkerContextWrapper::Init( ...@@ -39,16 +39,12 @@ void ServiceWorkerContextWrapper::Init(
} }
void ServiceWorkerContextWrapper::Shutdown() { void ServiceWorkerContextWrapper::Shutdown() {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK_CURRENTLY_ON(BrowserThread::UI); process_manager_->Shutdown();
browser_context_ = NULL; BrowserThread::PostTask(
BrowserThread::PostTask( BrowserThread::IO,
BrowserThread::IO, FROM_HERE, FROM_HERE,
base::Bind(&ServiceWorkerContextWrapper::Shutdown, this)); base::Bind(&ServiceWorkerContextWrapper::ShutdownOnIO, this));
return;
}
// Breaks the reference cycle through ServiceWorkerProcessManager.
context_core_.reset();
} }
ServiceWorkerContextCore* ServiceWorkerContextWrapper::context() { ServiceWorkerContextCore* ServiceWorkerContextWrapper::context() {
...@@ -149,13 +145,17 @@ void ServiceWorkerContextWrapper::InitInternal( ...@@ -149,13 +145,17 @@ void ServiceWorkerContextWrapper::InitInternal(
return; return;
} }
DCHECK(!context_core_); DCHECK(!context_core_);
context_core_.reset(new ServiceWorkerContextCore( context_core_.reset(new ServiceWorkerContextCore(user_data_directory,
user_data_directory, database_task_runner,
database_task_runner, disk_cache_thread,
disk_cache_thread, quota_manager_proxy,
quota_manager_proxy, observer_list_,
observer_list_, this));
make_scoped_ptr(new ServiceWorkerProcessManager(this)))); }
void ServiceWorkerContextWrapper::ShutdownOnIO() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
context_core_.reset();
} }
} // namespace content } // namespace content
...@@ -49,6 +49,11 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper ...@@ -49,6 +49,11 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
// The core context is only for use on the IO thread. // The core context is only for use on the IO thread.
ServiceWorkerContextCore* context(); ServiceWorkerContextCore* context();
// The process manager can be used on either UI or IO.
ServiceWorkerProcessManager* process_manager() {
return process_manager_.get();
}
// ServiceWorkerContext implementation: // ServiceWorkerContext implementation:
virtual void RegisterServiceWorker( virtual void RegisterServiceWorker(
const GURL& pattern, const GURL& pattern,
...@@ -71,11 +76,12 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper ...@@ -71,11 +76,12 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
base::SequencedTaskRunner* database_task_runner, base::SequencedTaskRunner* database_task_runner,
base::MessageLoopProxy* disk_cache_thread, base::MessageLoopProxy* disk_cache_thread,
quota::QuotaManagerProxy* quota_manager_proxy); quota::QuotaManagerProxy* quota_manager_proxy);
void ShutdownOnIO();
const scoped_refptr<ObserverListThreadSafe<ServiceWorkerContextObserver> > const scoped_refptr<ObserverListThreadSafe<ServiceWorkerContextObserver> >
observer_list_; observer_list_;
const scoped_ptr<ServiceWorkerProcessManager> process_manager_;
// Cleared in Shutdown(): // Cleared in Shutdown():
BrowserContext* browser_context_;
scoped_ptr<ServiceWorkerContextCore> context_core_; scoped_ptr<ServiceWorkerContextCore> context_core_;
}; };
......
...@@ -35,8 +35,8 @@ ServiceWorkerProcessManager::ProcessInfo::~ProcessInfo() { ...@@ -35,8 +35,8 @@ ServiceWorkerProcessManager::ProcessInfo::~ProcessInfo() {
} }
ServiceWorkerProcessManager::ServiceWorkerProcessManager( ServiceWorkerProcessManager::ServiceWorkerProcessManager(
ServiceWorkerContextWrapper* context_wrapper) BrowserContext* browser_context)
: context_wrapper_(context_wrapper), : browser_context_(browser_context),
process_id_for_test_(-1), process_id_for_test_(-1),
weak_this_factory_(this), weak_this_factory_(this),
weak_this_(weak_this_factory_.GetWeakPtr()) { weak_this_(weak_this_factory_.GetWeakPtr()) {
...@@ -44,6 +44,13 @@ ServiceWorkerProcessManager::ServiceWorkerProcessManager( ...@@ -44,6 +44,13 @@ ServiceWorkerProcessManager::ServiceWorkerProcessManager(
ServiceWorkerProcessManager::~ServiceWorkerProcessManager() { ServiceWorkerProcessManager::~ServiceWorkerProcessManager() {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(browser_context_ == NULL)
<< "Call Shutdown() before destroying |this|, so that racing method "
<< "invocations don't use a destroyed BrowserContext.";
}
void ServiceWorkerProcessManager::Shutdown() {
browser_context_ = NULL;
} }
void ServiceWorkerProcessManager::AllocateWorkerProcess( void ServiceWorkerProcessManager::AllocateWorkerProcess(
...@@ -91,7 +98,7 @@ void ServiceWorkerProcessManager::AllocateWorkerProcess( ...@@ -91,7 +98,7 @@ void ServiceWorkerProcessManager::AllocateWorkerProcess(
} }
} }
if (!context_wrapper_->browser_context_) { if (!browser_context_) {
// Shutdown has started. // Shutdown has started.
BrowserThread::PostTask( BrowserThread::PostTask(
BrowserThread::IO, BrowserThread::IO,
...@@ -100,8 +107,8 @@ void ServiceWorkerProcessManager::AllocateWorkerProcess( ...@@ -100,8 +107,8 @@ void ServiceWorkerProcessManager::AllocateWorkerProcess(
return; return;
} }
// No existing processes available; start a new one. // No existing processes available; start a new one.
scoped_refptr<SiteInstance> site_instance = SiteInstance::CreateForURL( scoped_refptr<SiteInstance> site_instance =
context_wrapper_->browser_context_, script_url); SiteInstance::CreateForURL(browser_context_, script_url);
RenderProcessHost* rph = site_instance->GetProcess(); RenderProcessHost* rph = site_instance->GetProcess();
// This Init() call posts a task to the IO thread that adds the RPH's // This Init() call posts a task to the IO thread that adds the RPH's
// ServiceWorkerDispatcherHost to the // ServiceWorkerDispatcherHost to the
......
...@@ -18,21 +18,25 @@ class GURL; ...@@ -18,21 +18,25 @@ class GURL;
namespace content { namespace content {
class BrowserContext; class BrowserContext;
class ServiceWorkerContextWrapper;
class SiteInstance; class SiteInstance;
// Interacts with the UI thread to keep RenderProcessHosts alive while the // Interacts with the UI thread to keep RenderProcessHosts alive while the
// ServiceWorker system is using them. Each instance of // ServiceWorker system is using them. Each instance of
// ServiceWorkerProcessManager is destroyed on the UI thread shortly after its // ServiceWorkerProcessManager is destroyed on the UI thread shortly after its
// ServiceWorkerContextCore is destroyed on the IO thread. // ServiceWorkerContextWrapper is destroyed.
class CONTENT_EXPORT ServiceWorkerProcessManager { class CONTENT_EXPORT ServiceWorkerProcessManager {
public: public:
// |*this| must be owned by |context_wrapper|->context(). // |*this| must be owned by a ServiceWorkerContextWrapper in a
explicit ServiceWorkerProcessManager( // StoragePartition within |browser_context|.
ServiceWorkerContextWrapper* context_wrapper); explicit ServiceWorkerProcessManager(BrowserContext* browser_context);
// Shutdown must be called before the ProcessManager is destroyed.
~ServiceWorkerProcessManager(); ~ServiceWorkerProcessManager();
// Synchronously prevents new processes from being allocated.
// TODO(jyasskin): Drop references to RenderProcessHosts too.
void Shutdown();
// Returns a reference to a running process suitable for starting the Service // Returns a reference to a running process suitable for starting the Service
// Worker at |script_url|. Processes in |process_ids| will be checked in order // Worker at |script_url|. Processes in |process_ids| will be checked in order
// for existence, and if none exist, then a new process will be created. Posts // for existence, and if none exist, then a new process will be created. Posts
...@@ -80,10 +84,8 @@ class CONTENT_EXPORT ServiceWorkerProcessManager { ...@@ -80,10 +84,8 @@ class CONTENT_EXPORT ServiceWorkerProcessManager {
int process_id; int process_id;
}; };
// These fields are only accessed on the UI thread after construction. // These fields are only accessed on the UI thread.
// The reference cycle through context_wrapper_ is broken in BrowserContext* browser_context_;
// ServiceWorkerContextWrapper::Shutdown().
scoped_refptr<ServiceWorkerContextWrapper> context_wrapper_;
// Maps the ID of a running EmbeddedWorkerInstance to information about the // Maps the ID of a running EmbeddedWorkerInstance to information about the
// process it's running inside. Since the Instances themselves live on the IO // process it's running inside. Since the Instances themselves live on the IO
......
...@@ -23,13 +23,13 @@ class ServiceWorkerProviderHostTest : public testing::Test { ...@@ -23,13 +23,13 @@ class ServiceWorkerProviderHostTest : public testing::Test {
virtual ~ServiceWorkerProviderHostTest() {} virtual ~ServiceWorkerProviderHostTest() {}
virtual void SetUp() OVERRIDE { virtual void SetUp() OVERRIDE {
context_.reset(new ServiceWorkerContextCore( context_.reset(
base::FilePath(), new ServiceWorkerContextCore(base::FilePath(),
base::MessageLoopProxy::current(), base::MessageLoopProxy::current(),
base::MessageLoopProxy::current(), base::MessageLoopProxy::current(),
NULL, NULL,
NULL, NULL,
scoped_ptr<ServiceWorkerProcessManager>())); NULL));
scope_ = GURL("http://www.example.com/*"); scope_ = GURL("http://www.example.com/*");
script_url_ = GURL("http://www.example.com/service_worker.js"); script_url_ = GURL("http://www.example.com/service_worker.js");
......
...@@ -22,13 +22,13 @@ class ServiceWorkerRegistrationTest : public testing::Test { ...@@ -22,13 +22,13 @@ class ServiceWorkerRegistrationTest : public testing::Test {
: io_thread_(BrowserThread::IO, &message_loop_) {} : io_thread_(BrowserThread::IO, &message_loop_) {}
virtual void SetUp() OVERRIDE { virtual void SetUp() OVERRIDE {
context_.reset(new ServiceWorkerContextCore( context_.reset(
base::FilePath(), new ServiceWorkerContextCore(base::FilePath(),
base::MessageLoopProxy::current(), base::MessageLoopProxy::current(),
base::MessageLoopProxy::current(), base::MessageLoopProxy::current(),
NULL, NULL,
NULL, NULL,
scoped_ptr<ServiceWorkerProcessManager>())); NULL));
context_ptr_ = context_->AsWeakPtr(); context_ptr_ = context_->AsWeakPtr();
} }
......
...@@ -150,13 +150,13 @@ class ServiceWorkerStorageTest : public testing::Test { ...@@ -150,13 +150,13 @@ class ServiceWorkerStorageTest : public testing::Test {
} }
virtual void SetUp() OVERRIDE { virtual void SetUp() OVERRIDE {
context_.reset(new ServiceWorkerContextCore( context_.reset(
base::FilePath(), new ServiceWorkerContextCore(base::FilePath(),
base::MessageLoopProxy::current(), base::MessageLoopProxy::current(),
base::MessageLoopProxy::current(), base::MessageLoopProxy::current(),
NULL, NULL,
NULL, NULL,
scoped_ptr<ServiceWorkerProcessManager>())); NULL));
context_ptr_ = context_->AsWeakPtr(); context_ptr_ = context_->AsWeakPtr();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment