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/shill/fake_shill_manager_client.h"
6 
7 #include <stddef.h>
8 
9 #include <memory>
10 #include <vector>
11 
12 #include "base/bind.h"
13 #include "base/callback_helpers.h"
14 #include "base/command_line.h"
15 #include "base/location.h"
16 #include "base/logging.h"
17 #include "base/single_thread_task_runner.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_split.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/stringprintf.h"
22 #include "base/threading/thread_task_runner_handle.h"
23 #include "chromeos/dbus/constants/dbus_switches.h"
24 #include "chromeos/dbus/shill/fake_shill_device_client.h"
25 #include "chromeos/dbus/shill/shill_device_client.h"
26 #include "chromeos/dbus/shill/shill_ipconfig_client.h"
27 #include "chromeos/dbus/shill/shill_profile_client.h"
28 #include "chromeos/dbus/shill/shill_property_changed_observer.h"
29 #include "chromeos/dbus/shill/shill_service_client.h"
30 #include "dbus/bus.h"
31 #include "dbus/message.h"
32 #include "dbus/object_path.h"
33 #include "dbus/values_util.h"
34 #include "third_party/cros_system_api/dbus/service_constants.h"
35 
36 namespace chromeos {
37 
38 namespace {
39 
40 int s_extra_wifi_networks = 0;
41 
42 // For testing dynamic WEP networks (uses wifi2).
43 bool s_dynamic_wep = false;
44 
45 // Used to compare values for finding entries to erase in a ListValue.
46 // (ListValue only implements a const_iterator version of Find).
47 struct ValueEquals {
ValueEqualschromeos::__anondaa4869a0111::ValueEquals48   explicit ValueEquals(const base::Value* first) : first_(first) {}
operator ()chromeos::__anondaa4869a0111::ValueEquals49   bool operator()(const base::Value* second) const {
50     return first_->Equals(second);
51   }
52   const base::Value* first_;
53 };
54 
GetBoolValue(const base::Value & dict,const char * key)55 bool GetBoolValue(const base::Value& dict, const char* key) {
56   const base::Value* value =
57       dict.FindKeyOfType(key, base::Value::Type::BOOLEAN);
58   return value ? value->GetBool() : false;
59 }
60 
GetIntValue(const base::Value & dict,const char * key)61 int GetIntValue(const base::Value& dict, const char* key) {
62   const base::Value* value =
63       dict.FindKeyOfType(key, base::Value::Type::INTEGER);
64   return value ? value->GetInt() : 0;
65 }
66 
GetString(const base::Value & dict,const char * key,std::string * result)67 bool GetString(const base::Value& dict, const char* key, std::string* result) {
68   // Note: FindPath uses path expansion which is currently required for the
69   // fake shill implementations.
70   const base::Value* v = dict.FindPathOfType(key, base::Value::Type::STRING);
71   if (!v)
72     return false;
73   return v->GetAsString(result);
74 }
75 
GetStringValue(const base::Value & dict,const char * key)76 std::string GetStringValue(const base::Value& dict, const char* key) {
77   const base::Value* value = dict.FindKeyOfType(key, base::Value::Type::STRING);
78   return value ? value->GetString() : std::string();
79 }
80 
IsPortalledState(const std::string & state)81 bool IsPortalledState(const std::string& state) {
82   return state == shill::kStatePortal || state == shill::kStateNoConnectivity ||
83          state == shill::kStateRedirectFound ||
84          state == shill::kStatePortalSuspected;
85 }
86 
GetStateOrder(const base::Value & dict)87 int GetStateOrder(const base::Value& dict) {
88   std::string state = GetStringValue(dict, shill::kStateProperty);
89   if (state == shill::kStateOnline)
90     return 1;
91   if (state == shill::kStateReady)
92     return 2;
93   if (IsPortalledState(state))
94     return 3;
95   if (state == shill::kStateAssociation || state == shill::kStateConfiguration)
96     return 4;
97   return 5;
98 }
99 
GetTechnologyOrder(const base::Value & dict)100 int GetTechnologyOrder(const base::Value& dict) {
101   std::string technology = GetStringValue(dict, shill::kTypeProperty);
102   // Note: In Shill, VPN is the highest priority network, but it is generally
103   // dependent on the underlying network and gets sorted after that network.
104   // For now, we simulate this by sorting VPN last. TODO(stevenjb): Support
105   // VPN dependencies.
106   if (technology == shill::kTypeVPN)
107     return 10;
108 
109   if (technology == shill::kTypeEthernet)
110     return 1;
111   if (technology == shill::kTypeWifi)
112     return 2;
113   if (technology == shill::kTypeCellular)
114     return 3;
115   return 4;
116 }
117 
GetSecurityOrder(const base::Value & dict)118 int GetSecurityOrder(const base::Value& dict) {
119   std::string security = GetStringValue(dict, shill::kSecurityProperty);
120   // No security is listed last.
121   if (security == shill::kSecurityNone)
122     return 3;
123 
124   // 8021x is listed first.
125   if (security == shill::kSecurity8021x)
126     return 1;
127 
128   // All other security types are equal priority.
129   return 2;
130 }
131 
132 // Matches Shill's Service::Compare function.
CompareNetworks(const base::Value & a,const base::Value & b)133 bool CompareNetworks(const base::Value& a, const base::Value& b) {
134   // Connection State: Online, Connected, Portal, Connecting
135   int state_order_a = GetStateOrder(a);
136   int state_order_b = GetStateOrder(b);
137   if (state_order_a != state_order_b)
138     return state_order_a < state_order_b;
139 
140   // Connectable (i.e. configured)
141   bool connectable_a = GetBoolValue(a, shill::kConnectableProperty);
142   bool connectable_b = GetBoolValue(b, shill::kConnectableProperty);
143   if (connectable_a != connectable_b)
144     return connectable_a;
145 
146   // Note: VPN is normally sorted first because of dependencies, see comment
147   // in GetTechnologyOrder.
148 
149   // Technology
150   int technology_order_a = GetTechnologyOrder(a);
151   int technology_order_b = GetTechnologyOrder(b);
152   if (technology_order_a != technology_order_b)
153     return technology_order_a < technology_order_b;
154 
155   // Priority
156   int priority_a = GetIntValue(a, shill::kPriorityProperty);
157   int priority_b = GetIntValue(b, shill::kPriorityProperty);
158   if (priority_a != priority_b)
159     return priority_a > priority_b;
160 
161   // TODO: Sort on: Managed
162 
163   // AutoConnect
164   bool auto_connect_a = GetBoolValue(a, shill::kAutoConnectProperty);
165   bool auto_connect_b = GetBoolValue(b, shill::kAutoConnectProperty);
166   if (auto_connect_a != auto_connect_b)
167     return auto_connect_a;
168 
169   // Security
170   int security_order_a = GetSecurityOrder(a);
171   int security_order_b = GetSecurityOrder(b);
172   if (security_order_a != security_order_b)
173     return security_order_a < security_order_b;
174 
175   // TODO: Sort on: Profile: User profile < Device profile
176   // TODO: Sort on: Has ever connected
177 
178   // SignalStrength
179   int strength_a = GetIntValue(a, shill::kSignalStrengthProperty);
180   int strength_b = GetIntValue(b, shill::kSignalStrengthProperty);
181   if (strength_a != strength_b)
182     return strength_a > strength_b;
183 
184   // Arbitrary identifier: SSID
185   return GetStringValue(a, shill::kSSIDProperty) <
186          GetStringValue(b, shill::kSSIDProperty);
187 }
188 
LogErrorCallback(const std::string & error_name,const std::string & error_message)189 void LogErrorCallback(const std::string& error_name,
190                       const std::string& error_message) {
191   LOG(ERROR) << error_name << ": " << error_message;
192 }
193 
IsConnectedState(const std::string & state)194 bool IsConnectedState(const std::string& state) {
195   return state == shill::kStateOnline || IsPortalledState(state) ||
196          state == shill::kStateReady;
197 }
198 
UpdatePortaledWifiState(const std::string & service_path)199 void UpdatePortaledWifiState(const std::string& service_path) {
200   ShillServiceClient::Get()->GetTestInterface()->SetServiceProperty(
201       service_path, shill::kStateProperty,
202       base::Value(shill::kStateNoConnectivity));
203 }
204 
IsCellularTechnology(const std::string & type)205 bool IsCellularTechnology(const std::string& type) {
206   return (type == shill::kNetworkTechnology1Xrtt ||
207           type == shill::kNetworkTechnologyEvdo ||
208           type == shill::kNetworkTechnologyGsm ||
209           type == shill::kNetworkTechnologyGprs ||
210           type == shill::kNetworkTechnologyEdge ||
211           type == shill::kNetworkTechnologyUmts ||
212           type == shill::kNetworkTechnologyHspa ||
213           type == shill::kNetworkTechnologyHspaPlus ||
214           type == shill::kNetworkTechnologyLte ||
215           type == shill::kNetworkTechnologyLteAdvanced);
216 }
217 
SetInitialDeviceProperty(const std::string & device_path,const std::string & name,const base::Value & value)218 void SetInitialDeviceProperty(const std::string& device_path,
219                               const std::string& name,
220                               const base::Value& value) {
221   ShillDeviceClient::Get()->GetTestInterface()->SetDeviceProperty(
222       device_path, name, value, /*notify_changed=*/false);
223 }
224 
225 const char kPathKey[] = "path";
226 
227 const char kTechnologyUnavailable[] = "unavailable";
228 const char kTechnologyInitializing[] = "initializing";
229 const char kNetworkActivated[] = "activated";
230 const char kNetworkDisabled[] = "disabled";
231 const char kCellularServicePath[] = "/service/cellular1";
232 const char kRoamingRequired[] = "required";
233 
234 }  // namespace
235 
236 // static
237 const char FakeShillManagerClient::kFakeEthernetNetworkGuid[] = "eth1_guid";
238 
FakeShillManagerClient()239 FakeShillManagerClient::FakeShillManagerClient()
240     : cellular_technology_(shill::kNetworkTechnologyGsm) {
241   ParseCommandLineSwitch();
242 }
243 
244 FakeShillManagerClient::~FakeShillManagerClient() = default;
245 
246 // ShillManagerClient overrides.
247 
AddPropertyChangedObserver(ShillPropertyChangedObserver * observer)248 void FakeShillManagerClient::AddPropertyChangedObserver(
249     ShillPropertyChangedObserver* observer) {
250   observer_list_.AddObserver(observer);
251 }
252 
RemovePropertyChangedObserver(ShillPropertyChangedObserver * observer)253 void FakeShillManagerClient::RemovePropertyChangedObserver(
254     ShillPropertyChangedObserver* observer) {
255   observer_list_.RemoveObserver(observer);
256 }
257 
GetProperties(DBusMethodCallback<base::Value> callback)258 void FakeShillManagerClient::GetProperties(
259     DBusMethodCallback<base::Value> callback) {
260   VLOG(1) << "Manager.GetProperties";
261   base::ThreadTaskRunnerHandle::Get()->PostTask(
262       FROM_HERE,
263       base::BindOnce(&FakeShillManagerClient::PassStubProperties,
264                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
265 }
266 
GetNetworksForGeolocation(DBusMethodCallback<base::Value> callback)267 void FakeShillManagerClient::GetNetworksForGeolocation(
268     DBusMethodCallback<base::Value> callback) {
269   base::ThreadTaskRunnerHandle::Get()->PostTask(
270       FROM_HERE,
271       base::BindOnce(&FakeShillManagerClient::PassStubGeoNetworks,
272                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
273 }
274 
SetProperty(const std::string & name,const base::Value & value,base::OnceClosure callback,ErrorCallback error_callback)275 void FakeShillManagerClient::SetProperty(const std::string& name,
276                                          const base::Value& value,
277                                          base::OnceClosure callback,
278                                          ErrorCallback error_callback) {
279   VLOG(2) << "SetProperty: " << name;
280   stub_properties_.SetKey(name, value.Clone());
281   CallNotifyObserversPropertyChanged(name);
282   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
283 }
284 
RequestScan(const std::string & type,base::OnceClosure callback,ErrorCallback error_callback)285 void FakeShillManagerClient::RequestScan(const std::string& type,
286                                          base::OnceClosure callback,
287                                          ErrorCallback error_callback) {
288   VLOG(1) << "RequestScan: " << type;
289   // For Stub purposes, default to a Wifi scan.
290   std::string device_type = type.empty() ? shill::kTypeWifi : type;
291   ShillDeviceClient::TestInterface* device_client =
292       ShillDeviceClient::Get()->GetTestInterface();
293   std::string device_path = device_client->GetDevicePathForType(device_type);
294   if (!device_path.empty()) {
295     device_client->SetDeviceProperty(device_path, shill::kScanningProperty,
296                                      base::Value(true),
297                                      /*notify_changed=*/true);
298     if (device_type == shill::kTypeCellular)
299       device_client->AddCellularFoundNetwork(device_path);
300   }
301   // Trigger |callback| immediately to indicate that the scan started.
302   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
303   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
304       FROM_HERE,
305       base::BindOnce(&FakeShillManagerClient::ScanCompleted,
306                      weak_ptr_factory_.GetWeakPtr(), device_path),
307       interactive_delay_);
308 }
309 
EnableTechnology(const std::string & type,base::OnceClosure callback,ErrorCallback error_callback)310 void FakeShillManagerClient::EnableTechnology(const std::string& type,
311                                               base::OnceClosure callback,
312                                               ErrorCallback error_callback) {
313   base::Value* enabled_list =
314       stub_properties_.FindListKey(shill::kAvailableTechnologiesProperty);
315   if (!enabled_list) {
316     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
317                                                   std::move(callback));
318     base::ThreadTaskRunnerHandle::Get()->PostTask(
319         FROM_HERE, base::BindOnce(std::move(error_callback), "StubError",
320                                   "Property not found"));
321     return;
322   }
323   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
324       FROM_HERE,
325       base::BindOnce(&FakeShillManagerClient::SetTechnologyEnabled,
326                      weak_ptr_factory_.GetWeakPtr(), type, std::move(callback),
327                      true),
328       interactive_delay_);
329 }
330 
DisableTechnology(const std::string & type,base::OnceClosure callback,ErrorCallback error_callback)331 void FakeShillManagerClient::DisableTechnology(const std::string& type,
332                                                base::OnceClosure callback,
333                                                ErrorCallback error_callback) {
334   base::Value* enabled_list =
335       stub_properties_.FindListKey(shill::kAvailableTechnologiesProperty);
336   if (!enabled_list) {
337     base::ThreadTaskRunnerHandle::Get()->PostTask(
338         FROM_HERE, base::BindOnce(std::move(error_callback), "StubError",
339                                   "Property not found"));
340     return;
341   }
342   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
343       FROM_HERE,
344       base::BindOnce(&FakeShillManagerClient::SetTechnologyEnabled,
345                      weak_ptr_factory_.GetWeakPtr(), type, std::move(callback),
346                      false),
347       interactive_delay_);
348 }
349 
ConfigureService(const base::Value & properties,ObjectPathCallback callback,ErrorCallback error_callback)350 void FakeShillManagerClient::ConfigureService(const base::Value& properties,
351                                               ObjectPathCallback callback,
352                                               ErrorCallback error_callback) {
353   switch (simulate_configuration_result_) {
354     case FakeShillSimulatedResult::kSuccess:
355       break;
356     case FakeShillSimulatedResult::kFailure:
357       base::ThreadTaskRunnerHandle::Get()->PostTask(
358           FROM_HERE, base::BindOnce(std::move(error_callback), "Error",
359                                     "Simulated failure"));
360       return;
361     case FakeShillSimulatedResult::kTimeout:
362       // No callbacks get executed and the caller should eventually timeout.
363       return;
364   }
365 
366   ShillServiceClient::TestInterface* service_client =
367       ShillServiceClient::Get()->GetTestInterface();
368 
369   std::string guid;
370   std::string type;
371   std::string name;
372   if (!GetString(properties, shill::kGuidProperty, &guid) ||
373       !GetString(properties, shill::kTypeProperty, &type)) {
374     LOG(ERROR) << "ConfigureService requires GUID and Type to be defined";
375     // If the properties aren't filled out completely, then just return an empty
376     // object path.
377     base::ThreadTaskRunnerHandle::Get()->PostTask(
378         FROM_HERE, base::BindOnce(std::move(callback), dbus::ObjectPath()));
379     return;
380   }
381 
382   if (type == shill::kTypeWifi) {
383     GetString(properties, shill::kSSIDProperty, &name);
384 
385     if (name.empty()) {
386       std::string hex_name;
387       GetString(properties, shill::kWifiHexSsid, &hex_name);
388       if (!hex_name.empty()) {
389         std::vector<uint8_t> bytes;
390         if (base::HexStringToBytes(hex_name, &bytes)) {
391           name.assign(reinterpret_cast<const char*>(&bytes[0]), bytes.size());
392         }
393       }
394     }
395   }
396   if (name.empty())
397     GetString(properties, shill::kNameProperty, &name);
398   if (name.empty())
399     name = guid;
400 
401   std::string ipconfig_path;
402   GetString(properties, shill::kIPConfigProperty, &ipconfig_path);
403 
404   std::string service_path = service_client->FindServiceMatchingGUID(guid);
405   if (service_path.empty())
406     service_path = service_client->FindSimilarService(properties);
407   if (service_path.empty()) {
408     // In the stub, service paths don't have to be DBus paths, so build
409     // something out of the GUID as service path.
410     // Don't use the GUID itself, so tests are forced to distinguish between
411     // service paths and GUIDs instead of assuming that service path == GUID.
412     service_path = "service_path_for_" + guid;
413     service_client->AddServiceWithIPConfig(
414         service_path, guid /* guid */, name /* name */, type, shill::kStateIdle,
415         ipconfig_path, true /* visible */);
416   }
417 
418   // Merge the new properties with existing properties.
419   base::Value merged_properties =
420       service_client->GetServiceProperties(service_path)->Clone();
421   merged_properties.MergeDictionary(&properties);
422 
423   // Now set all the properties.
424   for (auto iter : merged_properties.DictItems())
425     service_client->SetServiceProperty(service_path, iter.first, iter.second);
426 
427   // If the Profile property is set, add it to ProfileClient.
428   const std::string* profile_path =
429       merged_properties.FindStringKey(shill::kProfileProperty);
430   if (profile_path) {
431     auto* profile_client = ShillProfileClient::Get()->GetTestInterface();
432     if (!profile_client->UpdateService(*profile_path, service_path))
433       profile_client->AddService(*profile_path, service_path);
434   }
435 
436   base::ThreadTaskRunnerHandle::Get()->PostTask(
437       FROM_HERE,
438       base::BindOnce(std::move(callback), dbus::ObjectPath(service_path)));
439 }
440 
ConfigureServiceForProfile(const dbus::ObjectPath & profile_path,const base::Value & properties,ObjectPathCallback callback,ErrorCallback error_callback)441 void FakeShillManagerClient::ConfigureServiceForProfile(
442     const dbus::ObjectPath& profile_path,
443     const base::Value& properties,
444     ObjectPathCallback callback,
445     ErrorCallback error_callback) {
446   std::string profile_property;
447   GetString(properties, shill::kProfileProperty, &profile_property);
448   CHECK(profile_property == profile_path.value());
449   ConfigureService(properties, std::move(callback), std::move(error_callback));
450 }
451 
GetService(const base::Value & properties,ObjectPathCallback callback,ErrorCallback error_callback)452 void FakeShillManagerClient::GetService(const base::Value& properties,
453                                         ObjectPathCallback callback,
454                                         ErrorCallback error_callback) {
455   base::ThreadTaskRunnerHandle::Get()->PostTask(
456       FROM_HERE, base::BindOnce(std::move(callback), dbus::ObjectPath()));
457 }
458 
ConnectToBestServices(base::OnceClosure callback,ErrorCallback error_callback)459 void FakeShillManagerClient::ConnectToBestServices(
460     base::OnceClosure callback,
461     ErrorCallback error_callback) {
462   if (best_service_.empty()) {
463     VLOG(1) << "No 'best' service set.";
464     return;
465   }
466 
467   ShillServiceClient::Get()->Connect(dbus::ObjectPath(best_service_),
468                                      std::move(callback),
469                                      std::move(error_callback));
470 }
471 
GetTestInterface()472 ShillManagerClient::TestInterface* FakeShillManagerClient::GetTestInterface() {
473   return this;
474 }
475 
476 // ShillManagerClient::TestInterface overrides.
477 
AddDevice(const std::string & device_path)478 void FakeShillManagerClient::AddDevice(const std::string& device_path) {
479   if (GetListProperty(shill::kDevicesProperty)
480           ->AppendIfNotPresent(std::make_unique<base::Value>(device_path))) {
481     CallNotifyObserversPropertyChanged(shill::kDevicesProperty);
482   }
483 }
484 
RemoveDevice(const std::string & device_path)485 void FakeShillManagerClient::RemoveDevice(const std::string& device_path) {
486   base::Value device_path_value(device_path);
487   if (GetListProperty(shill::kDevicesProperty)
488           ->Remove(device_path_value, nullptr)) {
489     CallNotifyObserversPropertyChanged(shill::kDevicesProperty);
490   }
491 }
492 
ClearDevices()493 void FakeShillManagerClient::ClearDevices() {
494   GetListProperty(shill::kDevicesProperty)->Clear();
495   CallNotifyObserversPropertyChanged(shill::kDevicesProperty);
496 }
497 
AddTechnology(const std::string & type,bool enabled)498 void FakeShillManagerClient::AddTechnology(const std::string& type,
499                                            bool enabled) {
500   if (GetListProperty(shill::kAvailableTechnologiesProperty)
501           ->AppendIfNotPresent(std::make_unique<base::Value>(type))) {
502     CallNotifyObserversPropertyChanged(shill::kAvailableTechnologiesProperty);
503   }
504   if (enabled &&
505       GetListProperty(shill::kEnabledTechnologiesProperty)
506           ->AppendIfNotPresent(std::make_unique<base::Value>(type))) {
507     CallNotifyObserversPropertyChanged(shill::kEnabledTechnologiesProperty);
508   }
509 }
510 
RemoveTechnology(const std::string & type)511 void FakeShillManagerClient::RemoveTechnology(const std::string& type) {
512   base::Value type_value(type);
513   if (GetListProperty(shill::kAvailableTechnologiesProperty)
514           ->Remove(type_value, nullptr)) {
515     CallNotifyObserversPropertyChanged(shill::kAvailableTechnologiesProperty);
516   }
517   if (GetListProperty(shill::kEnabledTechnologiesProperty)
518           ->Remove(type_value, nullptr)) {
519     CallNotifyObserversPropertyChanged(shill::kEnabledTechnologiesProperty);
520   }
521 }
522 
SetTechnologyInitializing(const std::string & type,bool initializing)523 void FakeShillManagerClient::SetTechnologyInitializing(const std::string& type,
524                                                        bool initializing) {
525   if (initializing) {
526     if (GetListProperty(shill::kUninitializedTechnologiesProperty)
527             ->AppendIfNotPresent(std::make_unique<base::Value>(type))) {
528       CallNotifyObserversPropertyChanged(
529           shill::kUninitializedTechnologiesProperty);
530     }
531   } else {
532     if (GetListProperty(shill::kUninitializedTechnologiesProperty)
533             ->Remove(base::Value(type), nullptr)) {
534       CallNotifyObserversPropertyChanged(
535           shill::kUninitializedTechnologiesProperty);
536     }
537   }
538 }
539 
SetTechnologyProhibited(const std::string & type,bool prohibited)540 void FakeShillManagerClient::SetTechnologyProhibited(const std::string& type,
541                                                      bool prohibited) {
542   std::string prohibited_technologies =
543       GetStringValue(stub_properties_, shill::kProhibitedTechnologiesProperty);
544   std::vector<std::string> prohibited_list =
545       base::SplitString(prohibited_technologies, ",", base::TRIM_WHITESPACE,
546                         base::SPLIT_WANT_NONEMPTY);
547   std::set<std::string> prohibited_set(prohibited_list.begin(),
548                                        prohibited_list.end());
549   if (prohibited) {
550     auto iter = prohibited_set.find(type);
551     if (iter != prohibited_set.end())
552       return;
553     prohibited_set.insert(type);
554   } else {
555     auto iter = prohibited_set.find(type);
556     if (iter == prohibited_set.end())
557       return;
558     prohibited_set.erase(iter);
559   }
560   prohibited_list =
561       std::vector<std::string>(prohibited_set.begin(), prohibited_set.end());
562   prohibited_technologies = base::JoinString(prohibited_list, ",");
563   stub_properties_.SetStringKey(shill::kProhibitedTechnologiesProperty,
564                                 prohibited_technologies);
565   CallNotifyObserversPropertyChanged(shill::kProhibitedTechnologiesProperty);
566 }
567 
AddGeoNetwork(const std::string & technology,const base::Value & network)568 void FakeShillManagerClient::AddGeoNetwork(const std::string& technology,
569                                            const base::Value& network) {
570   base::Value* list_value =
571       stub_geo_networks_.FindKeyOfType(technology, base::Value::Type::LIST);
572   if (!list_value) {
573     list_value = stub_geo_networks_.SetKey(
574         technology, base::Value(base::Value::Type::LIST));
575   }
576   list_value->Append(network.Clone());
577 }
578 
AddProfile(const std::string & profile_path)579 void FakeShillManagerClient::AddProfile(const std::string& profile_path) {
580   const char* key = shill::kProfilesProperty;
581   if (GetListProperty(key)->AppendIfNotPresent(
582           std::make_unique<base::Value>(profile_path))) {
583     CallNotifyObserversPropertyChanged(key);
584   }
585 }
586 
ClearProperties()587 void FakeShillManagerClient::ClearProperties() {
588   stub_properties_ = base::Value(base::Value::Type::DICTIONARY);
589 }
590 
SetManagerProperty(const std::string & key,const base::Value & value)591 void FakeShillManagerClient::SetManagerProperty(const std::string& key,
592                                                 const base::Value& value) {
593   SetProperty(key, value, base::DoNothing(), base::BindOnce(&LogErrorCallback));
594 }
595 
AddManagerService(const std::string & service_path,bool notify_observers)596 void FakeShillManagerClient::AddManagerService(const std::string& service_path,
597                                                bool notify_observers) {
598   VLOG(2) << "AddManagerService: " << service_path;
599   GetListProperty(shill::kServiceCompleteListProperty)
600       ->AppendIfNotPresent(std::make_unique<base::Value>(service_path));
601   SortManagerServices(false);
602   if (notify_observers)
603     CallNotifyObserversPropertyChanged(shill::kServiceCompleteListProperty);
604 }
605 
RemoveManagerService(const std::string & service_path)606 void FakeShillManagerClient::RemoveManagerService(
607     const std::string& service_path) {
608   VLOG(2) << "RemoveManagerService: " << service_path;
609   base::Value service_path_value(service_path);
610   GetListProperty(shill::kServiceCompleteListProperty)
611       ->Remove(service_path_value, nullptr);
612   CallNotifyObserversPropertyChanged(shill::kServiceCompleteListProperty);
613 }
614 
ClearManagerServices()615 void FakeShillManagerClient::ClearManagerServices() {
616   VLOG(1) << "ClearManagerServices";
617   GetListProperty(shill::kServiceCompleteListProperty)->Clear();
618   CallNotifyObserversPropertyChanged(shill::kServiceCompleteListProperty);
619 }
620 
ServiceStateChanged(const std::string & service_path,const std::string & state)621 void FakeShillManagerClient::ServiceStateChanged(
622     const std::string& service_path,
623     const std::string& state) {
624   if (service_path == default_service_ && !IsConnectedState(state)) {
625     // Default service is no longer connected; clear.
626     default_service_.clear();
627     base::Value default_service_value(default_service_);
628     SetManagerProperty(shill::kDefaultServiceProperty, default_service_value);
629   }
630 }
631 
SortManagerServices(bool notify)632 void FakeShillManagerClient::SortManagerServices(bool notify) {
633   VLOG(1) << "SortManagerServices";
634 
635   // ServiceCompleteList contains string path values for each service.
636   base::Value* complete_path_list =
637       stub_properties_.FindListKey(shill::kServiceCompleteListProperty);
638   if (!complete_path_list || complete_path_list->GetList().empty())
639     return;
640   base::Value prev_complete_path_list = complete_path_list->Clone();
641 
642   base::Value* visible_services =
643       stub_properties_.FindListKey(shill::kServicesProperty);
644   if (!visible_services) {
645     visible_services = stub_properties_.SetKey(
646         shill::kServicesProperty, base::Value(base::Value::Type::LIST));
647   }
648 
649   // Networks for disabled services get appended to the end without sorting.
650   std::vector<std::string> disabled_path_list;
651 
652   // Build a list of dictionaries for each service in the list.
653   std::vector<base::Value> complete_dict_list;
654   for (const base::Value& value : complete_path_list->GetList()) {
655     std::string service_path = value.GetString();
656     const base::Value* properties =
657         ShillServiceClient::Get()->GetTestInterface()->GetServiceProperties(
658             service_path);
659     if (!properties) {
660       LOG(ERROR) << "Properties not found for service: " << service_path;
661       continue;
662     }
663 
664     std::string type = GetStringValue(*properties, shill::kTypeProperty);
665     if (!TechnologyEnabled(type)) {
666       disabled_path_list.push_back(service_path);
667       continue;
668     }
669 
670     base::Value properties_copy = properties->Clone();
671     properties_copy.SetKey(kPathKey, base::Value(service_path));
672     complete_dict_list.emplace_back(std::move(properties_copy));
673   }
674 
675   if (complete_dict_list.empty())
676     return;
677 
678   // Sort the service list using the same logic as Shill's Service::Compare.
679   std::sort(complete_dict_list.begin(), complete_dict_list.end(),
680             CompareNetworks);
681 
682   // Rebuild |complete_path_list| and |visible_services| with the new sort
683   // order.
684   complete_path_list->ClearList();
685   visible_services->ClearList();
686   for (const base::Value& dict : complete_dict_list) {
687     std::string service_path = GetStringValue(dict, kPathKey);
688     complete_path_list->Append(base::Value(service_path));
689     if (dict.FindBoolKey(shill::kVisibleProperty).value_or(false))
690       visible_services->Append(base::Value(service_path));
691   }
692   // Append disabled networks to the end of the complete path list.
693   for (const std::string& path : disabled_path_list)
694     complete_path_list->Append(base::Value(path));
695 
696   // Notify observers if the order changed.
697   if (notify && *complete_path_list != prev_complete_path_list)
698     CallNotifyObserversPropertyChanged(shill::kServiceCompleteListProperty);
699 
700   // Set the first connected service as the Default service. Note:
701   // |new_default_service| may be empty indicating no default network.
702   std::string new_default_service;
703   const base::Value& default_network = complete_dict_list[0];
704   if (IsConnectedState(
705           GetStringValue(default_network, shill::kStateProperty))) {
706     new_default_service = GetStringValue(default_network, kPathKey);
707   }
708   if (default_service_ != new_default_service) {
709     default_service_ = new_default_service;
710     SetManagerProperty(shill::kDefaultServiceProperty,
711                        base::Value(default_service_));
712   }
713 }
714 
GetInteractiveDelay() const715 base::TimeDelta FakeShillManagerClient::GetInteractiveDelay() const {
716   return interactive_delay_;
717 }
718 
SetInteractiveDelay(base::TimeDelta delay)719 void FakeShillManagerClient::SetInteractiveDelay(base::TimeDelta delay) {
720   interactive_delay_ = delay;
721 }
722 
SetBestServiceToConnect(const std::string & service_path)723 void FakeShillManagerClient::SetBestServiceToConnect(
724     const std::string& service_path) {
725   best_service_ = service_path;
726 }
727 
728 const ShillManagerClient::NetworkThrottlingStatus&
GetNetworkThrottlingStatus()729 FakeShillManagerClient::GetNetworkThrottlingStatus() {
730   return network_throttling_status_;
731 }
732 
SetNetworkThrottlingStatus(const NetworkThrottlingStatus & status,base::OnceClosure callback,ErrorCallback error_callback)733 void FakeShillManagerClient::SetNetworkThrottlingStatus(
734     const NetworkThrottlingStatus& status,
735     base::OnceClosure callback,
736     ErrorCallback error_callback) {
737   network_throttling_status_ = status;
738   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
739 }
740 
GetFastTransitionStatus()741 bool FakeShillManagerClient::GetFastTransitionStatus() {
742   base::Value* fast_transition_status = stub_properties_.FindKey(
743       base::StringPiece(shill::kWifiGlobalFTEnabledProperty));
744   return fast_transition_status && fast_transition_status->GetBool();
745 }
746 
SetSimulateConfigurationResult(FakeShillSimulatedResult configuration_result)747 void FakeShillManagerClient::SetSimulateConfigurationResult(
748     FakeShillSimulatedResult configuration_result) {
749   simulate_configuration_result_ = configuration_result;
750 }
751 
SetupDefaultEnvironment()752 void FakeShillManagerClient::SetupDefaultEnvironment() {
753   // Bail out from setup if there is no message loop. This will be the common
754   // case for tests that are not testing Shill.
755   if (!base::ThreadTaskRunnerHandle::IsSet())
756     return;
757 
758   ShillServiceClient::TestInterface* services =
759       ShillServiceClient::Get()->GetTestInterface();
760   DCHECK(services);
761   ShillProfileClient::TestInterface* profiles =
762       ShillProfileClient::Get()->GetTestInterface();
763   DCHECK(profiles);
764   ShillDeviceClient::TestInterface* devices =
765       ShillDeviceClient::Get()->GetTestInterface();
766   DCHECK(devices);
767   ShillIPConfigClient::TestInterface* ip_configs =
768       ShillIPConfigClient::Get()->GetTestInterface();
769   DCHECK(ip_configs);
770 
771   const std::string shared_profile = ShillProfileClient::GetSharedProfilePath();
772   profiles->AddProfile(shared_profile, std::string());
773 
774   const bool add_to_visible = true;
775 
776   // IPConfigs
777   base::Value ipconfig_v4_dictionary(base::Value::Type::DICTIONARY);
778   ipconfig_v4_dictionary.SetKey(shill::kAddressProperty,
779                                 base::Value("100.0.0.1"));
780   ipconfig_v4_dictionary.SetKey(shill::kGatewayProperty,
781                                 base::Value("100.0.0.2"));
782   ipconfig_v4_dictionary.SetKey(shill::kPrefixlenProperty, base::Value(1));
783   ipconfig_v4_dictionary.SetKey(shill::kMethodProperty,
784                                 base::Value(shill::kTypeIPv4));
785   ipconfig_v4_dictionary.SetKey(shill::kWebProxyAutoDiscoveryUrlProperty,
786                                 base::Value("http://wpad.com/wpad.dat"));
787   ip_configs->AddIPConfig("ipconfig_v4_path", ipconfig_v4_dictionary);
788   base::Value ipconfig_v6_dictionary(base::Value::Type::DICTIONARY);
789   ipconfig_v6_dictionary.SetKey(shill::kAddressProperty,
790                                 base::Value("0:0:0:0:100:0:0:1"));
791   ipconfig_v6_dictionary.SetKey(shill::kMethodProperty,
792                                 base::Value(shill::kTypeIPv6));
793   ip_configs->AddIPConfig("ipconfig_v6_path", ipconfig_v6_dictionary);
794 
795   bool enabled;
796   std::string state;
797 
798   // Ethernet
799   state = GetInitialStateForType(shill::kTypeEthernet, &enabled);
800   if (state == shill::kStateOnline || state == shill::kStateIdle) {
801     AddTechnology(shill::kTypeEthernet, enabled);
802     devices->AddDevice("/device/eth1", shill::kTypeEthernet,
803                        "stub_eth_device1");
804     SetInitialDeviceProperty("/device/eth1", shill::kAddressProperty,
805                              base::Value("0123456789ab"));
806     base::ListValue eth_ip_configs;
807     eth_ip_configs.AppendString("ipconfig_v4_path");
808     eth_ip_configs.AppendString("ipconfig_v6_path");
809     SetInitialDeviceProperty("/device/eth1", shill::kIPConfigsProperty,
810                              eth_ip_configs);
811     const std::string kFakeEthernetNetworkPath = "/service/eth1";
812     services->AddService(kFakeEthernetNetworkPath, kFakeEthernetNetworkGuid,
813                          "eth1" /* name */, shill::kTypeEthernet, state,
814                          add_to_visible);
815     profiles->AddService(shared_profile, kFakeEthernetNetworkPath);
816   }
817 
818   // Wifi
819   state = GetInitialStateForType(shill::kTypeWifi, &enabled);
820   if (state != kTechnologyUnavailable) {
821     bool portaled = false;
822     if (IsPortalledState(state)) {
823       portaled = true;
824       state = shill::kStateIdle;
825     }
826     AddTechnology(shill::kTypeWifi, enabled);
827     devices->AddDevice("/device/wifi1", shill::kTypeWifi, "stub_wifi_device1");
828     SetInitialDeviceProperty("/device/wifi1", shill::kAddressProperty,
829                              base::Value("23456789abcd"));
830     base::ListValue wifi_ip_configs;
831     wifi_ip_configs.AppendString("ipconfig_v4_path");
832     wifi_ip_configs.AppendString("ipconfig_v6_path");
833     SetInitialDeviceProperty("/device/wifi1", shill::kIPConfigsProperty,
834                              wifi_ip_configs);
835 
836     const std::string kWifi1Path = "/service/wifi1";
837     services->AddService(kWifi1Path, "wifi1_guid", "wifi1" /* name */,
838                          shill::kTypeWifi, state, add_to_visible);
839     services->SetServiceProperty(kWifi1Path, shill::kSecurityClassProperty,
840                                  base::Value(shill::kSecurityWep));
841     services->SetServiceProperty(kWifi1Path, shill::kConnectableProperty,
842                                  base::Value(true));
843     profiles->AddService(shared_profile, kWifi1Path);
844 
845     const std::string kWifi2Path = "/service/wifi2";
846     services->AddService(kWifi2Path, "wifi2_guid",
847                          s_dynamic_wep ? "wifi2_WEP" : "wifi2_PSK" /* name */,
848                          shill::kTypeWifi, shill::kStateIdle, add_to_visible);
849     if (s_dynamic_wep) {
850       services->SetServiceProperty(kWifi2Path, shill::kSecurityClassProperty,
851                                    base::Value(shill::kSecurityWep));
852       services->SetServiceProperty(kWifi2Path, shill::kEapKeyMgmtProperty,
853                                    base::Value(shill::kKeyManagementIEEE8021X));
854       services->SetServiceProperty(kWifi2Path, shill::kEapMethodProperty,
855                                    base::Value(shill::kEapMethodPEAP));
856       services->SetServiceProperty(kWifi2Path, shill::kEapIdentityProperty,
857                                    base::Value("John Doe"));
858     } else {
859       services->SetServiceProperty(kWifi2Path, shill::kSecurityClassProperty,
860                                    base::Value(shill::kSecurityPsk));
861     }
862     services->SetServiceProperty(kWifi2Path, shill::kConnectableProperty,
863                                  base::Value(false));
864     services->SetServiceProperty(kWifi2Path, shill::kPassphraseRequiredProperty,
865                                  base::Value(true));
866     services->SetServiceProperty(kWifi2Path, shill::kSignalStrengthProperty,
867                                  base::Value(80));
868     profiles->AddService(shared_profile, kWifi2Path);
869 
870     const std::string kWifi3Path = "/service/wifi3";
871     services->AddService(kWifi3Path, "", /* empty GUID */
872                          "wifi3" /* name */, shill::kTypeWifi,
873                          shill::kStateIdle, add_to_visible);
874     services->SetServiceProperty(kWifi3Path, shill::kSignalStrengthProperty,
875                                  base::Value(40));
876 
877     if (portaled) {
878       const std::string kPortaledWifiPath = "/service/portaled_wifi";
879       services->AddService(kPortaledWifiPath, "portaled_wifi_guid",
880                            "Portaled Wifi" /* name */, shill::kTypeWifi,
881                            shill::kStateIdle, add_to_visible);
882       services->SetServiceProperty(kPortaledWifiPath,
883                                    shill::kSecurityClassProperty,
884                                    base::Value(shill::kSecurityNone));
885       services->SetConnectBehavior(
886           kPortaledWifiPath,
887           base::BindRepeating(&UpdatePortaledWifiState, kPortaledWifiPath));
888       services->SetServiceProperty(
889           kPortaledWifiPath, shill::kConnectableProperty, base::Value(true));
890       profiles->AddService(shared_profile, kPortaledWifiPath);
891     }
892 
893     for (int i = 0; i < s_extra_wifi_networks; ++i) {
894       int id = 4 + i;
895       std::string path = base::StringPrintf("/service/wifi%d", id);
896       std::string guid = base::StringPrintf("wifi%d_guid", id);
897       std::string name = base::StringPrintf("wifi%d", id);
898       services->AddService(path, guid, name, shill::kTypeWifi,
899                            shill::kStateIdle, add_to_visible);
900     }
901   }
902 
903   // Cellular
904   state = GetInitialStateForType(shill::kTypeCellular, &enabled);
905   VLOG(1) << "Cellular state: " << state << " Enabled: " << enabled;
906   if (state == kTechnologyInitializing) {
907     SetTechnologyInitializing(shill::kTypeCellular, true);
908   } else if (state != kTechnologyUnavailable) {
909     bool activated = false;
910     if (state == kNetworkActivated) {
911       activated = true;
912       state = shill::kStateOnline;
913     }
914     AddTechnology(shill::kTypeCellular, enabled);
915     devices->AddDevice("/device/cellular1", shill::kTypeCellular,
916                        "stub_cellular_device1");
917     if (roaming_state_ == kRoamingRequired) {
918       SetInitialDeviceProperty("/device/cellular1",
919                                shill::kProviderRequiresRoamingProperty,
920                                base::Value(true));
921     }
922     if (cellular_technology_ == shill::kNetworkTechnologyGsm) {
923       SetInitialDeviceProperty("/device/cellular1",
924                                shill::kSupportNetworkScanProperty,
925                                base::Value(true));
926       SetInitialDeviceProperty("/device/cellular1", shill::kSIMPresentProperty,
927                                base::Value(true));
928       devices->SetSimLocked("/device/cellular1", false);
929     }
930 
931     if (state != shill::kStateIdle) {
932       services->AddService(kCellularServicePath, "cellular1_guid",
933                            "cellular1" /* name */, shill::kTypeCellular, state,
934                            add_to_visible);
935       base::Value technology_value(cellular_technology_);
936       SetInitialDeviceProperty("/device/cellular1",
937                                shill::kTechnologyFamilyProperty,
938                                technology_value);
939       services->SetServiceProperty(kCellularServicePath,
940                                    shill::kNetworkTechnologyProperty,
941                                    technology_value);
942       base::Value strength_value(50);
943       services->SetServiceProperty(
944           kCellularServicePath, shill::kSignalStrengthProperty, strength_value);
945 
946       if (activated) {
947         services->SetServiceProperty(
948             kCellularServicePath, shill::kActivationStateProperty,
949             base::Value(shill::kActivationStateActivated));
950         services->SetServiceProperty(kCellularServicePath,
951                                      shill::kConnectableProperty,
952                                      base::Value(true));
953       } else {
954         services->SetServiceProperty(
955             kCellularServicePath, shill::kActivationStateProperty,
956             base::Value(shill::kActivationStateNotActivated));
957       }
958 
959       base::Value payment_portal(base::Value::Type::DICTIONARY);
960       payment_portal.SetKey(shill::kPaymentPortalMethod, base::Value("POST"));
961       payment_portal.SetKey(shill::kPaymentPortalPostData,
962                             base::Value("iccid=123&imei=456&mdn=789"));
963       payment_portal.SetKey(shill::kPaymentPortalURL,
964                             base::Value(cellular_olp_));
965       services->SetServiceProperty(kCellularServicePath,
966                                    shill::kPaymentPortalProperty,
967                                    std::move(payment_portal));
968 
969       std::string shill_roaming_state;
970       if (roaming_state_ == kRoamingRequired)
971         shill_roaming_state = shill::kRoamingStateRoaming;
972       else if (roaming_state_.empty())
973         shill_roaming_state = shill::kRoamingStateHome;
974       else  // |roaming_state_| is expected to be a valid Shill state.
975         shill_roaming_state = roaming_state_;
976       services->SetServiceProperty(kCellularServicePath,
977                                    shill::kRoamingStateProperty,
978                                    base::Value(shill_roaming_state));
979 
980       base::Value apn(base::Value::Type::DICTIONARY);
981       apn.SetKey(shill::kApnProperty, base::Value("testapn"));
982       apn.SetKey(shill::kApnNameProperty, base::Value("Test APN"));
983       apn.SetKey(shill::kApnLocalizedNameProperty,
984                  base::Value("Localized Test APN"));
985       apn.SetKey(shill::kApnUsernameProperty, base::Value("User1"));
986       apn.SetKey(shill::kApnPasswordProperty, base::Value("password"));
987       apn.SetKey(shill::kApnAuthenticationProperty, base::Value("chap"));
988       base::Value apn2(base::Value::Type::DICTIONARY);
989       apn2.SetKey(shill::kApnProperty, base::Value("testapn2"));
990       services->SetServiceProperty(kCellularServicePath,
991                                    shill::kCellularApnProperty, apn);
992       services->SetServiceProperty(kCellularServicePath,
993                                    shill::kCellularLastGoodApnProperty, apn);
994       base::ListValue apn_list;
995       apn_list.Append(std::move(apn));
996       apn_list.Append(std::move(apn2));
997       SetInitialDeviceProperty("/device/cellular1",
998                                shill::kCellularApnListProperty, apn_list);
999 
1000       profiles->AddService(shared_profile, kCellularServicePath);
1001     }
1002   }
1003 
1004   // VPN
1005   state = GetInitialStateForType(shill::kTypeVPN, &enabled);
1006   if (state != kTechnologyUnavailable) {
1007     // Set the "Provider" dictionary properties. Note: when setting these in
1008     // Shill, "Provider.Type", etc keys are used, but when reading the values
1009     // "Provider" . "Type", etc keys are used. Here we are setting the values
1010     // that will be read (by the UI, tests, etc).
1011     base::Value provider_properties_openvpn(base::Value::Type::DICTIONARY);
1012     provider_properties_openvpn.SetStringKey(shill::kTypeProperty,
1013                                              shill::kProviderOpenVpn);
1014     provider_properties_openvpn.SetStringKey(shill::kHostProperty, "vpn_host");
1015 
1016     services->AddService("/service/vpn1", "vpn1_guid", "vpn1" /* name */,
1017                          shill::kTypeVPN, state, add_to_visible);
1018     services->SetServiceProperty("/service/vpn1", shill::kProviderProperty,
1019                                  provider_properties_openvpn);
1020     profiles->AddService(shared_profile, "/service/vpn1");
1021 
1022     base::Value provider_properties_l2tp(base::Value::Type::DICTIONARY);
1023     provider_properties_l2tp.SetStringKey(shill::kTypeProperty,
1024                                           shill::kProviderL2tpIpsec);
1025     provider_properties_l2tp.SetStringKey(shill::kHostProperty, "vpn_host2");
1026 
1027     services->AddService("/service/vpn2", "vpn2_guid", "vpn2" /* name */,
1028                          shill::kTypeVPN, shill::kStateIdle, add_to_visible);
1029     services->SetServiceProperty("/service/vpn2", shill::kProviderProperty,
1030                                  provider_properties_l2tp);
1031   }
1032 
1033   // Additional device states
1034   for (const auto& iter1 : shill_device_property_map_) {
1035     std::string device_type = iter1.first;
1036     std::string device_path = devices->GetDevicePathForType(device_type);
1037     for (const auto& iter2 : iter1.second)
1038       SetInitialDeviceProperty(device_path, iter2.first, iter2.second);
1039   }
1040   shill_device_property_map_.clear();
1041 
1042   SortManagerServices(true);
1043 }
1044 
1045 // Private methods
1046 
PassStubProperties(DBusMethodCallback<base::Value> callback) const1047 void FakeShillManagerClient::PassStubProperties(
1048     DBusMethodCallback<base::Value> callback) const {
1049   base::Value stub_properties = stub_properties_.Clone();
1050   stub_properties.SetKey(shill::kServiceCompleteListProperty,
1051                          GetEnabledServiceList());
1052   std::move(callback).Run(std::move(stub_properties));
1053 }
1054 
PassStubGeoNetworks(DBusMethodCallback<base::Value> callback) const1055 void FakeShillManagerClient::PassStubGeoNetworks(
1056     DBusMethodCallback<base::Value> callback) const {
1057   std::move(callback).Run(stub_geo_networks_.Clone());
1058 }
1059 
CallNotifyObserversPropertyChanged(const std::string & property)1060 void FakeShillManagerClient::CallNotifyObserversPropertyChanged(
1061     const std::string& property) {
1062   // Avoid unnecessary delayed task if we have no observers (e.g. during
1063   // initial setup).
1064   if (!observer_list_.might_have_observers())
1065     return;
1066   base::ThreadTaskRunnerHandle::Get()->PostTask(
1067       FROM_HERE,
1068       base::BindOnce(&FakeShillManagerClient::NotifyObserversPropertyChanged,
1069                      weak_ptr_factory_.GetWeakPtr(), property));
1070 }
1071 
NotifyObserversPropertyChanged(const std::string & property)1072 void FakeShillManagerClient::NotifyObserversPropertyChanged(
1073     const std::string& property) {
1074   VLOG(1) << "NotifyObserversPropertyChanged: " << property;
1075   base::Value* value = stub_properties_.FindKey(property);
1076   if (!value) {
1077     LOG(ERROR) << "Notify for unknown property: " << property;
1078     return;
1079   }
1080   if (property == shill::kServiceCompleteListProperty) {
1081     base::Value services = GetEnabledServiceList();
1082     for (auto& observer : observer_list_)
1083       observer.OnPropertyChanged(property, services);
1084     return;
1085   }
1086   for (auto& observer : observer_list_)
1087     observer.OnPropertyChanged(property, *value);
1088 }
1089 
GetListProperty(const std::string & property)1090 base::ListValue* FakeShillManagerClient::GetListProperty(
1091     const std::string& property) {
1092   base::Value* list_property =
1093       stub_properties_.FindKeyOfType(property, base::Value::Type::LIST);
1094   if (!list_property) {
1095     list_property =
1096         stub_properties_.SetKey(property, base::Value(base::Value::Type::LIST));
1097   }
1098   return static_cast<base::ListValue*>(list_property);
1099 }
1100 
TechnologyEnabled(const std::string & type) const1101 bool FakeShillManagerClient::TechnologyEnabled(const std::string& type) const {
1102   if (type == shill::kTypeVPN)
1103     return true;  // VPN is always "enabled" since there is no associated device
1104   if (type == shill::kTypeEthernetEap)
1105     return true;
1106   const base::Value* technologies =
1107       stub_properties_.FindListKey(shill::kEnabledTechnologiesProperty);
1108   if (technologies)
1109     return base::Contains(technologies->GetList(), base::Value(type));
1110   return false;
1111 }
1112 
SetTechnologyEnabled(const std::string & type,base::OnceClosure callback,bool enabled)1113 void FakeShillManagerClient::SetTechnologyEnabled(const std::string& type,
1114                                                   base::OnceClosure callback,
1115                                                   bool enabled) {
1116   base::ListValue* enabled_list =
1117       GetListProperty(shill::kEnabledTechnologiesProperty);
1118   if (enabled)
1119     enabled_list->AppendIfNotPresent(std::make_unique<base::Value>(type));
1120   else
1121     enabled_list->Remove(base::Value(type), nullptr);
1122   CallNotifyObserversPropertyChanged(shill::kEnabledTechnologiesProperty);
1123   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
1124   // May affect available services.
1125   SortManagerServices(true);
1126 }
1127 
GetEnabledServiceList() const1128 base::Value FakeShillManagerClient::GetEnabledServiceList() const {
1129   base::Value new_service_list(base::Value::Type::LIST);
1130   const base::Value* service_list =
1131       stub_properties_.FindListKey(shill::kServiceCompleteListProperty);
1132   if (service_list) {
1133     ShillServiceClient::TestInterface* service_client =
1134         ShillServiceClient::Get()->GetTestInterface();
1135     for (const base::Value& v : service_list->GetList()) {
1136       std::string service_path = v.GetString();
1137       const base::Value* properties =
1138           service_client->GetServiceProperties(service_path);
1139       if (!properties) {
1140         LOG(ERROR) << "Properties not found for service: " << service_path;
1141         continue;
1142       }
1143       const std::string* type = properties->FindStringKey(shill::kTypeProperty);
1144       if (type && TechnologyEnabled(*type))
1145         new_service_list.Append(v.Clone());
1146     }
1147   }
1148   return new_service_list;
1149 }
1150 
ScanCompleted(const std::string & device_path)1151 void FakeShillManagerClient::ScanCompleted(const std::string& device_path) {
1152   VLOG(1) << "ScanCompleted: " << device_path;
1153   if (!device_path.empty()) {
1154     ShillDeviceClient::Get()->GetTestInterface()->SetDeviceProperty(
1155         device_path, shill::kScanningProperty, base::Value(false),
1156         /*notify_changed=*/true);
1157   }
1158   CallNotifyObserversPropertyChanged(shill::kServiceCompleteListProperty);
1159 }
1160 
ParseCommandLineSwitch()1161 void FakeShillManagerClient::ParseCommandLineSwitch() {
1162   // Default setup
1163   SetInitialNetworkState(shill::kTypeEthernet, shill::kStateOnline);
1164   SetInitialNetworkState(shill::kTypeWifi, shill::kStateOnline);
1165   SetInitialNetworkState(shill::kTypeCellular, shill::kStateIdle);
1166   SetInitialNetworkState(shill::kTypeVPN, shill::kStateIdle);
1167 
1168   // Parse additional options
1169   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
1170   if (!command_line->HasSwitch(switches::kShillStub))
1171     return;
1172 
1173   std::string option_str =
1174       command_line->GetSwitchValueASCII(switches::kShillStub);
1175   VLOG(1) << "Parsing command line:" << option_str;
1176   base::StringPairs string_pairs;
1177   base::SplitStringIntoKeyValuePairs(option_str, '=', ',', &string_pairs);
1178   for (base::StringPairs::iterator iter = string_pairs.begin();
1179        iter != string_pairs.end(); ++iter) {
1180     ParseOption((*iter).first, (*iter).second);
1181   }
1182 }
1183 
ParseOption(const std::string & arg0,const std::string & arg1)1184 bool FakeShillManagerClient::ParseOption(const std::string& arg0,
1185                                          const std::string& arg1) {
1186   VLOG(1) << "Parsing command line option: '" << arg0 << "=" << arg1 << "'";
1187   if ((arg0 == "clear" || arg0 == "reset") && arg1 == "1") {
1188     shill_initial_state_map_.clear();
1189     return true;
1190   } else if (arg0 == "interactive") {
1191     int seconds = 3;
1192     if (!arg1.empty())
1193       base::StringToInt(arg1, &seconds);
1194     interactive_delay_ = base::TimeDelta::FromSeconds(seconds);
1195     return true;
1196   } else if (arg0 == "sim_lock") {
1197     bool locked = (arg1 == "1");
1198     base::Value simlock_dict(base::Value::Type::DICTIONARY);
1199     simlock_dict.SetBoolKey(shill::kSIMLockEnabledProperty, true);
1200     std::string lock_type = locked ? shill::kSIMLockPin : "";
1201     simlock_dict.SetStringKey(shill::kSIMLockTypeProperty, lock_type);
1202     if (locked) {
1203       simlock_dict.SetIntKey(shill::kSIMLockRetriesLeftProperty,
1204                              FakeShillDeviceClient::kSimPinRetryCount);
1205     }
1206     shill_device_property_map_[shill::kTypeCellular]
1207                               [shill::kSIMPresentProperty] = base::Value(true);
1208     shill_device_property_map_[shill::kTypeCellular]
1209                               [shill::kSIMLockStatusProperty] =
1210                                   std::move(simlock_dict);
1211     shill_device_property_map_[shill::kTypeCellular]
1212                               [shill::kTechnologyFamilyProperty] =
1213                                   base::Value(shill::kNetworkTechnologyGsm);
1214     return true;
1215   } else if (arg0 == "sim_present") {
1216     bool present = (arg1 == "1");
1217     shill_device_property_map_[shill::kTypeCellular]
1218                               [shill::kSIMPresentProperty] =
1219                                   base::Value(present);
1220     if (!present)
1221       shill_initial_state_map_[shill::kTypeCellular] = kNetworkDisabled;
1222     return true;
1223   } else if (arg0 == "olp") {
1224     cellular_olp_ = arg1;
1225     return true;
1226   } else if (arg0 == "roaming") {
1227     // "home", "roaming", or "required"
1228     roaming_state_ = arg1;
1229     return true;
1230   } else if (arg0 == "dynamic_wep" && arg1 == "1") {
1231     s_dynamic_wep = true;
1232     return true;
1233   }
1234   return SetInitialNetworkState(arg0, arg1);
1235 }
1236 
SetInitialNetworkState(std::string type_arg,const std::string & state_arg)1237 bool FakeShillManagerClient::SetInitialNetworkState(
1238     std::string type_arg,
1239     const std::string& state_arg) {
1240   int state_arg_as_int = -1;
1241   base::StringToInt(state_arg, &state_arg_as_int);
1242 
1243   std::string state;
1244   if (state_arg.empty() || state_arg == "1" || state_arg == "on" ||
1245       state_arg == "enabled" || state_arg == "connected" ||
1246       state_arg == "online" || state_arg == "inactive") {
1247     // Enabled and connected (default value)
1248     state = shill::kStateOnline;
1249   } else if (state_arg == "0" || state_arg == "off" ||
1250              state_arg == shill::kStateIdle) {
1251     // Technology enabled, services are created but are not connected.
1252     state = shill::kStateIdle;
1253   } else if (type_arg == shill::kTypeWifi && state_arg_as_int > 1) {
1254     // Enabled and connected, add extra wifi networks.
1255     state = shill::kStateOnline;
1256     s_extra_wifi_networks = state_arg_as_int - 1;
1257   } else if (state_arg == "disabled" || state_arg == "disconnect") {
1258     // Technology disabled but available, services created but not connected.
1259     state = kNetworkDisabled;
1260   } else if (state_arg == "none" || state_arg == "offline") {
1261     // Technology not available, do not create services.
1262     state = kTechnologyUnavailable;
1263   } else if (state_arg == "initializing") {
1264     // Technology available but not initialized.
1265     state = kTechnologyInitializing;
1266   } else if (state_arg == "portal") {
1267     // Technology is enabled, a service is connected and in Portal state.
1268     state = shill::kStateNoConnectivity;
1269   } else if (state_arg == "active" || state_arg == "activated") {
1270     // Technology is enabled, a service is connected and Activated.
1271     state = kNetworkActivated;
1272   } else if (type_arg == shill::kTypeCellular &&
1273              IsCellularTechnology(state_arg)) {
1274     state = shill::kStateOnline;
1275     cellular_technology_ = state_arg;
1276   } else if (type_arg == shill::kTypeCellular && state_arg == "LTEAdvanced") {
1277     // Special case, Shill name contains a ' '.
1278     state = shill::kStateOnline;
1279     cellular_technology_ = shill::kNetworkTechnologyLteAdvanced;
1280   } else {
1281     LOG(ERROR) << "Unrecognized initial state: " << type_arg << "="
1282                << state_arg;
1283     return false;
1284   }
1285 
1286   // Special cases
1287   if (type_arg == "wireless") {
1288     shill_initial_state_map_[shill::kTypeWifi] = state;
1289     shill_initial_state_map_[shill::kTypeCellular] = state;
1290     return true;
1291   }
1292   // Convenience synonyms.
1293   if (type_arg == "eth")
1294     type_arg = shill::kTypeEthernet;
1295 
1296   if (type_arg != shill::kTypeEthernet && type_arg != shill::kTypeWifi &&
1297       type_arg != shill::kTypeCellular && type_arg != shill::kTypeVPN) {
1298     LOG(WARNING) << "Unrecognized Shill network type: " << type_arg;
1299     return false;
1300   }
1301 
1302   // Disabled ethernet is the same as unavailable.
1303   if (type_arg == shill::kTypeEthernet && state == kNetworkDisabled)
1304     state = kTechnologyUnavailable;
1305 
1306   shill_initial_state_map_[type_arg] = state;
1307   return true;
1308 }
1309 
GetInitialStateForType(const std::string & type,bool * enabled)1310 std::string FakeShillManagerClient::GetInitialStateForType(
1311     const std::string& type,
1312     bool* enabled) {
1313   std::string result;
1314   std::map<std::string, std::string>::const_iterator iter =
1315       shill_initial_state_map_.find(type);
1316   if (iter == shill_initial_state_map_.end()) {
1317     *enabled = false;
1318     result = kTechnologyUnavailable;
1319   } else {
1320     std::string state = iter->second;
1321     if (state == kNetworkDisabled) {
1322       *enabled = false;
1323       result = shill::kStateIdle;
1324     } else {
1325       *enabled = true;
1326       result = state;
1327     }
1328     if ((IsPortalledState(state) && type != shill::kTypeWifi) ||
1329         (state == kNetworkActivated && type != shill::kTypeCellular)) {
1330       LOG(WARNING) << "Invalid state: " << state << " for " << type;
1331       result = shill::kStateIdle;
1332     }
1333   }
1334   VLOG(1) << "Initial state for: " << type << " = " << result
1335           << " Enabled: " << *enabled;
1336   return result;
1337 }
1338 
1339 }  // namespace chromeos
1340