Chromium Code Reviews| Index: content/browser/service_worker/service_worker_context_wrapper.cc |
| diff --git a/content/browser/service_worker/service_worker_context_wrapper.cc b/content/browser/service_worker/service_worker_context_wrapper.cc |
| index 2ccffa1f2202225b0791495d26f3a831ecd685e0..a3d38d4ed22d46ab258fe85a1cbcf26a7ee5ab8c 100644 |
| --- a/content/browser/service_worker/service_worker_context_wrapper.cc |
| +++ b/content/browser/service_worker/service_worker_context_wrapper.cc |
| @@ -4,17 +4,49 @@ |
| #include "content/browser/service_worker/service_worker_context_wrapper.h" |
| +#include "base/callback.h" |
| #include "base/files/file_path.h" |
| +#include "base/lazy_instance.h" |
| +#include "content/browser/renderer_host/render_process_host_impl.h" |
| #include "content/browser/service_worker/service_worker_context_core.h" |
| #include "content/browser/service_worker/service_worker_context_observer.h" |
| #include "content/public/browser/browser_thread.h" |
| +#include "content/public/browser/site_instance.h" |
| #include "webkit/browser/quota/quota_manager_proxy.h" |
| namespace content { |
| +namespace { |
| +base::LazyInstance<base::Callback<bool(int)> > s_increment_worker_refcount; |
| +base::LazyInstance<base::Callback<bool(int)> > s_decrement_worker_refcount; |
|
kinuko
2014/04/25 13:46:35
Whoa... ah ok it's for testing.
Jeffrey Yasskin
2014/04/26 03:52:19
And gone now.
|
| + |
| +bool IncrementWorkerRefcountByPid(int process_id) { |
| + if (!s_increment_worker_refcount.Get().is_null()) |
| + return s_increment_worker_refcount.Get().Run(process_id); |
| + |
| + RenderProcessHost* rph = RenderProcessHost::FromID(process_id); |
| + if (rph) |
|
kinuko
2014/04/25 13:46:35
Probably also check if (!rph->FastShutdownStarted(
Jeffrey Yasskin
2014/04/26 03:52:19
Done.
|
| + static_cast<RenderProcessHostImpl*>(rph)->IncrementWorkerRefCount(); |
| + |
| + return rph; |
|
kinuko
2014/04/25 13:46:35
I prefer explicitly return a boolean value.
Jeffrey Yasskin
2014/04/26 03:52:19
Done.
|
| +} |
| + |
| +bool DecrementWorkerRefcountByPid(int process_id) { |
| + if (!s_decrement_worker_refcount.Get().is_null()) |
| + return s_decrement_worker_refcount.Get().Run(process_id); |
| + |
| + RenderProcessHost* rph = RenderProcessHost::FromID(process_id); |
| + if (rph) |
| + static_cast<RenderProcessHostImpl*>(rph)->DecrementWorkerRefCount(); |
| + |
| + return rph; |
| +} |
| +} // namespace |
| ServiceWorkerContextWrapper::ServiceWorkerContextWrapper() |
| - : observer_list_( |
| - new ObserverListThreadSafe<ServiceWorkerContextObserver>()) {} |
| + : browser_context_(NULL), |
| + observer_list_( |
| + new ObserverListThreadSafe<ServiceWorkerContextObserver>()) { |
| +} |
| ServiceWorkerContextWrapper::~ServiceWorkerContextWrapper() { |
| } |
| @@ -32,16 +64,19 @@ void ServiceWorkerContextWrapper::Init( |
| } |
| DCHECK(!context_core_); |
| context_core_.reset(new ServiceWorkerContextCore( |
| - user_data_directory, quota_manager_proxy, observer_list_)); |
| + this, user_data_directory, quota_manager_proxy, observer_list_)); |
| } |
| void ServiceWorkerContextWrapper::Shutdown() { |
| if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + browser_context_ = NULL; |
| BrowserThread::PostTask( |
| BrowserThread::IO, FROM_HERE, |
| base::Bind(&ServiceWorkerContextWrapper::Shutdown, this)); |
| return; |
| } |
| + // This breaks a reference cycle from Core::wrapper_ back to this object. |
| context_core_.reset(); |
| } |
| @@ -50,12 +85,74 @@ ServiceWorkerContextCore* ServiceWorkerContextWrapper::context() { |
| return context_core_.get(); |
| } |
| +void ServiceWorkerContextWrapper::IncrementWorkerRef( |
| + const std::vector<int>& process_ids, |
| + const GURL& script_url, |
| + const base::Callback<void(ServiceWorkerStatusCode, int process_id)>& |
| + callback) const { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + |
| + for (std::vector<int>::const_iterator it = process_ids.begin(); |
| + it != process_ids.end(); |
| + ++it) { |
| + if (IncrementWorkerRefcountByPid(*it)) { |
| + BrowserThread::PostTask(BrowserThread::IO, |
| + FROM_HERE, |
| + base::Bind(callback, SERVICE_WORKER_OK, *it)); |
| + return; |
| + } |
| + } |
| + |
| + if (!browser_context_) { |
| + // If all of the processes that requested a SW went away before it was |
| + // created, we should just ignore the request. |
| + LOG(ERROR) << "Couldn't start a new process!"; |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, |
| + FROM_HERE, |
| + base::Bind(callback, SERVICE_WORKER_ERROR_START_WORKER_FAILED, -1)); |
| + return; |
| + } |
| + |
| + // No existing processes available; start a new one. |
| + scoped_refptr<SiteInstance> site_instance = |
| + SiteInstance::CreateForURL(browser_context_, script_url); |
| + RenderProcessHost* rph = site_instance->GetProcess(); |
| + // This Init() call posts a task to the IO thread that adds the RPH's |
| + // ServiceWorkerDispatcherHost to the |
| + // EmbeddedWorkerRegistry::process_sender_map_. |
| + if (!rph->Init()) { |
| + LOG(ERROR) << "Couldn't start a new process!"; |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, |
| + FROM_HERE, |
| + base::Bind(callback, SERVICE_WORKER_ERROR_START_WORKER_FAILED, -1)); |
| + return; |
| + } |
| + |
| + static_cast<RenderProcessHostImpl*>(rph)->IncrementWorkerRefCount(); |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, |
| + FROM_HERE, |
| + base::Bind(callback, SERVICE_WORKER_OK, rph->GetID())); |
| +} |
| + |
| +void ServiceWorkerContextWrapper::DecrementWorkerRef(int process_id) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + if (!DecrementWorkerRefcountByPid(process_id)) { |
| + DCHECK(false) << "DecrementWorkerRef(" << process_id |
| + << ") doesn't match a previous IncrementWorkerRef"; |
| + } |
| +} |
| + |
| static void FinishRegistrationOnIO( |
| const ServiceWorkerContext::ResultCallback& continuation, |
| ServiceWorkerStatusCode status, |
| int64 registration_id, |
| int64 version_id) { |
| DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| + if (status != SERVICE_WORKER_OK) |
| + LOG(ERROR) << ServiceWorkerStatusToString(status); |
| BrowserThread::PostTask( |
| BrowserThread::UI, |
| FROM_HERE, |
| @@ -65,9 +162,15 @@ static void FinishRegistrationOnIO( |
| void ServiceWorkerContextWrapper::RegisterServiceWorker( |
| const GURL& pattern, |
| const GURL& script_url, |
| - int source_process_id, |
| + BrowserContext* browser_context, |
| const ResultCallback& continuation) { |
| - if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
| + if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| + DCHECK(browser_context != NULL); |
| + if (browser_context_ != NULL) { |
| + DCHECK_EQ(browser_context_, browser_context) |
| + << "|context| must be the BrowserContext containing *this."; |
| + } |
| + browser_context_ = browser_context; |
| BrowserThread::PostTask( |
| BrowserThread::IO, |
| FROM_HERE, |
| @@ -75,15 +178,16 @@ void ServiceWorkerContextWrapper::RegisterServiceWorker( |
| this, |
| pattern, |
| script_url, |
| - source_process_id, |
| + browser_context, |
| continuation)); |
| return; |
| } |
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| context()->RegisterServiceWorker( |
| pattern, |
| script_url, |
| - source_process_id, |
| + -1, |
| NULL /* provider_host */, |
| base::Bind(&FinishRegistrationOnIO, continuation)); |
| } |
| @@ -92,6 +196,8 @@ static void FinishUnregistrationOnIO( |
| const ServiceWorkerContext::ResultCallback& continuation, |
| ServiceWorkerStatusCode status) { |
| DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| + if (status != SERVICE_WORKER_OK) |
| + LOG(ERROR) << ServiceWorkerStatusToString(status); |
| BrowserThread::PostTask( |
| BrowserThread::UI, |
| FROM_HERE, |
| @@ -131,4 +237,11 @@ void ServiceWorkerContextWrapper::RemoveObserver( |
| observer_list_->RemoveObserver(observer); |
| } |
| +void ServiceWorkerContextWrapper::ResetWorkerRefCountOperationsForTest( |
| + const base::Callback<bool(int)>& increment, |
| + const base::Callback<bool(int)>& decrement) { |
| + s_increment_worker_refcount.Get() = increment; |
| + s_decrement_worker_refcount.Get() = decrement; |
| +} |
| + |
| } // namespace content |