Home | History | Annotate | Download | only in automation
      1 // Copyright (c) 2011 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 "base/values.h"
      8 #include "chrome/browser/automation/automation_provider_json.h"
      9 #include "chrome/browser/automation/automation_provider_observers.h"
     10 #include "chrome/browser/chromeos/cros/cros_library.h"
     11 #include "chrome/browser/chromeos/cros/network_library.h"
     12 #include "chrome/browser/chromeos/cros/power_library.h"
     13 #include "chrome/browser/chromeos/cros/screen_lock_library.h"
     14 #include "chrome/browser/chromeos/cros/update_library.h"
     15 #include "chrome/browser/chromeos/login/existing_user_controller.h"
     16 #include "chrome/browser/chromeos/login/screen_locker.h"
     17 #include "chrome/browser/chromeos/proxy_cros_settings_provider.h"
     18 
     19 using chromeos::CrosLibrary;
     20 using chromeos::NetworkLibrary;
     21 using chromeos::UserManager;
     22 using chromeos::UpdateLibrary;
     23 
     24 namespace {
     25 
     26 bool EnsureCrosLibraryLoaded(AutomationProvider* provider,
     27                              IPC::Message* reply_message) {
     28   if (!CrosLibrary::Get()->EnsureLoaded()) {
     29     AutomationJSONReply(provider, reply_message).SendError(
     30         "Could not load cros library.");
     31     return false;
     32   }
     33   return true;
     34 }
     35 
     36 DictionaryValue* GetNetworkInfoDict(const chromeos::Network* network) {
     37   DictionaryValue* item = new DictionaryValue;
     38   item->SetString("name", network->name());
     39   item->SetString("device_path", network->device_path());
     40   item->SetString("ip_address", network->ip_address());
     41   item->SetString("status", network->GetStateString());
     42   return item;
     43 }
     44 
     45 Value* GetProxySetting(const std::string& setting_name) {
     46   chromeos::ProxyCrosSettingsProvider settings_provider;
     47   std::string setting_path = "cros.session.proxy.";
     48   setting_path.append(setting_name);
     49 
     50   if (setting_name == "ignorelist") {
     51     Value* value;
     52     if (settings_provider.Get(setting_path, &value))
     53       return value;
     54   } else {
     55     Value* setting;
     56     if (settings_provider.Get(setting_path, &setting)) {
     57       DictionaryValue* setting_dict = static_cast<DictionaryValue*>(setting);
     58       Value* value;
     59       bool found = setting_dict->Remove("value", &value);
     60       delete setting;
     61       if (found)
     62         return value;
     63     }
     64   }
     65   return NULL;
     66 }
     67 
     68 const char* UpdateStatusToString(chromeos::UpdateStatusOperation status) {
     69   switch (status) {
     70     case chromeos::UPDATE_STATUS_IDLE:
     71       return "idle";
     72     case chromeos::UPDATE_STATUS_CHECKING_FOR_UPDATE:
     73       return "checking for update";
     74     case chromeos::UPDATE_STATUS_UPDATE_AVAILABLE:
     75       return "update available";
     76     case chromeos::UPDATE_STATUS_DOWNLOADING:
     77       return "downloading";
     78     case chromeos::UPDATE_STATUS_VERIFYING:
     79       return "verifying";
     80     case chromeos::UPDATE_STATUS_FINALIZING:
     81       return "finalizing";
     82     case chromeos::UPDATE_STATUS_UPDATED_NEED_REBOOT:
     83       return "updated need reboot";
     84     case chromeos::UPDATE_STATUS_REPORTING_ERROR_EVENT:
     85       return "reporting error event";
     86     default:
     87       return "unknown";
     88   }
     89 }
     90 
     91 void GetReleaseTrackCallback(void* user_data, const char* track) {
     92   AutomationJSONReply* reply = static_cast<AutomationJSONReply*>(user_data);
     93 
     94   if (track == NULL) {
     95     reply->SendError("Unable to get release track.");
     96     delete reply;
     97     return;
     98   }
     99 
    100   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
    101   return_value->SetString("release_track", track);
    102 
    103   UpdateLibrary* update_library = CrosLibrary::Get()->GetUpdateLibrary();
    104   const UpdateLibrary::Status& status = update_library->status();
    105   chromeos::UpdateStatusOperation update_status = status.status;
    106   return_value->SetString("status", UpdateStatusToString(update_status));
    107   if (update_status == chromeos::UPDATE_STATUS_DOWNLOADING)
    108     return_value->SetDouble("download_progress", status.download_progress);
    109   if (status.last_checked_time > 0)
    110     return_value->SetInteger("last_checked_time", status.last_checked_time);
    111   if (status.new_size > 0)
    112     return_value->SetInteger("new_size", status.new_size);
    113 
    114   reply->SendSuccess(return_value.get());
    115   delete reply;
    116 }
    117 
    118 void UpdateCheckCallback(void* user_data, chromeos::UpdateResult result,
    119                          const char* error_msg) {
    120   AutomationJSONReply* reply = static_cast<AutomationJSONReply*>(user_data);
    121   if (result == chromeos::UPDATE_RESULT_SUCCESS)
    122     reply->SendSuccess(NULL);
    123   else
    124     reply->SendError(error_msg);
    125   delete reply;
    126 }
    127 
    128 }  // namespace
    129 
    130 void TestingAutomationProvider::GetLoginInfo(DictionaryValue* args,
    131                                              IPC::Message* reply_message) {
    132   AutomationJSONReply reply(this, reply_message);
    133   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
    134 
    135   const UserManager* user_manager = UserManager::Get();
    136   if (!user_manager)
    137     reply.SendError("No user manager!");
    138   const chromeos::ScreenLocker* screen_locker =
    139       chromeos::ScreenLocker::default_screen_locker();
    140 
    141   return_value->SetBoolean("is_owner", user_manager->current_user_is_owner());
    142   return_value->SetBoolean("is_logged_in", user_manager->user_is_logged_in());
    143   return_value->SetBoolean("is_screen_locked", screen_locker);
    144   if (user_manager->user_is_logged_in()) {
    145     return_value->SetBoolean("is_guest", user_manager->IsLoggedInAsGuest());
    146     return_value->SetString("email", user_manager->logged_in_user().email());
    147   }
    148 
    149   reply.SendSuccess(return_value.get());
    150 }
    151 
    152 // Logging in as guest will cause session_manager to restart Chrome with new
    153 // flags. If you used EnableChromeTesting, you will have to call it again.
    154 void TestingAutomationProvider::LoginAsGuest(DictionaryValue* args,
    155                                              IPC::Message* reply_message) {
    156   chromeos::ExistingUserController* controller =
    157       chromeos::ExistingUserController::current_controller();
    158   // Set up an observer (it will delete itself).
    159   new LoginManagerObserver(this, reply_message);
    160   controller->LoginAsGuest();
    161 }
    162 
    163 void TestingAutomationProvider::Login(DictionaryValue* args,
    164                                       IPC::Message* reply_message) {
    165   std::string username, password;
    166   if (!args->GetString("username", &username) ||
    167       !args->GetString("password", &password)) {
    168     AutomationJSONReply(this, reply_message).SendError(
    169         "Invalid or missing args.");
    170     return;
    171   }
    172 
    173   chromeos::ExistingUserController* controller =
    174       chromeos::ExistingUserController::current_controller();
    175   // Set up an observer (it will delete itself).
    176   new LoginManagerObserver(this, reply_message);
    177   controller->Login(username, password);
    178 }
    179 
    180 void TestingAutomationProvider::LockScreen(DictionaryValue* args,
    181                                            IPC::Message* reply_message) {
    182   if (!EnsureCrosLibraryLoaded(this, reply_message))
    183     return;
    184 
    185   new ScreenLockUnlockObserver(this, reply_message, true);
    186   CrosLibrary::Get()->GetScreenLockLibrary()->
    187       NotifyScreenLockRequested();
    188 }
    189 
    190 void TestingAutomationProvider::UnlockScreen(DictionaryValue* args,
    191                                              IPC::Message* reply_message) {
    192   if (!EnsureCrosLibraryLoaded(this, reply_message))
    193     return;
    194 
    195   new ScreenLockUnlockObserver(this, reply_message, false);
    196   CrosLibrary::Get()->GetScreenLockLibrary()->
    197       NotifyScreenUnlockRequested();
    198 }
    199 
    200 // Signing out could have undesirable side effects: session_manager is
    201 // killed, so its children, including chrome and the window manager, will
    202 // also be killed. Anything owned by chronos will probably be killed.
    203 void TestingAutomationProvider::SignoutInScreenLocker(
    204     DictionaryValue* args, IPC::Message* reply_message) {
    205   AutomationJSONReply reply(this, reply_message);
    206   chromeos::ScreenLocker* screen_locker =
    207       chromeos::ScreenLocker::default_screen_locker();
    208   if (!screen_locker) {
    209     reply.SendError(
    210         "No default screen locker. Are you sure the screen is locked?");
    211     return;
    212   }
    213 
    214   // Send success before stopping session because if we're a child of
    215   // session manager then we'll die when the session is stopped.
    216   reply.SendSuccess(NULL);
    217   screen_locker->Signout();
    218 }
    219 
    220 void TestingAutomationProvider::GetBatteryInfo(DictionaryValue* args,
    221                                                IPC::Message* reply_message) {
    222   if (!EnsureCrosLibraryLoaded(this, reply_message))
    223     return;
    224 
    225   chromeos::PowerLibrary* power_library = CrosLibrary::Get()->GetPowerLibrary();
    226   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
    227 
    228   return_value->SetBoolean("battery_is_present",
    229                            power_library->battery_is_present());
    230   return_value->SetBoolean("line_power_on", power_library->line_power_on());
    231   if (power_library->battery_is_present()) {
    232     return_value->SetBoolean("battery_fully_charged",
    233                              power_library->battery_fully_charged());
    234     return_value->SetDouble("battery_percentage",
    235                             power_library->battery_percentage());
    236     if (power_library->line_power_on()) {
    237       int time = power_library->battery_time_to_full().InSeconds();
    238       if (time > 0 || power_library->battery_fully_charged())
    239         return_value->SetInteger("battery_time_to_full", time);
    240     } else {
    241       int time = power_library->battery_time_to_empty().InSeconds();
    242       if (time > 0)
    243         return_value->SetInteger("battery_time_to_empty", time);
    244     }
    245   }
    246 
    247   AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
    248 }
    249 
    250 void TestingAutomationProvider::GetNetworkInfo(DictionaryValue* args,
    251                                                IPC::Message* reply_message) {
    252   if (!EnsureCrosLibraryLoaded(this, reply_message))
    253     return;
    254 
    255   NetworkLibrary* network_library = CrosLibrary::Get()->GetNetworkLibrary();
    256   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
    257 
    258   // IP address.
    259   return_value->SetString("ip_address", network_library->IPAddress());
    260 
    261   // Currently connected networks.
    262   if (network_library->ethernet_network())
    263     return_value->SetString(
    264         "connected_ethernet",
    265         network_library->ethernet_network()->service_path());
    266   if (network_library->wifi_network())
    267     return_value->SetString("connected_wifi",
    268                             network_library->wifi_network()->service_path());
    269   if (network_library->cellular_network())
    270     return_value->SetString(
    271         "connected_cellular",
    272         network_library->cellular_network()->service_path());
    273 
    274   // Ethernet network.
    275   bool ethernet_available = network_library->ethernet_available();
    276   bool ethernet_enabled = network_library->ethernet_enabled();
    277   if (ethernet_available && ethernet_enabled) {
    278     const chromeos::EthernetNetwork* ethernet_network =
    279         network_library->ethernet_network();
    280     if (ethernet_network) {
    281       DictionaryValue* items = new DictionaryValue;
    282       DictionaryValue* item = GetNetworkInfoDict(ethernet_network);
    283       items->Set(ethernet_network->service_path(), item);
    284       return_value->Set("ethernet_networks", items);
    285     }
    286   }
    287 
    288   // Wi-fi networks.
    289   bool wifi_available = network_library->wifi_available();
    290   bool wifi_enabled = network_library->wifi_enabled();
    291   if (wifi_available && wifi_enabled) {
    292     const chromeos::WifiNetworkVector& wifi_networks =
    293         network_library->wifi_networks();
    294     DictionaryValue* items = new DictionaryValue;
    295     for (chromeos::WifiNetworkVector::const_iterator iter =
    296          wifi_networks.begin(); iter != wifi_networks.end(); ++iter) {
    297       const chromeos::WifiNetwork* wifi = *iter;
    298       DictionaryValue* item = GetNetworkInfoDict(wifi);
    299       item->SetInteger("strength", wifi->strength());
    300       item->SetBoolean("encrypted", wifi->encrypted());
    301       item->SetString("encryption", wifi->GetEncryptionString());
    302       items->Set(wifi->service_path(), item);
    303     }
    304     return_value->Set("wifi_networks", items);
    305   }
    306 
    307   // Cellular networks.
    308   bool cellular_available = network_library->cellular_available();
    309   bool cellular_enabled = network_library->cellular_enabled();
    310   if (cellular_available && cellular_enabled) {
    311     const chromeos::CellularNetworkVector& cellular_networks =
    312         network_library->cellular_networks();
    313     DictionaryValue* items = new DictionaryValue;
    314     for (size_t i = 0; i < cellular_networks.size(); ++i) {
    315       DictionaryValue* item = GetNetworkInfoDict(cellular_networks[i]);
    316       item->SetInteger("strength", cellular_networks[i]->strength());
    317       item->SetString("operator_name", cellular_networks[i]->operator_name());
    318       item->SetString("operator_code", cellular_networks[i]->operator_code());
    319       item->SetString("payment_url", cellular_networks[i]->payment_url());
    320       item->SetString("usage_url", cellular_networks[i]->usage_url());
    321       item->SetString("network_technology",
    322                       cellular_networks[i]->GetNetworkTechnologyString());
    323       item->SetString("connectivity_state",
    324                       cellular_networks[i]->GetConnectivityStateString());
    325       item->SetString("activation_state",
    326                       cellular_networks[i]->GetActivationStateString());
    327       item->SetString("roaming_state",
    328                       cellular_networks[i]->GetRoamingStateString());
    329       items->Set(cellular_networks[i]->service_path(), item);
    330     }
    331     return_value->Set("cellular_networks", items);
    332   }
    333 
    334   AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
    335 }
    336 
    337 void TestingAutomationProvider::NetworkScan(DictionaryValue* args,
    338                                             IPC::Message* reply_message) {
    339   if (!EnsureCrosLibraryLoaded(this, reply_message))
    340     return;
    341 
    342   NetworkLibrary* network_library = CrosLibrary::Get()->GetNetworkLibrary();
    343   network_library->RequestNetworkScan();
    344 
    345   // Set up an observer (it will delete itself).
    346   new NetworkScanObserver(this, reply_message);
    347 }
    348 
    349 void TestingAutomationProvider::GetProxySettings(DictionaryValue* args,
    350                                                  IPC::Message* reply_message) {
    351   const char* settings[] = { "pacurl", "singlehttp", "singlehttpport",
    352                              "httpurl", "httpport", "httpsurl", "httpsport",
    353                              "type", "single", "ftpurl", "ftpport",
    354                              "socks", "socksport", "ignorelist" };
    355 
    356   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
    357   chromeos::ProxyCrosSettingsProvider settings_provider;
    358 
    359   for (size_t i = 0; i < arraysize(settings); ++i) {
    360     Value* setting = GetProxySetting(settings[i]);
    361     if (setting)
    362       return_value->Set(settings[i], setting);
    363   }
    364 
    365   AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
    366 }
    367 
    368 void TestingAutomationProvider::SetProxySettings(DictionaryValue* args,
    369                                                 IPC::Message* reply_message) {
    370   AutomationJSONReply reply(this, reply_message);
    371   std::string key;
    372   Value* value;
    373   if (!args->GetString("key", &key) || !args->Get("value", &value)) {
    374     reply.SendError("Invalid or missing args.");
    375     return;
    376   }
    377 
    378   std::string setting_path = "cros.session.proxy.";
    379   setting_path.append(key);
    380 
    381   // ProxyCrosSettingsProvider will own the Value* passed to Set().
    382   chromeos::ProxyCrosSettingsProvider().Set(setting_path, value->DeepCopy());
    383   reply.SendSuccess(NULL);
    384 }
    385 
    386 void TestingAutomationProvider::ConnectToWifiNetwork(
    387     DictionaryValue* args, IPC::Message* reply_message) {
    388   if (!EnsureCrosLibraryLoaded(this, reply_message))
    389     return;
    390 
    391   AutomationJSONReply reply(this, reply_message);
    392   std::string service_path, password, identity, certpath;
    393   if (!args->GetString("service_path", &service_path) ||
    394       !args->GetString("password", &password) ||
    395       !args->GetString("identity", &identity) ||
    396       !args->GetString("certpath", &certpath)) {
    397     reply.SendError("Invalid or missing args.");
    398     return;
    399   }
    400 
    401   NetworkLibrary* network_library = CrosLibrary::Get()->GetNetworkLibrary();
    402   chromeos::WifiNetwork* wifi =
    403       network_library->FindWifiNetworkByPath(service_path);
    404   if (!wifi) {
    405     reply.SendError("No network found with specified service path.");
    406     return;
    407   }
    408   if (!password.empty())
    409     wifi->SetPassphrase(password);
    410   if (!identity.empty())
    411     wifi->SetIdentity(identity);
    412   if (!certpath.empty())
    413     wifi->SetCertPath(certpath);
    414 
    415   // Set up an observer (it will delete itself).
    416   new ServicePathConnectObserver(this, reply_message, service_path);
    417 
    418   network_library->ConnectToWifiNetwork(wifi);
    419   network_library->RequestNetworkScan();
    420 }
    421 
    422 void TestingAutomationProvider::ConnectToHiddenWifiNetwork(
    423     DictionaryValue* args, IPC::Message* reply_message) {
    424   if (!CrosLibrary::Get()->EnsureLoaded()) {
    425     AutomationJSONReply(this, reply_message)
    426         .SendError("Could not load cros library.");
    427     return;
    428   }
    429 
    430   std::string ssid, security, password, identity, certpath;
    431   if (!args->GetString("ssid", &ssid) ||
    432       !args->GetString("security", &security) ||
    433       !args->GetString("password", &password) ||
    434       !args->GetString("identity", &identity) ||
    435       !args->GetString("certpath", &certpath)) {
    436     AutomationJSONReply(this, reply_message)
    437         .SendError("Invalid or missing args.");
    438     return;
    439   }
    440 
    441   std::map<std::string, chromeos::ConnectionSecurity> connection_security_map;
    442   connection_security_map["SECURITY_NONE"] = chromeos::SECURITY_NONE;
    443   connection_security_map["SECURITY_WEP"] = chromeos::SECURITY_WEP;
    444   connection_security_map["SECURITY_WPA"] = chromeos::SECURITY_WPA;
    445   connection_security_map["SECURITY_RSN"] = chromeos::SECURITY_RSN;
    446   connection_security_map["SECURITY_8021X"] = chromeos::SECURITY_8021X;
    447 
    448   if (connection_security_map.find(security) == connection_security_map.end()) {
    449     AutomationJSONReply(this, reply_message)
    450         .SendError("Unknown security type.");
    451     return;
    452   }
    453   chromeos::ConnectionSecurity connection_security =
    454       connection_security_map[security];
    455 
    456   NetworkLibrary* network_library = CrosLibrary::Get()->GetNetworkLibrary();
    457 
    458   // Set up an observer (it will delete itself).
    459   new SSIDConnectObserver(this, reply_message, ssid);
    460 
    461   network_library->ConnectToWifiNetwork(connection_security, ssid, password,
    462                                         identity, certpath);
    463 }
    464 
    465 void TestingAutomationProvider::DisconnectFromWifiNetwork(
    466     DictionaryValue* args, IPC::Message* reply_message) {
    467   if (!EnsureCrosLibraryLoaded(this, reply_message))
    468     return;
    469 
    470   AutomationJSONReply reply(this, reply_message);
    471   NetworkLibrary* network_library = CrosLibrary::Get()->GetNetworkLibrary();
    472   const chromeos::WifiNetwork* wifi = network_library->wifi_network();
    473   if (!wifi) {
    474     reply.SendError("Not connected to any wifi network.");
    475     return;
    476   }
    477 
    478   network_library->DisconnectFromNetwork(wifi);
    479   reply.SendSuccess(NULL);
    480 }
    481 
    482 void TestingAutomationProvider::GetUpdateInfo(DictionaryValue* args,
    483                                               IPC::Message* reply_message) {
    484   if (!EnsureCrosLibraryLoaded(this, reply_message))
    485     return;
    486 
    487   UpdateLibrary* update_library = CrosLibrary::Get()->GetUpdateLibrary();
    488   AutomationJSONReply* reply = new AutomationJSONReply(this, reply_message);
    489   update_library->GetReleaseTrack(GetReleaseTrackCallback, reply);
    490 }
    491 
    492 void TestingAutomationProvider::UpdateCheck(
    493     DictionaryValue* args,
    494     IPC::Message* reply_message) {
    495   if (!EnsureCrosLibraryLoaded(this, reply_message))
    496     return;
    497 
    498   UpdateLibrary* update_library = CrosLibrary::Get()->GetUpdateLibrary();
    499   AutomationJSONReply* reply = new AutomationJSONReply(this, reply_message);
    500   update_library->RequestUpdateCheck(UpdateCheckCallback, reply);
    501 }
    502 
    503 void TestingAutomationProvider::SetReleaseTrack(DictionaryValue* args,
    504                                                 IPC::Message* reply_message) {
    505   if (!EnsureCrosLibraryLoaded(this, reply_message))
    506     return;
    507 
    508   AutomationJSONReply reply(this, reply_message);
    509   std::string track;
    510   if (!args->GetString("track", &track)) {
    511     reply.SendError("Invalid or missing args.");
    512     return;
    513   }
    514 
    515   UpdateLibrary* update_library = CrosLibrary::Get()->GetUpdateLibrary();
    516   update_library->SetReleaseTrack(track);
    517   reply.SendSuccess(NULL);
    518 }
    519