CacheStorage: Remove unused interfaces from CacheStorageListener
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_internals_ui.cc
blob2176eb75946b79d9357034e99dc6cec3c62cc055
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 scoped_refptr<ServiceWorkerVersion> version =
82 context->GetLiveVersion(version_id);
83 if (!version.get()) {
84 callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND);
85 return;
87 (*version.get().*method)(callback);
90 void DispatchPushEventWithVersionID(
91 scoped_refptr<ServiceWorkerContextWrapper> context,
92 int64 version_id,
93 const ServiceWorkerInternalsUI::StatusCallback& callback) {
94 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
95 BrowserThread::PostTask(
96 BrowserThread::IO,
97 FROM_HERE,
98 base::Bind(DispatchPushEventWithVersionID,
99 context,
100 version_id,
101 callback));
102 return;
105 scoped_refptr<ServiceWorkerVersion> version =
106 context->GetLiveVersion(version_id);
107 if (!version.get()) {
108 callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND);
109 return;
111 std::string data = "Test push message from ServiceWorkerInternals.";
112 version->DispatchPushEvent(callback, data);
115 void UpdateVersionInfo(const ServiceWorkerVersionInfo& version,
116 DictionaryValue* info) {
117 switch (version.running_status) {
118 case ServiceWorkerVersion::STOPPED:
119 info->SetString("running_status", "STOPPED");
120 break;
121 case ServiceWorkerVersion::STARTING:
122 info->SetString("running_status", "STARTING");
123 break;
124 case ServiceWorkerVersion::RUNNING:
125 info->SetString("running_status", "RUNNING");
126 break;
127 case ServiceWorkerVersion::STOPPING:
128 info->SetString("running_status", "STOPPING");
129 break;
132 switch (version.status) {
133 case ServiceWorkerVersion::NEW:
134 info->SetString("status", "NEW");
135 break;
136 case ServiceWorkerVersion::INSTALLING:
137 info->SetString("status", "INSTALLING");
138 break;
139 case ServiceWorkerVersion::INSTALLED:
140 info->SetString("status", "INSTALLED");
141 break;
142 case ServiceWorkerVersion::ACTIVATING:
143 info->SetString("status", "ACTIVATING");
144 break;
145 case ServiceWorkerVersion::ACTIVATED:
146 info->SetString("status", "ACTIVATED");
147 break;
148 case ServiceWorkerVersion::REDUNDANT:
149 info->SetString("status", "REDUNDANT");
150 break;
152 info->SetString("script_url", version.script_url.spec());
153 info->SetString("version_id", base::Int64ToString(version.version_id));
154 info->SetInteger("process_id", version.process_id);
155 info->SetInteger("thread_id", version.thread_id);
156 info->SetInteger("devtools_agent_route_id", version.devtools_agent_route_id);
159 ListValue* GetRegistrationListValue(
160 const std::vector<ServiceWorkerRegistrationInfo>& registrations) {
161 ListValue* result = new ListValue();
162 for (std::vector<ServiceWorkerRegistrationInfo>::const_iterator it =
163 registrations.begin();
164 it != registrations.end();
165 ++it) {
166 const ServiceWorkerRegistrationInfo& registration = *it;
167 DictionaryValue* registration_info = new DictionaryValue();
168 registration_info->SetString("scope", registration.pattern.spec());
169 registration_info->SetString(
170 "registration_id", base::Int64ToString(registration.registration_id));
172 if (registration.active_version.version_id !=
173 kInvalidServiceWorkerVersionId) {
174 DictionaryValue* active_info = new DictionaryValue();
175 UpdateVersionInfo(registration.active_version, active_info);
176 registration_info->Set("active", active_info);
179 if (registration.waiting_version.version_id !=
180 kInvalidServiceWorkerVersionId) {
181 DictionaryValue* waiting_info = new DictionaryValue();
182 UpdateVersionInfo(registration.waiting_version, waiting_info);
183 registration_info->Set("waiting", waiting_info);
186 result->Append(registration_info);
188 return result;
191 ListValue* GetVersionListValue(
192 const std::vector<ServiceWorkerVersionInfo>& versions) {
193 ListValue* result = new ListValue();
194 for (std::vector<ServiceWorkerVersionInfo>::const_iterator it =
195 versions.begin();
196 it != versions.end();
197 ++it) {
198 DictionaryValue* info = new DictionaryValue();
199 UpdateVersionInfo(*it, info);
200 result->Append(info);
202 return result;
205 void DidGetStoredRegistrationsOnIOThread(
206 scoped_refptr<ServiceWorkerContextWrapper> context,
207 const GetRegistrationsCallback& callback,
208 const std::vector<ServiceWorkerRegistrationInfo>& stored_registrations) {
209 DCHECK_CURRENTLY_ON(BrowserThread::IO);
210 BrowserThread::PostTask(
211 BrowserThread::UI, FROM_HERE,
212 base::Bind(callback, context->GetAllLiveRegistrationInfo(),
213 context->GetAllLiveVersionInfo(), stored_registrations));
216 void GetRegistrationsOnIOThread(
217 scoped_refptr<ServiceWorkerContextWrapper> context,
218 const GetRegistrationsCallback& callback) {
219 DCHECK_CURRENTLY_ON(BrowserThread::IO);
220 context->GetAllRegistrations(
221 base::Bind(DidGetStoredRegistrationsOnIOThread, context, callback));
224 void DidGetRegistrations(
225 WeakPtr<ServiceWorkerInternalsUI> internals,
226 int partition_id,
227 const base::FilePath& context_path,
228 const std::vector<ServiceWorkerRegistrationInfo>& live_registrations,
229 const std::vector<ServiceWorkerVersionInfo>& live_versions,
230 const std::vector<ServiceWorkerRegistrationInfo>& stored_registrations) {
231 DCHECK_CURRENTLY_ON(BrowserThread::UI);
232 if (!internals)
233 return;
235 ScopedVector<const Value> args;
236 args.push_back(GetRegistrationListValue(live_registrations));
237 args.push_back(GetVersionListValue(live_versions));
238 args.push_back(GetRegistrationListValue(stored_registrations));
239 args.push_back(new FundamentalValue(partition_id));
240 args.push_back(new StringValue(context_path.value()));
241 internals->web_ui()->CallJavascriptFunction("serviceworker.onPartitionData",
242 args.get());
245 } // namespace
247 class ServiceWorkerInternalsUI::PartitionObserver
248 : public ServiceWorkerContextObserver {
249 public:
250 PartitionObserver(int partition_id, WebUI* web_ui)
251 : partition_id_(partition_id), web_ui_(web_ui) {}
252 ~PartitionObserver() override {}
253 // ServiceWorkerContextObserver overrides:
254 void OnRunningStateChanged(int64 version_id,
255 ServiceWorkerVersion::RunningStatus) override {
256 DCHECK_CURRENTLY_ON(BrowserThread::UI);
257 web_ui_->CallJavascriptFunction(
258 "serviceworker.onRunningStateChanged", FundamentalValue(partition_id_),
259 StringValue(base::Int64ToString(version_id)));
261 void OnVersionStateChanged(int64 version_id,
262 ServiceWorkerVersion::Status) override {
263 DCHECK_CURRENTLY_ON(BrowserThread::UI);
264 web_ui_->CallJavascriptFunction(
265 "serviceworker.onVersionStateChanged",
266 FundamentalValue(partition_id_),
267 StringValue(base::Int64ToString(version_id)));
269 void OnErrorReported(int64 version_id,
270 int process_id,
271 int thread_id,
272 const ErrorInfo& info) override {
273 DCHECK_CURRENTLY_ON(BrowserThread::UI);
274 ScopedVector<const Value> args;
275 args.push_back(new FundamentalValue(partition_id_));
276 args.push_back(new StringValue(base::Int64ToString(version_id)));
277 args.push_back(new FundamentalValue(process_id));
278 args.push_back(new FundamentalValue(thread_id));
279 scoped_ptr<DictionaryValue> value(new DictionaryValue());
280 value->SetString("message", info.error_message);
281 value->SetInteger("lineNumber", info.line_number);
282 value->SetInteger("columnNumber", info.column_number);
283 value->SetString("sourceURL", info.source_url.spec());
284 args.push_back(value.release());
285 web_ui_->CallJavascriptFunction("serviceworker.onErrorReported",
286 args.get());
288 void OnReportConsoleMessage(int64 version_id,
289 int process_id,
290 int thread_id,
291 const ConsoleMessage& message) override {
292 DCHECK_CURRENTLY_ON(BrowserThread::UI);
293 ScopedVector<const Value> args;
294 args.push_back(new FundamentalValue(partition_id_));
295 args.push_back(new StringValue(base::Int64ToString(version_id)));
296 args.push_back(new FundamentalValue(process_id));
297 args.push_back(new FundamentalValue(thread_id));
298 scoped_ptr<DictionaryValue> value(new DictionaryValue());
299 value->SetInteger("sourceIdentifier", message.source_identifier);
300 value->SetInteger("message_level", message.message_level);
301 value->SetString("message", message.message);
302 value->SetInteger("lineNumber", message.line_number);
303 value->SetString("sourceURL", message.source_url.spec());
304 args.push_back(value.release());
305 web_ui_->CallJavascriptFunction("serviceworker.onConsoleMessageReported",
306 args.get());
308 void OnRegistrationStored(int64 registration_id,
309 const GURL& pattern) override {
310 DCHECK_CURRENTLY_ON(BrowserThread::UI);
311 web_ui_->CallJavascriptFunction("serviceworker.onRegistrationStored",
312 StringValue(pattern.spec()));
314 void OnRegistrationDeleted(int64 registration_id,
315 const GURL& pattern) override {
316 web_ui_->CallJavascriptFunction("serviceworker.onRegistrationDeleted",
317 StringValue(pattern.spec()));
319 int partition_id() const { return partition_id_; }
321 private:
322 const int partition_id_;
323 WebUI* const web_ui_;
326 ServiceWorkerInternalsUI::ServiceWorkerInternalsUI(WebUI* web_ui)
327 : WebUIController(web_ui), next_partition_id_(0) {
328 WebUIDataSource* source =
329 WebUIDataSource::Create(kChromeUIServiceWorkerInternalsHost);
330 source->SetJsonPath("strings.js");
331 source->AddResourcePath("serviceworker_internals.js",
332 IDR_SERVICE_WORKER_INTERNALS_JS);
333 source->AddResourcePath("serviceworker_internals.css",
334 IDR_SERVICE_WORKER_INTERNALS_CSS);
335 source->SetDefaultResource(IDR_SERVICE_WORKER_INTERNALS_HTML);
336 source->DisableDenyXFrameOptions();
338 BrowserContext* browser_context =
339 web_ui->GetWebContents()->GetBrowserContext();
340 WebUIDataSource::Add(browser_context, source);
342 web_ui->RegisterMessageCallback(
343 "GetOptions",
344 base::Bind(&ServiceWorkerInternalsUI::GetOptions,
345 base::Unretained(this)));
346 web_ui->RegisterMessageCallback(
347 "SetOption",
348 base::Bind(&ServiceWorkerInternalsUI::SetOption, base::Unretained(this)));
349 web_ui->RegisterMessageCallback(
350 "getAllRegistrations",
351 base::Bind(&ServiceWorkerInternalsUI::GetAllRegistrations,
352 base::Unretained(this)));
353 web_ui->RegisterMessageCallback(
354 "stop",
355 base::Bind(&ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod,
356 base::Unretained(this),
357 &ServiceWorkerVersion::StopWorker));
358 web_ui->RegisterMessageCallback(
359 "sync",
360 base::Bind(&ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod,
361 base::Unretained(this),
362 &ServiceWorkerVersion::DispatchSyncEvent));
363 web_ui->RegisterMessageCallback(
364 "push",
365 base::Bind(&ServiceWorkerInternalsUI::DispatchPushEvent,
366 base::Unretained(this)));
367 web_ui->RegisterMessageCallback(
368 "inspect",
369 base::Bind(&ServiceWorkerInternalsUI::InspectWorker,
370 base::Unretained(this)));
371 web_ui->RegisterMessageCallback(
372 "unregister",
373 base::Bind(&ServiceWorkerInternalsUI::Unregister,
374 base::Unretained(this)));
375 web_ui->RegisterMessageCallback(
376 "start",
377 base::Bind(&ServiceWorkerInternalsUI::StartWorker,
378 base::Unretained(this)));
381 ServiceWorkerInternalsUI::~ServiceWorkerInternalsUI() {
382 BrowserContext* browser_context =
383 web_ui()->GetWebContents()->GetBrowserContext();
384 // Safe to use base::Unretained(this) because
385 // ForEachStoragePartition is synchronous.
386 BrowserContext::StoragePartitionCallback remove_observer_cb =
387 base::Bind(&ServiceWorkerInternalsUI::RemoveObserverFromStoragePartition,
388 base::Unretained(this));
389 BrowserContext::ForEachStoragePartition(browser_context, remove_observer_cb);
392 void ServiceWorkerInternalsUI::GetOptions(const ListValue* args) {
393 DictionaryValue options;
394 options.SetBoolean("debug_on_start",
395 ServiceWorkerDevToolsManager::GetInstance()
396 ->debug_service_worker_on_start());
397 web_ui()->CallJavascriptFunction("serviceworker.onOptions", options);
400 void ServiceWorkerInternalsUI::SetOption(const ListValue* args) {
401 std::string option_name;
402 bool option_boolean;
403 if (!args->GetString(0, &option_name) || option_name != "debug_on_start" ||
404 !args->GetBoolean(1, &option_boolean)) {
405 return;
407 ServiceWorkerDevToolsManager::GetInstance()
408 ->set_debug_service_worker_on_start(option_boolean);
411 void ServiceWorkerInternalsUI::GetAllRegistrations(const ListValue* args) {
412 DCHECK_CURRENTLY_ON(BrowserThread::UI);
413 BrowserContext* browser_context =
414 web_ui()->GetWebContents()->GetBrowserContext();
415 // Safe to use base::Unretained(this) because
416 // ForEachStoragePartition is synchronous.
417 BrowserContext::StoragePartitionCallback add_context_cb =
418 base::Bind(&ServiceWorkerInternalsUI::AddContextFromStoragePartition,
419 base::Unretained(this));
420 BrowserContext::ForEachStoragePartition(browser_context, add_context_cb);
423 void ServiceWorkerInternalsUI::AddContextFromStoragePartition(
424 StoragePartition* partition) {
425 int partition_id = 0;
426 scoped_refptr<ServiceWorkerContextWrapper> context =
427 static_cast<ServiceWorkerContextWrapper*>(
428 partition->GetServiceWorkerContext());
429 if (PartitionObserver* observer =
430 observers_.get(reinterpret_cast<uintptr_t>(partition))) {
431 partition_id = observer->partition_id();
432 } else {
433 partition_id = next_partition_id_++;
434 scoped_ptr<PartitionObserver> new_observer(
435 new PartitionObserver(partition_id, web_ui()));
436 context->AddObserver(new_observer.get());
437 observers_.set(reinterpret_cast<uintptr_t>(partition), new_observer.Pass());
440 BrowserThread::PostTask(
441 BrowserThread::IO, FROM_HERE,
442 base::Bind(GetRegistrationsOnIOThread, context,
443 base::Bind(DidGetRegistrations, AsWeakPtr(), partition_id,
444 context->is_incognito() ? base::FilePath()
445 : partition->GetPath())));
448 void ServiceWorkerInternalsUI::RemoveObserverFromStoragePartition(
449 StoragePartition* partition) {
450 scoped_ptr<PartitionObserver> observer(
451 observers_.take_and_erase(reinterpret_cast<uintptr_t>(partition)));
452 if (!observer.get())
453 return;
454 scoped_refptr<ServiceWorkerContextWrapper> context =
455 static_cast<ServiceWorkerContextWrapper*>(
456 partition->GetServiceWorkerContext());
457 context->RemoveObserver(observer.get());
460 void ServiceWorkerInternalsUI::FindContext(
461 int partition_id,
462 StoragePartition** result_partition,
463 StoragePartition* storage_partition) const {
464 PartitionObserver* observer =
465 observers_.get(reinterpret_cast<uintptr_t>(storage_partition));
466 if (observer && partition_id == observer->partition_id()) {
467 *result_partition = storage_partition;
471 bool ServiceWorkerInternalsUI::GetServiceWorkerContext(
472 int partition_id,
473 scoped_refptr<ServiceWorkerContextWrapper>* context) const {
474 BrowserContext* browser_context =
475 web_ui()->GetWebContents()->GetBrowserContext();
476 StoragePartition* result_partition(NULL);
477 BrowserContext::StoragePartitionCallback find_context_cb =
478 base::Bind(&ServiceWorkerInternalsUI::FindContext,
479 base::Unretained(this),
480 partition_id,
481 &result_partition);
482 BrowserContext::ForEachStoragePartition(browser_context, find_context_cb);
483 if (!result_partition)
484 return false;
485 *context = static_cast<ServiceWorkerContextWrapper*>(
486 result_partition->GetServiceWorkerContext());
487 return true;
490 void ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod(
491 ServiceWorkerVersionMethod method,
492 const ListValue* args) {
493 DCHECK_CURRENTLY_ON(BrowserThread::UI);
494 int callback_id;
495 const DictionaryValue* cmd_args = NULL;
496 int partition_id;
497 scoped_refptr<ServiceWorkerContextWrapper> context;
498 std::string version_id_string;
499 int64 version_id = 0;
500 if (!args->GetInteger(0, &callback_id) ||
501 !args->GetDictionary(1, &cmd_args) ||
502 !cmd_args->GetInteger("partition_id", &partition_id) ||
503 !GetServiceWorkerContext(partition_id, &context) ||
504 !cmd_args->GetString("version_id", &version_id_string) ||
505 !base::StringToInt64(version_id_string, &version_id)) {
506 return;
509 base::Callback<void(ServiceWorkerStatusCode)> callback =
510 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
511 CallServiceWorkerVersionMethodWithVersionID(
512 method, context, version_id, callback);
515 void ServiceWorkerInternalsUI::DispatchPushEvent(
516 const ListValue* args) {
517 DCHECK_CURRENTLY_ON(BrowserThread::UI);
518 int callback_id;
519 int partition_id;
520 int64 version_id = 0;
521 std::string version_id_string;
522 const DictionaryValue* cmd_args = NULL;
523 scoped_refptr<ServiceWorkerContextWrapper> context;
524 if (!args->GetInteger(0, &callback_id) ||
525 !args->GetDictionary(1, &cmd_args) ||
526 !cmd_args->GetInteger("partition_id", &partition_id) ||
527 !GetServiceWorkerContext(partition_id, &context) ||
528 !cmd_args->GetString("version_id", &version_id_string) ||
529 !base::StringToInt64(version_id_string, &version_id)) {
530 return;
533 base::Callback<void(ServiceWorkerStatusCode)> callback =
534 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
535 DispatchPushEventWithVersionID(context, version_id, callback);
538 void ServiceWorkerInternalsUI::InspectWorker(const ListValue* args) {
539 DCHECK_CURRENTLY_ON(BrowserThread::UI);
540 int callback_id;
541 const DictionaryValue* cmd_args = NULL;
542 int process_id = 0;
543 int devtools_agent_route_id = 0;
544 if (!args->GetInteger(0, &callback_id) ||
545 !args->GetDictionary(1, &cmd_args) ||
546 !cmd_args->GetInteger("process_id", &process_id) ||
547 !cmd_args->GetInteger("devtools_agent_route_id",
548 &devtools_agent_route_id)) {
549 return;
551 base::Callback<void(ServiceWorkerStatusCode)> callback =
552 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
553 scoped_refptr<DevToolsAgentHostImpl> agent_host(
554 ServiceWorkerDevToolsManager::GetInstance()
555 ->GetDevToolsAgentHostForWorker(process_id, devtools_agent_route_id));
556 if (!agent_host.get()) {
557 callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND);
558 return;
560 agent_host->Inspect(web_ui()->GetWebContents()->GetBrowserContext());
561 callback.Run(SERVICE_WORKER_OK);
564 void ServiceWorkerInternalsUI::Unregister(const ListValue* args) {
565 DCHECK_CURRENTLY_ON(BrowserThread::UI);
566 int callback_id;
567 int partition_id;
568 std::string scope_string;
569 const DictionaryValue* cmd_args = NULL;
570 scoped_refptr<ServiceWorkerContextWrapper> context;
571 if (!args->GetInteger(0, &callback_id) ||
572 !args->GetDictionary(1, &cmd_args) ||
573 !cmd_args->GetInteger("partition_id", &partition_id) ||
574 !GetServiceWorkerContext(partition_id, &context) ||
575 !cmd_args->GetString("scope", &scope_string)) {
576 return;
579 base::Callback<void(ServiceWorkerStatusCode)> callback =
580 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
581 UnregisterWithScope(context, GURL(scope_string), callback);
584 void ServiceWorkerInternalsUI::StartWorker(const ListValue* args) {
585 DCHECK_CURRENTLY_ON(BrowserThread::UI);
586 int callback_id;
587 int partition_id;
588 std::string scope_string;
589 const DictionaryValue* cmd_args = NULL;
590 scoped_refptr<ServiceWorkerContextWrapper> context;
591 if (!args->GetInteger(0, &callback_id) ||
592 !args->GetDictionary(1, &cmd_args) ||
593 !cmd_args->GetInteger("partition_id", &partition_id) ||
594 !GetServiceWorkerContext(partition_id, &context) ||
595 !cmd_args->GetString("scope", &scope_string)) {
596 return;
598 base::Callback<void(ServiceWorkerStatusCode)> callback =
599 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
600 context->StartServiceWorker(GURL(scope_string), callback);
603 void ServiceWorkerInternalsUI::UnregisterWithScope(
604 scoped_refptr<ServiceWorkerContextWrapper> context,
605 const GURL& scope,
606 const ServiceWorkerInternalsUI::StatusCallback& callback) const {
607 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
608 BrowserThread::PostTask(
609 BrowserThread::IO, FROM_HERE,
610 base::Bind(&ServiceWorkerInternalsUI::UnregisterWithScope,
611 base::Unretained(this), context, scope, callback));
612 return;
615 if (!context->context()) {
616 callback.Run(SERVICE_WORKER_ERROR_ABORT);
617 return;
620 // ServiceWorkerContextWrapper::UnregisterServiceWorker doesn't work here
621 // because that reduces a status code to boolean.
622 context->context()->UnregisterServiceWorker(scope, callback);
625 } // namespace content