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

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

Issue 304543002: Show the unregistered workers in chrome://serviceworker-internals and chrome://inspect (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Pass live_registrations to chrome://inspect. Created 6 years, 6 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_internals_ui.h" 5 #include "content/browser/service_worker/service_worker_internals_ui.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 17 matching lines...) Expand all
28 28
29 using base::DictionaryValue; 29 using base::DictionaryValue;
30 using base::FundamentalValue; 30 using base::FundamentalValue;
31 using base::ListValue; 31 using base::ListValue;
32 using base::StringValue; 32 using base::StringValue;
33 using base::Value; 33 using base::Value;
34 using base::WeakPtr; 34 using base::WeakPtr;
35 35
36 namespace content { 36 namespace content {
37 37
38 // This class proxies calls to the ServiceWorker APIs on the IO 38 namespace {
39 // thread, and then calls back JavaScript on the UI thread. 39
40 class ServiceWorkerInternalsUI::OperationProxy 40 typedef base::Callback<void(ServiceWorkerStatusCode)> StatusCallback;
41 : public base::RefCountedThreadSafe< 41 typedef void (ServiceWorkerVersion::*ServiceWorkerVersionMethod)(
42 ServiceWorkerInternalsUI::OperationProxy> { 42 const StatusCallback& callback);
falken 2014/05/28 08:21:40 These typedefs are duplicated in the .h file.
horo 2014/05/28 09:06:39 Done.
43 public: 43
44 OperationProxy(const WeakPtr<ServiceWorkerInternalsUI> internals, 44 void OperationCompleteCallback(
45 scoped_ptr<ListValue> original_args) 45 const WeakPtr<ServiceWorkerInternalsUI> internals,
falken 2014/05/28 08:21:40 Chrome code doesn't seem to use const WeakPtr... I
horo 2014/05/28 09:06:39 Done.
46 : internals_(internals), original_args_(original_args.Pass()) {} 46 int callback_id,
47 47 ServiceWorkerStatusCode status) {
48 void GetRegistrationsOnIOThread(int partition_id, 48 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
49 ServiceWorkerContextWrapper* context, 49 BrowserThread::PostTask(
50 const base::FilePath& context_path); 50 BrowserThread::UI,
51 void UnregisterOnIOThread(scoped_refptr<ServiceWorkerContextWrapper> context, 51 FROM_HERE,
52 const GURL& scope); 52 base::Bind(OperationCompleteCallback, internals, callback_id, status));
53 void StartWorkerOnIOThread(scoped_refptr<ServiceWorkerContextWrapper> context, 53 return;
54 const GURL& scope); 54 }
55 void StopWorkerOnIOThread(scoped_refptr<ServiceWorkerContextWrapper> context, 55 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
56 const GURL& scope); 56 if (internals)
falken 2014/05/28 08:21:40 this if should probably have braces as the body ha
horo 2014/05/28 09:06:39 Done.
57 void DispatchSyncEventToWorkerOnIOThread( 57 internals->web_ui()->CallJavascriptFunction(
58 scoped_refptr<ServiceWorkerContextWrapper> context, 58 "serviceworker.onOperationComplete",
59 const GURL& scope); 59 FundamentalValue(static_cast<int>(status)),
60 void InspectWorkerOnIOThread( 60 FundamentalValue(callback_id));
61 scoped_refptr<ServiceWorkerContextWrapper> context, 61 }
62 const GURL& scope); 62
63 63 void CallServiceWorkerVersionMethodWithVersionID(
64 private: 64 ServiceWorkerVersionMethod method,
65 friend class base::RefCountedThreadSafe<OperationProxy>; 65 scoped_refptr<ServiceWorkerContextWrapper> context,
66 ~OperationProxy() {} 66 int64 version_id,
67 void OnHaveRegistrations( 67 const StatusCallback& callback) {
68 int partition_id, 68 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
69 const base::FilePath& context_path, 69 BrowserThread::PostTask(
70 const std::vector<ServiceWorkerRegistrationInfo>& registrations); 70 BrowserThread::IO,
71 71 FROM_HERE,
72 void OperationComplete(ServiceWorkerStatusCode status); 72 base::Bind(CallServiceWorkerVersionMethodWithVersionID,
73 73 method,
74 void StartActiveWorker( 74 context,
75 ServiceWorkerStatusCode status, 75 version_id,
76 const scoped_refptr<ServiceWorkerRegistration>& registration); 76 callback));
77 77 return;
78 void StopActiveWorker( 78 }
79 ServiceWorkerStatusCode status, 79 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
80 const scoped_refptr<ServiceWorkerRegistration>& registration); 80 scoped_refptr<ServiceWorkerVersion> version =
81 81 context->context()->GetLiveVersion(version_id);
82 void DispatchSyncEventToActiveWorker( 82 if (!version) {
83 ServiceWorkerStatusCode status, 83 callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND);
84 const scoped_refptr<ServiceWorkerRegistration>& registration); 84 return;
85 85 }
86 void InspectActiveWorker( 86 (*version.*method)(callback);
87 const ServiceWorkerContextCore* const service_worker_context, 87 }
88 ServiceWorkerStatusCode status, 88
89 const scoped_refptr<ServiceWorkerRegistration>& registration); 89 void UnregisterWithScope(scoped_refptr<ServiceWorkerContextWrapper> context,
90 90 const GURL& scope,
91 void InspectWorkerOnUIThread( 91 const StatusCallback& callback) {
92 const ServiceWorkerContextCore* const service_worker_context, 92 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
93 int64 version_id); 93 BrowserThread::PostTask(
94 94 BrowserThread::IO,
95 WeakPtr<ServiceWorkerInternalsUI> internals_; 95 FROM_HERE,
96 scoped_ptr<ListValue> original_args_; 96 base::Bind(UnregisterWithScope, context, scope, callback));
97 }; 97 return;
98 }
99 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
100 context->context()->UnregisterServiceWorker(scope, callback);
101 }
102
103 void WorkerStarted(const scoped_refptr<ServiceWorkerRegistration>& registration,
104 const StatusCallback& callback,
105 ServiceWorkerStatusCode status) {
106 callback.Run(status);
107 }
108
109 void StartActiveWorker(
110 const StatusCallback& callback,
111 ServiceWorkerStatusCode status,
112 const scoped_refptr<ServiceWorkerRegistration>& registration) {
113 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
114 if (status == SERVICE_WORKER_OK) {
115 // Pass the reference of |registration| to WorkerStarted callback to prevent
116 // it from being deleted while starting the worker. It the refcount of
falken 2014/05/28 08:21:40 s/It/If/.... but why does StartWorker destroy the
horo 2014/05/28 09:06:39 Done. If there is no ServiceWorkerHandle which has
117 // |registration| is 1, it will be deleted after WorkerStarted is called.
118 registration->active_version()->StartWorker(
119 base::Bind(WorkerStarted, registration, callback));
120 return;
121 }
122 callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND);
123 }
124
125 void FindRegistrationForPattern(
126 scoped_refptr<ServiceWorkerContextWrapper> context,
127 const GURL& scope,
128 const ServiceWorkerStorage::FindRegistrationCallback callback) {
129 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
130 BrowserThread::PostTask(
131 BrowserThread::IO,
132 FROM_HERE,
133 base::Bind(FindRegistrationForPattern, context, scope, callback));
134 return;
135 }
136 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
137 context->context()->storage()->FindRegistrationForPattern(scope, callback);
138 }
139
140 void UpdateVersionInfo(const ServiceWorkerVersionInfo& version,
141 DictionaryValue* info) {
142 switch (version.running_status) {
143 case ServiceWorkerVersion::STOPPED:
144 info->SetString("running_status", "STOPPED");
145 break;
146 case ServiceWorkerVersion::STARTING:
147 info->SetString("running_status", "STARTING");
148 break;
149 case ServiceWorkerVersion::RUNNING:
150 info->SetString("running_status", "RUNNING");
151 break;
152 case ServiceWorkerVersion::STOPPING:
153 info->SetString("running_status", "STOPPING");
154 break;
155 }
156
157 switch (version.status) {
158 case ServiceWorkerVersion::NEW:
159 info->SetString("status", "NEW");
160 break;
161 case ServiceWorkerVersion::INSTALLING:
162 info->SetString("status", "INSTALLING");
163 break;
164 case ServiceWorkerVersion::INSTALLED:
165 info->SetString("status", "INSTALLED");
166 break;
167 case ServiceWorkerVersion::ACTIVATING:
168 info->SetString("status", "ACTIVATING");
169 break;
170 case ServiceWorkerVersion::ACTIVE:
171 info->SetString("status", "ACTIVE");
172 break;
173 case ServiceWorkerVersion::DEACTIVATED:
174 info->SetString("status", "DEACTIVATED");
175 break;
176 }
177 info->SetString("version_id", base::Int64ToString(version.version_id));
178 info->SetInteger("process_id", version.process_id);
179 info->SetInteger("thread_id", version.thread_id);
180 info->SetInteger("devtools_agent_route_id", version.devtools_agent_route_id);
181 }
182
183 ListValue* GetRegistrationListValue(
184 const std::vector<ServiceWorkerRegistrationInfo>& registrations) {
185 ListValue* result = new ListValue();
186 for (std::vector<ServiceWorkerRegistrationInfo>::const_iterator it =
187 registrations.begin();
188 it != registrations.end();
189 ++it) {
190 const ServiceWorkerRegistrationInfo& registration = *it;
191 DictionaryValue* registration_info = new DictionaryValue();
192 registration_info->SetString("scope", registration.pattern.spec());
193 registration_info->SetString("script_url", registration.script_url.spec());
194 registration_info->SetString(
195 "registration_id", base::Int64ToString(registration.registration_id));
196
197 if (!registration.active_version.is_null) {
198 DictionaryValue* active_info = new DictionaryValue();
199 UpdateVersionInfo(registration.active_version, active_info);
200 registration_info->Set("active", active_info);
201 }
202
203 if (!registration.pending_version.is_null) {
204 DictionaryValue* pending_info = new DictionaryValue();
205 UpdateVersionInfo(registration.pending_version, pending_info);
206 registration_info->Set("pending", pending_info);
207 }
208
209 result->Append(registration_info);
210 }
211 return result;
212 }
213
214 ListValue* GetVersionListValue(
215 const std::vector<ServiceWorkerVersionInfo>& versions) {
216 ListValue* result = new ListValue();
217 for (std::vector<ServiceWorkerVersionInfo>::const_iterator it =
218 versions.begin();
219 it != versions.end();
220 ++it) {
221 DictionaryValue* info = new DictionaryValue();
222 UpdateVersionInfo(*it, info);
223 result->Append(info);
224 }
225 return result;
226 }
227
228 void GetRegistrationsOnIOThread(
229 scoped_refptr<ServiceWorkerContextWrapper> context,
230 base::Callback<void(const std::vector<ServiceWorkerRegistrationInfo>&)>
231 callback) {
232 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
233 context->context()->storage()->GetAllRegistrations(callback);
234 }
235
236 void OnStoredRegistrations(
237 scoped_refptr<ServiceWorkerContextWrapper> context,
238 base::Callback<void(const std::vector<ServiceWorkerRegistrationInfo>&,
239 const std::vector<ServiceWorkerVersionInfo>&,
240 const std::vector<ServiceWorkerRegistrationInfo>&)>
241 callback,
242 const std::vector<ServiceWorkerRegistrationInfo>& stored_registrations) {
243 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
244 BrowserThread::PostTask(
245 BrowserThread::UI,
246 FROM_HERE,
247 base::Bind(callback,
248 context->context()->GetAllLiveRegistrationInfo(),
249 context->context()->GetAllLiveVersionInfo(),
250 stored_registrations));
251 }
252
253 void OnAllRegistrations(
254 const WeakPtr<ServiceWorkerInternalsUI> internals,
falken 2014/05/28 08:21:40 const WeakPtr again
horo 2014/05/28 09:06:39 Done.
255 int partition_id,
256 const base::FilePath& context_path,
257 const std::vector<ServiceWorkerRegistrationInfo>& live_registrations,
258 const std::vector<ServiceWorkerVersionInfo>& live_versions,
259 const std::vector<ServiceWorkerRegistrationInfo>& stored_registrations) {
260 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
261 if (!internals)
262 return;
263
264 ScopedVector<const Value> args;
265 args.push_back(GetRegistrationListValue(live_registrations));
266 args.push_back(GetVersionListValue(live_versions));
267 args.push_back(GetRegistrationListValue(stored_registrations));
268 args.push_back(new FundamentalValue(partition_id));
269 args.push_back(new StringValue(context_path.value()));
270 internals->web_ui()->CallJavascriptFunction("serviceworker.onPartitionData",
271 args.get());
272 }
273
274 } // namespace
98 275
99 class ServiceWorkerInternalsUI::PartitionObserver 276 class ServiceWorkerInternalsUI::PartitionObserver
100 : public ServiceWorkerContextObserver { 277 : public ServiceWorkerContextObserver {
101 public: 278 public:
102 PartitionObserver(int partition_id, WebUI* web_ui) 279 PartitionObserver(int partition_id, WebUI* web_ui)
103 : partition_id_(partition_id), web_ui_(web_ui) {} 280 : partition_id_(partition_id), web_ui_(web_ui) {}
104 virtual ~PartitionObserver() {} 281 virtual ~PartitionObserver() {}
105 // ServiceWorkerContextObserver overrides: 282 // ServiceWorkerContextObserver overrides:
106 virtual void OnWorkerStarted(int64 version_id, 283 virtual void OnWorkerStarted(int64 version_id,
107 int process_id, 284 int process_id,
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 379
203 BrowserContext* browser_context = 380 BrowserContext* browser_context =
204 web_ui->GetWebContents()->GetBrowserContext(); 381 web_ui->GetWebContents()->GetBrowserContext();
205 WebUIDataSource::Add(browser_context, source); 382 WebUIDataSource::Add(browser_context, source);
206 383
207 web_ui->RegisterMessageCallback( 384 web_ui->RegisterMessageCallback(
208 "getAllRegistrations", 385 "getAllRegistrations",
209 base::Bind(&ServiceWorkerInternalsUI::GetAllRegistrations, 386 base::Bind(&ServiceWorkerInternalsUI::GetAllRegistrations,
210 base::Unretained(this))); 387 base::Unretained(this)));
211 web_ui->RegisterMessageCallback( 388 web_ui->RegisterMessageCallback(
212 "start", 389 "stop",
213 base::Bind(&ServiceWorkerInternalsUI::StartWorker, 390 base::Bind(&ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod,
214 base::Unretained(this))); 391 base::Unretained(this),
392 &ServiceWorkerVersion::StopWorker));
215 web_ui->RegisterMessageCallback( 393 web_ui->RegisterMessageCallback(
216 "stop", 394 "sync",
217 base::Bind(&ServiceWorkerInternalsUI::StopWorker, 395 base::Bind(&ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod,
396 base::Unretained(this),
397 &ServiceWorkerVersion::DispatchSyncEvent));
398 web_ui->RegisterMessageCallback(
399 "inspect",
400 base::Bind(&ServiceWorkerInternalsUI::InspectWorker,
218 base::Unretained(this))); 401 base::Unretained(this)));
219 web_ui->RegisterMessageCallback( 402 web_ui->RegisterMessageCallback(
220 "unregister", 403 "unregister",
221 base::Bind(&ServiceWorkerInternalsUI::Unregister, 404 base::Bind(&ServiceWorkerInternalsUI::Unregister,
222 base::Unretained(this))); 405 base::Unretained(this)));
223 web_ui->RegisterMessageCallback( 406 web_ui->RegisterMessageCallback(
224 "sync", 407 "start",
225 base::Bind(&ServiceWorkerInternalsUI::DispatchSyncEventToWorker, 408 base::Bind(&ServiceWorkerInternalsUI::StartWorker,
226 base::Unretained(this)));
227 web_ui->RegisterMessageCallback(
228 "inspect",
229 base::Bind(&ServiceWorkerInternalsUI::InspectWorker,
230 base::Unretained(this))); 409 base::Unretained(this)));
231 } 410 }
232 411
233 ServiceWorkerInternalsUI::~ServiceWorkerInternalsUI() { 412 ServiceWorkerInternalsUI::~ServiceWorkerInternalsUI() {
234 BrowserContext* browser_context = 413 BrowserContext* browser_context =
235 web_ui()->GetWebContents()->GetBrowserContext(); 414 web_ui()->GetWebContents()->GetBrowserContext();
236 // Safe to use base::Unretained(this) because 415 // Safe to use base::Unretained(this) because
237 // ForEachStoragePartition is synchronous. 416 // ForEachStoragePartition is synchronous.
238 BrowserContext::StoragePartitionCallback remove_observer_cb = 417 BrowserContext::StoragePartitionCallback remove_observer_cb =
239 base::Bind(&ServiceWorkerInternalsUI::RemoveObserverFromStoragePartition, 418 base::Bind(&ServiceWorkerInternalsUI::RemoveObserverFromStoragePartition,
240 base::Unretained(this)); 419 base::Unretained(this));
241 BrowserContext::ForEachStoragePartition(browser_context, remove_observer_cb); 420 BrowserContext::ForEachStoragePartition(browser_context, remove_observer_cb);
242 } 421 }
243 422
244 void ServiceWorkerInternalsUI::GetAllRegistrations(const ListValue* args) { 423 void ServiceWorkerInternalsUI::GetAllRegistrations(const ListValue* args) {
245 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 424 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
246
247 BrowserContext* browser_context = 425 BrowserContext* browser_context =
248 web_ui()->GetWebContents()->GetBrowserContext(); 426 web_ui()->GetWebContents()->GetBrowserContext();
249
250 // Safe to use base::Unretained(this) because 427 // Safe to use base::Unretained(this) because
251 // ForEachStoragePartition is synchronous. 428 // ForEachStoragePartition is synchronous.
252 BrowserContext::StoragePartitionCallback add_context_cb = 429 BrowserContext::StoragePartitionCallback add_context_cb =
253 base::Bind(&ServiceWorkerInternalsUI::AddContextFromStoragePartition, 430 base::Bind(&ServiceWorkerInternalsUI::AddContextFromStoragePartition,
254 base::Unretained(this)); 431 base::Unretained(this));
255 BrowserContext::ForEachStoragePartition(browser_context, add_context_cb); 432 BrowserContext::ForEachStoragePartition(browser_context, add_context_cb);
256 } 433 }
257 434
258 void ServiceWorkerInternalsUI::AddContextFromStoragePartition( 435 void ServiceWorkerInternalsUI::AddContextFromStoragePartition(
259 StoragePartition* partition) { 436 StoragePartition* partition) {
260 int partition_id = 0; 437 int partition_id = 0;
261 scoped_refptr<ServiceWorkerContextWrapper> context = 438 scoped_refptr<ServiceWorkerContextWrapper> context =
262 static_cast<ServiceWorkerContextWrapper*>( 439 static_cast<ServiceWorkerContextWrapper*>(
263 partition->GetServiceWorkerContext()); 440 partition->GetServiceWorkerContext());
264 if (PartitionObserver* observer = 441 if (PartitionObserver* observer =
265 observers_.get(reinterpret_cast<uintptr_t>(partition))) { 442 observers_.get(reinterpret_cast<uintptr_t>(partition))) {
266 partition_id = observer->partition_id(); 443 partition_id = observer->partition_id();
267 } else { 444 } else {
268 partition_id = next_partition_id_++; 445 partition_id = next_partition_id_++;
269 scoped_ptr<PartitionObserver> new_observer( 446 scoped_ptr<PartitionObserver> new_observer(
270 new PartitionObserver(partition_id, web_ui())); 447 new PartitionObserver(partition_id, web_ui()));
271 context->AddObserver(new_observer.get()); 448 context->AddObserver(new_observer.get());
272 observers_.set(reinterpret_cast<uintptr_t>(partition), new_observer.Pass()); 449 observers_.set(reinterpret_cast<uintptr_t>(partition), new_observer.Pass());
273 } 450 }
274 BrowserThread::PostTask( 451 BrowserThread::PostTask(
275 BrowserThread::IO, 452 BrowserThread::IO,
276 FROM_HERE, 453 FROM_HERE,
277 base::Bind( 454 base::Bind(GetRegistrationsOnIOThread,
278 &ServiceWorkerInternalsUI::OperationProxy::GetRegistrationsOnIOThread, 455 context,
279 new OperationProxy(AsWeakPtr(), scoped_ptr<ListValue>()), 456 base::Bind(OnStoredRegistrations,
280 partition_id, 457 context,
281 context, 458 base::Bind(OnAllRegistrations,
282 partition->GetPath())); 459 AsWeakPtr(),
460 partition_id,
461 partition->GetPath()))));
283 } 462 }
284 463
285 void ServiceWorkerInternalsUI::RemoveObserverFromStoragePartition( 464 void ServiceWorkerInternalsUI::RemoveObserverFromStoragePartition(
286 StoragePartition* partition) { 465 StoragePartition* partition) {
287 scoped_ptr<PartitionObserver> observer( 466 scoped_ptr<PartitionObserver> observer(
288 observers_.take_and_erase(reinterpret_cast<uintptr_t>(partition))); 467 observers_.take_and_erase(reinterpret_cast<uintptr_t>(partition)));
289 if (!observer.get()) 468 if (!observer.get())
290 return; 469 return;
291 scoped_refptr<ServiceWorkerContextWrapper> context = 470 scoped_refptr<ServiceWorkerContextWrapper> context =
292 static_cast<ServiceWorkerContextWrapper*>( 471 static_cast<ServiceWorkerContextWrapper*>(
293 partition->GetServiceWorkerContext()); 472 partition->GetServiceWorkerContext());
294 context->RemoveObserver(observer.get()); 473 context->RemoveObserver(observer.get());
295 } 474 }
296 475
297 namespace { 476 void ServiceWorkerInternalsUI::FindContext(
298 void FindContext(const base::FilePath& partition_path, 477 int partition_id,
299 StoragePartition** result_partition, 478 StoragePartition** result_partition,
300 scoped_refptr<ServiceWorkerContextWrapper>* result_context, 479 StoragePartition* storage_partition) const {
301 StoragePartition* storage_partition) { 480 PartitionObserver* observer =
302 if (storage_partition->GetPath() == partition_path) { 481 observers_.get(reinterpret_cast<uintptr_t>(storage_partition));
482 if (observer && partition_id == observer->partition_id()) {
303 *result_partition = storage_partition; 483 *result_partition = storage_partition;
304 *result_context = static_cast<ServiceWorkerContextWrapper*>(
305 storage_partition->GetServiceWorkerContext());
306 } 484 }
307 } 485 }
308 } // namespace
309 486
310 bool ServiceWorkerInternalsUI::GetRegistrationInfo( 487 bool ServiceWorkerInternalsUI::GetServiceWorkerContext(
311 const ListValue* args, 488 int partition_id,
312 base::FilePath* partition_path,
313 GURL* scope,
314 scoped_refptr<ServiceWorkerContextWrapper>* context) const { 489 scoped_refptr<ServiceWorkerContextWrapper>* context) const {
315 base::FilePath::StringType path_string;
316 if (!args->GetString(0, &path_string))
317 return false;
318 *partition_path = base::FilePath(path_string);
319
320 std::string scope_string;
321 if (!args->GetString(1, &scope_string))
322 return false;
323 *scope = GURL(scope_string);
324
325 BrowserContext* browser_context = 490 BrowserContext* browser_context =
326 web_ui()->GetWebContents()->GetBrowserContext(); 491 web_ui()->GetWebContents()->GetBrowserContext();
327
328 StoragePartition* result_partition(NULL); 492 StoragePartition* result_partition(NULL);
329 BrowserContext::StoragePartitionCallback find_context_cb = 493 BrowserContext::StoragePartitionCallback find_context_cb =
330 base::Bind(&FindContext, *partition_path, &result_partition, context); 494 base::Bind(&ServiceWorkerInternalsUI::FindContext,
495 base::Unretained(this),
496 partition_id,
497 &result_partition);
331 BrowserContext::ForEachStoragePartition(browser_context, find_context_cb); 498 BrowserContext::ForEachStoragePartition(browser_context, find_context_cb);
332 499 if (!result_partition)
333 if (!result_partition || !(*context))
334 return false; 500 return false;
335 501 *context = static_cast<ServiceWorkerContextWrapper*>(
502 result_partition->GetServiceWorkerContext());
336 return true; 503 return true;
337 } 504 }
338 505
339 void ServiceWorkerInternalsUI::DispatchSyncEventToWorker( 506 void ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod(
507 ServiceWorkerVersionMethod method,
340 const ListValue* args) { 508 const ListValue* args) {
341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 509 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
342 base::FilePath partition_path; 510 int callback_id;
343 GURL scope; 511 int partition_id;
512 int64 version_id;
513 std::string version_id_string;
514 const DictionaryValue* cmd_args = NULL;
344 scoped_refptr<ServiceWorkerContextWrapper> context; 515 scoped_refptr<ServiceWorkerContextWrapper> context;
345 if (!GetRegistrationInfo(args, &partition_path, &scope, &context)) 516 if (!args->GetInteger(0, &callback_id) ||
517 !args->GetDictionary(1, &cmd_args) ||
518 !cmd_args->GetInteger("partition_id", &partition_id) ||
519 !GetServiceWorkerContext(partition_id, &context) ||
520 !cmd_args->GetString("version_id", &version_id_string) ||
521 !base::StringToInt64(version_id_string, &version_id)) {
346 return; 522 return;
523 }
347 524
348 scoped_ptr<ListValue> args_copy(args->DeepCopy()); 525 base::Callback<void(ServiceWorkerStatusCode)> callback =
349 BrowserThread::PostTask( 526 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
350 BrowserThread::IO, 527 CallServiceWorkerVersionMethodWithVersionID(
351 FROM_HERE, 528 method, context, version_id, callback);
352 base::Bind(&ServiceWorkerInternalsUI::OperationProxy::
353 DispatchSyncEventToWorkerOnIOThread,
354 new OperationProxy(AsWeakPtr(), args_copy.Pass()),
355 context,
356 scope));
357 } 529 }
358 530
359 void ServiceWorkerInternalsUI::InspectWorker(const ListValue* args) { 531 void ServiceWorkerInternalsUI::InspectWorker(const ListValue* args) {
360 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 532 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
361 base::FilePath partition_path; 533 int callback_id;
362 GURL scope; 534 int process_id;
535 int devtools_agent_route_id;
536 const DictionaryValue* cmd_args = NULL;
363 scoped_refptr<ServiceWorkerContextWrapper> context; 537 scoped_refptr<ServiceWorkerContextWrapper> context;
364 if (!GetRegistrationInfo(args, &partition_path, &scope, &context)) 538 if (!args->GetInteger(0, &callback_id) ||
539 !args->GetDictionary(1, &cmd_args) ||
540 !cmd_args->GetInteger("process_id", &process_id) ||
541 !cmd_args->GetInteger("devtools_agent_route_id",
542 &devtools_agent_route_id)) {
365 return; 543 return;
366 scoped_ptr<ListValue> args_copy(args->DeepCopy()); 544 }
367 BrowserThread::PostTask( 545 base::Callback<void(ServiceWorkerStatusCode)> callback =
368 BrowserThread::IO, 546 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
369 FROM_HERE, 547 scoped_refptr<DevToolsAgentHost> agent_host(
370 base::Bind( 548 EmbeddedWorkerDevToolsManager::GetInstance()
371 &ServiceWorkerInternalsUI::OperationProxy::InspectWorkerOnIOThread, 549 ->GetDevToolsAgentHostForWorker(process_id, devtools_agent_route_id));
372 new OperationProxy(AsWeakPtr(), args_copy.Pass()), 550 if (!agent_host) {
373 context, 551 callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND);
374 scope)); 552 return;
553 }
554 DevToolsManagerImpl::GetInstance()->Inspect(
555 web_ui()->GetWebContents()->GetBrowserContext(), agent_host.get());
556 callback.Run(SERVICE_WORKER_OK);
375 } 557 }
376 558
377 void ServiceWorkerInternalsUI::Unregister(const ListValue* args) { 559 void ServiceWorkerInternalsUI::Unregister(const ListValue* args) {
378 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 560 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
379 base::FilePath partition_path; 561 int callback_id;
380 GURL scope; 562 int partition_id;
563 std::string scope_string;
564 const DictionaryValue* cmd_args = NULL;
381 scoped_refptr<ServiceWorkerContextWrapper> context; 565 scoped_refptr<ServiceWorkerContextWrapper> context;
382 if (!GetRegistrationInfo(args, &partition_path, &scope, &context)) 566 if (!args->GetInteger(0, &callback_id) ||
567 !args->GetDictionary(1, &cmd_args) ||
568 !cmd_args->GetInteger("partition_id", &partition_id) ||
569 !GetServiceWorkerContext(partition_id, &context) ||
570 !cmd_args->GetString("scope", &scope_string)) {
383 return; 571 return;
572 }
384 573
385 scoped_ptr<ListValue> args_copy(args->DeepCopy()); 574 base::Callback<void(ServiceWorkerStatusCode)> callback =
386 BrowserThread::PostTask( 575 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
387 BrowserThread::IO, 576 UnregisterWithScope(context, GURL(scope_string), callback);
388 FROM_HERE,
389 base::Bind(
390 &ServiceWorkerInternalsUI::OperationProxy::UnregisterOnIOThread,
391 new OperationProxy(AsWeakPtr(), args_copy.Pass()),
392 context,
393 scope));
394 } 577 }
395 578
396 void ServiceWorkerInternalsUI::StartWorker(const ListValue* args) { 579 void ServiceWorkerInternalsUI::StartWorker(const ListValue* args) {
397 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 580 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
398 base::FilePath partition_path; 581 int callback_id;
399 GURL scope; 582 int partition_id;
583 std::string scope_string;
584 const DictionaryValue* cmd_args = NULL;
400 scoped_refptr<ServiceWorkerContextWrapper> context; 585 scoped_refptr<ServiceWorkerContextWrapper> context;
401 if (!GetRegistrationInfo(args, &partition_path, &scope, &context)) 586 if (!args->GetInteger(0, &callback_id) ||
402 return; 587 !args->GetDictionary(1, &cmd_args) ||
403 588 !cmd_args->GetInteger("partition_id", &partition_id) ||
404 scoped_ptr<ListValue> args_copy(args->DeepCopy()); 589 !GetServiceWorkerContext(partition_id, &context) ||
405 BrowserThread::PostTask( 590 !cmd_args->GetString("scope", &scope_string)) {
406 BrowserThread::IO,
407 FROM_HERE,
408 base::Bind(
409 &ServiceWorkerInternalsUI::OperationProxy::StartWorkerOnIOThread,
410 new OperationProxy(AsWeakPtr(), args_copy.Pass()),
411 context,
412 scope));
413 }
414
415 void ServiceWorkerInternalsUI::StopWorker(const ListValue* args) {
416 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
417 base::FilePath partition_path;
418 GURL scope;
419 scoped_refptr<ServiceWorkerContextWrapper> context;
420 if (!GetRegistrationInfo(args, &partition_path, &scope, &context))
421 return;
422
423 scoped_ptr<ListValue> args_copy(args->DeepCopy());
424 BrowserThread::PostTask(
425 BrowserThread::IO,
426 FROM_HERE,
427 base::Bind(
428 &ServiceWorkerInternalsUI::OperationProxy::StopWorkerOnIOThread,
429 new OperationProxy(AsWeakPtr(), args_copy.Pass()),
430 context,
431 scope));
432 }
433
434 void ServiceWorkerInternalsUI::OperationProxy::GetRegistrationsOnIOThread(
435 int partition_id,
436 ServiceWorkerContextWrapper* context,
437 const base::FilePath& context_path) {
438 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
439
440 context->context()->storage()->GetAllRegistrations(
441 base::Bind(&ServiceWorkerInternalsUI::OperationProxy::OnHaveRegistrations,
442 this,
443 partition_id,
444 context_path));
445 }
446
447 void ServiceWorkerInternalsUI::OperationProxy::UnregisterOnIOThread(
448 scoped_refptr<ServiceWorkerContextWrapper> context,
449 const GURL& scope) {
450 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
451 context->context()->UnregisterServiceWorker(
452 scope,
453 base::Bind(&ServiceWorkerInternalsUI::OperationProxy::OperationComplete,
454 this));
455 }
456
457 void ServiceWorkerInternalsUI::OperationProxy::StartWorkerOnIOThread(
458 scoped_refptr<ServiceWorkerContextWrapper> context,
459 const GURL& scope) {
460 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
461 // TODO(alecflett): Add support for starting/stopping workers for
462 // pending versions too.
463 context->context()->storage()->FindRegistrationForPattern(
464 scope,
465 base::Bind(&ServiceWorkerInternalsUI::OperationProxy::StartActiveWorker,
466 this));
467 }
468
469 void ServiceWorkerInternalsUI::OperationProxy::StopWorkerOnIOThread(
470 scoped_refptr<ServiceWorkerContextWrapper> context,
471 const GURL& scope) {
472 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
473 // TODO(alecflett): Add support for starting/stopping workers for
474 // pending versions too.
475 context->context()->storage()->FindRegistrationForPattern(
476 scope,
477 base::Bind(&ServiceWorkerInternalsUI::OperationProxy::StopActiveWorker,
478 this));
479 }
480
481 void
482 ServiceWorkerInternalsUI::OperationProxy::DispatchSyncEventToWorkerOnIOThread(
483 scoped_refptr<ServiceWorkerContextWrapper> context,
484 const GURL& scope) {
485 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
486 context->context()->storage()->FindRegistrationForPattern(
487 scope,
488 base::Bind(&ServiceWorkerInternalsUI::OperationProxy::
489 DispatchSyncEventToActiveWorker,
490 this));
491 }
492
493 void ServiceWorkerInternalsUI::OperationProxy::InspectWorkerOnIOThread(
494 scoped_refptr<ServiceWorkerContextWrapper> context,
495 const GURL& scope) {
496 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
497 context->context()->storage()->FindRegistrationForPattern(
498 scope,
499 base::Bind(&ServiceWorkerInternalsUI::OperationProxy::InspectActiveWorker,
500 this,
501 context->context()));
502 }
503
504 namespace {
505 void UpdateVersionInfo(const ServiceWorkerVersionInfo& version,
506 DictionaryValue* info) {
507 switch (version.running_status) {
508 case ServiceWorkerVersion::STOPPED:
509 info->SetString("running_status", "STOPPED");
510 break;
511 case ServiceWorkerVersion::STARTING:
512 info->SetString("running_status", "STARTING");
513 break;
514 case ServiceWorkerVersion::RUNNING:
515 info->SetString("running_status", "RUNNING");
516 break;
517 case ServiceWorkerVersion::STOPPING:
518 info->SetString("running_status", "STOPPING");
519 break;
520 }
521
522 switch (version.status) {
523 case ServiceWorkerVersion::NEW:
524 info->SetString("status", "NEW");
525 break;
526 case ServiceWorkerVersion::INSTALLING:
527 info->SetString("status", "INSTALLING");
528 break;
529 case ServiceWorkerVersion::INSTALLED:
530 info->SetString("status", "INSTALLED");
531 break;
532 case ServiceWorkerVersion::ACTIVATING:
533 info->SetString("status", "ACTIVATING");
534 break;
535 case ServiceWorkerVersion::ACTIVE:
536 info->SetString("status", "ACTIVE");
537 break;
538 case ServiceWorkerVersion::DEACTIVATED:
539 info->SetString("status", "DEACTIVATED");
540 break;
541 }
542 info->SetString("version_id", base::Int64ToString(version.version_id));
543 info->SetInteger("process_id", version.process_id);
544 info->SetInteger("thread_id", version.thread_id);
545 }
546 } // namespace
547
548 void ServiceWorkerInternalsUI::OperationProxy::OnHaveRegistrations(
549 int partition_id,
550 const base::FilePath& context_path,
551 const std::vector<ServiceWorkerRegistrationInfo>& registrations) {
552 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
553 BrowserThread::PostTask(
554 BrowserThread::UI,
555 FROM_HERE,
556 base::Bind(
557 &ServiceWorkerInternalsUI::OperationProxy::OnHaveRegistrations,
558 this,
559 partition_id,
560 context_path,
561 registrations));
562 return; 591 return;
563 } 592 }
564 593
565 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 594 base::Callback<void(ServiceWorkerStatusCode)> callback =
566 ListValue result; 595 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
567 for (std::vector<ServiceWorkerRegistrationInfo>::const_iterator it = 596 FindRegistrationForPattern(
568 registrations.begin(); 597 context, GURL(scope_string), base::Bind(StartActiveWorker, callback));
569 it != registrations.end();
570 ++it) {
571 const ServiceWorkerRegistrationInfo& registration = *it;
572 DictionaryValue* registration_info = new DictionaryValue();
573 registration_info->SetString("scope", registration.pattern.spec());
574 registration_info->SetString("script_url", registration.script_url.spec());
575
576 if (!registration.active_version.is_null) {
577 DictionaryValue* active_info = new DictionaryValue();
578 UpdateVersionInfo(registration.active_version, active_info);
579 registration_info->Set("active", active_info);
580 }
581
582 if (!registration.pending_version.is_null) {
583 DictionaryValue* pending_info = new DictionaryValue();
584 UpdateVersionInfo(registration.pending_version, pending_info);
585 registration_info->Set("pending", pending_info);
586 }
587
588 result.Append(registration_info);
589 }
590
591 if (internals_)
592 internals_->web_ui()->CallJavascriptFunction(
593 "serviceworker.onPartitionData",
594 result,
595 FundamentalValue(partition_id),
596 StringValue(context_path.value()));
597 }
598
599 void ServiceWorkerInternalsUI::OperationProxy::OperationComplete(
600 ServiceWorkerStatusCode status) {
601 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
602 BrowserThread::PostTask(
603 BrowserThread::UI,
604 FROM_HERE,
605 base::Bind(&ServiceWorkerInternalsUI::OperationProxy::OperationComplete,
606 this,
607 status));
608 return;
609 }
610
611 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
612 original_args_->Insert(0, new FundamentalValue(static_cast<int>(status)));
613 if (internals_)
614 internals_->web_ui()->CallJavascriptFunction(
615 "serviceworker.onOperationComplete",
616 std::vector<const Value*>(original_args_->begin(),
617 original_args_->end()));
618 }
619
620 void ServiceWorkerInternalsUI::OperationProxy::StartActiveWorker(
621 ServiceWorkerStatusCode status,
622 const scoped_refptr<ServiceWorkerRegistration>& registration) {
623 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
624 if (status == SERVICE_WORKER_OK) {
625 registration->active_version()->StartWorker(base::Bind(
626 &ServiceWorkerInternalsUI::OperationProxy::OperationComplete, this));
627 return;
628 }
629
630 OperationComplete(status);
631 }
632
633 void ServiceWorkerInternalsUI::OperationProxy::StopActiveWorker(
634 ServiceWorkerStatusCode status,
635 const scoped_refptr<ServiceWorkerRegistration>& registration) {
636 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
637 if (status == SERVICE_WORKER_OK) {
638 registration->active_version()->StopWorker(base::Bind(
639 &ServiceWorkerInternalsUI::OperationProxy::OperationComplete, this));
640 return;
641 }
642
643 OperationComplete(status);
644 }
645
646 void ServiceWorkerInternalsUI::OperationProxy::DispatchSyncEventToActiveWorker(
647 ServiceWorkerStatusCode status,
648 const scoped_refptr<ServiceWorkerRegistration>& registration) {
649 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
650 if (status == SERVICE_WORKER_OK && registration->active_version() &&
651 registration->active_version()->status() ==
652 ServiceWorkerVersion::ACTIVE) {
653 registration->active_version()->DispatchSyncEvent(base::Bind(
654 &ServiceWorkerInternalsUI::OperationProxy::OperationComplete, this));
655 return;
656 }
657
658 OperationComplete(SERVICE_WORKER_ERROR_FAILED);
659 }
660
661 void ServiceWorkerInternalsUI::OperationProxy::InspectActiveWorker(
662 const ServiceWorkerContextCore* const service_worker_context,
663 ServiceWorkerStatusCode status,
664 const scoped_refptr<ServiceWorkerRegistration>& registration) {
665 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
666 if (status == SERVICE_WORKER_OK) {
667 BrowserThread::PostTask(
668 BrowserThread::UI,
669 FROM_HERE,
670 base::Bind(&OperationProxy::InspectWorkerOnUIThread,
671 this,
672 service_worker_context,
673 registration->active_version()->version_id()));
674 return;
675 }
676
677 OperationComplete(status);
678 }
679
680 void ServiceWorkerInternalsUI::OperationProxy::InspectWorkerOnUIThread(
681 const ServiceWorkerContextCore* const service_worker_context,
682 int64 version_id) {
683 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
684 scoped_refptr<DevToolsAgentHost> agent_host(
685 EmbeddedWorkerDevToolsManager::GetInstance()
686 ->GetDevToolsAgentHostForServiceWorker(
687 EmbeddedWorkerDevToolsManager::ServiceWorkerIdentifier(
688 service_worker_context, version_id)));
689 if (agent_host) {
690 DevToolsManagerImpl::GetInstance()->Inspect(
691 internals_->web_ui()->GetWebContents()->GetBrowserContext(),
692 agent_host.get());
693 OperationComplete(SERVICE_WORKER_OK);
694 return;
695 }
696 OperationComplete(SERVICE_WORKER_ERROR_NOT_FOUND);
697 } 598 }
698 599
699 } // namespace content 600 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698