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 |
index 7395e7b7b7768675ed4d9225df4436e6a6ba5917..d50620eca1e334412a351935a932b306238043f9 100644 |
--- a/content/browser/service_worker/service_worker_process_manager.cc |
+++ b/content/browser/service_worker/service_worker_process_manager.cc |
@@ -12,6 +12,18 @@ |
namespace content { |
+namespace { |
+ |
+// Functor to sort by the .second element of a struct. |
+struct SecondGreater { |
+ template <typename Value> |
+ bool operator()(const Value& lhs, const Value& rhs) { |
+ return lhs.second > rhs.second; |
+ } |
+}; |
+ |
+} // namespace |
+ |
static bool IncrementWorkerRefCountByPid(int process_id) { |
RenderProcessHost* rph = RenderProcessHost::FromID(process_id); |
if (!rph || rph->FastShutdownStarted()) |
@@ -61,9 +73,112 @@ void ServiceWorkerProcessManager::Shutdown() { |
instance_info_.clear(); |
} |
+void ServiceWorkerProcessManager::AddScopePendingProcesses( |
+ const GURL& scope, const std::vector<int>& pending_processes) { |
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, |
+ FROM_HERE, |
+ base::Bind(&ServiceWorkerProcessManager::AddScopePendingProcesses, |
+ weak_this_, |
+ scope, |
+ pending_processes)); |
+ return; |
+ } |
+ |
+ ProcessRefMap& process_refs = scope_processes_[scope]; |
+ for (std::vector<int>::const_iterator it = pending_processes.begin(); |
+ it != pending_processes.end(); |
+ ++it) { |
+ if (process_refs.find(*it) != process_refs.end()) |
+ continue; |
+ if (RenderProcessHost* host = RenderProcessHost::FromID(*it)) |
+ host->AddObserver(this); |
+ else if (*it != process_id_for_test_) |
+ continue; |
+ process_refs.insert(std::make_pair(*it, 0)); |
+ } |
+} |
+ |
+void ServiceWorkerProcessManager::AddScopeProcessReference( |
+ const GURL& scope, int process_id) { |
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, |
+ FROM_HERE, |
+ base::Bind(&ServiceWorkerProcessManager::AddScopeProcessReference, |
+ weak_this_, |
+ scope, |
+ process_id)); |
+ return; |
+ } |
+ |
+ ProcessRefMap& process_refs = scope_processes_[scope]; |
+ 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 ServiceWorkerProcessManager::RemoveScopeProcessReference( |
+ const GURL& scope, int process_id) { |
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, |
+ FROM_HERE, |
+ base::Bind(&ServiceWorkerProcessManager::RemoveScopeProcessReference, |
+ weak_this_, |
+ scope, |
+ process_id)); |
+ return; |
+ } |
+ |
+ ScopeProcessRefMap::iterator it = scope_processes_.find(scope); |
+ if (it == scope_processes_.end()) { |
+ NOTREACHED() << "Scope process refrences not found: " << scope; |
+ return; |
+ } |
+ ProcessRefMap& process_refs = it->second; |
+ 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); |
+ if (process_refs.empty()) |
+ scope_processes_.erase(it); |
+ } |
+} |
+ |
+bool ServiceWorkerProcessManager::ScopeHasProcessToRun( |
+ const GURL& scope) const { |
+ ScopeProcessRefMap::const_iterator it = scope_processes_.find(scope); |
+ if (it == scope_processes_.end()) |
+ return false; |
+ return !it->second.empty(); |
+} |
+ |
+void ServiceWorkerProcessManager::RenderProcessHostDestroyed( |
+ RenderProcessHost* host) { |
+ for (ScopeProcessRefMap::iterator it = scope_processes_.begin(); |
+ it != scope_processes_.end(); ) { |
+ ProcessRefMap& process_refs = it->second; |
+ ProcessRefMap::iterator found = process_refs.find(host->GetID()); |
+ if (found != process_refs.end()) { |
+ process_refs.erase(found); |
+ if (process_refs.empty()) { |
+ it = scope_processes_.erase(it); |
+ continue; |
+ } |
+ } |
+ ++it; |
+ } |
+} |
+ |
void ServiceWorkerProcessManager::AllocateWorkerProcess( |
int embedded_worker_id, |
- const std::vector<int>& process_ids, |
+ const GURL& scope, |
const GURL& script_url, |
const base::Callback<void(ServiceWorkerStatusCode, int process_id)>& |
callback) { |
@@ -74,7 +189,7 @@ void ServiceWorkerProcessManager::AllocateWorkerProcess( |
base::Bind(&ServiceWorkerProcessManager::AllocateWorkerProcess, |
weak_this_, |
embedded_worker_id, |
- process_ids, |
+ scope, |
script_url, |
callback)); |
return; |
@@ -93,10 +208,13 @@ void ServiceWorkerProcessManager::AllocateWorkerProcess( |
DCHECK(!ContainsKey(instance_info_, embedded_worker_id)) |
<< embedded_worker_id << " already has a process allocated"; |
- for (std::vector<int>::const_iterator it = process_ids.begin(); |
- it != process_ids.end(); |
- ++it) { |
- if (IncrementWorkerRefCountByPid(*it)) { |
+ std::vector<int> sorted_candidates = SortProcessesForScope(scope); |
+ if (!sorted_candidates.empty()) { |
+ for (std::vector<int>::const_iterator it = sorted_candidates.begin(); |
+ it != sorted_candidates.end(); |
+ ++it) { |
+ if (!IncrementWorkerRefCountByPid(*it)) |
+ continue; |
instance_info_.insert( |
std::make_pair(embedded_worker_id, ProcessInfo(*it))); |
BrowserThread::PostTask(BrowserThread::IO, |
@@ -179,6 +297,22 @@ void ServiceWorkerProcessManager::ReleaseWorkerProcess(int embedded_worker_id) { |
instance_info_.erase(info); |
} |
+std::vector<int> ServiceWorkerProcessManager::SortProcessesForScope( |
+ const GURL& scope) const { |
+ ScopeProcessRefMap::const_iterator it = scope_processes_.find(scope); |
+ if (it == scope_processes_.end()) |
+ return std::vector<int>(); |
+ |
+ std::vector<std::pair<int, int> > counted( |
+ it->second.begin(), it->second.end()); |
+ std::sort(counted.begin(), counted.end(), SecondGreater()); |
+ |
+ std::vector<int> result(counted.size()); |
+ for (size_t i = 0; i < counted.size(); ++i) |
+ result[i] = counted[i].first; |
+ return result; |
+} |
+ |
} // namespace content |
namespace base { |