Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / service_worker / service_worker_internals_ui.cc
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.
4
5 #include "content/browser/service_worker/service_worker_internals_ui.h"
6
7 #include <string>
8 #include <vector>
9
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"
28
29 using base::DictionaryValue;
30 using base::FundamentalValue;
31 using base::ListValue;
32 using base::StringValue;
33 using base::Value;
34 using base::WeakPtr;
35
36 namespace content {
37
38 namespace {
39
40 void OperationCompleteCallback(WeakPtr<ServiceWorkerInternalsUI> internals,
41                                int callback_id,
42                                ServiceWorkerStatusCode status) {
43   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
44     BrowserThread::PostTask(
45         BrowserThread::UI,
46         FROM_HERE,
47         base::Bind(OperationCompleteCallback, internals, callback_id, status));
48     return;
49   }
50   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
51   if (internals) {
52     internals->web_ui()->CallJavascriptFunction(
53         "serviceworker.onOperationComplete",
54         FundamentalValue(static_cast<int>(status)),
55         FundamentalValue(callback_id));
56   }
57 }
58
59 void CallServiceWorkerVersionMethodWithVersionID(
60     ServiceWorkerInternalsUI::ServiceWorkerVersionMethod method,
61     scoped_refptr<ServiceWorkerContextWrapper> context,
62     int64 version_id,
63     const ServiceWorkerInternalsUI::StatusCallback& callback) {
64   if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
65     BrowserThread::PostTask(
66         BrowserThread::IO,
67         FROM_HERE,
68         base::Bind(CallServiceWorkerVersionMethodWithVersionID,
69                    method,
70                    context,
71                    version_id,
72                    callback));
73     return;
74   }
75   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
76   scoped_refptr<ServiceWorkerVersion> version =
77       context->context()->GetLiveVersion(version_id);
78   if (!version.get()) {
79     callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND);
80     return;
81   }
82   (*version.get().*method)(callback);
83 }
84
85 void DispatchPushEventWithVersionID(
86     scoped_refptr<ServiceWorkerContextWrapper> context,
87     int64 version_id,
88     const ServiceWorkerInternalsUI::StatusCallback& callback) {
89   if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
90     BrowserThread::PostTask(
91         BrowserThread::IO,
92         FROM_HERE,
93         base::Bind(DispatchPushEventWithVersionID,
94                    context,
95                    version_id,
96                    callback));
97     return;
98   }
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);
104     return;
105   }
106   std::string data = "Test push message from ServiceWorkerInternals.";
107   version->DispatchPushEvent(callback, data);
108 }
109
110 void UnregisterWithScope(
111     scoped_refptr<ServiceWorkerContextWrapper> context,
112     const GURL& scope,
113     const ServiceWorkerInternalsUI::StatusCallback& callback) {
114   if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
115     BrowserThread::PostTask(
116         BrowserThread::IO,
117         FROM_HERE,
118         base::Bind(UnregisterWithScope, context, scope, callback));
119     return;
120   }
121   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
122   context->context()->UnregisterServiceWorker(scope, callback);
123 }
124
125 void WorkerStarted(const scoped_refptr<ServiceWorkerRegistration>& registration,
126                    const ServiceWorkerInternalsUI::StatusCallback& callback,
127                    ServiceWorkerStatusCode status) {
128   callback.Run(status);
129 }
130
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));
142     return;
143   }
144   callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND);
145 }
146
147 void FindRegistrationForPattern(
148     scoped_refptr<ServiceWorkerContextWrapper> context,
149     const GURL& scope,
150     const ServiceWorkerStorage::FindRegistrationCallback callback) {
151   if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
152     BrowserThread::PostTask(
153         BrowserThread::IO,
154         FROM_HERE,
155         base::Bind(FindRegistrationForPattern, context, scope, callback));
156     return;
157   }
158   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
159   context->context()->storage()->FindRegistrationForPattern(scope, callback);
160 }
161
162 void UpdateVersionInfo(const ServiceWorkerVersionInfo& version,
163                        DictionaryValue* info) {
164   switch (version.running_status) {
165     case ServiceWorkerVersion::STOPPED:
166       info->SetString("running_status", "STOPPED");
167       break;
168     case ServiceWorkerVersion::STARTING:
169       info->SetString("running_status", "STARTING");
170       break;
171     case ServiceWorkerVersion::RUNNING:
172       info->SetString("running_status", "RUNNING");
173       break;
174     case ServiceWorkerVersion::STOPPING:
175       info->SetString("running_status", "STOPPING");
176       break;
177   }
178
179   switch (version.status) {
180     case ServiceWorkerVersion::NEW:
181       info->SetString("status", "NEW");
182       break;
183     case ServiceWorkerVersion::INSTALLING:
184       info->SetString("status", "INSTALLING");
185       break;
186     case ServiceWorkerVersion::INSTALLED:
187       info->SetString("status", "INSTALLED");
188       break;
189     case ServiceWorkerVersion::ACTIVATING:
190       info->SetString("status", "ACTIVATING");
191       break;
192     case ServiceWorkerVersion::ACTIVATED:
193       info->SetString("status", "ACTIVATED");
194       break;
195     case ServiceWorkerVersion::REDUNDANT:
196       info->SetString("status", "REDUNDANT");
197       break;
198   }
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);
204 }
205
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();
212        ++it) {
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));
218
219     if (registration.active_version.version_id !=
220         kInvalidServiceWorkerVersionId) {
221       DictionaryValue* active_info = new DictionaryValue();
222       UpdateVersionInfo(registration.active_version, active_info);
223       registration_info->Set("active", active_info);
224     }
225
226     if (registration.waiting_version.version_id !=
227         kInvalidServiceWorkerVersionId) {
228       DictionaryValue* waiting_info = new DictionaryValue();
229       UpdateVersionInfo(registration.waiting_version, waiting_info);
230       registration_info->Set("waiting", waiting_info);
231     }
232
233     result->Append(registration_info);
234   }
235   return result;
236 }
237
238 ListValue* GetVersionListValue(
239     const std::vector<ServiceWorkerVersionInfo>& versions) {
240   ListValue* result = new ListValue();
241   for (std::vector<ServiceWorkerVersionInfo>::const_iterator it =
242            versions.begin();
243        it != versions.end();
244        ++it) {
245     DictionaryValue* info = new DictionaryValue();
246     UpdateVersionInfo(*it, info);
247     result->Append(info);
248   }
249   return result;
250 }
251
252 void GetRegistrationsOnIOThread(
253     scoped_refptr<ServiceWorkerContextWrapper> context,
254     base::Callback<void(const std::vector<ServiceWorkerRegistrationInfo>&)>
255         callback) {
256   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
257   context->context()->storage()->GetAllRegistrations(callback);
258 }
259
260 void OnStoredRegistrations(
261     scoped_refptr<ServiceWorkerContextWrapper> context,
262     base::Callback<void(const std::vector<ServiceWorkerRegistrationInfo>&,
263                         const std::vector<ServiceWorkerVersionInfo>&,
264                         const std::vector<ServiceWorkerRegistrationInfo>&)>
265         callback,
266     const std::vector<ServiceWorkerRegistrationInfo>& stored_registrations) {
267   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
268   BrowserThread::PostTask(
269       BrowserThread::UI,
270       FROM_HERE,
271       base::Bind(callback,
272                  context->context()->GetAllLiveRegistrationInfo(),
273                  context->context()->GetAllLiveVersionInfo(),
274                  stored_registrations));
275 }
276
277 void OnAllRegistrations(
278     WeakPtr<ServiceWorkerInternalsUI> internals,
279     int partition_id,
280     const base::FilePath& context_path,
281     const std::vector<ServiceWorkerRegistrationInfo>& live_registrations,
282     const std::vector<ServiceWorkerVersionInfo>& live_versions,
283     const std::vector<ServiceWorkerRegistrationInfo>& stored_registrations) {
284   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
285   if (!internals)
286     return;
287
288   ScopedVector<const Value> args;
289   args.push_back(GetRegistrationListValue(live_registrations));
290   args.push_back(GetVersionListValue(live_versions));
291   args.push_back(GetRegistrationListValue(stored_registrations));
292   args.push_back(new FundamentalValue(partition_id));
293   args.push_back(new StringValue(context_path.value()));
294   internals->web_ui()->CallJavascriptFunction("serviceworker.onPartitionData",
295                                               args.get());
296 }
297
298 }  // namespace
299
300 class ServiceWorkerInternalsUI::PartitionObserver
301     : public ServiceWorkerContextObserver {
302  public:
303   PartitionObserver(int partition_id, WebUI* web_ui)
304       : partition_id_(partition_id), web_ui_(web_ui) {}
305   ~PartitionObserver() override {}
306   // ServiceWorkerContextObserver overrides:
307   void OnWorkerStarted(int64 version_id,
308                        int process_id,
309                        int thread_id) override {
310     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
311     web_ui_->CallJavascriptFunction(
312         "serviceworker.onWorkerStarted",
313         FundamentalValue(partition_id_),
314         StringValue(base::Int64ToString(version_id)),
315         FundamentalValue(process_id),
316         FundamentalValue(thread_id));
317   }
318   void OnWorkerStopped(int64 version_id,
319                        int process_id,
320                        int thread_id) override {
321     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
322     web_ui_->CallJavascriptFunction(
323         "serviceworker.onWorkerStopped",
324         FundamentalValue(partition_id_),
325         StringValue(base::Int64ToString(version_id)),
326         FundamentalValue(process_id),
327         FundamentalValue(thread_id));
328   }
329   void OnVersionStateChanged(int64 version_id) override {
330     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
331     web_ui_->CallJavascriptFunction(
332         "serviceworker.onVersionStateChanged",
333         FundamentalValue(partition_id_),
334         StringValue(base::Int64ToString(version_id)));
335   }
336   void OnErrorReported(int64 version_id,
337                        int process_id,
338                        int thread_id,
339                        const ErrorInfo& info) override {
340     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
341     ScopedVector<const Value> args;
342     args.push_back(new FundamentalValue(partition_id_));
343     args.push_back(new StringValue(base::Int64ToString(version_id)));
344     args.push_back(new FundamentalValue(process_id));
345     args.push_back(new FundamentalValue(thread_id));
346     scoped_ptr<DictionaryValue> value(new DictionaryValue());
347     value->SetString("message", info.error_message);
348     value->SetInteger("lineNumber", info.line_number);
349     value->SetInteger("columnNumber", info.column_number);
350     value->SetString("sourceURL", info.source_url.spec());
351     args.push_back(value.release());
352     web_ui_->CallJavascriptFunction("serviceworker.onErrorReported",
353                                     args.get());
354   }
355   void OnReportConsoleMessage(int64 version_id,
356                               int process_id,
357                               int thread_id,
358                               const ConsoleMessage& message) override {
359     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
360     ScopedVector<const Value> args;
361     args.push_back(new FundamentalValue(partition_id_));
362     args.push_back(new StringValue(base::Int64ToString(version_id)));
363     args.push_back(new FundamentalValue(process_id));
364     args.push_back(new FundamentalValue(thread_id));
365     scoped_ptr<DictionaryValue> value(new DictionaryValue());
366     value->SetInteger("sourceIdentifier", message.source_identifier);
367     value->SetInteger("message_level", message.message_level);
368     value->SetString("message", message.message);
369     value->SetInteger("lineNumber", message.line_number);
370     value->SetString("sourceURL", message.source_url.spec());
371     args.push_back(value.release());
372     web_ui_->CallJavascriptFunction("serviceworker.onConsoleMessageReported",
373                                     args.get());
374   }
375   void OnRegistrationStored(const GURL& pattern) override {
376     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
377     web_ui_->CallJavascriptFunction("serviceworker.onRegistrationStored",
378                                     StringValue(pattern.spec()));
379   }
380   void OnRegistrationDeleted(const GURL& pattern) override {
381     web_ui_->CallJavascriptFunction("serviceworker.onRegistrationDeleted",
382                                     StringValue(pattern.spec()));
383   }
384   int partition_id() const { return partition_id_; }
385
386  private:
387   const int partition_id_;
388   WebUI* const web_ui_;
389 };
390
391 ServiceWorkerInternalsUI::ServiceWorkerInternalsUI(WebUI* web_ui)
392     : WebUIController(web_ui), next_partition_id_(0) {
393   WebUIDataSource* source =
394       WebUIDataSource::Create(kChromeUIServiceWorkerInternalsHost);
395   source->SetJsonPath("strings.js");
396   source->AddResourcePath("serviceworker_internals.js",
397                           IDR_SERVICE_WORKER_INTERNALS_JS);
398   source->AddResourcePath("serviceworker_internals.css",
399                           IDR_SERVICE_WORKER_INTERNALS_CSS);
400   source->SetDefaultResource(IDR_SERVICE_WORKER_INTERNALS_HTML);
401   source->DisableDenyXFrameOptions();
402
403   BrowserContext* browser_context =
404       web_ui->GetWebContents()->GetBrowserContext();
405   WebUIDataSource::Add(browser_context, source);
406
407   web_ui->RegisterMessageCallback(
408       "GetOptions",
409       base::Bind(&ServiceWorkerInternalsUI::GetOptions,
410                  base::Unretained(this)));
411   web_ui->RegisterMessageCallback(
412       "SetOption",
413       base::Bind(&ServiceWorkerInternalsUI::SetOption, base::Unretained(this)));
414   web_ui->RegisterMessageCallback(
415       "getAllRegistrations",
416       base::Bind(&ServiceWorkerInternalsUI::GetAllRegistrations,
417                  base::Unretained(this)));
418   web_ui->RegisterMessageCallback(
419       "stop",
420       base::Bind(&ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod,
421                  base::Unretained(this),
422                  &ServiceWorkerVersion::StopWorker));
423   web_ui->RegisterMessageCallback(
424       "sync",
425       base::Bind(&ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod,
426                  base::Unretained(this),
427                  &ServiceWorkerVersion::DispatchSyncEvent));
428   web_ui->RegisterMessageCallback(
429       "push",
430       base::Bind(&ServiceWorkerInternalsUI::DispatchPushEvent,
431                  base::Unretained(this)));
432   web_ui->RegisterMessageCallback(
433       "inspect",
434       base::Bind(&ServiceWorkerInternalsUI::InspectWorker,
435                  base::Unretained(this)));
436   web_ui->RegisterMessageCallback(
437       "unregister",
438       base::Bind(&ServiceWorkerInternalsUI::Unregister,
439                  base::Unretained(this)));
440   web_ui->RegisterMessageCallback(
441       "start",
442       base::Bind(&ServiceWorkerInternalsUI::StartWorker,
443                  base::Unretained(this)));
444 }
445
446 ServiceWorkerInternalsUI::~ServiceWorkerInternalsUI() {
447   BrowserContext* browser_context =
448       web_ui()->GetWebContents()->GetBrowserContext();
449   // Safe to use base::Unretained(this) because
450   // ForEachStoragePartition is synchronous.
451   BrowserContext::StoragePartitionCallback remove_observer_cb =
452       base::Bind(&ServiceWorkerInternalsUI::RemoveObserverFromStoragePartition,
453                  base::Unretained(this));
454   BrowserContext::ForEachStoragePartition(browser_context, remove_observer_cb);
455 }
456
457 void ServiceWorkerInternalsUI::GetOptions(const ListValue* args) {
458   DictionaryValue options;
459   options.SetBoolean("debug_on_start",
460                      EmbeddedWorkerDevToolsManager::GetInstance()
461                          ->debug_service_worker_on_start());
462   web_ui()->CallJavascriptFunction("serviceworker.onOptions", options);
463 }
464
465 void ServiceWorkerInternalsUI::SetOption(const ListValue* args) {
466   std::string option_name;
467   bool option_boolean;
468   if (!args->GetString(0, &option_name) || option_name != "debug_on_start" ||
469       !args->GetBoolean(1, &option_boolean)) {
470     return;
471   }
472   EmbeddedWorkerDevToolsManager::GetInstance()
473       ->set_debug_service_worker_on_start(option_boolean);
474 }
475
476 void ServiceWorkerInternalsUI::GetAllRegistrations(const ListValue* args) {
477   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
478   BrowserContext* browser_context =
479       web_ui()->GetWebContents()->GetBrowserContext();
480   // Safe to use base::Unretained(this) because
481   // ForEachStoragePartition is synchronous.
482   BrowserContext::StoragePartitionCallback add_context_cb =
483       base::Bind(&ServiceWorkerInternalsUI::AddContextFromStoragePartition,
484                  base::Unretained(this));
485   BrowserContext::ForEachStoragePartition(browser_context, add_context_cb);
486 }
487
488 void ServiceWorkerInternalsUI::AddContextFromStoragePartition(
489     StoragePartition* partition) {
490   int partition_id = 0;
491   scoped_refptr<ServiceWorkerContextWrapper> context =
492       static_cast<ServiceWorkerContextWrapper*>(
493           partition->GetServiceWorkerContext());
494   if (PartitionObserver* observer =
495           observers_.get(reinterpret_cast<uintptr_t>(partition))) {
496     partition_id = observer->partition_id();
497   } else {
498     partition_id = next_partition_id_++;
499     scoped_ptr<PartitionObserver> new_observer(
500         new PartitionObserver(partition_id, web_ui()));
501     context->AddObserver(new_observer.get());
502     observers_.set(reinterpret_cast<uintptr_t>(partition), new_observer.Pass());
503   }
504
505   BrowserThread::PostTask(
506       BrowserThread::IO,
507       FROM_HERE,
508       base::Bind(GetRegistrationsOnIOThread,
509                  context,
510                  base::Bind(OnStoredRegistrations,
511                             context,
512                             base::Bind(OnAllRegistrations,
513                                        AsWeakPtr(),
514                                        partition_id,
515                                        context->is_incognito()
516                                            ? base::FilePath()
517                                            : partition->GetPath()))));
518 }
519
520 void ServiceWorkerInternalsUI::RemoveObserverFromStoragePartition(
521     StoragePartition* partition) {
522   scoped_ptr<PartitionObserver> observer(
523       observers_.take_and_erase(reinterpret_cast<uintptr_t>(partition)));
524   if (!observer.get())
525     return;
526   scoped_refptr<ServiceWorkerContextWrapper> context =
527       static_cast<ServiceWorkerContextWrapper*>(
528           partition->GetServiceWorkerContext());
529   context->RemoveObserver(observer.get());
530 }
531
532 void ServiceWorkerInternalsUI::FindContext(
533     int partition_id,
534     StoragePartition** result_partition,
535     StoragePartition* storage_partition) const {
536   PartitionObserver* observer =
537       observers_.get(reinterpret_cast<uintptr_t>(storage_partition));
538   if (observer && partition_id == observer->partition_id()) {
539     *result_partition = storage_partition;
540   }
541 }
542
543 bool ServiceWorkerInternalsUI::GetServiceWorkerContext(
544     int partition_id,
545     scoped_refptr<ServiceWorkerContextWrapper>* context) const {
546   BrowserContext* browser_context =
547       web_ui()->GetWebContents()->GetBrowserContext();
548   StoragePartition* result_partition(NULL);
549   BrowserContext::StoragePartitionCallback find_context_cb =
550       base::Bind(&ServiceWorkerInternalsUI::FindContext,
551                  base::Unretained(this),
552                  partition_id,
553                  &result_partition);
554   BrowserContext::ForEachStoragePartition(browser_context, find_context_cb);
555   if (!result_partition)
556     return false;
557   *context = static_cast<ServiceWorkerContextWrapper*>(
558       result_partition->GetServiceWorkerContext());
559   return true;
560 }
561
562 void ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod(
563     ServiceWorkerVersionMethod method,
564     const ListValue* args) {
565   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
566   int callback_id;
567   const DictionaryValue* cmd_args = NULL;
568   int partition_id;
569   scoped_refptr<ServiceWorkerContextWrapper> context;
570   std::string version_id_string;
571   int64 version_id = 0;
572   if (!args->GetInteger(0, &callback_id) ||
573       !args->GetDictionary(1, &cmd_args) ||
574       !cmd_args->GetInteger("partition_id", &partition_id) ||
575       !GetServiceWorkerContext(partition_id, &context) ||
576       !cmd_args->GetString("version_id", &version_id_string) ||
577       !base::StringToInt64(version_id_string, &version_id)) {
578     return;
579   }
580
581   base::Callback<void(ServiceWorkerStatusCode)> callback =
582       base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
583   CallServiceWorkerVersionMethodWithVersionID(
584       method, context, version_id, callback);
585 }
586
587 void ServiceWorkerInternalsUI::DispatchPushEvent(
588     const ListValue* args) {
589   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
590   int callback_id;
591   int partition_id;
592   int64 version_id = 0;
593   std::string version_id_string;
594   const DictionaryValue* cmd_args = NULL;
595   scoped_refptr<ServiceWorkerContextWrapper> context;
596   if (!args->GetInteger(0, &callback_id) ||
597       !args->GetDictionary(1, &cmd_args) ||
598       !cmd_args->GetInteger("partition_id", &partition_id) ||
599       !GetServiceWorkerContext(partition_id, &context) ||
600       !cmd_args->GetString("version_id", &version_id_string) ||
601       !base::StringToInt64(version_id_string, &version_id)) {
602     return;
603   }
604
605   base::Callback<void(ServiceWorkerStatusCode)> callback =
606       base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
607   DispatchPushEventWithVersionID(context, version_id, callback);
608 }
609
610 void ServiceWorkerInternalsUI::InspectWorker(const ListValue* args) {
611   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
612   int callback_id;
613   const DictionaryValue* cmd_args = NULL;
614   int process_id = 0;
615   int devtools_agent_route_id = 0;
616   if (!args->GetInteger(0, &callback_id) ||
617       !args->GetDictionary(1, &cmd_args) ||
618       !cmd_args->GetInteger("process_id", &process_id) ||
619       !cmd_args->GetInteger("devtools_agent_route_id",
620                             &devtools_agent_route_id)) {
621     return;
622   }
623   base::Callback<void(ServiceWorkerStatusCode)> callback =
624       base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
625   scoped_refptr<DevToolsAgentHostImpl> agent_host(
626       EmbeddedWorkerDevToolsManager::GetInstance()
627           ->GetDevToolsAgentHostForWorker(process_id, devtools_agent_route_id));
628   if (!agent_host.get()) {
629     callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND);
630     return;
631   }
632   agent_host->Inspect(web_ui()->GetWebContents()->GetBrowserContext());
633   callback.Run(SERVICE_WORKER_OK);
634 }
635
636 void ServiceWorkerInternalsUI::Unregister(const ListValue* args) {
637   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
638   int callback_id;
639   int partition_id;
640   std::string scope_string;
641   const DictionaryValue* cmd_args = NULL;
642   scoped_refptr<ServiceWorkerContextWrapper> context;
643   if (!args->GetInteger(0, &callback_id) ||
644       !args->GetDictionary(1, &cmd_args) ||
645       !cmd_args->GetInteger("partition_id", &partition_id) ||
646       !GetServiceWorkerContext(partition_id, &context) ||
647       !cmd_args->GetString("scope", &scope_string)) {
648     return;
649   }
650
651   base::Callback<void(ServiceWorkerStatusCode)> callback =
652       base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
653   UnregisterWithScope(context, GURL(scope_string), callback);
654 }
655
656 void ServiceWorkerInternalsUI::StartWorker(const ListValue* args) {
657   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
658   int callback_id;
659   int partition_id;
660   std::string scope_string;
661   const DictionaryValue* cmd_args = NULL;
662   scoped_refptr<ServiceWorkerContextWrapper> context;
663   if (!args->GetInteger(0, &callback_id) ||
664       !args->GetDictionary(1, &cmd_args) ||
665       !cmd_args->GetInteger("partition_id", &partition_id) ||
666       !GetServiceWorkerContext(partition_id, &context) ||
667       !cmd_args->GetString("scope", &scope_string)) {
668     return;
669   }
670
671   base::Callback<void(ServiceWorkerStatusCode)> callback =
672       base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
673   FindRegistrationForPattern(
674       context, GURL(scope_string), base::Bind(StartActiveWorker, callback));
675 }
676
677 }  // namespace content