1 // Copyright (c) 2012 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 "chrome/browser/automation/testing_automation_provider.h" 6 7 #include "ash/shell.h" 8 #include "ash/shell_delegate.h" 9 #include "ash/system/tray/system_tray_delegate.h" 10 #include "base/command_line.h" 11 #include "base/i18n/time_formatting.h" 12 #include "base/prefs/pref_service.h" 13 #include "base/strings/stringprintf.h" 14 #include "base/strings/utf_string_conversions.h" 15 #include "base/time/time.h" 16 #include "chrome/browser/automation/automation_provider_json.h" 17 #include "chrome/browser/automation/automation_provider_observers.h" 18 #include "chrome/browser/automation/automation_util.h" 19 #include "chrome/browser/browser_process.h" 20 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h" 21 #include "chrome/browser/chromeos/accessibility/accessibility_util.h" 22 #include "chrome/browser/chromeos/cros/network_library.h" 23 #include "chrome/browser/chromeos/login/default_user_images.h" 24 #include "chrome/browser/chromeos/login/enrollment/enrollment_screen.h" 25 #include "chrome/browser/chromeos/login/existing_user_controller.h" 26 #include "chrome/browser/chromeos/login/login_display.h" 27 #include "chrome/browser/chromeos/login/login_display_host_impl.h" 28 #include "chrome/browser/chromeos/login/screen_locker.h" 29 #include "chrome/browser/chromeos/login/screens/eula_screen.h" 30 #include "chrome/browser/chromeos/login/screens/network_screen.h" 31 #include "chrome/browser/chromeos/login/screens/update_screen.h" 32 #include "chrome/browser/chromeos/login/screens/user_image_screen.h" 33 #include "chrome/browser/chromeos/login/startup_utils.h" 34 #include "chrome/browser/chromeos/login/webui_login_display.h" 35 #include "chrome/browser/chromeos/login/wizard_controller.h" 36 #include "chrome/browser/chromeos/net/proxy_config_handler.h" 37 #include "chrome/browser/chromeos/settings/cros_settings.h" 38 #include "chrome/browser/chromeos/settings/cros_settings_names.h" 39 #include "chrome/browser/chromeos/system/timezone_settings.h" 40 #include "chrome/browser/prefs/proxy_config_dictionary.h" 41 #include "chrome/browser/ui/browser.h" 42 #include "chrome/browser/ui/browser_window.h" 43 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" 44 #include "chrome/common/pref_names.h" 45 #include "chromeos/audio/cras_audio_handler.h" 46 #include "chromeos/dbus/dbus_thread_manager.h" 47 #include "chromeos/dbus/session_manager_client.h" 48 #include "chromeos/dbus/update_engine_client.h" 49 #include "chromeos/network/network_state_handler.h" 50 #include "chromeos/network/onc/onc_utils.h" 51 #include "content/public/browser/web_contents.h" 52 #include "net/base/network_change_notifier.h" 53 #include "policy/policy_constants.h" 54 #include "ui/views/widget/widget.h" 55 56 using chromeos::DBusThreadManager; 57 using chromeos::ExistingUserController; 58 using chromeos::NetworkLibrary; 59 using chromeos::UpdateEngineClient; 60 using chromeos::User; 61 using chromeos::UserManager; 62 using chromeos::WizardController; 63 64 namespace { 65 66 DictionaryValue* GetNetworkInfoDict(const chromeos::Network* network) { 67 DictionaryValue* item = new DictionaryValue; 68 item->SetString("name", network->name()); 69 item->SetString("device_path", network->device_path()); 70 item->SetString("status", network->GetStateString()); 71 return item; 72 } 73 74 DictionaryValue* GetWifiInfoDict(const chromeos::WifiNetwork* wifi) { 75 DictionaryValue* item = GetNetworkInfoDict(wifi); 76 item->SetInteger("strength", wifi->strength()); 77 item->SetBoolean("encrypted", wifi->encrypted()); 78 item->SetString("encryption", wifi->GetEncryptionString()); 79 return item; 80 } 81 82 const char* UpdateStatusToString( 83 UpdateEngineClient::UpdateStatusOperation status) { 84 switch (status) { 85 case UpdateEngineClient::UPDATE_STATUS_IDLE: 86 return "idle"; 87 case UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE: 88 return "checking for update"; 89 case UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE: 90 return "update available"; 91 case UpdateEngineClient::UPDATE_STATUS_DOWNLOADING: 92 return "downloading"; 93 case UpdateEngineClient::UPDATE_STATUS_VERIFYING: 94 return "verifying"; 95 case UpdateEngineClient::UPDATE_STATUS_FINALIZING: 96 return "finalizing"; 97 case UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT: 98 return "updated need reboot"; 99 case UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT: 100 return "reporting error event"; 101 default: 102 return "unknown"; 103 } 104 } 105 106 void UpdateCheckCallback(AutomationJSONReply* reply, 107 UpdateEngineClient::UpdateCheckResult result) { 108 if (result == UpdateEngineClient::UPDATE_RESULT_SUCCESS) 109 reply->SendSuccess(NULL); 110 else 111 reply->SendError("update check failed"); 112 delete reply; 113 } 114 115 const std::string VPNProviderTypeToString( 116 chromeos::ProviderType provider_type) { 117 switch (provider_type) { 118 case chromeos::PROVIDER_TYPE_L2TP_IPSEC_PSK: 119 return std::string("L2TP_IPSEC_PSK"); 120 case chromeos::PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: 121 return std::string("L2TP_IPSEC_USER_CERT"); 122 case chromeos::PROVIDER_TYPE_OPEN_VPN: 123 return std::string("OPEN_VPN"); 124 default: 125 return std::string("UNSUPPORTED_PROVIDER_TYPE"); 126 } 127 } 128 129 } // namespace 130 131 #if defined(OS_CHROMEOS) 132 void TestingAutomationProvider::PowerChanged( 133 const power_manager::PowerSupplyProperties& proto) { 134 power_supply_properties_ = proto; 135 } 136 #endif 137 138 void TestingAutomationProvider::AcceptOOBENetworkScreen( 139 DictionaryValue* args, 140 IPC::Message* reply_message) { 141 WizardController* wizard_controller = WizardController::default_controller(); 142 if (!wizard_controller || wizard_controller->current_screen()->GetName() != 143 WizardController::kNetworkScreenName) { 144 AutomationJSONReply(this, reply_message).SendError( 145 "Network screen not active."); 146 return; 147 } 148 // Observer will delete itself. 149 new WizardControllerObserver(wizard_controller, this, reply_message); 150 wizard_controller->GetNetworkScreen()->OnContinuePressed(); 151 } 152 153 void TestingAutomationProvider::AcceptOOBEEula(DictionaryValue* args, 154 IPC::Message* reply_message) { 155 bool accepted; 156 bool usage_stats_reporting; 157 if (!args->GetBoolean("accepted", &accepted) || 158 !args->GetBoolean("usage_stats_reporting", &usage_stats_reporting)) { 159 AutomationJSONReply(this, reply_message).SendError( 160 "Invalid or missing args."); 161 return; 162 } 163 164 WizardController* wizard_controller = WizardController::default_controller(); 165 if (!wizard_controller || wizard_controller->current_screen()->GetName() != 166 WizardController::kEulaScreenName) { 167 AutomationJSONReply(this, reply_message).SendError( 168 "EULA screen not active."); 169 return; 170 } 171 // Observer will delete itself. 172 new WizardControllerObserver(wizard_controller, this, reply_message); 173 wizard_controller->GetEulaScreen()->OnExit(accepted, usage_stats_reporting); 174 } 175 176 void TestingAutomationProvider::CancelOOBEUpdate(DictionaryValue* args, 177 IPC::Message* reply_message) { 178 if (chromeos::StartupUtils::IsOobeCompleted()) { 179 // Update already finished. 180 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 181 return_value->SetString("next_screen", 182 WizardController::kLoginScreenName); 183 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get()); 184 return; 185 } 186 WizardController* wizard_controller = WizardController::default_controller(); 187 if (!wizard_controller || wizard_controller->current_screen()->GetName() != 188 WizardController::kUpdateScreenName) { 189 AutomationJSONReply(this, reply_message).SendError( 190 "Update screen not active."); 191 return; 192 } 193 // Observer will delete itself. 194 new WizardControllerObserver(wizard_controller, this, reply_message); 195 wizard_controller->GetUpdateScreen()->CancelUpdate(); 196 } 197 198 void TestingAutomationProvider::GetLoginInfo(DictionaryValue* args, 199 IPC::Message* reply_message) { 200 AutomationJSONReply reply(this, reply_message); 201 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 202 203 const UserManager* user_manager = UserManager::Get(); 204 if (!user_manager) 205 reply.SendError("No user manager!"); 206 const chromeos::ScreenLocker* screen_locker = 207 chromeos::ScreenLocker::default_screen_locker(); 208 209 return_value->SetString("login_ui_type", "webui"); 210 return_value->SetBoolean("is_owner", user_manager->IsCurrentUserOwner()); 211 return_value->SetBoolean("is_logged_in", user_manager->IsUserLoggedIn()); 212 return_value->SetBoolean("is_screen_locked", screen_locker); 213 if (user_manager->IsUserLoggedIn()) { 214 const User* user = user_manager->GetLoggedInUser(); 215 return_value->SetBoolean("is_guest", user_manager->IsLoggedInAsGuest()); 216 return_value->SetString("email", user->email()); 217 return_value->SetString("display_email", user->display_email()); 218 switch (user->image_index()) { 219 case User::kExternalImageIndex: 220 return_value->SetString("user_image", "file"); 221 break; 222 223 case User::kProfileImageIndex: 224 return_value->SetString("user_image", "profile"); 225 break; 226 227 default: 228 return_value->SetInteger("user_image", user->image_index()); 229 break; 230 } 231 } 232 233 reply.SendSuccess(return_value.get()); 234 } 235 236 // See the note under LoginAsGuest(). CreateAccount() causes a login as guest. 237 void TestingAutomationProvider::ShowCreateAccountUI( 238 DictionaryValue* args, IPC::Message* reply_message) { 239 ExistingUserController* controller = 240 ExistingUserController::current_controller(); 241 // Return immediately, since we're going to die before the login is finished. 242 AutomationJSONReply(this, reply_message).SendSuccess(NULL); 243 controller->CreateAccount(); 244 } 245 246 // Logging in as guest will cause session_manager to restart Chrome with new 247 // flags. If you used EnableChromeTesting, you will have to call it again. 248 void TestingAutomationProvider::LoginAsGuest(DictionaryValue* args, 249 IPC::Message* reply_message) { 250 ExistingUserController* controller = 251 ExistingUserController::current_controller(); 252 // Return immediately, since we're going to die before the login is finished. 253 AutomationJSONReply(this, reply_message).SendSuccess(NULL); 254 controller->LoginAsGuest(); 255 } 256 257 void TestingAutomationProvider::SubmitLoginForm(DictionaryValue* args, 258 IPC::Message* reply_message) { 259 AutomationJSONReply reply(this, reply_message); 260 261 std::string username, password; 262 if (!args->GetString("username", &username) || 263 !args->GetString("password", &password)) { 264 reply.SendError("Invalid or missing args."); 265 return; 266 } 267 268 chromeos::ExistingUserController* controller = 269 chromeos::ExistingUserController::current_controller(); 270 if (!controller) { 271 reply.SendError("Unable to access ExistingUserController"); 272 return; 273 } 274 275 // WebUI login. 276 chromeos::WebUILoginDisplay* webui_login_display = 277 static_cast<chromeos::WebUILoginDisplay*>(controller->login_display()); 278 VLOG(2) << "TestingAutomationProvider::SubmitLoginForm " 279 << "ShowSigninScreenForCreds(" << username << ", " << password << ")"; 280 281 webui_login_display->ShowSigninScreenForCreds(username, password); 282 reply.SendSuccess(NULL); 283 } 284 285 void TestingAutomationProvider::AddLoginEventObserver( 286 DictionaryValue* args, IPC::Message* reply_message) { 287 ExistingUserController* controller = 288 ExistingUserController::current_controller(); 289 AutomationJSONReply reply(this, reply_message); 290 if (!controller) { 291 // This may happen due to SkipToLogin not being called. 292 reply.SendError("Unable to access ExistingUserController"); 293 return; 294 } 295 296 if (!automation_event_queue_.get()) 297 automation_event_queue_.reset(new AutomationEventQueue); 298 299 int observer_id = automation_event_queue_->AddObserver( 300 new LoginEventObserver(automation_event_queue_.get(), this)); 301 302 // Return the observer's id. 303 DictionaryValue return_value; 304 return_value.SetInteger("observer_id", observer_id); 305 reply.SendSuccess(&return_value); 306 } 307 308 void TestingAutomationProvider::SignOut(DictionaryValue* args, 309 IPC::Message* reply_message) { 310 ash::Shell::GetInstance()->system_tray_delegate()->SignOut(); 311 // Sign out has the side effect of restarting the session_manager 312 // and chrome, thereby severing the automation channel, so it's 313 // not really necessary to send a reply back. The next line is 314 // for consistency with other methods. 315 AutomationJSONReply(this, reply_message).SendSuccess(NULL); 316 } 317 318 void TestingAutomationProvider::PickUserImage(DictionaryValue* args, 319 IPC::Message* reply_message) { 320 std::string image_type; 321 int image_number = -1; 322 if (!args->GetString("image", &image_type) 323 && !args->GetInteger("image", &image_number)) { 324 AutomationJSONReply(this, reply_message).SendError( 325 "Invalid or missing args."); 326 return; 327 } 328 WizardController* wizard_controller = WizardController::default_controller(); 329 if (!wizard_controller || wizard_controller->current_screen()->GetName() != 330 WizardController::kUserImageScreenName) { 331 AutomationJSONReply(this, reply_message).SendError( 332 "User image screen not active."); 333 return; 334 } 335 chromeos::UserImageScreen* image_screen = 336 wizard_controller->GetUserImageScreen(); 337 // Observer will delete itself unless error is returned. 338 WizardControllerObserver* observer = 339 new WizardControllerObserver(wizard_controller, this, reply_message); 340 if (image_type == "profile") { 341 image_screen->OnImageSelected("", image_type); 342 image_screen->OnImageAccepted(); 343 } else if (image_type.empty() && image_number >= 0 && 344 image_number < chromeos::kDefaultImagesCount) { 345 image_screen->OnImageSelected( 346 chromeos::GetDefaultImageUrl(image_number), image_type); 347 image_screen->OnImageAccepted(); 348 } else { 349 AutomationJSONReply(this, reply_message).SendError( 350 "Invalid or missing args."); 351 delete observer; 352 return; 353 } 354 } 355 356 void TestingAutomationProvider::SkipToLogin(DictionaryValue* args, 357 IPC::Message* reply_message) { 358 bool skip_post_login_screens; 359 // The argument name is a legacy. If set to |true|, this argument causes any 360 // screens that may otherwise be shown after login (registration, Terms of 361 // Service, user image selection) to be skipped. 362 if (!args->GetBoolean("skip_image_selection", &skip_post_login_screens)) { 363 AutomationJSONReply reply(this, reply_message); 364 reply.SendError("Invalid or missing args."); 365 return; 366 } 367 if (skip_post_login_screens) 368 WizardController::SkipPostLoginScreensForTesting(); 369 370 WizardController* wizard_controller = WizardController::default_controller(); 371 if (!wizard_controller) { 372 AutomationJSONReply reply(this, reply_message); 373 if (ExistingUserController::current_controller()) { 374 // Already at login screen. 375 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 376 return_value->SetString("next_screen", 377 WizardController::kLoginScreenName); 378 reply.SendSuccess(return_value.get()); 379 } else { 380 reply.SendError("OOBE not active."); 381 } 382 return; 383 } 384 385 // Observer will delete itself. 386 WizardControllerObserver* observer = 387 new WizardControllerObserver(wizard_controller, this, reply_message); 388 observer->set_screen_to_wait_for(WizardController::kLoginScreenName); 389 wizard_controller->SkipToLoginForTesting(); 390 } 391 392 void TestingAutomationProvider::GetOOBEScreenInfo(DictionaryValue* args, 393 IPC::Message* reply_message) { 394 static const char kScreenNameKey[] = "screen_name"; 395 AutomationJSONReply reply(this, reply_message); 396 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 397 398 WizardController* wizard_controller = WizardController::default_controller(); 399 if (wizard_controller) { 400 if (wizard_controller->login_screen_started()) { 401 return_value->SetString(kScreenNameKey, 402 WizardController::kLoginScreenName); 403 } else { 404 return_value->SetString(kScreenNameKey, 405 wizard_controller->current_screen()->GetName()); 406 } 407 } else if (ExistingUserController::current_controller()) { 408 return_value->SetString(kScreenNameKey, WizardController::kLoginScreenName); 409 } else { 410 // Already logged in. 411 reply.SendSuccess(NULL); 412 return; 413 } 414 reply.SendSuccess(return_value.get()); 415 } 416 417 void TestingAutomationProvider::LockScreen(DictionaryValue* args, 418 IPC::Message* reply_message) { 419 new ScreenLockUnlockObserver(this, reply_message, true); 420 DBusThreadManager::Get()->GetSessionManagerClient()->RequestLockScreen(); 421 } 422 423 void TestingAutomationProvider::UnlockScreen(DictionaryValue* args, 424 IPC::Message* reply_message) { 425 std::string password; 426 if (!args->GetString("password", &password)) { 427 AutomationJSONReply(this, reply_message).SendError( 428 "Invalid or missing args."); 429 return; 430 } 431 432 chromeos::ScreenLocker* screen_locker = 433 chromeos::ScreenLocker::default_screen_locker(); 434 if (!screen_locker) { 435 AutomationJSONReply(this, reply_message).SendError( 436 "No default screen locker. Are you sure the screen is locked?"); 437 return; 438 } 439 440 new ScreenUnlockObserver(this, reply_message); 441 screen_locker->AuthenticateByPassword(password); 442 } 443 444 // Signing out could have undesirable side effects: session_manager is 445 // killed, so its children, including chrome and the window manager, will 446 // also be killed. Anything owned by chronos will probably be killed. 447 void TestingAutomationProvider::SignoutInScreenLocker( 448 DictionaryValue* args, IPC::Message* reply_message) { 449 AutomationJSONReply reply(this, reply_message); 450 chromeos::ScreenLocker* screen_locker = 451 chromeos::ScreenLocker::default_screen_locker(); 452 if (!screen_locker) { 453 reply.SendError( 454 "No default screen locker. Are you sure the screen is locked?"); 455 return; 456 } 457 458 // Send success before stopping session because if we're a child of 459 // session manager then we'll die when the session is stopped. 460 reply.SendSuccess(NULL); 461 screen_locker->Signout(); 462 } 463 464 void TestingAutomationProvider::GetBatteryInfo(DictionaryValue* args, 465 IPC::Message* reply_message) { 466 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 467 468 const bool battery_is_present = power_supply_properties_.battery_state() != 469 power_manager::PowerSupplyProperties_BatteryState_NOT_PRESENT; 470 const bool line_power_on = power_supply_properties_.external_power() != 471 power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED; 472 473 return_value->SetBoolean("battery_is_present", battery_is_present); 474 return_value->SetBoolean("line_power_on", line_power_on); 475 476 if (battery_is_present) { 477 const bool battery_is_full = power_supply_properties_.battery_state() == 478 power_manager::PowerSupplyProperties_BatteryState_FULL; 479 return_value->SetBoolean("battery_fully_charged", battery_is_full); 480 return_value->SetDouble("battery_percentage", 481 power_supply_properties_.battery_percent()); 482 if (line_power_on) { 483 int64 time = power_supply_properties_.battery_time_to_full_sec(); 484 if (time > 0 || battery_is_full) 485 return_value->SetInteger("battery_seconds_to_full", time); 486 } else { 487 int64 time = power_supply_properties_.battery_time_to_empty_sec(); 488 if (time > 0) 489 return_value->SetInteger("battery_seconds_to_empty", time); 490 } 491 } 492 493 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get()); 494 } 495 496 void TestingAutomationProvider::GetNetworkInfo(DictionaryValue* args, 497 IPC::Message* reply_message) { 498 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 499 NetworkLibrary* network_library = NetworkLibrary::Get(); 500 501 return_value->SetBoolean("offline_mode", 502 net::NetworkChangeNotifier::IsOffline()); 503 504 // Currently connected networks. 505 if (network_library->ethernet_network()) 506 return_value->SetString( 507 "connected_ethernet", 508 network_library->ethernet_network()->service_path()); 509 if (network_library->wifi_network()) 510 return_value->SetString("connected_wifi", 511 network_library->wifi_network()->service_path()); 512 if (network_library->cellular_network()) 513 return_value->SetString( 514 "connected_cellular", 515 network_library->cellular_network()->service_path()); 516 517 // Ethernet network. 518 bool ethernet_available = network_library->ethernet_available(); 519 bool ethernet_enabled = network_library->ethernet_enabled(); 520 return_value->SetBoolean("ethernet_available", ethernet_available); 521 return_value->SetBoolean("ethernet_enabled", ethernet_enabled); 522 if (ethernet_available && ethernet_enabled) { 523 const chromeos::EthernetNetwork* ethernet_network = 524 network_library->ethernet_network(); 525 if (ethernet_network) { 526 DictionaryValue* items = new DictionaryValue; 527 DictionaryValue* item = GetNetworkInfoDict(ethernet_network); 528 items->Set(ethernet_network->service_path(), item); 529 items->SetInteger("network_type", chromeos::TYPE_ETHERNET); 530 return_value->Set("ethernet_networks", items); 531 } 532 } 533 534 // Wi-fi networks. 535 bool wifi_available = network_library->wifi_available(); 536 bool wifi_enabled = network_library->wifi_enabled(); 537 return_value->SetBoolean("wifi_available", wifi_available); 538 return_value->SetBoolean("wifi_enabled", wifi_enabled); 539 if (wifi_available && wifi_enabled) { 540 const chromeos::WifiNetworkVector& wifi_networks = 541 network_library->wifi_networks(); 542 DictionaryValue* items = new DictionaryValue; 543 for (chromeos::WifiNetworkVector::const_iterator iter = 544 wifi_networks.begin(); iter != wifi_networks.end(); ++iter) { 545 const chromeos::WifiNetwork* wifi = *iter; 546 DictionaryValue* item = GetWifiInfoDict(wifi); 547 items->Set(wifi->service_path(), item); 548 } 549 items->SetInteger("network_type", chromeos::TYPE_WIFI); 550 return_value->Set("wifi_networks", items); 551 } 552 553 // Cellular networks. 554 bool cellular_available = network_library->cellular_available(); 555 bool cellular_enabled = network_library->cellular_enabled(); 556 return_value->SetBoolean("cellular_available", cellular_available); 557 return_value->SetBoolean("cellular_enabled", cellular_enabled); 558 if (cellular_available && cellular_enabled) { 559 const chromeos::CellularNetworkVector& cellular_networks = 560 network_library->cellular_networks(); 561 DictionaryValue* items = new DictionaryValue; 562 for (size_t i = 0; i < cellular_networks.size(); ++i) { 563 DictionaryValue* item = GetNetworkInfoDict(cellular_networks[i]); 564 item->SetInteger("strength", cellular_networks[i]->strength()); 565 item->SetString("operator_name", cellular_networks[i]->operator_name()); 566 item->SetString("operator_code", cellular_networks[i]->operator_code()); 567 item->SetString("payment_url", cellular_networks[i]->payment_url()); 568 item->SetString("usage_url", cellular_networks[i]->usage_url()); 569 item->SetString("network_technology", 570 cellular_networks[i]->GetNetworkTechnologyString()); 571 item->SetString("activation_state", 572 cellular_networks[i]->GetActivationStateString()); 573 item->SetString("roaming_state", 574 cellular_networks[i]->GetRoamingStateString()); 575 items->Set(cellular_networks[i]->service_path(), item); 576 } 577 items->SetInteger("network_type", chromeos::TYPE_CELLULAR); 578 return_value->Set("cellular_networks", items); 579 } 580 581 // Remembered Wifi Networks. 582 const chromeos::WifiNetworkVector& remembered_wifi = 583 network_library->remembered_wifi_networks(); 584 DictionaryValue* remembered_wifi_items = new DictionaryValue; 585 for (chromeos::WifiNetworkVector::const_iterator iter = 586 remembered_wifi.begin(); iter != remembered_wifi.end(); 587 ++iter) { 588 const chromeos::WifiNetwork* wifi = *iter; 589 DictionaryValue* item = GetWifiInfoDict(wifi); 590 remembered_wifi_items->Set(wifi->service_path(), item); 591 } 592 remembered_wifi_items->SetInteger("network_type", chromeos::TYPE_WIFI); 593 return_value->Set("remembered_wifi", remembered_wifi_items); 594 595 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get()); 596 } 597 598 void TestingAutomationProvider::NetworkScan(DictionaryValue* args, 599 IPC::Message* reply_message) { 600 NetworkLibrary* network_library = NetworkLibrary::Get(); 601 network_library->RequestNetworkScan(); 602 603 // Set up an observer (it will delete itself). 604 new NetworkScanObserver(this, reply_message); 605 } 606 607 void TestingAutomationProvider::ToggleNetworkDevice( 608 DictionaryValue* args, IPC::Message* reply_message) { 609 AutomationJSONReply reply(this, reply_message); 610 std::string device; 611 bool enable; 612 if (!args->GetString("device", &device) || 613 !args->GetBoolean("enable", &enable)) { 614 reply.SendError("Invalid or missing args."); 615 return; 616 } 617 618 // Set up an observer (it will delete itself). 619 new ToggleNetworkDeviceObserver(this, reply_message, device, enable); 620 621 NetworkLibrary* network_library = NetworkLibrary::Get(); 622 if (device == "ethernet") { 623 network_library->EnableEthernetNetworkDevice(enable); 624 } else if (device == "wifi") { 625 network_library->EnableWifiNetworkDevice(enable); 626 } else if (device == "cellular") { 627 network_library->EnableCellularNetworkDevice(enable); 628 } else { 629 reply.SendError( 630 "Unknown device. Valid devices are ethernet, wifi, cellular."); 631 return; 632 } 633 } 634 635 void TestingAutomationProvider::SetSharedProxies( 636 DictionaryValue* args, 637 IPC::Message* reply_message) { 638 639 AutomationJSONReply reply(this, reply_message); 640 base::Value* value; 641 if (!args->Get("value", &value)) { 642 reply.SendError("Invalid or missing value argument."); 643 return; 644 } 645 std::string error_message; 646 Profile* profile = 647 automation_util::GetCurrentProfileOnChromeOS(&error_message); 648 if (!profile) { 649 reply.SendError(error_message); 650 return; 651 } 652 PrefService* pref_service = profile->GetPrefs(); 653 pref_service->Set(prefs::kUseSharedProxies, *value); 654 reply.SendSuccess(NULL); 655 } 656 657 void TestingAutomationProvider::SetProxySettings(DictionaryValue* args, 658 IPC::Message* reply_message) { 659 AutomationJSONReply reply(this, reply_message); 660 std::string proxy_config_str; 661 if (!args->GetString("proxy_config", &proxy_config_str)) { 662 reply.SendError("Invalid or missing args."); 663 return; 664 } 665 666 const chromeos::NetworkState* network = chromeos::NetworkHandler::Get()-> 667 network_state_handler()->DefaultNetwork(); 668 if (!network) { 669 reply.SendError("No network connected."); 670 return; 671 } 672 673 scoped_ptr<base::DictionaryValue> proxy_config_dict( 674 chromeos::onc::ReadDictionaryFromJson(proxy_config_str)); 675 ProxyConfigDictionary proxy_config(proxy_config_dict.get()); 676 chromeos::proxy_config::SetProxyConfigForNetwork(proxy_config, *network); 677 678 reply.SendSuccess(NULL); 679 } 680 681 void TestingAutomationProvider::ConnectToCellularNetwork( 682 DictionaryValue* args, IPC::Message* reply_message) { 683 std::string service_path; 684 if (!args->GetString("service_path", &service_path)) { 685 AutomationJSONReply(this, reply_message).SendError( 686 "Invalid or missing args."); 687 return; 688 } 689 690 NetworkLibrary* network_library = NetworkLibrary::Get(); 691 chromeos::CellularNetwork* cellular = 692 network_library->FindCellularNetworkByPath(service_path); 693 if (!cellular) { 694 AutomationJSONReply(this, reply_message).SendError( 695 "No network found with specified service path."); 696 return; 697 } 698 699 // Set up an observer (it will delete itself). 700 new ServicePathConnectObserver(this, reply_message, service_path); 701 702 network_library->ConnectToCellularNetwork(cellular); 703 network_library->RequestNetworkScan(); 704 } 705 706 void TestingAutomationProvider::DisconnectFromCellularNetwork( 707 DictionaryValue* args, IPC::Message* reply_message) { 708 NetworkLibrary* network_library = NetworkLibrary::Get(); 709 const chromeos::CellularNetwork* cellular = 710 network_library->cellular_network(); 711 if (!cellular) { 712 AutomationJSONReply(this, reply_message).SendError( 713 "Not connected to any cellular network."); 714 return; 715 } 716 717 // Set up an observer (it will delete itself). 718 new NetworkDisconnectObserver(this, reply_message, cellular->service_path()); 719 720 network_library->DisconnectFromNetwork(cellular); 721 } 722 723 void TestingAutomationProvider::ConnectToWifiNetwork( 724 DictionaryValue* args, IPC::Message* reply_message) { 725 AutomationJSONReply reply(this, reply_message); 726 std::string service_path, password; 727 bool shared; 728 if (!args->GetString("service_path", &service_path) || 729 !args->GetString("password", &password) || 730 !args->GetBoolean("shared", &shared)) { 731 reply.SendError("Invalid or missing args."); 732 return; 733 } 734 735 NetworkLibrary* network_library = NetworkLibrary::Get(); 736 chromeos::WifiNetwork* wifi = 737 network_library->FindWifiNetworkByPath(service_path); 738 if (!wifi) { 739 reply.SendError("No network found with specified service path."); 740 return; 741 } 742 if (!password.empty()) 743 wifi->SetPassphrase(password); 744 745 // Regardless of what was passed, if the network is open and visible, 746 // the network must be shared because of a UI restriction. 747 if (wifi->encryption() == chromeos::SECURITY_NONE) 748 shared = true; 749 750 // Set up an observer (it will delete itself). 751 new ServicePathConnectObserver(this, reply_message, service_path); 752 753 network_library->ConnectToWifiNetwork(wifi, shared); 754 network_library->RequestNetworkScan(); 755 } 756 757 void TestingAutomationProvider::ForgetWifiNetwork( 758 DictionaryValue* args, IPC::Message* reply_message) { 759 std::string service_path; 760 if (!args->GetString("service_path", &service_path)) { 761 AutomationJSONReply(this, reply_message).SendError( 762 "Invalid or missing args."); 763 return; 764 } 765 766 NetworkLibrary::Get()->ForgetNetwork(service_path); 767 AutomationJSONReply(this, reply_message).SendSuccess(NULL); 768 } 769 770 void TestingAutomationProvider::ConnectToHiddenWifiNetwork( 771 DictionaryValue* args, IPC::Message* reply_message) { 772 std::string ssid, security, password; 773 bool shared; 774 if (!args->GetString("ssid", &ssid) || 775 !args->GetString("security", &security) || 776 !args->GetString("password", &password) || 777 !args->GetBoolean("shared", &shared)) { 778 AutomationJSONReply(this, reply_message).SendError( 779 "Invalid or missing args."); 780 return; 781 } 782 783 std::map<std::string, chromeos::ConnectionSecurity> connection_security_map; 784 connection_security_map["SECURITY_NONE"] = chromeos::SECURITY_NONE; 785 connection_security_map["SECURITY_WEP"] = chromeos::SECURITY_WEP; 786 connection_security_map["SECURITY_WPA"] = chromeos::SECURITY_WPA; 787 connection_security_map["SECURITY_RSN"] = chromeos::SECURITY_RSN; 788 connection_security_map["SECURITY_8021X"] = chromeos::SECURITY_8021X; 789 790 if (connection_security_map.find(security) == connection_security_map.end()) { 791 AutomationJSONReply(this, reply_message).SendError( 792 "Unknown security type."); 793 return; 794 } 795 chromeos::ConnectionSecurity connection_security = 796 connection_security_map[security]; 797 798 NetworkLibrary* network_library = NetworkLibrary::Get(); 799 800 // Set up an observer (it will delete itself). 801 new SSIDConnectObserver(this, reply_message, ssid); 802 803 bool save_credentials = false; 804 805 if (connection_security == chromeos::SECURITY_8021X) { 806 chromeos::NetworkLibrary::EAPConfigData config_data; 807 std::string eap_method, eap_auth, eap_identity; 808 if (!args->GetString("eap_method", &eap_method) || 809 !args->GetString("eap_auth", &eap_auth) || 810 !args->GetString("eap_identity", &eap_identity) || 811 !args->GetBoolean("save_credentials", &save_credentials)) { 812 AutomationJSONReply(this, reply_message).SendError( 813 "Invalid or missing EAP args."); 814 return; 815 } 816 817 std::map<std::string, chromeos::EAPMethod> eap_method_map; 818 eap_method_map["EAP_METHOD_NONE"] = chromeos::EAP_METHOD_UNKNOWN; 819 eap_method_map["EAP_METHOD_PEAP"] = chromeos::EAP_METHOD_PEAP; 820 eap_method_map["EAP_METHOD_TLS"] = chromeos::EAP_METHOD_TLS; 821 eap_method_map["EAP_METHOD_TTLS"] = chromeos::EAP_METHOD_TTLS; 822 eap_method_map["EAP_METHOD_LEAP"] = chromeos::EAP_METHOD_LEAP; 823 if (eap_method_map.find(eap_method) == eap_method_map.end()) { 824 AutomationJSONReply(this, reply_message).SendError( 825 "Unknown EAP Method type."); 826 return; 827 } 828 config_data.method = eap_method_map[eap_method]; 829 830 std::map<std::string, chromeos::EAPPhase2Auth> eap_auth_map; 831 eap_auth_map["EAP_PHASE_2_AUTH_AUTO"] = chromeos::EAP_PHASE_2_AUTH_AUTO; 832 eap_auth_map["EAP_PHASE_2_AUTH_MD5"] = chromeos::EAP_PHASE_2_AUTH_MD5; 833 eap_auth_map["EAP_PHASE_2_AUTH_MSCHAP"] = 834 chromeos::EAP_PHASE_2_AUTH_MSCHAP; 835 eap_auth_map["EAP_PHASE_2_AUTH_MSCHAPV2"] = 836 chromeos::EAP_PHASE_2_AUTH_MSCHAPV2; 837 eap_auth_map["EAP_PHASE_2_AUTH_PAP"] = chromeos::EAP_PHASE_2_AUTH_PAP; 838 eap_auth_map["EAP_PHASE_2_AUTH_CHAP"] = chromeos::EAP_PHASE_2_AUTH_CHAP; 839 if (eap_auth_map.find(eap_auth) == eap_auth_map.end()) { 840 AutomationJSONReply(this, reply_message).SendError( 841 "Unknown EAP Phase2 Auth type."); 842 return; 843 } 844 config_data.auth = eap_auth_map[eap_auth]; 845 846 config_data.identity = eap_identity; 847 848 // TODO(stevenjb): Parse cert values? 849 config_data.use_system_cas = false; 850 config_data.client_cert_pkcs11_id = ""; 851 852 network_library->ConnectToUnconfiguredWifiNetwork( 853 ssid, chromeos::SECURITY_8021X, password, &config_data, 854 save_credentials, shared); 855 } else { 856 network_library->ConnectToUnconfiguredWifiNetwork( 857 ssid, connection_security, password, NULL, 858 save_credentials, shared); 859 } 860 } 861 862 void TestingAutomationProvider::DisconnectFromWifiNetwork( 863 DictionaryValue* args, IPC::Message* reply_message) { 864 AutomationJSONReply reply(this, reply_message); 865 NetworkLibrary* network_library = NetworkLibrary::Get(); 866 const chromeos::WifiNetwork* wifi = network_library->wifi_network(); 867 if (!wifi) { 868 reply.SendError("Not connected to any wifi network."); 869 return; 870 } 871 872 network_library->DisconnectFromNetwork(wifi); 873 reply.SendSuccess(NULL); 874 } 875 876 void TestingAutomationProvider::AddPrivateNetwork( 877 DictionaryValue* args, IPC::Message* reply_message) { 878 std::string hostname, service_name, provider_type, key, cert_id, username, 879 password; 880 if (!args->GetString("hostname", &hostname) || 881 !args->GetString("service_name", &service_name) || 882 !args->GetString("provider_type", &provider_type) || 883 !args->GetString("username", &username) || 884 !args->GetString("password", &password)) { 885 AutomationJSONReply(this, reply_message) 886 .SendError("Invalid or missing args."); 887 return; 888 } 889 890 NetworkLibrary* network_library = NetworkLibrary::Get(); 891 892 // Attempt to connect to the VPN based on the provider type. 893 if (provider_type == VPNProviderTypeToString( 894 chromeos::PROVIDER_TYPE_L2TP_IPSEC_PSK)) { 895 if (!args->GetString("key", &key)) { 896 AutomationJSONReply(this, reply_message) 897 .SendError("Missing key arg."); 898 return; 899 } 900 new VirtualConnectObserver(this, reply_message, service_name); 901 // Connect using a pre-shared key. 902 chromeos::NetworkLibrary::VPNConfigData config_data; 903 config_data.psk = key; 904 config_data.username = username; 905 config_data.user_passphrase = password; 906 network_library->ConnectToUnconfiguredVirtualNetwork( 907 service_name, 908 hostname, 909 chromeos::PROVIDER_TYPE_L2TP_IPSEC_PSK, 910 config_data); 911 } else if (provider_type == VPNProviderTypeToString( 912 chromeos::PROVIDER_TYPE_L2TP_IPSEC_USER_CERT)) { 913 if (!args->GetString("cert_id", &cert_id)) { 914 AutomationJSONReply(this, reply_message) 915 .SendError("Missing a certificate arg."); 916 return; 917 } 918 new VirtualConnectObserver(this, reply_message, service_name); 919 // Connect using a user certificate. 920 chromeos::NetworkLibrary::VPNConfigData config_data; 921 config_data.client_cert_pkcs11_id = cert_id; 922 config_data.username = username; 923 config_data.user_passphrase = password; 924 network_library->ConnectToUnconfiguredVirtualNetwork( 925 service_name, 926 hostname, 927 chromeos::PROVIDER_TYPE_L2TP_IPSEC_USER_CERT, 928 config_data); 929 } else if (provider_type == VPNProviderTypeToString( 930 chromeos::PROVIDER_TYPE_OPEN_VPN)) { 931 std::string otp; 932 args->GetString("otp", &otp); 933 // Connect using OPEN_VPN. 934 chromeos::NetworkLibrary::VPNConfigData config_data; 935 config_data.client_cert_pkcs11_id = cert_id; 936 config_data.username = username; 937 config_data.user_passphrase = password; 938 config_data.otp = otp; 939 network_library->ConnectToUnconfiguredVirtualNetwork( 940 service_name, 941 hostname, 942 chromeos::PROVIDER_TYPE_OPEN_VPN, 943 config_data); 944 } else { 945 AutomationJSONReply(this, reply_message) 946 .SendError("Unsupported provider type."); 947 return; 948 } 949 } 950 951 void TestingAutomationProvider::ConnectToPrivateNetwork( 952 DictionaryValue* args, IPC::Message* reply_message) { 953 AutomationJSONReply reply(this, reply_message); 954 std::string service_path; 955 if (!args->GetString("service_path", &service_path)) { 956 reply.SendError("Invalid or missing args."); 957 return; 958 } 959 960 // Connect to a remembered VPN by its service_path. Valid service_paths 961 // can be found in the dictionary returned by GetPrivateNetworkInfo. 962 NetworkLibrary* network_library = NetworkLibrary::Get(); 963 chromeos::VirtualNetwork* network = 964 network_library->FindVirtualNetworkByPath(service_path); 965 if (!network) { 966 reply.SendError(base::StringPrintf("No virtual network found: %s", 967 service_path.c_str())); 968 return; 969 } 970 if (network->NeedMoreInfoToConnect()) { 971 reply.SendError("Virtual network is missing info required to connect."); 972 return; 973 }; 974 975 // Set up an observer (it will delete itself). 976 new VirtualConnectObserver(this, reply_message, network->name()); 977 network_library->ConnectToVirtualNetwork(network); 978 } 979 980 void TestingAutomationProvider::GetPrivateNetworkInfo( 981 DictionaryValue* args, IPC::Message* reply_message) { 982 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 983 NetworkLibrary* network_library = NetworkLibrary::Get(); 984 const chromeos::VirtualNetworkVector& virtual_networks = 985 network_library->virtual_networks(); 986 987 // Construct a dictionary of fields describing remembered VPNs. Also list 988 // the currently active VPN, if any. 989 if (network_library->virtual_network()) 990 return_value->SetString("connected", 991 network_library->virtual_network()->service_path()); 992 for (chromeos::VirtualNetworkVector::const_iterator iter = 993 virtual_networks.begin(); iter != virtual_networks.end(); ++iter) { 994 const chromeos::VirtualNetwork* virt = *iter; 995 DictionaryValue* item = new DictionaryValue; 996 item->SetString("name", virt->name()); 997 item->SetString("provider_type", 998 VPNProviderTypeToString(virt->provider_type())); 999 item->SetString("hostname", virt->server_hostname()); 1000 item->SetString("key", virt->psk_passphrase()); 1001 item->SetString("cert_id", virt->client_cert_id()); 1002 item->SetString("username", virt->username()); 1003 item->SetString("password", virt->user_passphrase()); 1004 return_value->Set(virt->service_path(), item); 1005 } 1006 1007 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get()); 1008 } 1009 1010 void TestingAutomationProvider::DisconnectFromPrivateNetwork( 1011 DictionaryValue* args, IPC::Message* reply_message) { 1012 AutomationJSONReply reply(this, reply_message); 1013 NetworkLibrary* network_library = NetworkLibrary::Get(); 1014 const chromeos::VirtualNetwork* virt = network_library->virtual_network(); 1015 if (!virt) { 1016 reply.SendError("Not connected to any virtual network."); 1017 return; 1018 } 1019 1020 network_library->DisconnectFromNetwork(virt); 1021 reply.SendSuccess(NULL); 1022 } 1023 1024 void TestingAutomationProvider::ExecuteJavascriptInOOBEWebUI( 1025 DictionaryValue* args, IPC::Message* reply_message) { 1026 std::string javascript, frame_xpath; 1027 if (!args->GetString("javascript", &javascript)) { 1028 AutomationJSONReply(this, reply_message) 1029 .SendError("'javascript' missing or invalid"); 1030 return; 1031 } 1032 if (!args->GetString("frame_xpath", &frame_xpath)) { 1033 AutomationJSONReply(this, reply_message) 1034 .SendError("'frame_xpath' missing or invalid"); 1035 return; 1036 } 1037 const UserManager* user_manager = UserManager::Get(); 1038 if (!user_manager) { 1039 AutomationJSONReply(this, reply_message).SendError( 1040 "No user manager!"); 1041 return; 1042 } 1043 if (user_manager->IsUserLoggedIn()) { 1044 AutomationJSONReply(this, reply_message).SendError( 1045 "User is already logged in."); 1046 return; 1047 } 1048 ExistingUserController* controller = 1049 ExistingUserController::current_controller(); 1050 if (!controller) { 1051 AutomationJSONReply(this, reply_message).SendError( 1052 "Unable to access ExistingUserController"); 1053 return; 1054 } 1055 chromeos::LoginDisplayHostImpl* webui_host = 1056 static_cast<chromeos::LoginDisplayHostImpl*>( 1057 controller->login_display_host()); 1058 content::WebContents* web_contents = 1059 webui_host->GetOobeUI()->web_ui()->GetWebContents(); 1060 1061 new DomOperationMessageSender(this, reply_message, true); 1062 ExecuteJavascriptInRenderViewFrame(ASCIIToUTF16(frame_xpath), 1063 ASCIIToUTF16(javascript), 1064 reply_message, 1065 web_contents->GetRenderViewHost()); 1066 } 1067 1068 void TestingAutomationProvider::EnableSpokenFeedback( 1069 DictionaryValue* args, IPC::Message* reply_message) { 1070 AutomationJSONReply reply(this, reply_message); 1071 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 1072 bool enabled; 1073 if (!args->GetBoolean("enabled", &enabled)) { 1074 reply.SendError("Invalid or missing args."); 1075 return; 1076 } 1077 chromeos::AccessibilityManager::Get()->EnableSpokenFeedback( 1078 enabled, ash::A11Y_NOTIFICATION_NONE); 1079 1080 reply.SendSuccess(return_value.get()); 1081 } 1082 1083 void TestingAutomationProvider::IsSpokenFeedbackEnabled( 1084 DictionaryValue* args, IPC::Message* reply_message) { 1085 AutomationJSONReply reply(this, reply_message); 1086 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 1087 return_value->SetBoolean( 1088 "spoken_feedback", 1089 chromeos::AccessibilityManager::Get()->IsSpokenFeedbackEnabled()); 1090 reply.SendSuccess(return_value.get()); 1091 } 1092 1093 void TestingAutomationProvider::GetTimeInfo(Browser* browser, 1094 DictionaryValue* args, 1095 IPC::Message* reply_message) { 1096 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 1097 base::Time time(base::Time::Now()); 1098 bool use_24hour_clock = browser && browser->profile()->GetPrefs()->GetBoolean( 1099 prefs::kUse24HourClock); 1100 base::HourClockType hour_clock_type = 1101 use_24hour_clock ? base::k24HourClock : base::k12HourClock; 1102 string16 display_time = base::TimeFormatTimeOfDayWithHourClockType( 1103 time, hour_clock_type, base::kDropAmPm); 1104 string16 timezone = 1105 chromeos::system::TimezoneSettings::GetInstance()->GetCurrentTimezoneID(); 1106 return_value->SetString("display_time", display_time); 1107 return_value->SetString("display_date", base::TimeFormatFriendlyDate(time)); 1108 return_value->SetString("timezone", timezone); 1109 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get()); 1110 } 1111 1112 void TestingAutomationProvider::GetTimeInfo(DictionaryValue* args, 1113 IPC::Message* reply_message) { 1114 GetTimeInfo(NULL, args, reply_message); 1115 } 1116 1117 void TestingAutomationProvider::SetTimezone(DictionaryValue* args, 1118 IPC::Message* reply_message) { 1119 AutomationJSONReply reply(this, reply_message); 1120 std::string timezone_id; 1121 if (!args->GetString("timezone", &timezone_id)) { 1122 reply.SendError("Invalid or missing args."); 1123 return; 1124 } 1125 chromeos::CrosSettings* settings = chromeos::CrosSettings::Get(); 1126 settings->SetString(chromeos::kSystemTimezone, timezone_id); 1127 reply.SendSuccess(NULL); 1128 } 1129 1130 void TestingAutomationProvider::UpdateCheck( 1131 DictionaryValue* args, 1132 IPC::Message* reply_message) { 1133 AutomationJSONReply* reply = new AutomationJSONReply(this, reply_message); 1134 DBusThreadManager::Get()->GetUpdateEngineClient() 1135 ->RequestUpdateCheck(base::Bind(UpdateCheckCallback, reply)); 1136 } 1137 1138 void TestingAutomationProvider::GetVolumeInfo(DictionaryValue* args, 1139 IPC::Message* reply_message) { 1140 AutomationJSONReply reply(this, reply_message); 1141 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 1142 chromeos::CrasAudioHandler* audio_handler = chromeos::CrasAudioHandler::Get(); 1143 if (!audio_handler) { 1144 reply.SendError("CrasAudioHandler not initialized."); 1145 return; 1146 } 1147 return_value->SetDouble("volume", audio_handler->GetOutputVolumePercent()); 1148 return_value->SetBoolean("is_mute", audio_handler->IsOutputMuted()); 1149 reply.SendSuccess(return_value.get()); 1150 } 1151 1152 void TestingAutomationProvider::SetVolume(DictionaryValue* args, 1153 IPC::Message* reply_message) { 1154 AutomationJSONReply reply(this, reply_message); 1155 double volume_percent; 1156 if (!args->GetDouble("volume", &volume_percent)) { 1157 reply.SendError("Invalid or missing args."); 1158 return; 1159 } 1160 chromeos::CrasAudioHandler* audio_handler = chromeos::CrasAudioHandler::Get(); 1161 if (!audio_handler) { 1162 reply.SendError("CrasAudioHandler not initialized."); 1163 return; 1164 } 1165 audio_handler->SetOutputVolumePercent(volume_percent); 1166 reply.SendSuccess(NULL); 1167 } 1168 1169 void TestingAutomationProvider::SetMute(DictionaryValue* args, 1170 IPC::Message* reply_message) { 1171 AutomationJSONReply reply(this, reply_message); 1172 bool mute; 1173 if (!args->GetBoolean("mute", &mute)) { 1174 reply.SendError("Invalid or missing args."); 1175 return; 1176 } 1177 chromeos::CrasAudioHandler* audio_handler = chromeos::CrasAudioHandler::Get(); 1178 if (!audio_handler) { 1179 reply.SendError("CrasAudioHandler not initialized."); 1180 return; 1181 } 1182 audio_handler->SetOutputMute(mute); 1183 reply.SendSuccess(NULL); 1184 } 1185 1186 void TestingAutomationProvider::OpenCrosh(DictionaryValue* args, 1187 IPC::Message* reply_message) { 1188 new NavigationNotificationObserver( 1189 NULL, this, reply_message, 1, false, true); 1190 ash::Shell::GetInstance()->delegate()->OpenCrosh(); 1191 } 1192 1193 void TestingAutomationProvider::AddChromeosObservers() { 1194 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()-> 1195 AddObserver(this); 1196 } 1197 1198 void TestingAutomationProvider::RemoveChromeosObservers() { 1199 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()-> 1200 RemoveObserver(this); 1201 } 1202