Chromium Code Reviews| 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..65e9aba6c710af4413368fd7785409b2f376bb2d 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,117 @@ void ServiceWorkerProcessManager::Shutdown() { |
| instance_info_.clear(); |
| } |
| +void ServiceWorkerProcessManager::AddScopePendingProcesses( |
| + const GURL& scope, const std::vector<int>& pending_processes) { |
|
kinuko
2014/08/12 15:27:07
Looks like these methods are called only on IO thr
kinuko
2014/08/12 15:42:48
Oops, this comment was irrelevant, please ignore t
|
| + 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; |
| + RenderProcessHost* host = RenderProcessHost::FromID(*it); |
| + if (!host && *it != process_id_for_test_) |
| + continue; |
| + if (host) { |
| + // FIXME: the pending process maybe contained by multiple scopes, as |
|
Jeffrey Yasskin
2014/08/19 23:42:24
s/maybe/may be/
|
| + // RPH doesn't have "HasObserver" method, let's remove it first. |
|
Jeffrey Yasskin
2014/08/19 23:42:24
s/method, let's/method. Let's/
xiang
2014/08/29 07:49:39
this method is removed.
|
| + host->RemoveObserver(this); |
| + host->AddObserver(this); |
| + } |
| + 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); |
|
Jeffrey Yasskin
2014/08/19 23:42:24
You can write these 4 lines as:
++process_refs[pr
xiang
2014/08/29 07:49:39
Done.
|
| + 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) { |
|
Jeffrey Yasskin
2014/08/19 23:42:23
You're not guarding against releasing a pending pr
xiang
2014/08/29 07:49:39
we don't have pending process now.
|
| + 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) { |
| + ScopeProcessRefMap::iterator it = scope_processes_.begin(); |
| + while (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()) { |
| + 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 +194,7 @@ void ServiceWorkerProcessManager::AllocateWorkerProcess( |
| base::Bind(&ServiceWorkerProcessManager::AllocateWorkerProcess, |
| weak_this_, |
| embedded_worker_id, |
| - process_ids, |
| + scope, |
| script_url, |
| callback)); |
| return; |
| @@ -93,10 +213,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()) { |
|
Jeffrey Yasskin
2014/08/19 23:42:23
You don't need to check this. If sorted_candidates
xiang
2014/08/29 07:49:39
Done.
|
| + 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 +302,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 { |