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