1 // Copyright 2013 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 "chromeos/dbus/fake_shill_manager_client.h" 6 7 #include "base/bind.h" 8 #include "base/command_line.h" 9 #include "base/message_loop/message_loop.h" 10 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/string_split.h" 12 #include "base/strings/string_util.h" 13 #include "base/values.h" 14 #include "chromeos/chromeos_switches.h" 15 #include "chromeos/dbus/dbus_thread_manager.h" 16 #include "chromeos/dbus/shill_device_client.h" 17 #include "chromeos/dbus/shill_ipconfig_client.h" 18 #include "chromeos/dbus/shill_profile_client.h" 19 #include "chromeos/dbus/shill_property_changed_observer.h" 20 #include "chromeos/dbus/shill_service_client.h" 21 #include "dbus/bus.h" 22 #include "dbus/message.h" 23 #include "dbus/object_path.h" 24 #include "dbus/values_util.h" 25 #include "third_party/cros_system_api/dbus/service_constants.h" 26 27 namespace chromeos { 28 29 namespace { 30 31 // Used to compare values for finding entries to erase in a ListValue. 32 // (ListValue only implements a const_iterator version of Find). 33 struct ValueEquals { 34 explicit ValueEquals(const base::Value* first) : first_(first) {} 35 bool operator()(const base::Value* second) const { 36 return first_->Equals(second); 37 } 38 const base::Value* first_; 39 }; 40 41 // Appends string entries from |service_list_in| whose entries in ServiceClient 42 // have Type |match_type| to one of the output lists based on the entry's State. 43 void AppendServicesForType( 44 const base::ListValue* service_list_in, 45 const char* match_type, 46 bool technology_enabled, 47 std::vector<std::string>* active_service_list_out, 48 std::vector<std::string>* inactive_service_list_out, 49 std::vector<std::string>* disabled_service_list_out) { 50 ShillServiceClient::TestInterface* service_client = 51 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface(); 52 for (base::ListValue::const_iterator iter = service_list_in->begin(); 53 iter != service_list_in->end(); ++iter) { 54 std::string service_path; 55 if (!(*iter)->GetAsString(&service_path)) 56 continue; 57 const base::DictionaryValue* properties = 58 service_client->GetServiceProperties(service_path); 59 if (!properties) { 60 LOG(ERROR) << "Properties not found for service: " << service_path; 61 continue; 62 } 63 std::string type; 64 properties->GetString(shill::kTypeProperty, &type); 65 if (type != match_type) 66 continue; 67 bool visible = false; 68 if (technology_enabled) 69 properties->GetBoolean(shill::kVisibleProperty, &visible); 70 if (!visible) { 71 disabled_service_list_out->push_back(service_path); 72 continue; 73 } 74 std::string state; 75 properties->GetString(shill::kStateProperty, &state); 76 if (state == shill::kStateOnline || 77 state == shill::kStateAssociation || 78 state == shill::kStateConfiguration || 79 state == shill::kStatePortal || 80 state == shill::kStateReady) { 81 active_service_list_out->push_back(service_path); 82 } else { 83 inactive_service_list_out->push_back(service_path); 84 } 85 } 86 } 87 88 void LogErrorCallback(const std::string& error_name, 89 const std::string& error_message) { 90 LOG(ERROR) << error_name << ": " << error_message; 91 } 92 93 bool IsConnectedState(const std::string& state) { 94 return state == shill::kStateOnline || state == shill::kStatePortal || 95 state == shill::kStateReady; 96 } 97 98 void UpdatePortaledWifiState(const std::string& service_path) { 99 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface() 100 ->SetServiceProperty(service_path, 101 shill::kStateProperty, 102 base::StringValue(shill::kStatePortal)); 103 } 104 105 const char* kTechnologyUnavailable = "unavailable"; 106 const char* kNetworkActivated = "activated"; 107 const char* kNetworkDisabled = "disabled"; 108 109 } // namespace 110 111 // static 112 const char FakeShillManagerClient::kFakeEthernetNetworkPath[] = "/service/eth1"; 113 114 FakeShillManagerClient::FakeShillManagerClient() 115 : interactive_delay_(0), 116 weak_ptr_factory_(this) { 117 ParseCommandLineSwitch(); 118 } 119 120 FakeShillManagerClient::~FakeShillManagerClient() {} 121 122 // ShillManagerClient overrides. 123 124 void FakeShillManagerClient::Init(dbus::Bus* bus) {} 125 126 void FakeShillManagerClient::AddPropertyChangedObserver( 127 ShillPropertyChangedObserver* observer) { 128 observer_list_.AddObserver(observer); 129 } 130 131 void FakeShillManagerClient::RemovePropertyChangedObserver( 132 ShillPropertyChangedObserver* observer) { 133 observer_list_.RemoveObserver(observer); 134 } 135 136 void FakeShillManagerClient::GetProperties( 137 const DictionaryValueCallback& callback) { 138 DVLOG(1) << "Manager.GetProperties"; 139 base::MessageLoop::current()->PostTask( 140 FROM_HERE, base::Bind( 141 &FakeShillManagerClient::PassStubProperties, 142 weak_ptr_factory_.GetWeakPtr(), 143 callback)); 144 } 145 146 void FakeShillManagerClient::GetNetworksForGeolocation( 147 const DictionaryValueCallback& callback) { 148 base::MessageLoop::current()->PostTask( 149 FROM_HERE, base::Bind( 150 &FakeShillManagerClient::PassStubGeoNetworks, 151 weak_ptr_factory_.GetWeakPtr(), 152 callback)); 153 } 154 155 void FakeShillManagerClient::SetProperty(const std::string& name, 156 const base::Value& value, 157 const base::Closure& callback, 158 const ErrorCallback& error_callback) { 159 DVLOG(2) << "SetProperty: " << name; 160 stub_properties_.SetWithoutPathExpansion(name, value.DeepCopy()); 161 CallNotifyObserversPropertyChanged(name); 162 base::MessageLoop::current()->PostTask(FROM_HERE, callback); 163 } 164 165 void FakeShillManagerClient::RequestScan(const std::string& type, 166 const base::Closure& callback, 167 const ErrorCallback& error_callback) { 168 // For Stub purposes, default to a Wifi scan. 169 std::string device_type = shill::kTypeWifi; 170 if (!type.empty()) 171 device_type = type; 172 ShillDeviceClient::TestInterface* device_client = 173 DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface(); 174 std::string device_path = device_client->GetDevicePathForType(device_type); 175 if (!device_path.empty()) { 176 device_client->SetDeviceProperty( 177 device_path, shill::kScanningProperty, base::FundamentalValue(true)); 178 } 179 base::MessageLoop::current()->PostDelayedTask( 180 FROM_HERE, 181 base::Bind(&FakeShillManagerClient::ScanCompleted, 182 weak_ptr_factory_.GetWeakPtr(), 183 device_path, 184 callback), 185 base::TimeDelta::FromSeconds(interactive_delay_)); 186 } 187 188 void FakeShillManagerClient::EnableTechnology( 189 const std::string& type, 190 const base::Closure& callback, 191 const ErrorCallback& error_callback) { 192 base::ListValue* enabled_list = NULL; 193 if (!stub_properties_.GetListWithoutPathExpansion( 194 shill::kAvailableTechnologiesProperty, &enabled_list)) { 195 base::MessageLoop::current()->PostTask(FROM_HERE, callback); 196 base::MessageLoop::current()->PostTask( 197 FROM_HERE, 198 base::Bind(error_callback, "StubError", "Property not found")); 199 return; 200 } 201 base::MessageLoop::current()->PostDelayedTask( 202 FROM_HERE, 203 base::Bind(&FakeShillManagerClient::SetTechnologyEnabled, 204 weak_ptr_factory_.GetWeakPtr(), 205 type, 206 callback, 207 true), 208 base::TimeDelta::FromSeconds(interactive_delay_)); 209 } 210 211 void FakeShillManagerClient::DisableTechnology( 212 const std::string& type, 213 const base::Closure& callback, 214 const ErrorCallback& error_callback) { 215 base::ListValue* enabled_list = NULL; 216 if (!stub_properties_.GetListWithoutPathExpansion( 217 shill::kAvailableTechnologiesProperty, &enabled_list)) { 218 base::MessageLoop::current()->PostTask( 219 FROM_HERE, 220 base::Bind(error_callback, "StubError", "Property not found")); 221 return; 222 } 223 base::MessageLoop::current()->PostDelayedTask( 224 FROM_HERE, 225 base::Bind(&FakeShillManagerClient::SetTechnologyEnabled, 226 weak_ptr_factory_.GetWeakPtr(), 227 type, 228 callback, 229 false), 230 base::TimeDelta::FromSeconds(interactive_delay_)); 231 } 232 233 void FakeShillManagerClient::ConfigureService( 234 const base::DictionaryValue& properties, 235 const ObjectPathCallback& callback, 236 const ErrorCallback& error_callback) { 237 ShillServiceClient::TestInterface* service_client = 238 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface(); 239 240 std::string guid; 241 std::string type; 242 if (!properties.GetString(shill::kGuidProperty, &guid) || 243 !properties.GetString(shill::kTypeProperty, &type)) { 244 LOG(ERROR) << "ConfigureService requires GUID and Type to be defined"; 245 // If the properties aren't filled out completely, then just return an empty 246 // object path. 247 base::MessageLoop::current()->PostTask( 248 FROM_HERE, base::Bind(callback, dbus::ObjectPath())); 249 return; 250 } 251 252 // For the purposes of this stub, we're going to assume that the GUID property 253 // is set to the service path because we don't want to re-implement Shill's 254 // property matching magic here. 255 std::string service_path = guid; 256 257 std::string ipconfig_path; 258 properties.GetString(shill::kIPConfigProperty, &ipconfig_path); 259 260 // Merge the new properties with existing properties, if any. 261 const base::DictionaryValue* existing_properties = 262 service_client->GetServiceProperties(service_path); 263 if (!existing_properties) { 264 // Add a new service to the service client stub because none exists, yet. 265 // This calls AddManagerService. 266 service_client->AddServiceWithIPConfig(service_path, 267 guid /* guid */, 268 guid /* name */, 269 type, 270 shill::kStateIdle, ipconfig_path, 271 true /* visible */); 272 existing_properties = service_client->GetServiceProperties(service_path); 273 } 274 275 scoped_ptr<base::DictionaryValue> merged_properties( 276 existing_properties->DeepCopy()); 277 merged_properties->MergeDictionary(&properties); 278 279 // Now set all the properties. 280 for (base::DictionaryValue::Iterator iter(*merged_properties); 281 !iter.IsAtEnd(); iter.Advance()) { 282 service_client->SetServiceProperty(service_path, iter.key(), iter.value()); 283 } 284 285 // If the Profile property is set, add it to ProfileClient. 286 std::string profile_path; 287 merged_properties->GetStringWithoutPathExpansion(shill::kProfileProperty, 288 &profile_path); 289 if (!profile_path.empty()) { 290 DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface()-> 291 AddService(profile_path, service_path); 292 } 293 294 base::MessageLoop::current()->PostTask( 295 FROM_HERE, base::Bind(callback, dbus::ObjectPath(service_path))); 296 } 297 298 void FakeShillManagerClient::ConfigureServiceForProfile( 299 const dbus::ObjectPath& profile_path, 300 const base::DictionaryValue& properties, 301 const ObjectPathCallback& callback, 302 const ErrorCallback& error_callback) { 303 std::string profile_property; 304 properties.GetStringWithoutPathExpansion(shill::kProfileProperty, 305 &profile_property); 306 CHECK(profile_property == profile_path.value()); 307 ConfigureService(properties, callback, error_callback); 308 } 309 310 311 void FakeShillManagerClient::GetService( 312 const base::DictionaryValue& properties, 313 const ObjectPathCallback& callback, 314 const ErrorCallback& error_callback) { 315 base::MessageLoop::current()->PostTask( 316 FROM_HERE, base::Bind(callback, dbus::ObjectPath())); 317 } 318 319 void FakeShillManagerClient::VerifyDestination( 320 const VerificationProperties& properties, 321 const BooleanCallback& callback, 322 const ErrorCallback& error_callback) { 323 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback, true)); 324 } 325 326 void FakeShillManagerClient::VerifyAndEncryptCredentials( 327 const VerificationProperties& properties, 328 const std::string& service_path, 329 const StringCallback& callback, 330 const ErrorCallback& error_callback) { 331 base::MessageLoop::current()->PostTask( 332 FROM_HERE, base::Bind(callback, "encrypted_credentials")); 333 } 334 335 void FakeShillManagerClient::VerifyAndEncryptData( 336 const VerificationProperties& properties, 337 const std::string& data, 338 const StringCallback& callback, 339 const ErrorCallback& error_callback) { 340 base::MessageLoop::current()->PostTask( 341 FROM_HERE, base::Bind(callback, "encrypted_data")); 342 } 343 344 void FakeShillManagerClient::ConnectToBestServices( 345 const base::Closure& callback, 346 const ErrorCallback& error_callback) { 347 if (best_service_.empty()) { 348 VLOG(1) << "No 'best' service set."; 349 return; 350 } 351 352 DBusThreadManager::Get()->GetShillServiceClient()->Connect( 353 dbus::ObjectPath(best_service_), callback, error_callback); 354 } 355 356 ShillManagerClient::TestInterface* FakeShillManagerClient::GetTestInterface() { 357 return this; 358 } 359 360 // ShillManagerClient::TestInterface overrides. 361 362 void FakeShillManagerClient::AddDevice(const std::string& device_path) { 363 if (GetListProperty(shill::kDevicesProperty)->AppendIfNotPresent( 364 base::Value::CreateStringValue(device_path))) { 365 CallNotifyObserversPropertyChanged(shill::kDevicesProperty); 366 } 367 } 368 369 void FakeShillManagerClient::RemoveDevice(const std::string& device_path) { 370 base::StringValue device_path_value(device_path); 371 if (GetListProperty(shill::kDevicesProperty)->Remove( 372 device_path_value, NULL)) { 373 CallNotifyObserversPropertyChanged(shill::kDevicesProperty); 374 } 375 } 376 377 void FakeShillManagerClient::ClearDevices() { 378 GetListProperty(shill::kDevicesProperty)->Clear(); 379 CallNotifyObserversPropertyChanged(shill::kDevicesProperty); 380 } 381 382 void FakeShillManagerClient::AddTechnology(const std::string& type, 383 bool enabled) { 384 if (GetListProperty(shill::kAvailableTechnologiesProperty)-> 385 AppendIfNotPresent(base::Value::CreateStringValue(type))) { 386 CallNotifyObserversPropertyChanged( 387 shill::kAvailableTechnologiesProperty); 388 } 389 if (enabled && 390 GetListProperty(shill::kEnabledTechnologiesProperty)-> 391 AppendIfNotPresent(base::Value::CreateStringValue(type))) { 392 CallNotifyObserversPropertyChanged( 393 shill::kEnabledTechnologiesProperty); 394 } 395 } 396 397 void FakeShillManagerClient::RemoveTechnology(const std::string& type) { 398 base::StringValue type_value(type); 399 if (GetListProperty(shill::kAvailableTechnologiesProperty)->Remove( 400 type_value, NULL)) { 401 CallNotifyObserversPropertyChanged( 402 shill::kAvailableTechnologiesProperty); 403 } 404 if (GetListProperty(shill::kEnabledTechnologiesProperty)->Remove( 405 type_value, NULL)) { 406 CallNotifyObserversPropertyChanged( 407 shill::kEnabledTechnologiesProperty); 408 } 409 } 410 411 void FakeShillManagerClient::SetTechnologyInitializing(const std::string& type, 412 bool initializing) { 413 if (initializing) { 414 if (GetListProperty(shill::kUninitializedTechnologiesProperty)-> 415 AppendIfNotPresent(base::Value::CreateStringValue(type))) { 416 CallNotifyObserversPropertyChanged( 417 shill::kUninitializedTechnologiesProperty); 418 } 419 } else { 420 if (GetListProperty(shill::kUninitializedTechnologiesProperty)->Remove( 421 base::StringValue(type), NULL)) { 422 CallNotifyObserversPropertyChanged( 423 shill::kUninitializedTechnologiesProperty); 424 } 425 } 426 } 427 428 void FakeShillManagerClient::AddGeoNetwork( 429 const std::string& technology, 430 const base::DictionaryValue& network) { 431 base::ListValue* list_value = NULL; 432 if (!stub_geo_networks_.GetListWithoutPathExpansion(technology, 433 &list_value)) { 434 list_value = new base::ListValue; 435 stub_geo_networks_.SetWithoutPathExpansion(technology, list_value); 436 } 437 list_value->Append(network.DeepCopy()); 438 } 439 440 void FakeShillManagerClient::AddProfile(const std::string& profile_path) { 441 const char* key = shill::kProfilesProperty; 442 if (GetListProperty(key) 443 ->AppendIfNotPresent(new base::StringValue(profile_path))) { 444 CallNotifyObserversPropertyChanged(key); 445 } 446 } 447 448 void FakeShillManagerClient::ClearProperties() { 449 stub_properties_.Clear(); 450 } 451 452 void FakeShillManagerClient::SetManagerProperty(const std::string& key, 453 const base::Value& value) { 454 SetProperty(key, value, 455 base::Bind(&base::DoNothing), base::Bind(&LogErrorCallback)); 456 } 457 458 void FakeShillManagerClient::AddManagerService( 459 const std::string& service_path, 460 bool notify_observers) { 461 DVLOG(2) << "AddManagerService: " << service_path; 462 GetListProperty(shill::kServiceCompleteListProperty)->AppendIfNotPresent( 463 base::Value::CreateStringValue(service_path)); 464 SortManagerServices(false); 465 if (notify_observers) 466 CallNotifyObserversPropertyChanged(shill::kServiceCompleteListProperty); 467 } 468 469 void FakeShillManagerClient::RemoveManagerService( 470 const std::string& service_path) { 471 DVLOG(2) << "RemoveManagerService: " << service_path; 472 base::StringValue service_path_value(service_path); 473 GetListProperty(shill::kServiceCompleteListProperty)->Remove( 474 service_path_value, NULL); 475 CallNotifyObserversPropertyChanged(shill::kServiceCompleteListProperty); 476 } 477 478 void FakeShillManagerClient::ClearManagerServices() { 479 DVLOG(1) << "ClearManagerServices"; 480 GetListProperty(shill::kServiceCompleteListProperty)->Clear(); 481 CallNotifyObserversPropertyChanged(shill::kServiceCompleteListProperty); 482 } 483 484 void FakeShillManagerClient::ServiceStateChanged( 485 const std::string& service_path, 486 const std::string& state) { 487 if (service_path == default_service_ && !IsConnectedState(state)) { 488 // Default service is no longer connected; clear. 489 default_service_.clear(); 490 base::StringValue default_service_value(default_service_); 491 SetManagerProperty(shill::kDefaultServiceProperty, default_service_value); 492 } 493 } 494 495 void FakeShillManagerClient::SortManagerServices(bool notify) { 496 DVLOG(1) << "SortManagerServices"; 497 static const char* ordered_types[] = {shill::kTypeEthernet, 498 shill::kTypeWifi, 499 shill::kTypeCellular, 500 shill::kTypeWimax, 501 shill::kTypeVPN}; 502 503 base::ListValue* complete_list = 504 GetListProperty(shill::kServiceCompleteListProperty); 505 if (complete_list->empty()) 506 return; 507 scoped_ptr<base::ListValue> prev_complete_list(complete_list->DeepCopy()); 508 509 std::vector<std::string> active_services; 510 std::vector<std::string> inactive_services; 511 std::vector<std::string> disabled_services; 512 for (size_t i = 0; i < arraysize(ordered_types); ++i) { 513 AppendServicesForType(complete_list, 514 ordered_types[i], 515 TechnologyEnabled(ordered_types[i]), 516 &active_services, 517 &inactive_services, 518 &disabled_services); 519 } 520 complete_list->Clear(); 521 for (size_t i = 0; i < active_services.size(); ++i) 522 complete_list->AppendString(active_services[i]); 523 for (size_t i = 0; i < inactive_services.size(); ++i) 524 complete_list->AppendString(inactive_services[i]); 525 for (size_t i = 0; i < disabled_services.size(); ++i) 526 complete_list->AppendString(disabled_services[i]); 527 528 if (notify && !complete_list->Equals(prev_complete_list.get())) 529 CallNotifyObserversPropertyChanged(shill::kServiceCompleteListProperty); 530 531 // Set the first active service as the Default service. 532 std::string new_default_service; 533 if (!active_services.empty()) { 534 ShillServiceClient::TestInterface* service_client = 535 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface(); 536 std::string service_path = active_services[0]; 537 const base::DictionaryValue* properties = 538 service_client->GetServiceProperties(service_path); 539 if (!properties) { 540 LOG(ERROR) << "Properties not found for service: " << service_path; 541 } else { 542 std::string state; 543 properties->GetString(shill::kStateProperty, &state); 544 if (IsConnectedState(state)) 545 new_default_service = service_path; 546 } 547 } 548 if (default_service_ != new_default_service) { 549 default_service_ = new_default_service; 550 base::StringValue default_service_value(default_service_); 551 SetManagerProperty(shill::kDefaultServiceProperty, default_service_value); 552 } 553 } 554 555 int FakeShillManagerClient::GetInteractiveDelay() const { 556 return interactive_delay_; 557 } 558 559 void FakeShillManagerClient::SetBestServiceToConnect( 560 const std::string& service_path) { 561 best_service_ = service_path; 562 } 563 564 void FakeShillManagerClient::SetupDefaultEnvironment() { 565 DBusThreadManager* dbus_manager = DBusThreadManager::Get(); 566 ShillServiceClient::TestInterface* services = 567 dbus_manager->GetShillServiceClient()->GetTestInterface(); 568 DCHECK(services); 569 ShillProfileClient::TestInterface* profiles = 570 dbus_manager->GetShillProfileClient()->GetTestInterface(); 571 DCHECK(profiles); 572 ShillDeviceClient::TestInterface* devices = 573 dbus_manager->GetShillDeviceClient()->GetTestInterface(); 574 DCHECK(devices); 575 ShillIPConfigClient::TestInterface* ip_configs = 576 dbus_manager->GetShillIPConfigClient()->GetTestInterface(); 577 DCHECK(ip_configs); 578 579 const std::string shared_profile = ShillProfileClient::GetSharedProfilePath(); 580 profiles->AddProfile(shared_profile, std::string()); 581 582 const bool add_to_visible = true; 583 584 bool enabled; 585 std::string state; 586 587 // IPConfigs 588 base::DictionaryValue ipconfig_v4_dictionary; 589 ipconfig_v4_dictionary.SetStringWithoutPathExpansion( 590 shill::kAddressProperty, "0.0.0.0"); 591 ipconfig_v4_dictionary.SetStringWithoutPathExpansion( 592 shill::kGatewayProperty, "0.0.0.1"); 593 ipconfig_v4_dictionary.SetIntegerWithoutPathExpansion( 594 shill::kPrefixlenProperty, 0); 595 ipconfig_v4_dictionary.SetStringWithoutPathExpansion( 596 shill::kMethodProperty, shill::kTypeIPv4); 597 ip_configs->AddIPConfig("ipconfig_v4_path", ipconfig_v4_dictionary); 598 base::DictionaryValue ipconfig_v6_dictionary; 599 ipconfig_v6_dictionary.SetStringWithoutPathExpansion( 600 shill::kAddressProperty, "0:0:0:0:0:0:0:0"); 601 ipconfig_v6_dictionary.SetStringWithoutPathExpansion( 602 shill::kMethodProperty, shill::kTypeIPv6); 603 ip_configs->AddIPConfig("ipconfig_v6_path", ipconfig_v6_dictionary); 604 605 // Ethernet 606 state = GetInitialStateForType(shill::kTypeEthernet, &enabled); 607 if (state == shill::kStateOnline) { 608 AddTechnology(shill::kTypeEthernet, enabled); 609 devices->AddDevice( 610 "/device/eth1", shill::kTypeEthernet, "stub_eth_device1"); 611 devices->SetDeviceProperty("/device/eth1", 612 shill::kAddressProperty, 613 base::StringValue("0123456789ab")); 614 base::ListValue eth_ip_configs; 615 eth_ip_configs.AppendString("ipconfig_v4_path"); 616 eth_ip_configs.AppendString("ipconfig_v6_path"); 617 devices->SetDeviceProperty("/device/eth1", 618 shill::kIPConfigsProperty, 619 eth_ip_configs); 620 services->AddService(kFakeEthernetNetworkPath, "eth1", 621 shill::kTypeEthernet, 622 state, 623 add_to_visible); 624 profiles->AddService(shared_profile, kFakeEthernetNetworkPath); 625 } 626 627 // Wifi 628 state = GetInitialStateForType(shill::kTypeWifi, &enabled); 629 if (state != kTechnologyUnavailable) { 630 bool portaled = false; 631 if (state == shill::kStatePortal) { 632 portaled = true; 633 state = shill::kStateIdle; 634 } 635 AddTechnology(shill::kTypeWifi, enabled); 636 devices->AddDevice("/device/wifi1", shill::kTypeWifi, "stub_wifi_device1"); 637 devices->SetDeviceProperty("/device/wifi1", 638 shill::kAddressProperty, 639 base::StringValue("23456789abc")); 640 base::ListValue wifi_ip_configs; 641 wifi_ip_configs.AppendString("ipconfig_v4_path"); 642 wifi_ip_configs.AppendString("ipconfig_v6_path"); 643 devices->SetDeviceProperty("/device/wifi1", 644 shill::kIPConfigsProperty, 645 wifi_ip_configs); 646 647 services->AddService("/service/wifi1", 648 "wifi1", 649 shill::kTypeWifi, 650 state, 651 add_to_visible); 652 services->SetServiceProperty("/service/wifi1", 653 shill::kSecurityProperty, 654 base::StringValue(shill::kSecurityWep)); 655 profiles->AddService(shared_profile, "/service/wifi1"); 656 657 services->AddService("/service/wifi2", 658 "wifi2_PSK", 659 shill::kTypeWifi, 660 shill::kStateIdle, 661 add_to_visible); 662 services->SetServiceProperty("/service/wifi2", 663 shill::kSecurityProperty, 664 base::StringValue(shill::kSecurityPsk)); 665 666 base::FundamentalValue strength_value(80); 667 services->SetServiceProperty( 668 "/service/wifi2", shill::kSignalStrengthProperty, strength_value); 669 profiles->AddService(shared_profile, "/service/wifi2"); 670 671 if (portaled) { 672 const std::string kPortaledWifiPath = "/service/portaled_wifi"; 673 services->AddService(kPortaledWifiPath, 674 "Portaled Wifi", 675 shill::kTypeWifi, 676 shill::kStatePortal, 677 add_to_visible); 678 services->SetServiceProperty(kPortaledWifiPath, 679 shill::kSecurityProperty, 680 base::StringValue(shill::kSecurityNone)); 681 services->SetConnectBehavior(kPortaledWifiPath, 682 base::Bind(&UpdatePortaledWifiState, 683 "portaled_wifi")); 684 services->SetServiceProperty(kPortaledWifiPath, 685 shill::kConnectableProperty, 686 base::FundamentalValue(true)); 687 profiles->AddService(shared_profile, kPortaledWifiPath); 688 } 689 } 690 691 // Wimax 692 state = GetInitialStateForType(shill::kTypeWimax, &enabled); 693 if (state != kTechnologyUnavailable) { 694 AddTechnology(shill::kTypeWimax, enabled); 695 devices->AddDevice( 696 "/device/wimax1", shill::kTypeWimax, "stub_wimax_device1"); 697 698 services->AddService("/service/wimax1", 699 "wimax1", 700 shill::kTypeWimax, 701 state, 702 add_to_visible); 703 services->SetServiceProperty("/service/wimax1", 704 shill::kConnectableProperty, 705 base::FundamentalValue(true)); 706 } 707 708 // Cellular 709 state = GetInitialStateForType(shill::kTypeCellular, &enabled); 710 if (state != kTechnologyUnavailable) { 711 bool activated = false; 712 if (state == kNetworkActivated) { 713 activated = true; 714 state = shill::kStateIdle; 715 } 716 AddTechnology(shill::kTypeCellular, enabled); 717 devices->AddDevice( 718 "/device/cellular1", shill::kTypeCellular, "stub_cellular_device1"); 719 devices->SetDeviceProperty("/device/cellular1", 720 shill::kCarrierProperty, 721 base::StringValue(shill::kCarrierSprint)); 722 723 services->AddService("/service/cellular1", 724 "cellular1", 725 shill::kTypeCellular, 726 state, 727 add_to_visible); 728 base::StringValue technology_value(shill::kNetworkTechnologyGsm); 729 services->SetServiceProperty("/service/cellular1", 730 shill::kNetworkTechnologyProperty, 731 technology_value); 732 733 if (activated) { 734 services->SetServiceProperty( 735 "/service/cellular1", 736 shill::kActivationStateProperty, 737 base::StringValue(shill::kActivationStateActivated)); 738 services->SetServiceProperty("/service/cellular1", 739 shill::kConnectableProperty, 740 base::FundamentalValue(true)); 741 } else { 742 services->SetServiceProperty( 743 "/service/cellular1", 744 shill::kActivationStateProperty, 745 base::StringValue(shill::kActivationStateNotActivated)); 746 } 747 748 services->SetServiceProperty("/service/cellular1", 749 shill::kRoamingStateProperty, 750 base::StringValue(shill::kRoamingStateHome)); 751 } 752 753 // VPN 754 state = GetInitialStateForType(shill::kTypeVPN, &enabled); 755 if (state != kTechnologyUnavailable) { 756 // Set the "Provider" dictionary properties. Note: when setting these in 757 // Shill, "Provider.Type", etc keys are used, but when reading the values 758 // "Provider" . "Type", etc keys are used. Here we are setting the values 759 // that will be read (by the UI, tests, etc). 760 base::DictionaryValue provider_properties; 761 provider_properties.SetString(shill::kTypeProperty, 762 shill::kProviderOpenVpn); 763 provider_properties.SetString(shill::kHostProperty, "vpn_host"); 764 765 services->AddService("/service/vpn1", 766 "vpn1", 767 shill::kTypeVPN, 768 state, 769 add_to_visible); 770 services->SetServiceProperty( 771 "/service/vpn1", shill::kProviderProperty, provider_properties); 772 profiles->AddService(shared_profile, "/service/vpn1"); 773 774 services->AddService("/service/vpn2", 775 "vpn2", 776 shill::kTypeVPN, 777 shill::kStateIdle, 778 add_to_visible); 779 services->SetServiceProperty( 780 "/service/vpn2", shill::kProviderProperty, provider_properties); 781 } 782 783 SortManagerServices(true); 784 } 785 786 // Private methods 787 788 void FakeShillManagerClient::PassStubProperties( 789 const DictionaryValueCallback& callback) const { 790 scoped_ptr<base::DictionaryValue> stub_properties( 791 stub_properties_.DeepCopy()); 792 stub_properties->SetWithoutPathExpansion( 793 shill::kServiceCompleteListProperty, 794 GetEnabledServiceList(shill::kServiceCompleteListProperty)); 795 callback.Run(DBUS_METHOD_CALL_SUCCESS, *stub_properties); 796 } 797 798 void FakeShillManagerClient::PassStubGeoNetworks( 799 const DictionaryValueCallback& callback) const { 800 callback.Run(DBUS_METHOD_CALL_SUCCESS, stub_geo_networks_); 801 } 802 803 void FakeShillManagerClient::CallNotifyObserversPropertyChanged( 804 const std::string& property) { 805 // Avoid unnecessary delayed task if we have no observers (e.g. during 806 // initial setup). 807 if (!observer_list_.might_have_observers()) 808 return; 809 base::MessageLoop::current()->PostTask( 810 FROM_HERE, 811 base::Bind(&FakeShillManagerClient::NotifyObserversPropertyChanged, 812 weak_ptr_factory_.GetWeakPtr(), 813 property)); 814 } 815 816 void FakeShillManagerClient::NotifyObserversPropertyChanged( 817 const std::string& property) { 818 DVLOG(1) << "NotifyObserversPropertyChanged: " << property; 819 base::Value* value = NULL; 820 if (!stub_properties_.GetWithoutPathExpansion(property, &value)) { 821 LOG(ERROR) << "Notify for unknown property: " << property; 822 return; 823 } 824 if (property == shill::kServiceCompleteListProperty) { 825 scoped_ptr<base::ListValue> services(GetEnabledServiceList(property)); 826 FOR_EACH_OBSERVER(ShillPropertyChangedObserver, 827 observer_list_, 828 OnPropertyChanged(property, *(services.get()))); 829 return; 830 } 831 FOR_EACH_OBSERVER(ShillPropertyChangedObserver, 832 observer_list_, 833 OnPropertyChanged(property, *value)); 834 } 835 836 base::ListValue* FakeShillManagerClient::GetListProperty( 837 const std::string& property) { 838 base::ListValue* list_property = NULL; 839 if (!stub_properties_.GetListWithoutPathExpansion( 840 property, &list_property)) { 841 list_property = new base::ListValue; 842 stub_properties_.SetWithoutPathExpansion(property, list_property); 843 } 844 return list_property; 845 } 846 847 bool FakeShillManagerClient::TechnologyEnabled(const std::string& type) const { 848 if (type == shill::kTypeVPN) 849 return true; // VPN is always "enabled" since there is no associated device 850 bool enabled = false; 851 const base::ListValue* technologies; 852 if (stub_properties_.GetListWithoutPathExpansion( 853 shill::kEnabledTechnologiesProperty, &technologies)) { 854 base::StringValue type_value(type); 855 if (technologies->Find(type_value) != technologies->end()) 856 enabled = true; 857 } 858 return enabled; 859 } 860 861 void FakeShillManagerClient::SetTechnologyEnabled( 862 const std::string& type, 863 const base::Closure& callback, 864 bool enabled) { 865 base::ListValue* enabled_list = 866 GetListProperty(shill::kEnabledTechnologiesProperty); 867 if (enabled) 868 enabled_list->AppendIfNotPresent(new base::StringValue(type)); 869 else 870 enabled_list->Remove(base::StringValue(type), NULL); 871 CallNotifyObserversPropertyChanged( 872 shill::kEnabledTechnologiesProperty); 873 base::MessageLoop::current()->PostTask(FROM_HERE, callback); 874 // May affect available services. 875 SortManagerServices(true); 876 } 877 878 base::ListValue* FakeShillManagerClient::GetEnabledServiceList( 879 const std::string& property) const { 880 base::ListValue* new_service_list = new base::ListValue; 881 const base::ListValue* service_list; 882 if (stub_properties_.GetListWithoutPathExpansion(property, &service_list)) { 883 ShillServiceClient::TestInterface* service_client = 884 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface(); 885 for (base::ListValue::const_iterator iter = service_list->begin(); 886 iter != service_list->end(); ++iter) { 887 std::string service_path; 888 if (!(*iter)->GetAsString(&service_path)) 889 continue; 890 const base::DictionaryValue* properties = 891 service_client->GetServiceProperties(service_path); 892 if (!properties) { 893 LOG(ERROR) << "Properties not found for service: " << service_path; 894 continue; 895 } 896 std::string type; 897 properties->GetString(shill::kTypeProperty, &type); 898 if (TechnologyEnabled(type)) 899 new_service_list->Append((*iter)->DeepCopy()); 900 } 901 } 902 return new_service_list; 903 } 904 905 void FakeShillManagerClient::ScanCompleted(const std::string& device_path, 906 const base::Closure& callback) { 907 if (!device_path.empty()) { 908 DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface()-> 909 SetDeviceProperty(device_path, 910 shill::kScanningProperty, 911 base::FundamentalValue(false)); 912 } 913 DVLOG(2) << "ScanCompleted"; 914 CallNotifyObserversPropertyChanged(shill::kServiceCompleteListProperty); 915 base::MessageLoop::current()->PostTask(FROM_HERE, callback); 916 } 917 918 void FakeShillManagerClient::ParseCommandLineSwitch() { 919 CommandLine* command_line = CommandLine::ForCurrentProcess(); 920 if (command_line->HasSwitch(switches::kShillStub)) { 921 std::string option_str = 922 command_line->GetSwitchValueASCII(switches::kShillStub); 923 base::StringPairs string_pairs; 924 base::SplitStringIntoKeyValuePairs(option_str, '=', ',', &string_pairs); 925 for (base::StringPairs::iterator iter = string_pairs.begin(); 926 iter != string_pairs.end(); ++iter) { 927 ParseOption((*iter).first, (*iter).second); 928 } 929 return; 930 } 931 // Default setup 932 SetInitialNetworkState(shill::kTypeEthernet, shill::kStateOnline); 933 SetInitialNetworkState(shill::kTypeWifi, shill::kStateOnline); 934 SetInitialNetworkState(shill::kTypeCellular, shill::kStateIdle); 935 SetInitialNetworkState(shill::kTypeVPN, shill::kStateIdle); 936 } 937 938 bool FakeShillManagerClient::ParseOption(const std::string& arg0, 939 const std::string& arg1) { 940 if (arg0 == "interactive") { 941 int seconds = 3; 942 if (!arg1.empty()) 943 base::StringToInt(arg1, &seconds); 944 interactive_delay_ = seconds; 945 return true; 946 } 947 return SetInitialNetworkState(arg0, arg1); 948 } 949 950 bool FakeShillManagerClient::SetInitialNetworkState(std::string type_arg, 951 std::string state_arg) { 952 std::string state; 953 state_arg = StringToLowerASCII(state_arg); 954 if (state_arg.empty() || state_arg == "1" || state_arg == "on" || 955 state_arg == "enabled" || state_arg == "connected" || 956 state_arg == "online") { 957 // Enabled and connected (default value) 958 state = shill::kStateOnline; 959 } else if (state_arg == "0" || state_arg == "off" || 960 state_arg == "inactive" || state_arg == shill::kStateIdle) { 961 // Technology enabled, services are created but are not connected. 962 state = shill::kStateIdle; 963 } else if (state_arg == "disabled" || state_arg == "disconnect") { 964 // Technology disabled but available, services created but not connected. 965 state = kNetworkDisabled; 966 } else if (state_arg == "none" || state_arg == "offline") { 967 // Technology not available, do not create services. 968 state = kTechnologyUnavailable; 969 } else if (state_arg == "portal") { 970 // Technology is enabled, a service is connected and in Portal state. 971 state = shill::kStatePortal; 972 } else if (state_arg == "active" || state_arg == "activated") { 973 // Technology is enabled, a service is connected and Activated. 974 state = kNetworkActivated; 975 } else { 976 LOG(ERROR) << "Unrecognized initial state: " << state_arg; 977 return false; 978 } 979 980 type_arg = StringToLowerASCII(type_arg); 981 // Special cases 982 if (type_arg == "wireless") { 983 shill_initial_state_map_[shill::kTypeWifi] = state; 984 shill_initial_state_map_[shill::kTypeCellular] = state; 985 return true; 986 } 987 // Convenience synonyms. 988 if (type_arg == "eth") 989 type_arg = shill::kTypeEthernet; 990 991 if (type_arg != shill::kTypeEthernet && 992 type_arg != shill::kTypeWifi && 993 type_arg != shill::kTypeCellular && 994 type_arg != shill::kTypeWimax && 995 type_arg != shill::kTypeVPN) { 996 LOG(WARNING) << "Unrecognized Shill network type: " << type_arg; 997 return false; 998 } 999 1000 // Unconnected or disabled ethernet is the same as unavailable. 1001 if (type_arg == shill::kTypeEthernet && 1002 (state == shill::kStateIdle || state == kNetworkDisabled)) { 1003 state = kTechnologyUnavailable; 1004 } 1005 1006 shill_initial_state_map_[type_arg] = state; 1007 return true; 1008 } 1009 1010 std::string FakeShillManagerClient::GetInitialStateForType( 1011 const std::string& type, 1012 bool* enabled) { 1013 std::map<std::string, std::string>::const_iterator iter = 1014 shill_initial_state_map_.find(type); 1015 if (iter == shill_initial_state_map_.end()) { 1016 *enabled = false; 1017 return kTechnologyUnavailable; 1018 } 1019 std::string state = iter->second; 1020 if (state == kNetworkDisabled) { 1021 *enabled = false; 1022 return shill::kStateIdle; 1023 } 1024 *enabled = true; 1025 if ((state == shill::kStatePortal && type != shill::kTypeWifi) || 1026 (state == kNetworkActivated && type != shill::kTypeCellular)) { 1027 LOG(WARNING) << "Invalid state: " << state << " for " << type; 1028 return shill::kStateIdle; 1029 } 1030 return state; 1031 } 1032 1033 } // namespace chromeos 1034