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

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: incorporated falken's comment 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 void OperationCompleteCallback(WeakPtr<ServiceWorkerInternalsUI> internals,
41 : public base::RefCountedThreadSafe< 41 int callback_id,
42 ServiceWorkerInternalsUI::OperationProxy> { 42 ServiceWorkerStatusCode status) {
43 public: 43 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
44 OperationProxy(const WeakPtr<ServiceWorkerInternalsUI> internals, 44 BrowserThread::PostTask(
45 scoped_ptr<ListValue> original_args) 45 BrowserThread::UI,
46 : internals_(internals), original_args_(original_args.Pass()) {} 46 FROM_HERE,
47 47 base::Bind(OperationCompleteCallback, internals, callback_id, status));
48 void GetRegistrationsOnIOThread(int partition_id, 48 return;
49 ServiceWorkerContextWrapper* context, 49 }
50 const base::FilePath& context_path); 50 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
51 void UnregisterOnIOThread(scoped_refptr<ServiceWorkerContextWrapper> context, 51 if (internals) {
52 const GURL& scope); 52 internals->web_ui()->CallJavascriptFunction(
53 void StartWorkerOnIOThread(scoped_refptr<ServiceWorkerContextWrapper> context, 53 "serviceworker.onOperationComplete",
54 const GURL& scope); 54 FundamentalValue(static_cast<int>(status)),
55 void StopWorkerOnIOThread(scoped_refptr<ServiceWorkerContextWrapper> context, 55 FundamentalValue(callback_id));
56 const GURL& scope); 56 }
57 void DispatchSyncEventToWorkerOnIOThread( 57 }
58 scoped_refptr<ServiceWorkerContextWrapper> context, 58
59 const GURL& scope); 59 void CallServiceWorkerVersionMethodWithVersionID(
60 void InspectWorkerOnIOThread( 60 ServiceWorkerInternalsUI::ServiceWorkerVersionMethod method,
61 scoped_refptr<ServiceWorkerContextWrapper> context, 61 scoped_refptr<ServiceWorkerContextWrapper> context,
62 const GURL& scope); 62 int64 version_id,
63 63 const ServiceWorkerInternalsUI::StatusCallback& callback) {
64 private: 64 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
65 friend class base::RefCountedThreadSafe<OperationProxy>; 65 BrowserThread::PostTask(
66 ~OperationProxy() {} 66 BrowserThread::IO,
67 void OnHaveRegistrations( 67 FROM_HERE,
68 int partition_id, 68 base::Bind(CallServiceWorkerVersionMethodWithVersionID,
69 const base::FilePath& context_path, 69 method,
70 const std::vector<ServiceWorkerRegistrationInfo>& registrations); 70 context,
71 71 version_id,
72 void OperationComplete(ServiceWorkerStatusCode status); 72 callback));
73 73 return;
74 void StartActiveWorker( 74 }
75 ServiceWorkerStatusCode status, 75 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
76 const scoped_refptr<ServiceWorkerRegistration>& registration); 76 scoped_refptr<ServiceWorkerVersion> version =
77 77 context->context()->GetLiveVersion(version_id);
78 void StopActiveWorker( 78 if (!version) {
79 ServiceWorkerStatusCode status, 79 callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND);
80 const scoped_refptr<ServiceWorkerRegistration>& registration); 80 return;
81 81 }
82 void DispatchSyncEventToActiveWorker( 82 (*version.*method)(callback);
83 ServiceWorkerStatusCode status, 83 }
84 const scoped_refptr<ServiceWorkerRegistration>& registration); 84
85 85 void UnregisterWithScope(
86 void InspectActiveWorker( 86 scoped_refptr<ServiceWorkerContextWrapper> context,
87 const ServiceWorkerContextCore* const service_worker_context, 87 const GURL& scope,
88 ServiceWorkerStatusCode status, 88 const ServiceWorkerInternalsUI::StatusCallback& callback) {
89 const scoped_refptr<ServiceWorkerRegistration>& registration); 89 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
90 90 BrowserThread::PostTask(
91 void InspectWorkerOnUIThread( 91 BrowserThread::IO,
92 const ServiceWorkerContextCore* const service_worker_context, 92 FROM_HERE,
93 int64 version_id); 93 base::Bind(UnregisterWithScope, context, scope, callback));
94 94 return;
95 WeakPtr<ServiceWorkerInternalsUI> internals_; 95 }
96 scoped_ptr<ListValue> original_args_; 96 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
97 }; 97 context->context()->UnregisterServiceWorker(scope, callback);
98 }
99
100 void WorkerStarted(const scoped_refptr<ServiceWorkerRegistration>& registration,
101 const ServiceWorkerInternalsUI::StatusCallback& callback,
102 ServiceWorkerStatusCode status) {
103 callback.Run(status);
104 }
105
106 void StartActiveWorker(
107 const ServiceWorkerInternalsUI::StatusCallback& callback,
108 ServiceWorkerStatusCode status,
109 const scoped_refptr<ServiceWorkerRegistration>& registration) {
110 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
111 if (status == SERVICE_WORKER_OK) {
112 // Pass the reference of |registration| to WorkerStarted callback to prevent
113 // it from being deleted while starting the worker. If the refcount of
114 // |registration| is 1, it will be deleted after WorkerStarted is called.
115 registration->active_version()->StartWorker(
116 base::Bind(WorkerStarted, registration, callback));
117 return;
118 }
119 callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND);
120 }
121
122 void FindRegistrationForPattern(
123 scoped_refptr<ServiceWorkerContextWrapper> context,
124 const GURL& scope,
125 const ServiceWorkerStorage::FindRegistrationCallback callback) {
126 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
127 BrowserThread::PostTask(
128 BrowserThread::IO,
129 FROM_HERE,
130 base::Bind(FindRegistrationForPattern, context, scope, callback));
131 return;
132 }
133 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
134 context->context()->storage()->FindRegistrationForPattern(scope, callback);
135 }
136
137 void UpdateVersionInfo(const ServiceWorkerVersionInfo& version,
138 DictionaryValue* info) {
139 switch (version.running_status) {
140 case ServiceWorkerVersion::STOPPED:
141 info->SetString("running_status", "STOPPED");
142 break;
143 case ServiceWorkerVersion::STARTING:
144 info->SetString("running_status", "STARTING");
145 break;
146 case ServiceWorkerVersion::RUNNING:
147 info->SetString("running_status", "RUNNING");
148 break;
149 case ServiceWorkerVersion::STOPPING:
150 info->SetString("running_status", "STOPPING");
151 break;
152 }
153
154 switch (version.status) {
155 case ServiceWorkerVersion::NEW:
156 info->SetString("status", "NEW");
157 break;
158 case ServiceWorkerVersion::INSTALLING:
159 info->SetString("status", "INSTALLING");
160 break;
161 case ServiceWorkerVersion::INSTALLED:
162 info->SetString("status", "INSTALLED");
163 break;
164 case ServiceWorkerVersion::ACTIVATING:
165 info->SetString("status", "ACTIVATING");
166 break;
167 case ServiceWorkerVersion::ACTIVE:
168 info->SetString("status", "ACTIVE");
169 break;
170 case ServiceWorkerVersion::DEACTIVATED:
171 info->SetString("status", "DEACTIVATED");
172 break;
173 }
174 info->SetString("version_id", base::Int64ToString(version.version_id));
175 info->SetInteger("process_id", version.process_id);
176 info->SetInteger("thread_id", version.thread_id);
177 info->SetInteger("devtools_agent_route_id", version.devtools_agent_route_id);
178 }
179
180 ListValue* GetRegistrationListValue(
181 const std::vector<ServiceWorkerRegistrationInfo>& registrations) {
182 ListValue* result = new ListValue();
183 for (std::vector<ServiceWorkerRegistrationInfo>::const_iterator it =
184 registrations.begin();
185 it != registrations.end();
186 ++it) {
187 const ServiceWorkerRegistrationInfo& registration = *it;
188 DictionaryValue* registration_info = new DictionaryValue();
189 registration_info->SetString("scope", registration.pattern.spec());
190 registration_info->SetString("script_url", registration.script_url.spec());
191 registration_info->SetString(
192 "registration_id", base::Int64ToString(registration.registration_id));
193
194 if (!registration.active_version.is_null) {
195 DictionaryValue* active_info = new DictionaryValue();
196 UpdateVersionInfo(registration.active_version, active_info);
197 registration_info->Set("active", active_info);
198 }
199
200 if (!registration.pending_version.is_null) {
201 DictionaryValue* pending_info = new DictionaryValue();
202 UpdateVersionInfo(registration.pending_version, pending_info);
203 registration_info->Set("pending", pending_info);
204 }
205
206 result->Append(registration_info);
207 }
208 return result;
209 }
210
211 ListValue* GetVersionListValue(
212 const std::vector<ServiceWorkerVersionInfo>& versions) {
213 ListValue* result = new ListValue();
214 for (std::vector<ServiceWorkerVersionInfo>::const_iterator it =
215 versions.begin();
216 it != versions.end();
217 ++it) {
218 DictionaryValue* info = new DictionaryValue();
219 UpdateVersionInfo(*it, info);
220 result->Append(info);
221 }
222 return result;
223 }
224
225 void GetRegistrationsOnIOThread(
226 scoped_refptr<ServiceWorkerContextWrapper> context,
227 base::Callback<void(const std::vector<ServiceWorkerRegistrationInfo>&)>
228 callback) {
229 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
230 context->context()->storage()->GetAllRegistrations(callback);
231 }
232
233 void OnStoredRegistrations(
234 scoped_refptr<ServiceWorkerContextWrapper> context,
235 base::Callback<void(const std::vector<ServiceWorkerRegistrationInfo>&,
236 const std::vector<ServiceWorkerVersionInfo>&,
237 const std::vector<ServiceWorkerRegistrationInfo>&)>
238 callback,
239 const std::vector<ServiceWorkerRegistrationInfo>& stored_registrations) {
240 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
241 BrowserThread::PostTask(
242 BrowserThread::UI,
243 FROM_HERE,
244 base::Bind(callback,
245 context->context()->GetAllLiveRegistrationInfo(),
246 context->context()->GetAllLiveVersionInfo(),
247 stored_registrations));
248 }
249
250 void OnAllRegistrations(
251 WeakPtr<ServiceWorkerInternalsUI> internals,
252 int partition_id,
253 const base::FilePath& context_path,
254 const std::vector<ServiceWorkerRegistrationInfo>& live_registrations,
255 const std::vector<ServiceWorkerVersionInfo>& live_versions,
256 const std::vector<ServiceWorkerRegistrationInfo>& stored_registrations) {
257 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
258 if (!internals)
259 return;
260
261 ScopedVector<const Value> args;
262 args.push_back(GetRegistrationListValue(live_registrations));
263 args.push_back(GetVersionListValue(live_versions));
264 args.push_back(GetRegistrationListValue(stored_registrations));
265 args.push_back(new FundamentalValue(partition_id));
266 args.push_back(new StringValue(context_path.value()));
267 internals->web_ui()->CallJavascriptFunction("serviceworker.onPartitionData",
268 args.get());
269 }
270
271 } // namespace
98 272
99 class ServiceWorkerInternalsUI::PartitionObserver 273 class ServiceWorkerInternalsUI::PartitionObserver
100 : public ServiceWorkerContextObserver { 274 : public ServiceWorkerContextObserver {
101 public: 275 public:
102 PartitionObserver(int partition_id, WebUI* web_ui) 276 PartitionObserver(int partition_id, WebUI* web_ui)
103 : partition_id_(partition_id), web_ui_(web_ui) {} 277 : partition_id_(partition_id), web_ui_(web_ui) {}
104 virtual ~PartitionObserver() {} 278 virtual ~PartitionObserver() {}
105 // ServiceWorkerContextObserver overrides: 279 // ServiceWorkerContextObserver overrides:
106 virtual void OnWorkerStarted(int64 version_id, 280 virtual void OnWorkerStarted(int64 version_id,
107 int process_id, 281 int process_id,
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 376
203 BrowserContext* browser_context = 377 BrowserContext* browser_context =
204 web_ui->GetWebContents()->GetBrowserContext(); 378 web_ui->GetWebContents()->GetBrowserContext();
205 WebUIDataSource::Add(browser_context, source); 379 WebUIDataSource::Add(browser_context, source);
206 380
207 web_ui->RegisterMessageCallback( 381 web_ui->RegisterMessageCallback(
208 "getAllRegistrations", 382 "getAllRegistrations",
209 base::Bind(&ServiceWorkerInternalsUI::GetAllRegistrations, 383 base::Bind(&ServiceWorkerInternalsUI::GetAllRegistrations,
210 base::Unretained(this))); 384 base::Unretained(this)));
211 web_ui->RegisterMessageCallback( 385 web_ui->RegisterMessageCallback(
212 "start", 386 "stop",
213 base::Bind(&ServiceWorkerInternalsUI::StartWorker, 387 base::Bind(&ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod,
214 base::Unretained(this))); 388 base::Unretained(this),
389 &ServiceWorkerVersion::StopWorker));
215 web_ui->RegisterMessageCallback( 390 web_ui->RegisterMessageCallback(
216 "stop", 391 "sync",
217 base::Bind(&ServiceWorkerInternalsUI::StopWorker, 392 base::Bind(&ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod,
393 base::Unretained(this),
394 &ServiceWorkerVersion::DispatchSyncEvent));
395 web_ui->RegisterMessageCallback(
396 "inspect",
397 base::Bind(&ServiceWorkerInternalsUI::InspectWorker,
218 base::Unretained(this))); 398 base::Unretained(this)));
219 web_ui->RegisterMessageCallback( 399 web_ui->RegisterMessageCallback(
220 "unregister", 400 "unregister",
221 base::Bind(&ServiceWorkerInternalsUI::Unregister, 401 base::Bind(&ServiceWorkerInternalsUI::Unregister,
222 base::Unretained(this))); 402 base::Unretained(this)));
223 web_ui->RegisterMessageCallback( 403 web_ui->RegisterMessageCallback(
224 "sync", 404 "start",
225 base::Bind(&ServiceWorkerInternalsUI::DispatchSyncEventToWorker, 405 base::Bind(&ServiceWorkerInternalsUI::StartWorker,
226 base::Unretained(this)));
227 web_ui->RegisterMessageCallback(
228 "inspect",
229 base::Bind(&ServiceWorkerInternalsUI::InspectWorker,
230 base::Unretained(this))); 406 base::Unretained(this)));
231 } 407 }
232 408
233 ServiceWorkerInternalsUI::~ServiceWorkerInternalsUI() { 409 ServiceWorkerInternalsUI::~ServiceWorkerInternalsUI() {
234 BrowserContext* browser_context = 410 BrowserContext* browser_context =
235 web_ui()->GetWebContents()->GetBrowserContext(); 411 web_ui()->GetWebContents()->GetBrowserContext();
236 // Safe to use base::Unretained(this) because 412 // Safe to use base::Unretained(this) because
237 // ForEachStoragePartition is synchronous. 413 // ForEachStoragePartition is synchronous.
238 BrowserContext::StoragePartitionCallback remove_observer_cb = 414 BrowserContext::StoragePartitionCallback remove_observer_cb =
239 base::Bind(&ServiceWorkerInternalsUI::RemoveObserverFromStoragePartition, 415 base::Bind(&ServiceWorkerInternalsUI::RemoveObserverFromStoragePartition,
240 base::Unretained(this)); 416 base::Unretained(this));
241 BrowserContext::ForEachStoragePartition(browser_context, remove_observer_cb); 417 BrowserContext::ForEachStoragePartition(browser_context, remove_observer_cb);
242 } 418 }
243 419
244 void ServiceWorkerInternalsUI::GetAllRegistrations(const ListValue* args) { 420 void ServiceWorkerInternalsUI::GetAllRegistrations(const ListValue* args) {
245 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 421 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
246
247 BrowserContext* browser_context = 422 BrowserContext* browser_context =
248 web_ui()->GetWebContents()->GetBrowserContext(); 423 web_ui()->GetWebContents()->GetBrowserContext();
249
250 // Safe to use base::Unretained(this) because 424 // Safe to use base::Unretained(this) because
251 // ForEachStoragePartition is synchronous. 425 // ForEachStoragePartition is synchronous.
252 BrowserContext::StoragePartitionCallback add_context_cb = 426 BrowserContext::StoragePartitionCallback add_context_cb =
253 base::Bind(&ServiceWorkerInternalsUI::AddContextFromStoragePartition, 427 base::Bind(&ServiceWorkerInternalsUI::AddContextFromStoragePartition,
254 base::Unretained(this)); 428 base::Unretained(this));
255 BrowserContext::ForEachStoragePartition(browser_context, add_context_cb); 429 BrowserContext::ForEachStoragePartition(browser_context, add_context_cb);
256 } 430 }
257 431
258 void ServiceWorkerInternalsUI::AddContextFromStoragePartition( 432 void ServiceWorkerInternalsUI::AddContextFromStoragePartition(
259 StoragePartition* partition) { 433 StoragePartition* partition) {
260 int partition_id = 0; 434 int partition_id = 0;
261 scoped_refptr<ServiceWorkerContextWrapper> context = 435 scoped_refptr<ServiceWorkerContextWrapper> context =
262 static_cast<ServiceWorkerContextWrapper*>( 436 static_cast<ServiceWorkerContextWrapper*>(
263 partition->GetServiceWorkerContext()); 437 partition->GetServiceWorkerContext());
264 if (PartitionObserver* observer = 438 if (PartitionObserver* observer =
265 observers_.get(reinterpret_cast<uintptr_t>(partition))) { 439 observers_.get(reinterpret_cast<uintptr_t>(partition))) {
266 partition_id = observer->partition_id(); 440 partition_id = observer->partition_id();
267 } else { 441 } else {
268 partition_id = next_partition_id_++; 442 partition_id = next_partition_id_++;
269 scoped_ptr<PartitionObserver> new_observer( 443 scoped_ptr<PartitionObserver> new_observer(
270 new PartitionObserver(partition_id, web_ui())); 444 new PartitionObserver(partition_id, web_ui()));
271 context->AddObserver(new_observer.get()); 445 context->AddObserver(new_observer.get());
272 observers_.set(reinterpret_cast<uintptr_t>(partition), new_observer.Pass()); 446 observers_.set(reinterpret_cast<uintptr_t>(partition), new_observer.Pass());
273 } 447 }
274 BrowserThread::PostTask( 448 BrowserThread::PostTask(
275 BrowserThread::IO, 449 BrowserThread::IO,
276 FROM_HERE, 450 FROM_HERE,
277 base::Bind( 451 base::Bind(GetRegistrationsOnIOThread,
278 &ServiceWorkerInternalsUI::OperationProxy::GetRegistrationsOnIOThread, 452 context,
279 new OperationProxy(AsWeakPtr(), scoped_ptr<ListValue>()), 453 base::Bind(OnStoredRegistrations,
280 partition_id, 454 context,
281 context, 455 base::Bind(OnAllRegistrations,
282 partition->GetPath())); 456 AsWeakPtr(),
457 partition_id,
458 partition->GetPath()))));
283 } 459 }
284 460
285 void ServiceWorkerInternalsUI::RemoveObserverFromStoragePartition( 461 void ServiceWorkerInternalsUI::RemoveObserverFromStoragePartition(
286 StoragePartition* partition) { 462 StoragePartition* partition) {
287 scoped_ptr<PartitionObserver> observer( 463 scoped_ptr<PartitionObserver> observer(
288 observers_.take_and_erase(reinterpret_cast<uintptr_t>(partition))); 464 observers_.take_and_erase(reinterpret_cast<uintptr_t>(partition)));
289 if (!observer.get()) 465 if (!observer.get())
290 return; 466 return;
291 scoped_refptr<ServiceWorkerContextWrapper> context = 467 scoped_refptr<ServiceWorkerContextWrapper> context =
292 static_cast<ServiceWorkerContextWrapper*>( 468 static_cast<ServiceWorkerContextWrapper*>(
293 partition->GetServiceWorkerContext()); 469 partition->GetServiceWorkerContext());
294 context->RemoveObserver(observer.get()); 470 context->RemoveObserver(observer.get());
295 } 471 }
296 472
297 namespace { 473 void ServiceWorkerInternalsUI::FindContext(
298 void FindContext(const base::FilePath& partition_path, 474 int partition_id,
299 StoragePartition** result_partition, 475 StoragePartition** result_partition,
300 scoped_refptr<ServiceWorkerContextWrapper>* result_context, 476 StoragePartition* storage_partition) const {
301 StoragePartition* storage_partition) { 477 PartitionObserver* observer =
302 if (storage_partition->GetPath() == partition_path) { 478 observers_.get(reinterpret_cast<uintptr_t>(storage_partition));
479 if (observer && partition_id == observer->partition_id()) {
303 *result_partition = storage_partition; 480 *result_partition = storage_partition;
304 *result_context = static_cast<ServiceWorkerContextWrapper*>(
305 storage_partition->GetServiceWorkerContext());
306 } 481 }
307 } 482 }
308 } // namespace
309 483
310 bool ServiceWorkerInternalsUI::GetRegistrationInfo( 484 bool ServiceWorkerInternalsUI::GetServiceWorkerContext(
311 const ListValue* args, 485 int partition_id,
312 base::FilePath* partition_path,
313 GURL* scope,
314 scoped_refptr<ServiceWorkerContextWrapper>* context) const { 486 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 = 487 BrowserContext* browser_context =
326 web_ui()->GetWebContents()->GetBrowserContext(); 488 web_ui()->GetWebContents()->GetBrowserContext();
327
328 StoragePartition* result_partition(NULL); 489 StoragePartition* result_partition(NULL);
329 BrowserContext::StoragePartitionCallback find_context_cb = 490 BrowserContext::StoragePartitionCallback find_context_cb =
330 base::Bind(&FindContext, *partition_path, &result_partition, context); 491 base::Bind(&ServiceWorkerInternalsUI::FindContext,
492 base::Unretained(this),
493 partition_id,
494 &result_partition);
331 BrowserContext::ForEachStoragePartition(browser_context, find_context_cb); 495 BrowserContext::ForEachStoragePartition(browser_context, find_context_cb);
332 496 if (!result_partition)
333 if (!result_partition || !(*context))
334 return false; 497 return false;
335 498 *context = static_cast<ServiceWorkerContextWrapper*>(
499 result_partition->GetServiceWorkerContext());
336 return true; 500 return true;
337 } 501 }
338 502
339 void ServiceWorkerInternalsUI::DispatchSyncEventToWorker( 503 void ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod(
504 ServiceWorkerVersionMethod method,
340 const ListValue* args) { 505 const ListValue* args) {
341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 506 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
342 base::FilePath partition_path; 507 int callback_id;
343 GURL scope; 508 int partition_id;
509 int64 version_id;
510 std::string version_id_string;
511 const DictionaryValue* cmd_args = NULL;
344 scoped_refptr<ServiceWorkerContextWrapper> context; 512 scoped_refptr<ServiceWorkerContextWrapper> context;
345 if (!GetRegistrationInfo(args, &partition_path, &scope, &context)) 513 if (!args->GetInteger(0, &callback_id) ||
514 !args->GetDictionary(1, &cmd_args) ||
515 !cmd_args->GetInteger("partition_id", &partition_id) ||
516 !GetServiceWorkerContext(partition_id, &context) ||
517 !cmd_args->GetString("version_id", &version_id_string) ||
518 !base::StringToInt64(version_id_string, &version_id)) {
346 return; 519 return;
520 }
347 521
348 scoped_ptr<ListValue> args_copy(args->DeepCopy()); 522 base::Callback<void(ServiceWorkerStatusCode)> callback =
349 BrowserThread::PostTask( 523 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
350 BrowserThread::IO, 524 CallServiceWorkerVersionMethodWithVersionID(
351 FROM_HERE, 525 method, context, version_id, callback);
352 base::Bind(&ServiceWorkerInternalsUI::OperationProxy::
353 DispatchSyncEventToWorkerOnIOThread,
354 new OperationProxy(AsWeakPtr(), args_copy.Pass()),
355 context,
356 scope));
357 } 526 }
358 527
359 void ServiceWorkerInternalsUI::InspectWorker(const ListValue* args) { 528 void ServiceWorkerInternalsUI::InspectWorker(const ListValue* args) {
360 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 529 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
361 base::FilePath partition_path; 530 int callback_id;
362 GURL scope; 531 int process_id;
532 int devtools_agent_route_id;
533 const DictionaryValue* cmd_args = NULL;
363 scoped_refptr<ServiceWorkerContextWrapper> context; 534 scoped_refptr<ServiceWorkerContextWrapper> context;
364 if (!GetRegistrationInfo(args, &partition_path, &scope, &context)) 535 if (!args->GetInteger(0, &callback_id) ||
536 !args->GetDictionary(1, &cmd_args) ||
537 !cmd_args->GetInteger("process_id", &process_id) ||
538 !cmd_args->GetInteger("devtools_agent_route_id",
539 &devtools_agent_route_id)) {
365 return; 540 return;
366 scoped_ptr<ListValue> args_copy(args->DeepCopy()); 541 }
367 BrowserThread::PostTask( 542 base::Callback<void(ServiceWorkerStatusCode)> callback =
368 BrowserThread::IO, 543 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
369 FROM_HERE, 544 scoped_refptr<DevToolsAgentHost> agent_host(
370 base::Bind( 545 EmbeddedWorkerDevToolsManager::GetInstance()
371 &ServiceWorkerInternalsUI::OperationProxy::InspectWorkerOnIOThread, 546 ->GetDevToolsAgentHostForWorker(process_id, devtools_agent_route_id));
372 new OperationProxy(AsWeakPtr(), args_copy.Pass()), 547 if (!agent_host) {
373 context, 548 callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND);
374 scope)); 549 return;
550 }
551 DevToolsManagerImpl::GetInstance()->Inspect(
552 web_ui()->GetWebContents()->GetBrowserContext(), agent_host.get());
553 callback.Run(SERVICE_WORKER_OK);
375 } 554 }
376 555
377 void ServiceWorkerInternalsUI::Unregister(const ListValue* args) { 556 void ServiceWorkerInternalsUI::Unregister(const ListValue* args) {
378 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 557 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
379 base::FilePath partition_path; 558 int callback_id;
380 GURL scope; 559 int partition_id;
560 std::string scope_string;
561 const DictionaryValue* cmd_args = NULL;
381 scoped_refptr<ServiceWorkerContextWrapper> context; 562 scoped_refptr<ServiceWorkerContextWrapper> context;
382 if (!GetRegistrationInfo(args, &partition_path, &scope, &context)) 563 if (!args->GetInteger(0, &callback_id) ||
564 !args->GetDictionary(1, &cmd_args) ||
565 !cmd_args->GetInteger("partition_id", &partition_id) ||
566 !GetServiceWorkerContext(partition_id, &context) ||
567 !cmd_args->GetString("scope", &scope_string)) {
383 return; 568 return;
569 }
384 570
385 scoped_ptr<ListValue> args_copy(args->DeepCopy()); 571 base::Callback<void(ServiceWorkerStatusCode)> callback =
386 BrowserThread::PostTask( 572 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
387 BrowserThread::IO, 573 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 } 574 }
395 575
396 void ServiceWorkerInternalsUI::StartWorker(const ListValue* args) { 576 void ServiceWorkerInternalsUI::StartWorker(const ListValue* args) {
397 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 577 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
398 base::FilePath partition_path; 578 int callback_id;
399 GURL scope; 579 int partition_id;
580 std::string scope_string;
581 const DictionaryValue* cmd_args = NULL;
400 scoped_refptr<ServiceWorkerContextWrapper> context; 582 scoped_refptr<ServiceWorkerContextWrapper> context;
401 if (!GetRegistrationInfo(args, &partition_path, &scope, &context)) 583 if (!args->GetInteger(0, &callback_id) ||
402 return; 584 !args->GetDictionary(1, &cmd_args) ||
403 585 !cmd_args->GetInteger("partition_id", &partition_id) ||
404 scoped_ptr<ListValue> args_copy(args->DeepCopy()); 586 !GetServiceWorkerContext(partition_id, &context) ||
405 BrowserThread::PostTask( 587 !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; 588 return;
563 } 589 }
564 590
565 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 591 base::Callback<void(ServiceWorkerStatusCode)> callback =
566 ListValue result; 592 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
567 for (std::vector<ServiceWorkerRegistrationInfo>::const_iterator it = 593 FindRegistrationForPattern(
568 registrations.begin(); 594 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 } 595 }
698 596
699 } // namespace content 597 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698