Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_internals_ui.cc
blob0a0df729c797cffd1b037e85696ce1fbe29c3792
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
3 // found in the LICENSE file.
5 #include "content/browser/service_worker/service_worker_internals_ui.h"
7 #include <string>
8 #include <vector>
10 #include "base/bind.h"
11 #include "base/memory/scoped_vector.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/values.h"
14 #include "content/browser/devtools/devtools_agent_host_impl.h"
15 #include "content/browser/devtools/service_worker_devtools_manager.h"
16 #include "content/browser/service_worker/service_worker_context_observer.h"
17 #include "content/browser/service_worker/service_worker_context_wrapper.h"
18 #include "content/browser/service_worker/service_worker_registration.h"
19 #include "content/browser/service_worker/service_worker_version.h"
20 #include "content/grit/content_resources.h"
21 #include "content/public/browser/browser_context.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "content/public/browser/storage_partition.h"
24 #include "content/public/browser/web_contents.h"
25 #include "content/public/browser/web_ui.h"
26 #include "content/public/browser/web_ui_data_source.h"
27 #include "content/public/common/url_constants.h"
29 using base::DictionaryValue;
30 using base::FundamentalValue;
31 using base::ListValue;
32 using base::StringValue;
33 using base::Value;
34 using base::WeakPtr;
36 namespace content {
38 namespace {
40 using GetRegistrationsCallback =
41 base::Callback<void(const std::vector<ServiceWorkerRegistrationInfo>&,
42 const std::vector<ServiceWorkerVersionInfo>&,
43 const std::vector<ServiceWorkerRegistrationInfo>&)>;
45 void OperationCompleteCallback(WeakPtr<ServiceWorkerInternalsUI> internals,
46 int callback_id,
47 ServiceWorkerStatusCode status) {
48 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
49 BrowserThread::PostTask(
50 BrowserThread::UI,
51 FROM_HERE,
52 base::Bind(OperationCompleteCallback, internals, callback_id, status));
53 return;
55 DCHECK_CURRENTLY_ON(BrowserThread::UI);
56 if (internals) {
57 internals->web_ui()->CallJavascriptFunction(
58 "serviceworker.onOperationComplete",
59 FundamentalValue(static_cast<int>(status)),
60 FundamentalValue(callback_id));
64 void CallServiceWorkerVersionMethodWithVersionID(
65 ServiceWorkerInternalsUI::ServiceWorkerVersionMethod method,
66 scoped_refptr<ServiceWorkerContextWrapper> context,
67 int64 version_id,
68 const ServiceWorkerInternalsUI::StatusCallback& callback) {
69 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
70 BrowserThread::PostTask(
71 BrowserThread::IO,
72 FROM_HERE,
73 base::Bind(CallServiceWorkerVersionMethodWithVersionID,
74 method,
75 context,
76 version_id,
77 callback));
78 return;
81 if (!context->context()) {
82 callback.Run(SERVICE_WORKER_ERROR_ABORT);
83 return;
86 scoped_refptr<ServiceWorkerVersion> version =
87 context->context()->GetLiveVersion(version_id);
88 if (!version.get()) {
89 callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND);
90 return;
92 (*version.get().*method)(callback);
95 void DispatchPushEventWithVersionID(
96 scoped_refptr<ServiceWorkerContextWrapper> context,
97 int64 version_id,
98 const ServiceWorkerInternalsUI::StatusCallback& callback) {
99 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
100 BrowserThread::PostTask(
101 BrowserThread::IO,
102 FROM_HERE,
103 base::Bind(DispatchPushEventWithVersionID,
104 context,
105 version_id,
106 callback));
107 return;
110 if (!context->context()) {
111 callback.Run(SERVICE_WORKER_ERROR_ABORT);
112 return;
115 scoped_refptr<ServiceWorkerVersion> version =
116 context->context()->GetLiveVersion(version_id);
117 if (!version.get()) {
118 callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND);
119 return;
121 std::string data = "Test push message from ServiceWorkerInternals.";
122 version->DispatchPushEvent(callback, data);
125 void UnregisterWithScope(
126 scoped_refptr<ServiceWorkerContextWrapper> context,
127 const GURL& scope,
128 const ServiceWorkerInternalsUI::StatusCallback& callback) {
129 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
130 BrowserThread::PostTask(
131 BrowserThread::IO,
132 FROM_HERE,
133 base::Bind(UnregisterWithScope, context, scope, callback));
134 return;
137 if (!context->context()) {
138 callback.Run(SERVICE_WORKER_ERROR_ABORT);
139 return;
141 context->context()->UnregisterServiceWorker(scope, callback);
144 void FindRegistrationForPattern(
145 scoped_refptr<ServiceWorkerContextWrapper> context,
146 const GURL& scope,
147 const ServiceWorkerStorage::FindRegistrationCallback callback) {
148 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
149 BrowserThread::PostTask(
150 BrowserThread::IO,
151 FROM_HERE,
152 base::Bind(FindRegistrationForPattern, context, scope, callback));
153 return;
156 if (!context->context()) {
157 callback.Run(SERVICE_WORKER_ERROR_ABORT,
158 scoped_refptr<ServiceWorkerRegistration>());
159 return;
161 context->context()->storage()->FindRegistrationForPattern(scope, callback);
164 void UpdateVersionInfo(const ServiceWorkerVersionInfo& version,
165 DictionaryValue* info) {
166 switch (version.running_status) {
167 case ServiceWorkerVersion::STOPPED:
168 info->SetString("running_status", "STOPPED");
169 break;
170 case ServiceWorkerVersion::STARTING:
171 info->SetString("running_status", "STARTING");
172 break;
173 case ServiceWorkerVersion::RUNNING:
174 info->SetString("running_status", "RUNNING");
175 break;
176 case ServiceWorkerVersion::STOPPING:
177 info->SetString("running_status", "STOPPING");
178 break;
181 switch (version.status) {
182 case ServiceWorkerVersion::NEW:
183 info->SetString("status", "NEW");
184 break;
185 case ServiceWorkerVersion::INSTALLING:
186 info->SetString("status", "INSTALLING");
187 break;
188 case ServiceWorkerVersion::INSTALLED:
189 info->SetString("status", "INSTALLED");
190 break;
191 case ServiceWorkerVersion::ACTIVATING:
192 info->SetString("status", "ACTIVATING");
193 break;
194 case ServiceWorkerVersion::ACTIVATED:
195 info->SetString("status", "ACTIVATED");
196 break;
197 case ServiceWorkerVersion::REDUNDANT:
198 info->SetString("status", "REDUNDANT");
199 break;
201 info->SetString("script_url", version.script_url.spec());
202 info->SetString("version_id", base::Int64ToString(version.version_id));
203 info->SetInteger("process_id", version.process_id);
204 info->SetInteger("thread_id", version.thread_id);
205 info->SetInteger("devtools_agent_route_id", version.devtools_agent_route_id);
208 ListValue* GetRegistrationListValue(
209 const std::vector<ServiceWorkerRegistrationInfo>& registrations) {
210 ListValue* result = new ListValue();
211 for (std::vector<ServiceWorkerRegistrationInfo>::const_iterator it =
212 registrations.begin();
213 it != registrations.end();
214 ++it) {
215 const ServiceWorkerRegistrationInfo& registration = *it;
216 DictionaryValue* registration_info = new DictionaryValue();
217 registration_info->SetString("scope", registration.pattern.spec());
218 registration_info->SetString(
219 "registration_id", base::Int64ToString(registration.registration_id));
221 if (registration.active_version.version_id !=
222 kInvalidServiceWorkerVersionId) {
223 DictionaryValue* active_info = new DictionaryValue();
224 UpdateVersionInfo(registration.active_version, active_info);
225 registration_info->Set("active", active_info);
228 if (registration.waiting_version.version_id !=
229 kInvalidServiceWorkerVersionId) {
230 DictionaryValue* waiting_info = new DictionaryValue();
231 UpdateVersionInfo(registration.waiting_version, waiting_info);
232 registration_info->Set("waiting", waiting_info);
235 result->Append(registration_info);
237 return result;
240 ListValue* GetVersionListValue(
241 const std::vector<ServiceWorkerVersionInfo>& versions) {
242 ListValue* result = new ListValue();
243 for (std::vector<ServiceWorkerVersionInfo>::const_iterator it =
244 versions.begin();
245 it != versions.end();
246 ++it) {
247 DictionaryValue* info = new DictionaryValue();
248 UpdateVersionInfo(*it, info);
249 result->Append(info);
251 return result;
254 void DidGetStoredRegistrationsOnIOThread(
255 scoped_refptr<ServiceWorkerContextWrapper> context,
256 const GetRegistrationsCallback& callback,
257 const std::vector<ServiceWorkerRegistrationInfo>& stored_registrations) {
258 DCHECK_CURRENTLY_ON(BrowserThread::IO);
259 if (!context->context()) {
260 BrowserThread::PostTask(
261 BrowserThread::UI, FROM_HERE,
262 base::Bind(callback, std::vector<ServiceWorkerRegistrationInfo>(),
263 std::vector<ServiceWorkerVersionInfo>(),
264 std::vector<ServiceWorkerRegistrationInfo>()));
265 return;
268 BrowserThread::PostTask(
269 BrowserThread::UI,
270 FROM_HERE,
271 base::Bind(callback,
272 context->context()->GetAllLiveRegistrationInfo(),
273 context->context()->GetAllLiveVersionInfo(),
274 stored_registrations));
277 void GetRegistrationsOnIOThread(
278 scoped_refptr<ServiceWorkerContextWrapper> context,
279 const GetRegistrationsCallback& callback) {
280 DCHECK_CURRENTLY_ON(BrowserThread::IO);
281 if (!context->context()) {
282 BrowserThread::PostTask(
283 BrowserThread::UI, FROM_HERE,
284 base::Bind(callback, std::vector<ServiceWorkerRegistrationInfo>(),
285 std::vector<ServiceWorkerVersionInfo>(),
286 std::vector<ServiceWorkerRegistrationInfo>()));
287 return;
289 context->context()->storage()->GetAllRegistrations(
290 base::Bind(DidGetStoredRegistrationsOnIOThread, context, callback));
293 void DidGetRegistrations(
294 WeakPtr<ServiceWorkerInternalsUI> internals,
295 int partition_id,
296 const base::FilePath& context_path,
297 const std::vector<ServiceWorkerRegistrationInfo>& live_registrations,
298 const std::vector<ServiceWorkerVersionInfo>& live_versions,
299 const std::vector<ServiceWorkerRegistrationInfo>& stored_registrations) {
300 DCHECK_CURRENTLY_ON(BrowserThread::UI);
301 if (!internals)
302 return;
304 ScopedVector<const Value> args;
305 args.push_back(GetRegistrationListValue(live_registrations));
306 args.push_back(GetVersionListValue(live_versions));
307 args.push_back(GetRegistrationListValue(stored_registrations));
308 args.push_back(new FundamentalValue(partition_id));
309 args.push_back(new StringValue(context_path.value()));
310 internals->web_ui()->CallJavascriptFunction("serviceworker.onPartitionData",
311 args.get());
314 } // namespace
316 class ServiceWorkerInternalsUI::PartitionObserver
317 : public ServiceWorkerContextObserver {
318 public:
319 PartitionObserver(int partition_id, WebUI* web_ui)
320 : partition_id_(partition_id), web_ui_(web_ui) {}
321 ~PartitionObserver() override {}
322 // ServiceWorkerContextObserver overrides:
323 void OnRunningStateChanged(int64 version_id,
324 ServiceWorkerVersion::RunningStatus) override {
325 DCHECK_CURRENTLY_ON(BrowserThread::UI);
326 web_ui_->CallJavascriptFunction(
327 "serviceworker.onRunningStateChanged", FundamentalValue(partition_id_),
328 StringValue(base::Int64ToString(version_id)));
330 void OnVersionStateChanged(int64 version_id,
331 ServiceWorkerVersion::Status) override {
332 DCHECK_CURRENTLY_ON(BrowserThread::UI);
333 web_ui_->CallJavascriptFunction(
334 "serviceworker.onVersionStateChanged",
335 FundamentalValue(partition_id_),
336 StringValue(base::Int64ToString(version_id)));
338 void OnErrorReported(int64 version_id,
339 int process_id,
340 int thread_id,
341 const ErrorInfo& info) override {
342 DCHECK_CURRENTLY_ON(BrowserThread::UI);
343 ScopedVector<const Value> args;
344 args.push_back(new FundamentalValue(partition_id_));
345 args.push_back(new StringValue(base::Int64ToString(version_id)));
346 args.push_back(new FundamentalValue(process_id));
347 args.push_back(new FundamentalValue(thread_id));
348 scoped_ptr<DictionaryValue> value(new DictionaryValue());
349 value->SetString("message", info.error_message);
350 value->SetInteger("lineNumber", info.line_number);
351 value->SetInteger("columnNumber", info.column_number);
352 value->SetString("sourceURL", info.source_url.spec());
353 args.push_back(value.release());
354 web_ui_->CallJavascriptFunction("serviceworker.onErrorReported",
355 args.get());
357 void OnReportConsoleMessage(int64 version_id,
358 int process_id,
359 int thread_id,
360 const ConsoleMessage& message) override {
361 DCHECK_CURRENTLY_ON(BrowserThread::UI);
362 ScopedVector<const Value> args;
363 args.push_back(new FundamentalValue(partition_id_));
364 args.push_back(new StringValue(base::Int64ToString(version_id)));
365 args.push_back(new FundamentalValue(process_id));
366 args.push_back(new FundamentalValue(thread_id));
367 scoped_ptr<DictionaryValue> value(new DictionaryValue());
368 value->SetInteger("sourceIdentifier", message.source_identifier);
369 value->SetInteger("message_level", message.message_level);
370 value->SetString("message", message.message);
371 value->SetInteger("lineNumber", message.line_number);
372 value->SetString("sourceURL", message.source_url.spec());
373 args.push_back(value.release());
374 web_ui_->CallJavascriptFunction("serviceworker.onConsoleMessageReported",
375 args.get());
377 void OnRegistrationStored(int64 registration_id,
378 const GURL& pattern) override {
379 DCHECK_CURRENTLY_ON(BrowserThread::UI);
380 web_ui_->CallJavascriptFunction("serviceworker.onRegistrationStored",
381 StringValue(pattern.spec()));
383 void OnRegistrationDeleted(int64 registration_id,
384 const GURL& pattern) override {
385 web_ui_->CallJavascriptFunction("serviceworker.onRegistrationDeleted",
386 StringValue(pattern.spec()));
388 int partition_id() const { return partition_id_; }
390 private:
391 const int partition_id_;
392 WebUI* const web_ui_;
395 ServiceWorkerInternalsUI::ServiceWorkerInternalsUI(WebUI* web_ui)
396 : WebUIController(web_ui), next_partition_id_(0) {
397 WebUIDataSource* source =
398 WebUIDataSource::Create(kChromeUIServiceWorkerInternalsHost);
399 source->SetJsonPath("strings.js");
400 source->AddResourcePath("serviceworker_internals.js",
401 IDR_SERVICE_WORKER_INTERNALS_JS);
402 source->AddResourcePath("serviceworker_internals.css",
403 IDR_SERVICE_WORKER_INTERNALS_CSS);
404 source->SetDefaultResource(IDR_SERVICE_WORKER_INTERNALS_HTML);
405 source->DisableDenyXFrameOptions();
407 BrowserContext* browser_context =
408 web_ui->GetWebContents()->GetBrowserContext();
409 WebUIDataSource::Add(browser_context, source);
411 web_ui->RegisterMessageCallback(
412 "GetOptions",
413 base::Bind(&ServiceWorkerInternalsUI::GetOptions,
414 base::Unretained(this)));
415 web_ui->RegisterMessageCallback(
416 "SetOption",
417 base::Bind(&ServiceWorkerInternalsUI::SetOption, base::Unretained(this)));
418 web_ui->RegisterMessageCallback(
419 "getAllRegistrations",
420 base::Bind(&ServiceWorkerInternalsUI::GetAllRegistrations,
421 base::Unretained(this)));
422 web_ui->RegisterMessageCallback(
423 "stop",
424 base::Bind(&ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod,
425 base::Unretained(this),
426 &ServiceWorkerVersion::StopWorker));
427 web_ui->RegisterMessageCallback(
428 "sync",
429 base::Bind(&ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod,
430 base::Unretained(this),
431 &ServiceWorkerVersion::DispatchSyncEvent));
432 web_ui->RegisterMessageCallback(
433 "push",
434 base::Bind(&ServiceWorkerInternalsUI::DispatchPushEvent,
435 base::Unretained(this)));
436 web_ui->RegisterMessageCallback(
437 "inspect",
438 base::Bind(&ServiceWorkerInternalsUI::InspectWorker,
439 base::Unretained(this)));
440 web_ui->RegisterMessageCallback(
441 "unregister",
442 base::Bind(&ServiceWorkerInternalsUI::Unregister,
443 base::Unretained(this)));
444 web_ui->RegisterMessageCallback(
445 "start",
446 base::Bind(&ServiceWorkerInternalsUI::StartWorker,
447 base::Unretained(this)));
450 ServiceWorkerInternalsUI::~ServiceWorkerInternalsUI() {
451 BrowserContext* browser_context =
452 web_ui()->GetWebContents()->GetBrowserContext();
453 // Safe to use base::Unretained(this) because
454 // ForEachStoragePartition is synchronous.
455 BrowserContext::StoragePartitionCallback remove_observer_cb =
456 base::Bind(&ServiceWorkerInternalsUI::RemoveObserverFromStoragePartition,
457 base::Unretained(this));
458 BrowserContext::ForEachStoragePartition(browser_context, remove_observer_cb);
461 void ServiceWorkerInternalsUI::GetOptions(const ListValue* args) {
462 DictionaryValue options;
463 options.SetBoolean("debug_on_start",
464 ServiceWorkerDevToolsManager::GetInstance()
465 ->debug_service_worker_on_start());
466 web_ui()->CallJavascriptFunction("serviceworker.onOptions", options);
469 void ServiceWorkerInternalsUI::SetOption(const ListValue* args) {
470 std::string option_name;
471 bool option_boolean;
472 if (!args->GetString(0, &option_name) || option_name != "debug_on_start" ||
473 !args->GetBoolean(1, &option_boolean)) {
474 return;
476 ServiceWorkerDevToolsManager::GetInstance()
477 ->set_debug_service_worker_on_start(option_boolean);
480 void ServiceWorkerInternalsUI::GetAllRegistrations(const ListValue* args) {
481 DCHECK_CURRENTLY_ON(BrowserThread::UI);
482 BrowserContext* browser_context =
483 web_ui()->GetWebContents()->GetBrowserContext();
484 // Safe to use base::Unretained(this) because
485 // ForEachStoragePartition is synchronous.
486 BrowserContext::StoragePartitionCallback add_context_cb =
487 base::Bind(&ServiceWorkerInternalsUI::AddContextFromStoragePartition,
488 base::Unretained(this));
489 BrowserContext::ForEachStoragePartition(browser_context, add_context_cb);
492 void ServiceWorkerInternalsUI::AddContextFromStoragePartition(
493 StoragePartition* partition) {
494 int partition_id = 0;
495 scoped_refptr<ServiceWorkerContextWrapper> context =
496 static_cast<ServiceWorkerContextWrapper*>(
497 partition->GetServiceWorkerContext());
498 if (PartitionObserver* observer =
499 observers_.get(reinterpret_cast<uintptr_t>(partition))) {
500 partition_id = observer->partition_id();
501 } else {
502 partition_id = next_partition_id_++;
503 scoped_ptr<PartitionObserver> new_observer(
504 new PartitionObserver(partition_id, web_ui()));
505 context->AddObserver(new_observer.get());
506 observers_.set(reinterpret_cast<uintptr_t>(partition), new_observer.Pass());
509 BrowserThread::PostTask(
510 BrowserThread::IO, FROM_HERE,
511 base::Bind(GetRegistrationsOnIOThread, context,
512 base::Bind(DidGetRegistrations, AsWeakPtr(), partition_id,
513 context->is_incognito() ? base::FilePath()
514 : partition->GetPath())));
517 void ServiceWorkerInternalsUI::RemoveObserverFromStoragePartition(
518 StoragePartition* partition) {
519 scoped_ptr<PartitionObserver> observer(
520 observers_.take_and_erase(reinterpret_cast<uintptr_t>(partition)));
521 if (!observer.get())
522 return;
523 scoped_refptr<ServiceWorkerContextWrapper> context =
524 static_cast<ServiceWorkerContextWrapper*>(
525 partition->GetServiceWorkerContext());
526 context->RemoveObserver(observer.get());
529 void ServiceWorkerInternalsUI::FindContext(
530 int partition_id,
531 StoragePartition** result_partition,
532 StoragePartition* storage_partition) const {
533 PartitionObserver* observer =
534 observers_.get(reinterpret_cast<uintptr_t>(storage_partition));
535 if (observer && partition_id == observer->partition_id()) {
536 *result_partition = storage_partition;
540 bool ServiceWorkerInternalsUI::GetServiceWorkerContext(
541 int partition_id,
542 scoped_refptr<ServiceWorkerContextWrapper>* context) const {
543 BrowserContext* browser_context =
544 web_ui()->GetWebContents()->GetBrowserContext();
545 StoragePartition* result_partition(NULL);
546 BrowserContext::StoragePartitionCallback find_context_cb =
547 base::Bind(&ServiceWorkerInternalsUI::FindContext,
548 base::Unretained(this),
549 partition_id,
550 &result_partition);
551 BrowserContext::ForEachStoragePartition(browser_context, find_context_cb);
552 if (!result_partition)
553 return false;
554 *context = static_cast<ServiceWorkerContextWrapper*>(
555 result_partition->GetServiceWorkerContext());
556 return true;
559 void ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod(
560 ServiceWorkerVersionMethod method,
561 const ListValue* args) {
562 DCHECK_CURRENTLY_ON(BrowserThread::UI);
563 int callback_id;
564 const DictionaryValue* cmd_args = NULL;
565 int partition_id;
566 scoped_refptr<ServiceWorkerContextWrapper> context;
567 std::string version_id_string;
568 int64 version_id = 0;
569 if (!args->GetInteger(0, &callback_id) ||
570 !args->GetDictionary(1, &cmd_args) ||
571 !cmd_args->GetInteger("partition_id", &partition_id) ||
572 !GetServiceWorkerContext(partition_id, &context) ||
573 !cmd_args->GetString("version_id", &version_id_string) ||
574 !base::StringToInt64(version_id_string, &version_id)) {
575 return;
578 base::Callback<void(ServiceWorkerStatusCode)> callback =
579 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
580 CallServiceWorkerVersionMethodWithVersionID(
581 method, context, version_id, callback);
584 void ServiceWorkerInternalsUI::DispatchPushEvent(
585 const ListValue* args) {
586 DCHECK_CURRENTLY_ON(BrowserThread::UI);
587 int callback_id;
588 int partition_id;
589 int64 version_id = 0;
590 std::string version_id_string;
591 const DictionaryValue* cmd_args = NULL;
592 scoped_refptr<ServiceWorkerContextWrapper> context;
593 if (!args->GetInteger(0, &callback_id) ||
594 !args->GetDictionary(1, &cmd_args) ||
595 !cmd_args->GetInteger("partition_id", &partition_id) ||
596 !GetServiceWorkerContext(partition_id, &context) ||
597 !cmd_args->GetString("version_id", &version_id_string) ||
598 !base::StringToInt64(version_id_string, &version_id)) {
599 return;
602 base::Callback<void(ServiceWorkerStatusCode)> callback =
603 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
604 DispatchPushEventWithVersionID(context, version_id, callback);
607 void ServiceWorkerInternalsUI::InspectWorker(const ListValue* args) {
608 DCHECK_CURRENTLY_ON(BrowserThread::UI);
609 int callback_id;
610 const DictionaryValue* cmd_args = NULL;
611 int process_id = 0;
612 int devtools_agent_route_id = 0;
613 if (!args->GetInteger(0, &callback_id) ||
614 !args->GetDictionary(1, &cmd_args) ||
615 !cmd_args->GetInteger("process_id", &process_id) ||
616 !cmd_args->GetInteger("devtools_agent_route_id",
617 &devtools_agent_route_id)) {
618 return;
620 base::Callback<void(ServiceWorkerStatusCode)> callback =
621 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
622 scoped_refptr<DevToolsAgentHostImpl> agent_host(
623 ServiceWorkerDevToolsManager::GetInstance()
624 ->GetDevToolsAgentHostForWorker(process_id, devtools_agent_route_id));
625 if (!agent_host.get()) {
626 callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND);
627 return;
629 agent_host->Inspect(web_ui()->GetWebContents()->GetBrowserContext());
630 callback.Run(SERVICE_WORKER_OK);
633 void ServiceWorkerInternalsUI::Unregister(const ListValue* args) {
634 DCHECK_CURRENTLY_ON(BrowserThread::UI);
635 int callback_id;
636 int partition_id;
637 std::string scope_string;
638 const DictionaryValue* cmd_args = NULL;
639 scoped_refptr<ServiceWorkerContextWrapper> context;
640 if (!args->GetInteger(0, &callback_id) ||
641 !args->GetDictionary(1, &cmd_args) ||
642 !cmd_args->GetInteger("partition_id", &partition_id) ||
643 !GetServiceWorkerContext(partition_id, &context) ||
644 !cmd_args->GetString("scope", &scope_string)) {
645 return;
648 base::Callback<void(ServiceWorkerStatusCode)> callback =
649 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
650 UnregisterWithScope(context, GURL(scope_string), callback);
653 void ServiceWorkerInternalsUI::StartWorker(const ListValue* args) {
654 DCHECK_CURRENTLY_ON(BrowserThread::UI);
655 int callback_id;
656 int partition_id;
657 std::string scope_string;
658 const DictionaryValue* cmd_args = NULL;
659 scoped_refptr<ServiceWorkerContextWrapper> context;
660 if (!args->GetInteger(0, &callback_id) ||
661 !args->GetDictionary(1, &cmd_args) ||
662 !cmd_args->GetInteger("partition_id", &partition_id) ||
663 !GetServiceWorkerContext(partition_id, &context) ||
664 !cmd_args->GetString("scope", &scope_string)) {
665 return;
667 base::Callback<void(ServiceWorkerStatusCode)> callback =
668 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
669 context->StartServiceWorker(GURL(scope_string), callback);
672 } // namespace content