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"
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/embedded_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
;
40 void OperationCompleteCallback(WeakPtr
<ServiceWorkerInternalsUI
> internals
,
42 ServiceWorkerStatusCode status
) {
43 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
44 BrowserThread::PostTask(
47 base::Bind(OperationCompleteCallback
, internals
, callback_id
, status
));
50 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
52 internals
->web_ui()->CallJavascriptFunction(
53 "serviceworker.onOperationComplete",
54 FundamentalValue(static_cast<int>(status
)),
55 FundamentalValue(callback_id
));
59 void CallServiceWorkerVersionMethodWithVersionID(
60 ServiceWorkerInternalsUI::ServiceWorkerVersionMethod method
,
61 scoped_refptr
<ServiceWorkerContextWrapper
> context
,
63 const ServiceWorkerInternalsUI::StatusCallback
& callback
) {
64 if (!BrowserThread::CurrentlyOn(BrowserThread::IO
)) {
65 BrowserThread::PostTask(
68 base::Bind(CallServiceWorkerVersionMethodWithVersionID
,
75 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
76 scoped_refptr
<ServiceWorkerVersion
> version
=
77 context
->context()->GetLiveVersion(version_id
);
79 callback
.Run(SERVICE_WORKER_ERROR_NOT_FOUND
);
82 (*version
.get().*method
)(callback
);
85 void DispatchPushEventWithVersionID(
86 scoped_refptr
<ServiceWorkerContextWrapper
> context
,
88 const ServiceWorkerInternalsUI::StatusCallback
& callback
) {
89 if (!BrowserThread::CurrentlyOn(BrowserThread::IO
)) {
90 BrowserThread::PostTask(
93 base::Bind(DispatchPushEventWithVersionID
,
99 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
100 scoped_refptr
<ServiceWorkerVersion
> version
=
101 context
->context()->GetLiveVersion(version_id
);
102 if (!version
.get()) {
103 callback
.Run(SERVICE_WORKER_ERROR_NOT_FOUND
);
106 std::string data
= "Test push message from ServiceWorkerInternals.";
107 version
->DispatchPushEvent(callback
, data
);
110 void UnregisterWithScope(
111 scoped_refptr
<ServiceWorkerContextWrapper
> context
,
113 const ServiceWorkerInternalsUI::StatusCallback
& callback
) {
114 if (!BrowserThread::CurrentlyOn(BrowserThread::IO
)) {
115 BrowserThread::PostTask(
118 base::Bind(UnregisterWithScope
, context
, scope
, callback
));
121 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
122 context
->context()->UnregisterServiceWorker(scope
, callback
);
125 void WorkerStarted(const scoped_refptr
<ServiceWorkerRegistration
>& registration
,
126 const ServiceWorkerInternalsUI::StatusCallback
& callback
,
127 ServiceWorkerStatusCode status
) {
128 callback
.Run(status
);
131 void StartActiveWorker(
132 const ServiceWorkerInternalsUI::StatusCallback
& callback
,
133 ServiceWorkerStatusCode status
,
134 const scoped_refptr
<ServiceWorkerRegistration
>& registration
) {
135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
136 if (status
== SERVICE_WORKER_OK
) {
137 // Pass the reference of |registration| to WorkerStarted callback to prevent
138 // it from being deleted while starting the worker. If the refcount of
139 // |registration| is 1, it will be deleted after WorkerStarted is called.
140 registration
->active_version()->StartWorker(
141 base::Bind(WorkerStarted
, registration
, callback
));
144 callback
.Run(SERVICE_WORKER_ERROR_NOT_FOUND
);
147 void FindRegistrationForPattern(
148 scoped_refptr
<ServiceWorkerContextWrapper
> context
,
150 const ServiceWorkerStorage::FindRegistrationCallback callback
) {
151 if (!BrowserThread::CurrentlyOn(BrowserThread::IO
)) {
152 BrowserThread::PostTask(
155 base::Bind(FindRegistrationForPattern
, context
, scope
, callback
));
158 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
159 context
->context()->storage()->FindRegistrationForPattern(scope
, callback
);
162 void UpdateVersionInfo(const ServiceWorkerVersionInfo
& version
,
163 DictionaryValue
* info
) {
164 switch (version
.running_status
) {
165 case ServiceWorkerVersion::STOPPED
:
166 info
->SetString("running_status", "STOPPED");
168 case ServiceWorkerVersion::STARTING
:
169 info
->SetString("running_status", "STARTING");
171 case ServiceWorkerVersion::RUNNING
:
172 info
->SetString("running_status", "RUNNING");
174 case ServiceWorkerVersion::STOPPING
:
175 info
->SetString("running_status", "STOPPING");
179 switch (version
.status
) {
180 case ServiceWorkerVersion::NEW
:
181 info
->SetString("status", "NEW");
183 case ServiceWorkerVersion::INSTALLING
:
184 info
->SetString("status", "INSTALLING");
186 case ServiceWorkerVersion::INSTALLED
:
187 info
->SetString("status", "INSTALLED");
189 case ServiceWorkerVersion::ACTIVATING
:
190 info
->SetString("status", "ACTIVATING");
192 case ServiceWorkerVersion::ACTIVATED
:
193 info
->SetString("status", "ACTIVATED");
195 case ServiceWorkerVersion::REDUNDANT
:
196 info
->SetString("status", "REDUNDANT");
199 info
->SetString("script_url", version
.script_url
.spec());
200 info
->SetString("version_id", base::Int64ToString(version
.version_id
));
201 info
->SetInteger("process_id", version
.process_id
);
202 info
->SetInteger("thread_id", version
.thread_id
);
203 info
->SetInteger("devtools_agent_route_id", version
.devtools_agent_route_id
);
206 ListValue
* GetRegistrationListValue(
207 const std::vector
<ServiceWorkerRegistrationInfo
>& registrations
) {
208 ListValue
* result
= new ListValue();
209 for (std::vector
<ServiceWorkerRegistrationInfo
>::const_iterator it
=
210 registrations
.begin();
211 it
!= registrations
.end();
213 const ServiceWorkerRegistrationInfo
& registration
= *it
;
214 DictionaryValue
* registration_info
= new DictionaryValue();
215 registration_info
->SetString("scope", registration
.pattern
.spec());
216 registration_info
->SetString(
217 "registration_id", base::Int64ToString(registration
.registration_id
));
219 if (!registration
.active_version
.is_null
) {
220 DictionaryValue
* active_info
= new DictionaryValue();
221 UpdateVersionInfo(registration
.active_version
, active_info
);
222 registration_info
->Set("active", active_info
);
225 if (!registration
.waiting_version
.is_null
) {
226 DictionaryValue
* waiting_info
= new DictionaryValue();
227 UpdateVersionInfo(registration
.waiting_version
, waiting_info
);
228 registration_info
->Set("waiting", waiting_info
);
231 result
->Append(registration_info
);
236 ListValue
* GetVersionListValue(
237 const std::vector
<ServiceWorkerVersionInfo
>& versions
) {
238 ListValue
* result
= new ListValue();
239 for (std::vector
<ServiceWorkerVersionInfo
>::const_iterator it
=
241 it
!= versions
.end();
243 DictionaryValue
* info
= new DictionaryValue();
244 UpdateVersionInfo(*it
, info
);
245 result
->Append(info
);
250 void GetRegistrationsOnIOThread(
251 scoped_refptr
<ServiceWorkerContextWrapper
> context
,
252 base::Callback
<void(const std::vector
<ServiceWorkerRegistrationInfo
>&)>
254 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
255 context
->context()->storage()->GetAllRegistrations(callback
);
258 void OnStoredRegistrations(
259 scoped_refptr
<ServiceWorkerContextWrapper
> context
,
260 base::Callback
<void(const std::vector
<ServiceWorkerRegistrationInfo
>&,
261 const std::vector
<ServiceWorkerVersionInfo
>&,
262 const std::vector
<ServiceWorkerRegistrationInfo
>&)>
264 const std::vector
<ServiceWorkerRegistrationInfo
>& stored_registrations
) {
265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
266 BrowserThread::PostTask(
270 context
->context()->GetAllLiveRegistrationInfo(),
271 context
->context()->GetAllLiveVersionInfo(),
272 stored_registrations
));
275 void OnAllRegistrations(
276 WeakPtr
<ServiceWorkerInternalsUI
> internals
,
278 const base::FilePath
& context_path
,
279 const std::vector
<ServiceWorkerRegistrationInfo
>& live_registrations
,
280 const std::vector
<ServiceWorkerVersionInfo
>& live_versions
,
281 const std::vector
<ServiceWorkerRegistrationInfo
>& stored_registrations
) {
282 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
286 ScopedVector
<const Value
> args
;
287 args
.push_back(GetRegistrationListValue(live_registrations
));
288 args
.push_back(GetVersionListValue(live_versions
));
289 args
.push_back(GetRegistrationListValue(stored_registrations
));
290 args
.push_back(new FundamentalValue(partition_id
));
291 args
.push_back(new StringValue(context_path
.value()));
292 internals
->web_ui()->CallJavascriptFunction("serviceworker.onPartitionData",
298 class ServiceWorkerInternalsUI::PartitionObserver
299 : public ServiceWorkerContextObserver
{
301 PartitionObserver(int partition_id
, WebUI
* web_ui
)
302 : partition_id_(partition_id
), web_ui_(web_ui
) {}
303 ~PartitionObserver() override
{}
304 // ServiceWorkerContextObserver overrides:
305 void OnWorkerStarted(int64 version_id
,
307 int thread_id
) override
{
308 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
309 web_ui_
->CallJavascriptFunction(
310 "serviceworker.onWorkerStarted",
311 FundamentalValue(partition_id_
),
312 StringValue(base::Int64ToString(version_id
)),
313 FundamentalValue(process_id
),
314 FundamentalValue(thread_id
));
316 void OnWorkerStopped(int64 version_id
,
318 int thread_id
) override
{
319 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
320 web_ui_
->CallJavascriptFunction(
321 "serviceworker.onWorkerStopped",
322 FundamentalValue(partition_id_
),
323 StringValue(base::Int64ToString(version_id
)),
324 FundamentalValue(process_id
),
325 FundamentalValue(thread_id
));
327 void OnVersionStateChanged(int64 version_id
) override
{
328 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
329 web_ui_
->CallJavascriptFunction(
330 "serviceworker.onVersionStateChanged",
331 FundamentalValue(partition_id_
),
332 StringValue(base::Int64ToString(version_id
)));
334 void OnErrorReported(int64 version_id
,
337 const ErrorInfo
& info
) override
{
338 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
339 ScopedVector
<const Value
> args
;
340 args
.push_back(new FundamentalValue(partition_id_
));
341 args
.push_back(new StringValue(base::Int64ToString(version_id
)));
342 args
.push_back(new FundamentalValue(process_id
));
343 args
.push_back(new FundamentalValue(thread_id
));
344 scoped_ptr
<DictionaryValue
> value(new DictionaryValue());
345 value
->SetString("message", info
.error_message
);
346 value
->SetInteger("lineNumber", info
.line_number
);
347 value
->SetInteger("columnNumber", info
.column_number
);
348 value
->SetString("sourceURL", info
.source_url
.spec());
349 args
.push_back(value
.release());
350 web_ui_
->CallJavascriptFunction("serviceworker.onErrorReported",
353 void OnReportConsoleMessage(int64 version_id
,
356 const ConsoleMessage
& message
) override
{
357 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
358 ScopedVector
<const Value
> args
;
359 args
.push_back(new FundamentalValue(partition_id_
));
360 args
.push_back(new StringValue(base::Int64ToString(version_id
)));
361 args
.push_back(new FundamentalValue(process_id
));
362 args
.push_back(new FundamentalValue(thread_id
));
363 scoped_ptr
<DictionaryValue
> value(new DictionaryValue());
364 value
->SetInteger("sourceIdentifier", message
.source_identifier
);
365 value
->SetInteger("message_level", message
.message_level
);
366 value
->SetString("message", message
.message
);
367 value
->SetInteger("lineNumber", message
.line_number
);
368 value
->SetString("sourceURL", message
.source_url
.spec());
369 args
.push_back(value
.release());
370 web_ui_
->CallJavascriptFunction("serviceworker.onConsoleMessageReported",
373 void OnRegistrationStored(const GURL
& pattern
) override
{
374 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
375 web_ui_
->CallJavascriptFunction("serviceworker.onRegistrationStored",
376 StringValue(pattern
.spec()));
378 void OnRegistrationDeleted(const GURL
& pattern
) override
{
379 web_ui_
->CallJavascriptFunction("serviceworker.onRegistrationDeleted",
380 StringValue(pattern
.spec()));
382 int partition_id() const { return partition_id_
; }
385 const int partition_id_
;
386 WebUI
* const web_ui_
;
389 ServiceWorkerInternalsUI::ServiceWorkerInternalsUI(WebUI
* web_ui
)
390 : WebUIController(web_ui
), next_partition_id_(0) {
391 WebUIDataSource
* source
=
392 WebUIDataSource::Create(kChromeUIServiceWorkerInternalsHost
);
393 source
->SetJsonPath("strings.js");
394 source
->AddResourcePath("serviceworker_internals.js",
395 IDR_SERVICE_WORKER_INTERNALS_JS
);
396 source
->AddResourcePath("serviceworker_internals.css",
397 IDR_SERVICE_WORKER_INTERNALS_CSS
);
398 source
->SetDefaultResource(IDR_SERVICE_WORKER_INTERNALS_HTML
);
399 source
->DisableDenyXFrameOptions();
401 BrowserContext
* browser_context
=
402 web_ui
->GetWebContents()->GetBrowserContext();
403 WebUIDataSource::Add(browser_context
, source
);
405 web_ui
->RegisterMessageCallback(
407 base::Bind(&ServiceWorkerInternalsUI::GetOptions
,
408 base::Unretained(this)));
409 web_ui
->RegisterMessageCallback(
411 base::Bind(&ServiceWorkerInternalsUI::SetOption
, base::Unretained(this)));
412 web_ui
->RegisterMessageCallback(
413 "getAllRegistrations",
414 base::Bind(&ServiceWorkerInternalsUI::GetAllRegistrations
,
415 base::Unretained(this)));
416 web_ui
->RegisterMessageCallback(
418 base::Bind(&ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod
,
419 base::Unretained(this),
420 &ServiceWorkerVersion::StopWorker
));
421 web_ui
->RegisterMessageCallback(
423 base::Bind(&ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod
,
424 base::Unretained(this),
425 &ServiceWorkerVersion::DispatchSyncEvent
));
426 web_ui
->RegisterMessageCallback(
428 base::Bind(&ServiceWorkerInternalsUI::DispatchPushEvent
,
429 base::Unretained(this)));
430 web_ui
->RegisterMessageCallback(
432 base::Bind(&ServiceWorkerInternalsUI::InspectWorker
,
433 base::Unretained(this)));
434 web_ui
->RegisterMessageCallback(
436 base::Bind(&ServiceWorkerInternalsUI::Unregister
,
437 base::Unretained(this)));
438 web_ui
->RegisterMessageCallback(
440 base::Bind(&ServiceWorkerInternalsUI::StartWorker
,
441 base::Unretained(this)));
444 ServiceWorkerInternalsUI::~ServiceWorkerInternalsUI() {
445 BrowserContext
* browser_context
=
446 web_ui()->GetWebContents()->GetBrowserContext();
447 // Safe to use base::Unretained(this) because
448 // ForEachStoragePartition is synchronous.
449 BrowserContext::StoragePartitionCallback remove_observer_cb
=
450 base::Bind(&ServiceWorkerInternalsUI::RemoveObserverFromStoragePartition
,
451 base::Unretained(this));
452 BrowserContext::ForEachStoragePartition(browser_context
, remove_observer_cb
);
455 void ServiceWorkerInternalsUI::GetOptions(const ListValue
* args
) {
456 DictionaryValue options
;
457 options
.SetBoolean("debug_on_start",
458 EmbeddedWorkerDevToolsManager::GetInstance()
459 ->debug_service_worker_on_start());
460 web_ui()->CallJavascriptFunction("serviceworker.onOptions", options
);
463 void ServiceWorkerInternalsUI::SetOption(const ListValue
* args
) {
464 std::string option_name
;
466 if (!args
->GetString(0, &option_name
) || option_name
!= "debug_on_start" ||
467 !args
->GetBoolean(1, &option_boolean
)) {
470 EmbeddedWorkerDevToolsManager::GetInstance()
471 ->set_debug_service_worker_on_start(option_boolean
);
474 void ServiceWorkerInternalsUI::GetAllRegistrations(const ListValue
* args
) {
475 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
476 BrowserContext
* browser_context
=
477 web_ui()->GetWebContents()->GetBrowserContext();
478 // Safe to use base::Unretained(this) because
479 // ForEachStoragePartition is synchronous.
480 BrowserContext::StoragePartitionCallback add_context_cb
=
481 base::Bind(&ServiceWorkerInternalsUI::AddContextFromStoragePartition
,
482 base::Unretained(this));
483 BrowserContext::ForEachStoragePartition(browser_context
, add_context_cb
);
486 void ServiceWorkerInternalsUI::AddContextFromStoragePartition(
487 StoragePartition
* partition
) {
488 int partition_id
= 0;
489 scoped_refptr
<ServiceWorkerContextWrapper
> context
=
490 static_cast<ServiceWorkerContextWrapper
*>(
491 partition
->GetServiceWorkerContext());
492 if (PartitionObserver
* observer
=
493 observers_
.get(reinterpret_cast<uintptr_t>(partition
))) {
494 partition_id
= observer
->partition_id();
496 partition_id
= next_partition_id_
++;
497 scoped_ptr
<PartitionObserver
> new_observer(
498 new PartitionObserver(partition_id
, web_ui()));
499 context
->AddObserver(new_observer
.get());
500 observers_
.set(reinterpret_cast<uintptr_t>(partition
), new_observer
.Pass());
503 BrowserThread::PostTask(
506 base::Bind(GetRegistrationsOnIOThread
,
508 base::Bind(OnStoredRegistrations
,
510 base::Bind(OnAllRegistrations
,
513 context
->is_incognito()
515 : partition
->GetPath()))));
518 void ServiceWorkerInternalsUI::RemoveObserverFromStoragePartition(
519 StoragePartition
* partition
) {
520 scoped_ptr
<PartitionObserver
> observer(
521 observers_
.take_and_erase(reinterpret_cast<uintptr_t>(partition
)));
524 scoped_refptr
<ServiceWorkerContextWrapper
> context
=
525 static_cast<ServiceWorkerContextWrapper
*>(
526 partition
->GetServiceWorkerContext());
527 context
->RemoveObserver(observer
.get());
530 void ServiceWorkerInternalsUI::FindContext(
532 StoragePartition
** result_partition
,
533 StoragePartition
* storage_partition
) const {
534 PartitionObserver
* observer
=
535 observers_
.get(reinterpret_cast<uintptr_t>(storage_partition
));
536 if (observer
&& partition_id
== observer
->partition_id()) {
537 *result_partition
= storage_partition
;
541 bool ServiceWorkerInternalsUI::GetServiceWorkerContext(
543 scoped_refptr
<ServiceWorkerContextWrapper
>* context
) const {
544 BrowserContext
* browser_context
=
545 web_ui()->GetWebContents()->GetBrowserContext();
546 StoragePartition
* result_partition(NULL
);
547 BrowserContext::StoragePartitionCallback find_context_cb
=
548 base::Bind(&ServiceWorkerInternalsUI::FindContext
,
549 base::Unretained(this),
552 BrowserContext::ForEachStoragePartition(browser_context
, find_context_cb
);
553 if (!result_partition
)
555 *context
= static_cast<ServiceWorkerContextWrapper
*>(
556 result_partition
->GetServiceWorkerContext());
560 void ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod(
561 ServiceWorkerVersionMethod method
,
562 const ListValue
* args
) {
563 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
565 const DictionaryValue
* cmd_args
= NULL
;
567 scoped_refptr
<ServiceWorkerContextWrapper
> context
;
568 std::string version_id_string
;
569 int64 version_id
= 0;
570 if (!args
->GetInteger(0, &callback_id
) ||
571 !args
->GetDictionary(1, &cmd_args
) ||
572 !cmd_args
->GetInteger("partition_id", &partition_id
) ||
573 !GetServiceWorkerContext(partition_id
, &context
) ||
574 !cmd_args
->GetString("version_id", &version_id_string
) ||
575 !base::StringToInt64(version_id_string
, &version_id
)) {
579 base::Callback
<void(ServiceWorkerStatusCode
)> callback
=
580 base::Bind(OperationCompleteCallback
, AsWeakPtr(), callback_id
);
581 CallServiceWorkerVersionMethodWithVersionID(
582 method
, context
, version_id
, callback
);
585 void ServiceWorkerInternalsUI::DispatchPushEvent(
586 const ListValue
* args
) {
587 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
590 int64 version_id
= 0;
591 std::string version_id_string
;
592 const DictionaryValue
* cmd_args
= NULL
;
593 scoped_refptr
<ServiceWorkerContextWrapper
> context
;
594 if (!args
->GetInteger(0, &callback_id
) ||
595 !args
->GetDictionary(1, &cmd_args
) ||
596 !cmd_args
->GetInteger("partition_id", &partition_id
) ||
597 !GetServiceWorkerContext(partition_id
, &context
) ||
598 !cmd_args
->GetString("version_id", &version_id_string
) ||
599 !base::StringToInt64(version_id_string
, &version_id
)) {
603 base::Callback
<void(ServiceWorkerStatusCode
)> callback
=
604 base::Bind(OperationCompleteCallback
, AsWeakPtr(), callback_id
);
605 DispatchPushEventWithVersionID(context
, version_id
, callback
);
608 void ServiceWorkerInternalsUI::InspectWorker(const ListValue
* args
) {
609 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
611 const DictionaryValue
* cmd_args
= NULL
;
613 int devtools_agent_route_id
= 0;
614 if (!args
->GetInteger(0, &callback_id
) ||
615 !args
->GetDictionary(1, &cmd_args
) ||
616 !cmd_args
->GetInteger("process_id", &process_id
) ||
617 !cmd_args
->GetInteger("devtools_agent_route_id",
618 &devtools_agent_route_id
)) {
621 base::Callback
<void(ServiceWorkerStatusCode
)> callback
=
622 base::Bind(OperationCompleteCallback
, AsWeakPtr(), callback_id
);
623 scoped_refptr
<DevToolsAgentHostImpl
> agent_host(
624 EmbeddedWorkerDevToolsManager::GetInstance()
625 ->GetDevToolsAgentHostForWorker(process_id
, devtools_agent_route_id
));
626 if (!agent_host
.get()) {
627 callback
.Run(SERVICE_WORKER_ERROR_NOT_FOUND
);
630 agent_host
->Inspect(web_ui()->GetWebContents()->GetBrowserContext());
631 callback
.Run(SERVICE_WORKER_OK
);
634 void ServiceWorkerInternalsUI::Unregister(const ListValue
* args
) {
635 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
638 std::string scope_string
;
639 const DictionaryValue
* cmd_args
= NULL
;
640 scoped_refptr
<ServiceWorkerContextWrapper
> context
;
641 if (!args
->GetInteger(0, &callback_id
) ||
642 !args
->GetDictionary(1, &cmd_args
) ||
643 !cmd_args
->GetInteger("partition_id", &partition_id
) ||
644 !GetServiceWorkerContext(partition_id
, &context
) ||
645 !cmd_args
->GetString("scope", &scope_string
)) {
649 base::Callback
<void(ServiceWorkerStatusCode
)> callback
=
650 base::Bind(OperationCompleteCallback
, AsWeakPtr(), callback_id
);
651 UnregisterWithScope(context
, GURL(scope_string
), callback
);
654 void ServiceWorkerInternalsUI::StartWorker(const ListValue
* args
) {
655 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
658 std::string scope_string
;
659 const DictionaryValue
* cmd_args
= NULL
;
660 scoped_refptr
<ServiceWorkerContextWrapper
> context
;
661 if (!args
->GetInteger(0, &callback_id
) ||
662 !args
->GetDictionary(1, &cmd_args
) ||
663 !cmd_args
->GetInteger("partition_id", &partition_id
) ||
664 !GetServiceWorkerContext(partition_id
, &context
) ||
665 !cmd_args
->GetString("scope", &scope_string
)) {
669 base::Callback
<void(ServiceWorkerStatusCode
)> callback
=
670 base::Bind(OperationCompleteCallback
, AsWeakPtr(), callback_id
);
671 FindRegistrationForPattern(
672 context
, GURL(scope_string
), base::Bind(StartActiveWorker
, callback
));
675 } // namespace content