Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/service_worker/service_worker_process_manager.h" | 5 #include "content/browser/service_worker/service_worker_process_manager.h" |
| 6 | 6 |
| 7 #include "content/browser/renderer_host/render_process_host_impl.h" | 7 #include "content/browser/renderer_host/render_process_host_impl.h" |
| 8 #include "content/browser/service_worker/service_worker_context_wrapper.h" | 8 #include "content/browser/service_worker/service_worker_context_wrapper.h" |
| 9 #include "content/public/browser/browser_thread.h" | 9 #include "content/public/browser/browser_thread.h" |
| 10 #include "content/public/browser/site_instance.h" | 10 #include "content/public/browser/site_instance.h" |
| 11 #include "url/gurl.h" | 11 #include "url/gurl.h" |
| 12 | 12 |
| 13 namespace content { | 13 namespace content { |
| 14 | 14 |
| 15 namespace { | |
| 16 | |
| 17 // Functor to sort by the .second element of a struct. | |
| 18 struct SecondGreater { | |
| 19 template <typename Value> | |
| 20 bool operator()(const Value& lhs, const Value& rhs) { | |
| 21 return lhs.second > rhs.second; | |
| 22 } | |
| 23 }; | |
| 24 | |
| 25 } // namespace | |
| 26 | |
| 15 static bool IncrementWorkerRefCountByPid(int process_id) { | 27 static bool IncrementWorkerRefCountByPid(int process_id) { |
| 16 RenderProcessHost* rph = RenderProcessHost::FromID(process_id); | 28 RenderProcessHost* rph = RenderProcessHost::FromID(process_id); |
| 17 if (!rph || rph->FastShutdownStarted()) | 29 if (!rph || rph->FastShutdownStarted()) |
| 18 return false; | 30 return false; |
| 19 | 31 |
| 20 static_cast<RenderProcessHostImpl*>(rph)->IncrementWorkerRefCount(); | 32 static_cast<RenderProcessHostImpl*>(rph)->IncrementWorkerRefCount(); |
| 21 return true; | 33 return true; |
| 22 } | 34 } |
| 23 | 35 |
| 24 ServiceWorkerProcessManager::ProcessInfo::ProcessInfo( | 36 ServiceWorkerProcessManager::ProcessInfo::ProcessInfo( |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 54 for (std::map<int, ProcessInfo>::const_iterator it = instance_info_.begin(); | 66 for (std::map<int, ProcessInfo>::const_iterator it = instance_info_.begin(); |
| 55 it != instance_info_.end(); | 67 it != instance_info_.end(); |
| 56 ++it) { | 68 ++it) { |
| 57 RenderProcessHost* rph = RenderProcessHost::FromID(it->second.process_id); | 69 RenderProcessHost* rph = RenderProcessHost::FromID(it->second.process_id); |
| 58 DCHECK(rph); | 70 DCHECK(rph); |
| 59 static_cast<RenderProcessHostImpl*>(rph)->DecrementWorkerRefCount(); | 71 static_cast<RenderProcessHostImpl*>(rph)->DecrementWorkerRefCount(); |
| 60 } | 72 } |
| 61 instance_info_.clear(); | 73 instance_info_.clear(); |
| 62 } | 74 } |
| 63 | 75 |
| 76 void ServiceWorkerProcessManager::AddScopePendingProcesses( | |
| 77 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
| |
| 78 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
| 79 BrowserThread::PostTask( | |
| 80 BrowserThread::UI, | |
| 81 FROM_HERE, | |
| 82 base::Bind(&ServiceWorkerProcessManager::AddScopePendingProcesses, | |
| 83 weak_this_, | |
| 84 scope, | |
| 85 pending_processes)); | |
| 86 return; | |
| 87 } | |
| 88 | |
| 89 ProcessRefMap& process_refs = scope_processes_[scope]; | |
| 90 for (std::vector<int>::const_iterator it = pending_processes.begin(); | |
| 91 it != pending_processes.end(); | |
| 92 ++it) { | |
| 93 if (process_refs.find(*it) != process_refs.end()) | |
| 94 continue; | |
| 95 RenderProcessHost* host = RenderProcessHost::FromID(*it); | |
| 96 if (!host && *it != process_id_for_test_) | |
| 97 continue; | |
| 98 if (host) { | |
| 99 // FIXME: the pending process maybe contained by multiple scopes, as | |
|
Jeffrey Yasskin
2014/08/19 23:42:24
s/maybe/may be/
| |
| 100 // 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.
| |
| 101 host->RemoveObserver(this); | |
| 102 host->AddObserver(this); | |
| 103 } | |
| 104 process_refs.insert(std::make_pair(*it, 0)); | |
| 105 } | |
| 106 } | |
| 107 | |
| 108 void ServiceWorkerProcessManager::AddScopeProcessReference( | |
| 109 const GURL& scope, int process_id) { | |
| 110 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
| 111 BrowserThread::PostTask( | |
| 112 BrowserThread::UI, | |
| 113 FROM_HERE, | |
| 114 base::Bind(&ServiceWorkerProcessManager::AddScopeProcessReference, | |
| 115 weak_this_, | |
| 116 scope, | |
| 117 process_id)); | |
| 118 return; | |
| 119 } | |
| 120 | |
| 121 ProcessRefMap& process_refs = scope_processes_[scope]; | |
| 122 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.
| |
| 123 if (found == process_refs.end()) | |
| 124 found = process_refs.insert(std::make_pair(process_id, 0)).first; | |
| 125 ++found->second; | |
| 126 } | |
| 127 | |
| 128 void ServiceWorkerProcessManager::RemoveScopeProcessReference( | |
| 129 const GURL& scope, int process_id) { | |
| 130 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
| 131 BrowserThread::PostTask( | |
| 132 BrowserThread::UI, | |
| 133 FROM_HERE, | |
| 134 base::Bind(&ServiceWorkerProcessManager::RemoveScopeProcessReference, | |
| 135 weak_this_, | |
| 136 scope, | |
| 137 process_id)); | |
| 138 return; | |
| 139 } | |
| 140 | |
| 141 ScopeProcessRefMap::iterator it = scope_processes_.find(scope); | |
| 142 if (it == scope_processes_.end()) { | |
| 143 NOTREACHED() << "Scope process refrences not found: " << scope; | |
| 144 return; | |
| 145 } | |
| 146 ProcessRefMap& process_refs = it->second; | |
| 147 ProcessRefMap::iterator found = process_refs.find(process_id); | |
| 148 if (found == process_refs.end()) { | |
| 149 NOTREACHED() << "Releasing unknown process ref " << process_id; | |
| 150 return; | |
| 151 } | |
| 152 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.
| |
| 153 process_refs.erase(found); | |
| 154 if (process_refs.empty()) | |
| 155 scope_processes_.erase(it); | |
| 156 } | |
| 157 } | |
| 158 | |
| 159 bool ServiceWorkerProcessManager::ScopeHasProcessToRun( | |
| 160 const GURL& scope) const { | |
| 161 ScopeProcessRefMap::const_iterator it = scope_processes_.find(scope); | |
| 162 if (it == scope_processes_.end()) | |
| 163 return false; | |
| 164 return !it->second.empty(); | |
| 165 } | |
| 166 | |
| 167 void ServiceWorkerProcessManager::RenderProcessHostDestroyed( | |
| 168 RenderProcessHost* host) { | |
| 169 ScopeProcessRefMap::iterator it = scope_processes_.begin(); | |
| 170 while (it != scope_processes_.end()) { | |
| 171 ProcessRefMap& process_refs = it->second; | |
| 172 ProcessRefMap::iterator found = process_refs.find(host->GetID()); | |
| 173 if (found != process_refs.end()) { | |
| 174 process_refs.erase(found); | |
| 175 if (process_refs.empty()) { | |
| 176 scope_processes_.erase(it++); | |
| 177 continue; | |
| 178 } | |
| 179 } | |
| 180 ++it; | |
| 181 } | |
| 182 } | |
| 183 | |
| 64 void ServiceWorkerProcessManager::AllocateWorkerProcess( | 184 void ServiceWorkerProcessManager::AllocateWorkerProcess( |
| 65 int embedded_worker_id, | 185 int embedded_worker_id, |
| 66 const std::vector<int>& process_ids, | 186 const GURL& scope, |
| 67 const GURL& script_url, | 187 const GURL& script_url, |
| 68 const base::Callback<void(ServiceWorkerStatusCode, int process_id)>& | 188 const base::Callback<void(ServiceWorkerStatusCode, int process_id)>& |
| 69 callback) { | 189 callback) { |
| 70 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 190 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 71 BrowserThread::PostTask( | 191 BrowserThread::PostTask( |
| 72 BrowserThread::UI, | 192 BrowserThread::UI, |
| 73 FROM_HERE, | 193 FROM_HERE, |
| 74 base::Bind(&ServiceWorkerProcessManager::AllocateWorkerProcess, | 194 base::Bind(&ServiceWorkerProcessManager::AllocateWorkerProcess, |
| 75 weak_this_, | 195 weak_this_, |
| 76 embedded_worker_id, | 196 embedded_worker_id, |
| 77 process_ids, | 197 scope, |
| 78 script_url, | 198 script_url, |
| 79 callback)); | 199 callback)); |
| 80 return; | 200 return; |
| 81 } | 201 } |
| 82 | 202 |
| 83 if (process_id_for_test_ != -1) { | 203 if (process_id_for_test_ != -1) { |
| 84 // Let tests specify the returned process ID. Note: We may need to be able | 204 // Let tests specify the returned process ID. Note: We may need to be able |
| 85 // to specify the error code too. | 205 // to specify the error code too. |
| 86 BrowserThread::PostTask( | 206 BrowserThread::PostTask( |
| 87 BrowserThread::IO, | 207 BrowserThread::IO, |
| 88 FROM_HERE, | 208 FROM_HERE, |
| 89 base::Bind(callback, SERVICE_WORKER_OK, process_id_for_test_)); | 209 base::Bind(callback, SERVICE_WORKER_OK, process_id_for_test_)); |
| 90 return; | 210 return; |
| 91 } | 211 } |
| 92 | 212 |
| 93 DCHECK(!ContainsKey(instance_info_, embedded_worker_id)) | 213 DCHECK(!ContainsKey(instance_info_, embedded_worker_id)) |
| 94 << embedded_worker_id << " already has a process allocated"; | 214 << embedded_worker_id << " already has a process allocated"; |
| 95 | 215 |
| 96 for (std::vector<int>::const_iterator it = process_ids.begin(); | 216 std::vector<int> sorted_candidates = SortProcessesForScope(scope); |
| 97 it != process_ids.end(); | 217 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.
| |
| 98 ++it) { | 218 for (std::vector<int>::const_iterator it = sorted_candidates.begin(); |
| 99 if (IncrementWorkerRefCountByPid(*it)) { | 219 it != sorted_candidates.end(); |
| 220 ++it) { | |
| 221 if (!IncrementWorkerRefCountByPid(*it)) | |
| 222 continue; | |
| 100 instance_info_.insert( | 223 instance_info_.insert( |
| 101 std::make_pair(embedded_worker_id, ProcessInfo(*it))); | 224 std::make_pair(embedded_worker_id, ProcessInfo(*it))); |
| 102 BrowserThread::PostTask(BrowserThread::IO, | 225 BrowserThread::PostTask(BrowserThread::IO, |
| 103 FROM_HERE, | 226 FROM_HERE, |
| 104 base::Bind(callback, SERVICE_WORKER_OK, *it)); | 227 base::Bind(callback, SERVICE_WORKER_OK, *it)); |
| 105 return; | 228 return; |
| 106 } | 229 } |
| 107 } | 230 } |
| 108 | 231 |
| 109 if (!browser_context_) { | 232 if (!browser_context_) { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 172 } else { | 295 } else { |
| 173 rph = RenderProcessHost::FromID(info->second.process_id); | 296 rph = RenderProcessHost::FromID(info->second.process_id); |
| 174 DCHECK(rph) | 297 DCHECK(rph) |
| 175 << "Process " << info->second.process_id | 298 << "Process " << info->second.process_id |
| 176 << " was destroyed unexpectedly. Did we actually hold a reference?"; | 299 << " was destroyed unexpectedly. Did we actually hold a reference?"; |
| 177 } | 300 } |
| 178 static_cast<RenderProcessHostImpl*>(rph)->DecrementWorkerRefCount(); | 301 static_cast<RenderProcessHostImpl*>(rph)->DecrementWorkerRefCount(); |
| 179 instance_info_.erase(info); | 302 instance_info_.erase(info); |
| 180 } | 303 } |
| 181 | 304 |
| 305 std::vector<int> ServiceWorkerProcessManager::SortProcessesForScope( | |
| 306 const GURL& scope) const { | |
| 307 ScopeProcessRefMap::const_iterator it = scope_processes_.find(scope); | |
| 308 if (it == scope_processes_.end()) | |
| 309 return std::vector<int>(); | |
| 310 | |
| 311 std::vector<std::pair<int, int> > counted( | |
| 312 it->second.begin(), it->second.end()); | |
| 313 std::sort(counted.begin(), counted.end(), SecondGreater()); | |
| 314 | |
| 315 std::vector<int> result(counted.size()); | |
| 316 for (size_t i = 0; i < counted.size(); ++i) | |
| 317 result[i] = counted[i].first; | |
| 318 return result; | |
| 319 } | |
| 320 | |
| 182 } // namespace content | 321 } // namespace content |
| 183 | 322 |
| 184 namespace base { | 323 namespace base { |
| 185 // Destroying ServiceWorkerProcessManagers only on the UI thread allows the | 324 // Destroying ServiceWorkerProcessManagers only on the UI thread allows the |
| 186 // member WeakPtr to safely guard the object's lifetime when used on that | 325 // member WeakPtr to safely guard the object's lifetime when used on that |
| 187 // thread. | 326 // thread. |
| 188 void DefaultDeleter<content::ServiceWorkerProcessManager>::operator()( | 327 void DefaultDeleter<content::ServiceWorkerProcessManager>::operator()( |
| 189 content::ServiceWorkerProcessManager* ptr) const { | 328 content::ServiceWorkerProcessManager* ptr) const { |
| 190 content::BrowserThread::DeleteSoon( | 329 content::BrowserThread::DeleteSoon( |
| 191 content::BrowserThread::UI, FROM_HERE, ptr); | 330 content::BrowserThread::UI, FROM_HERE, ptr); |
| 192 } | 331 } |
| 193 } // namespace base | 332 } // namespace base |
| OLD | NEW |