Index: content/browser/service_worker/service_worker_process_manager.cc |
diff --git a/content/browser/service_worker/service_worker_process_manager.cc b/content/browser/service_worker/service_worker_process_manager.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a9bff94bb25ca19d3d31f5bb612c65ff3bbd8622 |
--- /dev/null |
+++ b/content/browser/service_worker/service_worker_process_manager.cc |
@@ -0,0 +1,139 @@ |
+// Copyright 2014 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/service_worker_process_manager.h" |
+ |
+#include "content/browser/renderer_host/render_process_host_impl.h" |
+#include "content/browser/service_worker/service_worker_context_wrapper.h" |
+#include "content/public/browser/browser_thread.h" |
+#include "content/public/browser/site_instance.h" |
+#include "url/gurl.h" |
+ |
+namespace base { |
+// Destroying ServiceWorkerProcessManagers only on the UI thread allows the |
+// member WeakPtr to safely guard the object's lifetime when used on that |
+// thread. |
+void DefaultDeleter<content::ServiceWorkerProcessManager>::operator()( |
+ content::ServiceWorkerProcessManager* ptr) const { |
+ content::BrowserThread::DeleteSoon( |
+ content::BrowserThread::UI, FROM_HERE, ptr); |
+} |
+} // namespace base |
+ |
+namespace content { |
+ |
+ServiceWorkerProcessManager::ServiceWorkerProcessManager( |
+ ServiceWorkerContextWrapper* context_wrapper, |
+ const base::Callback<bool(int)>& increment_for_test, |
+ const base::Callback<bool(int)>& decrement_for_test) |
+ : context_wrapper_(context_wrapper), |
+ increment_for_test_(increment_for_test), |
+ decrement_for_test_(decrement_for_test), |
+ weak_this_factory_(this), |
+ weak_this_(weak_this_factory_.GetWeakPtr()) { |
+} |
+ |
+ServiceWorkerProcessManager::~ServiceWorkerProcessManager() { |
+ DCHECK_CURRENTLY_ON(BrowserThread::UI); |
+} |
+ |
+void ServiceWorkerProcessManager::AllocateWorkerProcess( |
+ const std::vector<int>& process_ids, |
+ const GURL& script_url, |
+ const base::Callback<void(ServiceWorkerStatusCode, int process_id)>& |
+ callback) const { |
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, |
+ FROM_HERE, |
+ base::Bind(&ServiceWorkerProcessManager::AllocateWorkerProcess, |
+ weak_this_, |
kinuko
2014/04/28 06:58:16
nit: This doesn't seem necessary given that it's p
Jeffrey Yasskin
2014/04/28 20:47:40
Yeah, I believe we don't need the WeakPtrFactory a
|
+ process_ids, |
+ script_url, |
+ callback)); |
+ return; |
+ } |
+ |
+ 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 (!context_wrapper_->browser_context_) { |
+ // Shutdown has started. |
kinuko
2014/04/28 06:58:16
Should this be checked before we loop over process
Jeffrey Yasskin
2014/04/28 20:47:40
No, if we do that, a lot of the unittests would ne
|
+ BrowserThread::PostTask( |
+ BrowserThread::IO, |
+ FROM_HERE, |
+ base::Bind(callback, SERVICE_WORKER_ERROR_START_WORKER_FAILED, -1)); |
+ } |
+ // No existing processes available; start a new one. |
+ scoped_refptr<SiteInstance> site_instance = SiteInstance::CreateForURL( |
+ context_wrapper_->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 ServiceWorkerProcessManager::ReleaseWorkerProcess(int process_id) { |
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, |
+ FROM_HERE, |
+ base::Bind(&ServiceWorkerProcessManager::ReleaseWorkerProcess, |
+ weak_this_, |
+ process_id)); |
+ return; |
+ } |
+ if (!DecrementWorkerRefcountByPid(process_id)) { |
+ DCHECK(false) << "DecrementWorkerRef(" << process_id |
+ << ") doesn't match a previous IncrementWorkerRef"; |
+ } |
+} |
+ |
+bool ServiceWorkerProcessManager::IncrementWorkerRefcountByPid( |
+ int process_id) const { |
+ if (!increment_for_test_.is_null()) |
+ return increment_for_test_.Run(process_id); |
+ |
+ RenderProcessHost* rph = RenderProcessHost::FromID(process_id); |
+ if (rph && !rph->FastShutdownStarted()) |
+ static_cast<RenderProcessHostImpl*>(rph)->IncrementWorkerRefCount(); |
+ |
+ return rph != NULL; |
kinuko
2014/04/28 06:58:16
Since we only increment worker-ref when line 121 i
Jeffrey Yasskin
2014/04/28 20:47:40
Yep, I forgot to update enough of this when I adde
|
+} |
+ |
+bool ServiceWorkerProcessManager::DecrementWorkerRefcountByPid( |
+ int process_id) const { |
+ if (!decrement_for_test_.is_null()) |
+ return decrement_for_test_.Run(process_id); |
+ |
+ RenderProcessHost* rph = RenderProcessHost::FromID(process_id); |
+ if (rph) |
+ static_cast<RenderProcessHostImpl*>(rph)->DecrementWorkerRefCount(); |
+ |
+ return rph != NULL; |
+} |
+ |
+} // namespace content |