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_manager_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/public/browser/browser_context.h" 21 #include "content/public/browser/browser_thread.h" 22 #include "content/public/browser/storage_partition.h" 23 #include "content/public/browser/web_contents.h" 24 #include "content/public/browser/web_ui.h" 25 #include "content/public/browser/web_ui_data_source.h" 26 #include "content/public/common/url_constants.h" 27 #include "grit/content_resources.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) { 79 callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND); 80 return; 81 } 82 (*version.*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) { 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::ACTIVE: 193 info->SetString("status", "ACTIVE"); 194 break; 195 case ServiceWorkerVersion::DEACTIVATED: 196 info->SetString("status", "DEACTIVATED"); 197 break; 198 } 199 info->SetString("version_id", base::Int64ToString(version.version_id)); 200 info->SetInteger("process_id", version.process_id); 201 info->SetInteger("thread_id", version.thread_id); 202 info->SetInteger("devtools_agent_route_id", version.devtools_agent_route_id); 203 } 204 205 ListValue* GetRegistrationListValue( 206 const std::vector<ServiceWorkerRegistrationInfo>& registrations) { 207 ListValue* result = new ListValue(); 208 for (std::vector<ServiceWorkerRegistrationInfo>::const_iterator it = 209 registrations.begin(); 210 it != registrations.end(); 211 ++it) { 212 const ServiceWorkerRegistrationInfo& registration = *it; 213 DictionaryValue* registration_info = new DictionaryValue(); 214 registration_info->SetString("scope", registration.pattern.spec()); 215 registration_info->SetString("script_url", registration.script_url.spec()); 216 registration_info->SetString( 217 "registration_id", base::Int64ToString(registration.registration_id)); 218 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); 223 } 224 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); 229 } 230 231 result->Append(registration_info); 232 } 233 return result; 234 } 235 236 ListValue* GetVersionListValue( 237 const std::vector<ServiceWorkerVersionInfo>& versions) { 238 ListValue* result = new ListValue(); 239 for (std::vector<ServiceWorkerVersionInfo>::const_iterator it = 240 versions.begin(); 241 it != versions.end(); 242 ++it) { 243 DictionaryValue* info = new DictionaryValue(); 244 UpdateVersionInfo(*it, info); 245 result->Append(info); 246 } 247 return result; 248 } 249 250 void GetRegistrationsOnIOThread( 251 scoped_refptr<ServiceWorkerContextWrapper> context, 252 base::Callback<void(const std::vector<ServiceWorkerRegistrationInfo>&)> 253 callback) { 254 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 255 context->context()->storage()->GetAllRegistrations(callback); 256 } 257 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>&)> 263 callback, 264 const std::vector<ServiceWorkerRegistrationInfo>& stored_registrations) { 265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 266 BrowserThread::PostTask( 267 BrowserThread::UI, 268 FROM_HERE, 269 base::Bind(callback, 270 context->context()->GetAllLiveRegistrationInfo(), 271 context->context()->GetAllLiveVersionInfo(), 272 stored_registrations)); 273 } 274 275 void OnAllRegistrations( 276 WeakPtr<ServiceWorkerInternalsUI> internals, 277 int partition_id, 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)); 283 if (!internals) 284 return; 285 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", 293 args.get()); 294 } 295 296 } // namespace 297 298 class ServiceWorkerInternalsUI::PartitionObserver 299 : public ServiceWorkerContextObserver { 300 public: 301 PartitionObserver(int partition_id, WebUI* web_ui) 302 : partition_id_(partition_id), web_ui_(web_ui) {} 303 virtual ~PartitionObserver() {} 304 // ServiceWorkerContextObserver overrides: 305 virtual void OnWorkerStarted(int64 version_id, 306 int process_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)); 315 } 316 virtual void OnWorkerStopped(int64 version_id, 317 int process_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)); 326 } 327 virtual 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))); 333 } 334 virtual void OnErrorReported(int64 version_id, 335 int process_id, 336 int thread_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", 351 args.get()); 352 } 353 virtual void OnReportConsoleMessage(int64 version_id, 354 int process_id, 355 int thread_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", 371 args.get()); 372 } 373 virtual void OnRegistrationStored(const GURL& pattern) OVERRIDE { 374 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 375 web_ui_->CallJavascriptFunction("serviceworker.onRegistrationStored", 376 StringValue(pattern.spec())); 377 } 378 virtual void OnRegistrationDeleted(const GURL& pattern) OVERRIDE { 379 web_ui_->CallJavascriptFunction("serviceworker.onRegistrationDeleted", 380 StringValue(pattern.spec())); 381 } 382 int partition_id() const { return partition_id_; } 383 384 private: 385 const int partition_id_; 386 WebUI* const web_ui_; 387 }; 388 389 ServiceWorkerInternalsUI::ServiceWorkerInternalsUI(WebUI* web_ui) 390 : WebUIController(web_ui), next_partition_id_(0) { 391 WebUIDataSource* source = 392 WebUIDataSource::Create(kChromeUIServiceWorkerInternalsHost); 393 source->SetUseJsonJSFormatV2(); 394 source->SetJsonPath("strings.js"); 395 source->AddResourcePath("serviceworker_internals.js", 396 IDR_SERVICE_WORKER_INTERNALS_JS); 397 source->AddResourcePath("serviceworker_internals.css", 398 IDR_SERVICE_WORKER_INTERNALS_CSS); 399 source->SetDefaultResource(IDR_SERVICE_WORKER_INTERNALS_HTML); 400 source->DisableDenyXFrameOptions(); 401 402 BrowserContext* browser_context = 403 web_ui->GetWebContents()->GetBrowserContext(); 404 WebUIDataSource::Add(browser_context, source); 405 406 web_ui->RegisterMessageCallback( 407 "GetOptions", 408 base::Bind(&ServiceWorkerInternalsUI::GetOptions, 409 base::Unretained(this))); 410 web_ui->RegisterMessageCallback( 411 "SetOption", 412 base::Bind(&ServiceWorkerInternalsUI::SetOption, base::Unretained(this))); 413 web_ui->RegisterMessageCallback( 414 "getAllRegistrations", 415 base::Bind(&ServiceWorkerInternalsUI::GetAllRegistrations, 416 base::Unretained(this))); 417 web_ui->RegisterMessageCallback( 418 "stop", 419 base::Bind(&ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod, 420 base::Unretained(this), 421 &ServiceWorkerVersion::StopWorker)); 422 web_ui->RegisterMessageCallback( 423 "sync", 424 base::Bind(&ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod, 425 base::Unretained(this), 426 &ServiceWorkerVersion::DispatchSyncEvent)); 427 web_ui->RegisterMessageCallback( 428 "push", 429 base::Bind(&ServiceWorkerInternalsUI::DispatchPushEvent, 430 base::Unretained(this))); 431 web_ui->RegisterMessageCallback( 432 "inspect", 433 base::Bind(&ServiceWorkerInternalsUI::InspectWorker, 434 base::Unretained(this))); 435 web_ui->RegisterMessageCallback( 436 "unregister", 437 base::Bind(&ServiceWorkerInternalsUI::Unregister, 438 base::Unretained(this))); 439 web_ui->RegisterMessageCallback( 440 "start", 441 base::Bind(&ServiceWorkerInternalsUI::StartWorker, 442 base::Unretained(this))); 443 } 444 445 ServiceWorkerInternalsUI::~ServiceWorkerInternalsUI() { 446 BrowserContext* browser_context = 447 web_ui()->GetWebContents()->GetBrowserContext(); 448 // Safe to use base::Unretained(this) because 449 // ForEachStoragePartition is synchronous. 450 BrowserContext::StoragePartitionCallback remove_observer_cb = 451 base::Bind(&ServiceWorkerInternalsUI::RemoveObserverFromStoragePartition, 452 base::Unretained(this)); 453 BrowserContext::ForEachStoragePartition(browser_context, remove_observer_cb); 454 } 455 456 void ServiceWorkerInternalsUI::GetOptions(const ListValue* args) { 457 DictionaryValue options; 458 options.SetBoolean("debug_on_start", 459 EmbeddedWorkerDevToolsManager::GetInstance() 460 ->debug_service_worker_on_start()); 461 web_ui()->CallJavascriptFunction("serviceworker.onOptions", options); 462 } 463 464 void ServiceWorkerInternalsUI::SetOption(const ListValue* args) { 465 std::string option_name; 466 bool option_boolean; 467 if (!args->GetString(0, &option_name) || option_name != "debug_on_start" || 468 !args->GetBoolean(1, &option_boolean)) { 469 return; 470 } 471 EmbeddedWorkerDevToolsManager::GetInstance() 472 ->set_debug_service_worker_on_start(option_boolean); 473 } 474 475 void ServiceWorkerInternalsUI::GetAllRegistrations(const ListValue* args) { 476 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 477 BrowserContext* browser_context = 478 web_ui()->GetWebContents()->GetBrowserContext(); 479 // Safe to use base::Unretained(this) because 480 // ForEachStoragePartition is synchronous. 481 BrowserContext::StoragePartitionCallback add_context_cb = 482 base::Bind(&ServiceWorkerInternalsUI::AddContextFromStoragePartition, 483 base::Unretained(this)); 484 BrowserContext::ForEachStoragePartition(browser_context, add_context_cb); 485 } 486 487 void ServiceWorkerInternalsUI::AddContextFromStoragePartition( 488 StoragePartition* partition) { 489 int partition_id = 0; 490 scoped_refptr<ServiceWorkerContextWrapper> context = 491 static_cast<ServiceWorkerContextWrapper*>( 492 partition->GetServiceWorkerContext()); 493 if (PartitionObserver* observer = 494 observers_.get(reinterpret_cast<uintptr_t>(partition))) { 495 partition_id = observer->partition_id(); 496 } else { 497 partition_id = next_partition_id_++; 498 scoped_ptr<PartitionObserver> new_observer( 499 new PartitionObserver(partition_id, web_ui())); 500 context->AddObserver(new_observer.get()); 501 observers_.set(reinterpret_cast<uintptr_t>(partition), new_observer.Pass()); 502 } 503 BrowserThread::PostTask( 504 BrowserThread::IO, 505 FROM_HERE, 506 base::Bind(GetRegistrationsOnIOThread, 507 context, 508 base::Bind(OnStoredRegistrations, 509 context, 510 base::Bind(OnAllRegistrations, 511 AsWeakPtr(), 512 partition_id, 513 partition->GetPath())))); 514 } 515 516 void ServiceWorkerInternalsUI::RemoveObserverFromStoragePartition( 517 StoragePartition* partition) { 518 scoped_ptr<PartitionObserver> observer( 519 observers_.take_and_erase(reinterpret_cast<uintptr_t>(partition))); 520 if (!observer.get()) 521 return; 522 scoped_refptr<ServiceWorkerContextWrapper> context = 523 static_cast<ServiceWorkerContextWrapper*>( 524 partition->GetServiceWorkerContext()); 525 context->RemoveObserver(observer.get()); 526 } 527 528 void ServiceWorkerInternalsUI::FindContext( 529 int partition_id, 530 StoragePartition** result_partition, 531 StoragePartition* storage_partition) const { 532 PartitionObserver* observer = 533 observers_.get(reinterpret_cast<uintptr_t>(storage_partition)); 534 if (observer && partition_id == observer->partition_id()) { 535 *result_partition = storage_partition; 536 } 537 } 538 539 bool ServiceWorkerInternalsUI::GetServiceWorkerContext( 540 int partition_id, 541 scoped_refptr<ServiceWorkerContextWrapper>* context) const { 542 BrowserContext* browser_context = 543 web_ui()->GetWebContents()->GetBrowserContext(); 544 StoragePartition* result_partition(NULL); 545 BrowserContext::StoragePartitionCallback find_context_cb = 546 base::Bind(&ServiceWorkerInternalsUI::FindContext, 547 base::Unretained(this), 548 partition_id, 549 &result_partition); 550 BrowserContext::ForEachStoragePartition(browser_context, find_context_cb); 551 if (!result_partition) 552 return false; 553 *context = static_cast<ServiceWorkerContextWrapper*>( 554 result_partition->GetServiceWorkerContext()); 555 return true; 556 } 557 558 void ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod( 559 ServiceWorkerVersionMethod method, 560 const ListValue* args) { 561 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 562 int callback_id; 563 int partition_id; 564 int64 version_id; 565 std::string version_id_string; 566 const DictionaryValue* cmd_args = NULL; 567 scoped_refptr<ServiceWorkerContextWrapper> context; 568 if (!args->GetInteger(0, &callback_id) || 569 !args->GetDictionary(1, &cmd_args) || 570 !cmd_args->GetInteger("partition_id", &partition_id) || 571 !GetServiceWorkerContext(partition_id, &context) || 572 !cmd_args->GetString("version_id", &version_id_string) || 573 !base::StringToInt64(version_id_string, &version_id)) { 574 return; 575 } 576 577 base::Callback<void(ServiceWorkerStatusCode)> callback = 578 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id); 579 CallServiceWorkerVersionMethodWithVersionID( 580 method, context, version_id, callback); 581 } 582 583 void ServiceWorkerInternalsUI::DispatchPushEvent( 584 const ListValue* args) { 585 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 586 int callback_id; 587 int partition_id; 588 int64 version_id; 589 std::string version_id_string; 590 const DictionaryValue* cmd_args = NULL; 591 scoped_refptr<ServiceWorkerContextWrapper> context; 592 if (!args->GetInteger(0, &callback_id) || 593 !args->GetDictionary(1, &cmd_args) || 594 !cmd_args->GetInteger("partition_id", &partition_id) || 595 !GetServiceWorkerContext(partition_id, &context) || 596 !cmd_args->GetString("version_id", &version_id_string) || 597 !base::StringToInt64(version_id_string, &version_id)) { 598 return; 599 } 600 601 base::Callback<void(ServiceWorkerStatusCode)> callback = 602 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id); 603 DispatchPushEventWithVersionID(context, version_id, callback); 604 } 605 606 void ServiceWorkerInternalsUI::InspectWorker(const ListValue* args) { 607 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 608 int callback_id; 609 int process_id; 610 int devtools_agent_route_id; 611 const DictionaryValue* cmd_args = NULL; 612 scoped_refptr<ServiceWorkerContextWrapper> context; 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; 619 } 620 base::Callback<void(ServiceWorkerStatusCode)> callback = 621 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id); 622 scoped_refptr<DevToolsAgentHost> agent_host( 623 EmbeddedWorkerDevToolsManager::GetInstance() 624 ->GetDevToolsAgentHostForWorker(process_id, devtools_agent_route_id)); 625 if (!agent_host) { 626 callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND); 627 return; 628 } 629 DevToolsManagerImpl::GetInstance()->Inspect( 630 web_ui()->GetWebContents()->GetBrowserContext(), agent_host.get()); 631 callback.Run(SERVICE_WORKER_OK); 632 } 633 634 void ServiceWorkerInternalsUI::Unregister(const ListValue* args) { 635 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 636 int callback_id; 637 int partition_id; 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)) { 646 return; 647 } 648 649 base::Callback<void(ServiceWorkerStatusCode)> callback = 650 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id); 651 UnregisterWithScope(context, GURL(scope_string), callback); 652 } 653 654 void ServiceWorkerInternalsUI::StartWorker(const ListValue* args) { 655 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 656 int callback_id; 657 int partition_id; 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)) { 666 return; 667 } 668 669 base::Callback<void(ServiceWorkerStatusCode)> callback = 670 base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id); 671 FindRegistrationForPattern( 672 context, GURL(scope_string), base::Bind(StartActiveWorker, callback)); 673 } 674 675 } // namespace content 676