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