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