| 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 {
|
|
|