Home | History | Annotate | Download | only in automation
      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