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