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/automation_provider_observers.h" 6 7 #include "base/values.h" 8 #include "chrome/browser/automation/automation_provider.h" 9 #include "chrome/browser/chrome_notification_types.h" 10 #include "chrome/browser/chromeos/login/authentication_notification_details.h" 11 #include "chrome/browser/chromeos/login/enrollment/enrollment_screen_actor.h" 12 #include "chrome/browser/chromeos/login/existing_user_controller.h" 13 #include "chrome/browser/chromeos/login/screen_locker.h" 14 #include "chrome/browser/chromeos/login/screens/wizard_screen.h" 15 #include "chrome/browser/chromeos/login/user_image.h" 16 #include "chrome/browser/chromeos/login/user_image_manager.h" 17 #include "chrome/browser/chromeos/login/user_manager.h" 18 #include "chrome/browser/chromeos/login/wizard_controller.h" 19 #include "content/public/browser/notification_service.h" 20 21 using chromeos::NetworkLibrary; 22 using chromeos::WizardController; 23 24 namespace { 25 26 // Fake screen name for the user session (reported by WizardControllerObserver). 27 const char kSessionScreenName[] = "session"; 28 29 } 30 31 NetworkManagerInitObserver::NetworkManagerInitObserver( 32 AutomationProvider* automation) 33 : automation_(automation->AsWeakPtr()) { 34 } 35 36 NetworkManagerInitObserver::~NetworkManagerInitObserver() { 37 NetworkLibrary::Get()->RemoveNetworkManagerObserver(this); 38 } 39 40 bool NetworkManagerInitObserver::Init() { 41 if (!NetworkLibrary::Get()->IsCros()) { 42 // If the network library is not the production version, don't wait for 43 // the network library to finish initializing, because it'll wait 44 // forever. 45 automation_->OnNetworkLibraryInit(); 46 return false; 47 } 48 49 NetworkLibrary::Get()->AddNetworkManagerObserver(this); 50 return true; 51 } 52 53 void NetworkManagerInitObserver::OnNetworkManagerChanged(NetworkLibrary* obj) { 54 if (!obj->wifi_scanning()) { 55 if (automation_) 56 automation_->OnNetworkLibraryInit(); 57 delete this; 58 } 59 } 60 61 OOBEWebuiReadyObserver::OOBEWebuiReadyObserver(AutomationProvider* automation) 62 : automation_(automation->AsWeakPtr()) { 63 if (WizardController::default_controller() && 64 WizardController::default_controller()->current_screen()) { 65 OOBEWebuiReady(); 66 } else { 67 registrar_.Add(this, chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, 68 content::NotificationService::AllSources()); 69 } 70 } 71 72 void OOBEWebuiReadyObserver::Observe( 73 int type, 74 const content::NotificationSource& source, 75 const content::NotificationDetails& details) { 76 DCHECK(type == chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE); 77 OOBEWebuiReady(); 78 } 79 80 void OOBEWebuiReadyObserver::OOBEWebuiReady() { 81 if (automation_) 82 automation_->OnOOBEWebuiReady(); 83 delete this; 84 } 85 86 LoginObserver::LoginObserver(chromeos::ExistingUserController* controller, 87 AutomationProvider* automation, 88 IPC::Message* reply_message) 89 : controller_(controller), 90 automation_(automation->AsWeakPtr()), 91 reply_message_(reply_message) { 92 controller_->set_login_status_consumer(this); 93 } 94 95 LoginObserver::~LoginObserver() { 96 controller_->set_login_status_consumer(NULL); 97 } 98 99 void LoginObserver::OnLoginFailure(const chromeos::LoginFailure& error) { 100 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 101 return_value->SetString("error_string", error.GetErrorString()); 102 AutomationJSONReply(automation_.get(), reply_message_.release()) 103 .SendSuccess(return_value.get()); 104 delete this; 105 } 106 107 void LoginObserver::OnLoginSuccess( 108 const chromeos::UserContext& user_context, 109 bool pending_requests, 110 bool using_oauth) { 111 controller_->set_login_status_consumer(NULL); 112 AutomationJSONReply(automation_.get(), reply_message_.release()) 113 .SendSuccess(NULL); 114 delete this; 115 } 116 117 WizardControllerObserver::WizardControllerObserver( 118 WizardController* wizard_controller, 119 AutomationProvider* automation, 120 IPC::Message* reply_message) 121 : wizard_controller_(wizard_controller), 122 automation_(automation->AsWeakPtr()), 123 reply_message_(reply_message) { 124 wizard_controller_->AddObserver(this); 125 registrar_.Add(this, chrome::NOTIFICATION_LOGIN_WEBUI_LOADED, 126 content::NotificationService::AllSources()); 127 } 128 129 WizardControllerObserver::~WizardControllerObserver() { 130 wizard_controller_->RemoveObserver(this); 131 } 132 133 void WizardControllerObserver::OnScreenChanged( 134 chromeos::WizardScreen* next_screen) { 135 std::string screen_name = next_screen->GetName(); 136 if (screen_to_wait_for_.empty() || screen_to_wait_for_ == screen_name) { 137 SendReply(screen_name); 138 } else { 139 DVLOG(2) << "Still waiting for " << screen_to_wait_for_; 140 } 141 } 142 143 void WizardControllerObserver::OnSessionStart() { 144 SendReply(kSessionScreenName); 145 } 146 147 void WizardControllerObserver::Observe( 148 int type, 149 const content::NotificationSource& source, 150 const content::NotificationDetails& details) { 151 DCHECK(type == chrome::NOTIFICATION_LOGIN_WEBUI_LOADED); 152 SendReply(WizardController::kLoginScreenName); 153 } 154 155 void WizardControllerObserver::SendReply(const std::string& screen_name) { 156 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 157 return_value->SetString("next_screen", screen_name); 158 AutomationJSONReply(automation_.get(), reply_message_.release()) 159 .SendSuccess(return_value.get()); 160 delete this; 161 } 162 163 ScreenLockUnlockObserver::ScreenLockUnlockObserver( 164 AutomationProvider* automation, 165 IPC::Message* reply_message, 166 bool lock_screen) 167 : automation_(automation->AsWeakPtr()), 168 reply_message_(reply_message), 169 lock_screen_(lock_screen) { 170 registrar_.Add(this, chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED, 171 content::NotificationService::AllSources()); 172 } 173 174 ScreenLockUnlockObserver::~ScreenLockUnlockObserver() {} 175 176 void ScreenLockUnlockObserver::Observe( 177 int type, 178 const content::NotificationSource& source, 179 const content::NotificationDetails& details) { 180 DCHECK(type == chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED); 181 if (automation_) { 182 AutomationJSONReply reply(automation_.get(), reply_message_.release()); 183 bool is_screen_locked = *content::Details<bool>(details).ptr(); 184 if (lock_screen_ == is_screen_locked) 185 reply.SendSuccess(NULL); 186 else 187 reply.SendError("Screen lock failure."); 188 } 189 delete this; 190 } 191 192 ScreenUnlockObserver::ScreenUnlockObserver(AutomationProvider* automation, 193 IPC::Message* reply_message) 194 : ScreenLockUnlockObserver(automation, reply_message, false) { 195 chromeos::ScreenLocker::default_screen_locker()->SetLoginStatusConsumer(this); 196 } 197 198 ScreenUnlockObserver::~ScreenUnlockObserver() { 199 chromeos::ScreenLocker* screen_locker = 200 chromeos::ScreenLocker::default_screen_locker(); 201 if (screen_locker) 202 screen_locker->SetLoginStatusConsumer(NULL); 203 } 204 205 void ScreenUnlockObserver::OnLoginFailure(const chromeos::LoginFailure& error) { 206 if (automation_) { 207 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 208 return_value->SetString("error_string", error.GetErrorString()); 209 AutomationJSONReply(automation_.get(), reply_message_.release()) 210 .SendSuccess(return_value.get()); 211 } 212 delete this; 213 } 214 215 NetworkScanObserver::NetworkScanObserver(AutomationProvider* automation, 216 IPC::Message* reply_message) 217 : automation_(automation->AsWeakPtr()), reply_message_(reply_message) { 218 NetworkLibrary* network_library = NetworkLibrary::Get(); 219 network_library->AddNetworkManagerObserver(this); 220 } 221 222 NetworkScanObserver::~NetworkScanObserver() { 223 NetworkLibrary* network_library = NetworkLibrary::Get(); 224 network_library->RemoveNetworkManagerObserver(this); 225 } 226 227 void NetworkScanObserver::OnNetworkManagerChanged(NetworkLibrary* obj) { 228 if (obj->wifi_scanning()) 229 return; 230 231 if (automation_) { 232 AutomationJSONReply(automation_.get(), reply_message_.release()) 233 .SendSuccess(NULL); 234 } 235 delete this; 236 } 237 238 ToggleNetworkDeviceObserver::ToggleNetworkDeviceObserver( 239 AutomationProvider* automation, IPC::Message* reply_message, 240 const std::string& device, bool enable) 241 : automation_(automation->AsWeakPtr()), reply_message_(reply_message), 242 device_(device), enable_(enable) { 243 NetworkLibrary* network_library = NetworkLibrary::Get(); 244 network_library->AddNetworkManagerObserver(this); 245 } 246 247 ToggleNetworkDeviceObserver::~ToggleNetworkDeviceObserver() { 248 NetworkLibrary* network_library = NetworkLibrary::Get(); 249 network_library->RemoveNetworkManagerObserver(this); 250 } 251 252 void ToggleNetworkDeviceObserver::OnNetworkManagerChanged(NetworkLibrary* obj) { 253 if ((device_ == "ethernet" && enable_ == obj->ethernet_enabled()) || 254 (device_ == "wifi" && enable_ == obj->wifi_enabled()) || 255 (device_ == "cellular" && enable_ == obj->cellular_enabled())) { 256 if (automation_) { 257 AutomationJSONReply(automation_.get(), reply_message_.release()) 258 .SendSuccess(NULL); 259 } 260 delete this; 261 } 262 } 263 264 NetworkStatusObserver::NetworkStatusObserver(AutomationProvider* automation, 265 IPC::Message* reply_message) 266 : automation_(automation->AsWeakPtr()), reply_message_(reply_message) { 267 NetworkLibrary* network_library = NetworkLibrary::Get(); 268 network_library->AddNetworkManagerObserver(this); 269 } 270 271 NetworkStatusObserver::~NetworkStatusObserver() { 272 NetworkLibrary* network_library = NetworkLibrary::Get(); 273 network_library->RemoveNetworkManagerObserver(this); 274 } 275 276 void NetworkStatusObserver::OnNetworkManagerChanged(NetworkLibrary* obj) { 277 const chromeos::Network* network = GetNetwork(obj); 278 if (!network) { 279 // The network was not found, and we assume it no longer exists. 280 // This could be because the ssid is invalid, or the network went away. 281 if (automation_) { 282 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 283 return_value->SetString("error_string", "Network not found."); 284 AutomationJSONReply(automation_.get(), reply_message_.release()) 285 .SendSuccess(return_value.get()); 286 } 287 delete this; 288 return; 289 } 290 291 NetworkStatusCheck(network); 292 } 293 294 NetworkConnectObserver::NetworkConnectObserver( 295 AutomationProvider* automation, IPC::Message* reply_message) 296 : NetworkStatusObserver(automation, reply_message) {} 297 298 void NetworkConnectObserver::NetworkStatusCheck(const chromeos::Network* 299 network) { 300 if (network->failed()) { 301 if (automation_) { 302 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 303 return_value->SetString("error_string", network->GetErrorString()); 304 AutomationJSONReply(automation_.get(), reply_message_.release()) 305 .SendSuccess(return_value.get()); 306 } 307 delete this; 308 } else if (network->connected()) { 309 if (automation_) { 310 AutomationJSONReply(automation_.get(), reply_message_.release()) 311 .SendSuccess(NULL); 312 } 313 delete this; 314 } 315 316 // The network is in the NetworkLibrary's list, but there's no failure or 317 // success condition, so just continue waiting for more network events. 318 } 319 320 NetworkDisconnectObserver::NetworkDisconnectObserver( 321 AutomationProvider* automation, IPC::Message* reply_message, 322 const std::string& service_path) 323 : NetworkStatusObserver(automation, reply_message), 324 service_path_(service_path) {} 325 326 void NetworkDisconnectObserver::NetworkStatusCheck(const chromeos::Network* 327 network) { 328 if (!network->connected()) { 329 AutomationJSONReply(automation_.get(), reply_message_.release()) 330 .SendSuccess(NULL); 331 delete this; 332 } 333 } 334 335 const chromeos::Network* NetworkDisconnectObserver::GetNetwork( 336 NetworkLibrary* network_library) { 337 return network_library->FindNetworkByPath(service_path_); 338 } 339 340 ServicePathConnectObserver::ServicePathConnectObserver( 341 AutomationProvider* automation, IPC::Message* reply_message, 342 const std::string& service_path) 343 : NetworkConnectObserver(automation, reply_message), 344 service_path_(service_path) {} 345 346 const chromeos::Network* ServicePathConnectObserver::GetNetwork( 347 NetworkLibrary* network_library) { 348 return network_library->FindNetworkByPath(service_path_); 349 } 350 351 SSIDConnectObserver::SSIDConnectObserver( 352 AutomationProvider* automation, IPC::Message* reply_message, 353 const std::string& ssid) 354 : NetworkConnectObserver(automation, reply_message), ssid_(ssid) {} 355 356 const chromeos::Network* SSIDConnectObserver::GetNetwork( 357 NetworkLibrary* network_library) { 358 const chromeos::WifiNetworkVector& wifi_networks = 359 network_library->wifi_networks(); 360 for (chromeos::WifiNetworkVector::const_iterator iter = wifi_networks.begin(); 361 iter != wifi_networks.end(); ++iter) { 362 const chromeos::WifiNetwork* wifi = *iter; 363 if (wifi->name() == ssid_) 364 return wifi; 365 } 366 return NULL; 367 } 368 369 VirtualConnectObserver::VirtualConnectObserver(AutomationProvider* automation, 370 IPC::Message* reply_message, 371 const std::string& service_name) 372 : automation_(automation->AsWeakPtr()), 373 reply_message_(reply_message), 374 service_name_(service_name) { 375 NetworkLibrary* network_library = NetworkLibrary::Get(); 376 network_library->AddNetworkManagerObserver(this); 377 } 378 379 VirtualConnectObserver::~VirtualConnectObserver() { 380 NetworkLibrary* network_library = NetworkLibrary::Get(); 381 network_library->RemoveNetworkManagerObserver(this); 382 } 383 384 void VirtualConnectObserver::OnNetworkManagerChanged(NetworkLibrary* cros) { 385 const chromeos::VirtualNetwork* virt = GetVirtualNetwork(cros); 386 if (!virt) { 387 // The network hasn't been added to the NetworkLibrary's list yet, 388 // just continue waiting for more network events. 389 return; 390 } 391 392 if (virt->failed()) { 393 if (automation_) { 394 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 395 return_value->SetString("error_string", virt->GetErrorString()); 396 AutomationJSONReply(automation_.get(), reply_message_.release()) 397 .SendSuccess(return_value.get()); 398 } 399 delete this; 400 } else if (virt->connected()) { 401 if (automation_) { 402 AutomationJSONReply(automation_.get(), reply_message_.release()) 403 .SendSuccess(NULL); 404 } 405 delete this; 406 } 407 // The network is in the NetworkLibrary's list, but there's no failure or 408 // success condition, so just continue waiting for more network events. 409 } 410 411 chromeos::VirtualNetwork* VirtualConnectObserver::GetVirtualNetwork( 412 const chromeos::NetworkLibrary* cros) { 413 chromeos::VirtualNetwork* virt = NULL; 414 const chromeos::VirtualNetworkVector& virtual_networks = 415 cros->virtual_networks(); 416 417 for (chromeos::VirtualNetworkVector::const_iterator iter = 418 virtual_networks.begin(); iter != virtual_networks.end(); ++iter) { 419 chromeos::VirtualNetwork* v = *iter; 420 if (v->name() == service_name_) { 421 virt = v; 422 break; 423 } 424 } 425 return virt; 426 } 427