Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chromeos / dbus / fake_shill_manager_client.cc
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