Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(160)

Side by Side Diff: content/browser/service_worker/service_worker_process_manager.cc

Issue 443593002: ServiceWorker: Move worker candidate process knowledge to ServiceWorkerProcessManager. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: RPH observer DCHECK and browser tests build fix Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698