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.
5 #include "chromeos/dbus/fake_shill_service_client.h"
8 #include "base/bind_helpers.h"
9 #include "base/location.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/stl_util.h"
12 #include "base/strings/string_util.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "base/values.h"
15 #include "chromeos/dbus/dbus_thread_manager.h"
16 #include "chromeos/dbus/shill_device_client.h"
17 #include "chromeos/dbus/shill_manager_client.h"
18 #include "chromeos/dbus/shill_profile_client.h"
19 #include "chromeos/dbus/shill_property_changed_observer.h"
20 #include "chromeos/network/shill_property_util.h"
22 #include "dbus/message.h"
23 #include "dbus/object_path.h"
24 #include "third_party/cros_system_api/dbus/service_constants.h"
30 void PassStubListValue(const ShillServiceClient::ListValueCallback
& callback
,
31 base::ListValue
* value
) {
35 void PassStubServiceProperties(
36 const ShillServiceClient::DictionaryValueCallback
& callback
,
37 DBusMethodCallStatus call_status
,
38 const base::DictionaryValue
* properties
) {
39 callback
.Run(call_status
, *properties
);
42 void CallSortManagerServices() {
43 DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
44 SortManagerServices(true);
47 int GetInteractiveDelay() {
48 return DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
49 GetInteractiveDelay();
54 FakeShillServiceClient::FakeShillServiceClient() : weak_ptr_factory_(this) {
57 FakeShillServiceClient::~FakeShillServiceClient() {
58 STLDeleteContainerPairSecondPointers(
59 observer_list_
.begin(), observer_list_
.end());
63 // ShillServiceClient overrides.
65 void FakeShillServiceClient::Init(dbus::Bus
* bus
) {
68 void FakeShillServiceClient::AddPropertyChangedObserver(
69 const dbus::ObjectPath
& service_path
,
70 ShillPropertyChangedObserver
* observer
) {
71 GetObserverList(service_path
).AddObserver(observer
);
74 void FakeShillServiceClient::RemovePropertyChangedObserver(
75 const dbus::ObjectPath
& service_path
,
76 ShillPropertyChangedObserver
* observer
) {
77 GetObserverList(service_path
).RemoveObserver(observer
);
80 void FakeShillServiceClient::GetProperties(
81 const dbus::ObjectPath
& service_path
,
82 const DictionaryValueCallback
& callback
) {
83 base::DictionaryValue
* nested_dict
= NULL
;
84 scoped_ptr
<base::DictionaryValue
> result_properties
;
85 DBusMethodCallStatus call_status
;
86 stub_services_
.GetDictionaryWithoutPathExpansion(service_path
.value(),
89 result_properties
.reset(nested_dict
->DeepCopy());
90 // Remove credentials that Shill wouldn't send.
91 result_properties
->RemoveWithoutPathExpansion(shill::kPassphraseProperty
,
93 call_status
= DBUS_METHOD_CALL_SUCCESS
;
95 // This may happen if we remove services from the list.
96 VLOG(2) << "Properties not found for: " << service_path
.value();
97 result_properties
.reset(new base::DictionaryValue
);
98 call_status
= DBUS_METHOD_CALL_FAILURE
;
101 base::ThreadTaskRunnerHandle::Get()->PostTask(
102 FROM_HERE
, base::Bind(&PassStubServiceProperties
, callback
, call_status
,
103 base::Owned(result_properties
.release())));
106 void FakeShillServiceClient::SetProperty(const dbus::ObjectPath
& service_path
,
107 const std::string
& name
,
108 const base::Value
& value
,
109 const base::Closure
& callback
,
110 const ErrorCallback
& error_callback
) {
111 if (!SetServiceProperty(service_path
.value(), name
, value
)) {
112 LOG(ERROR
) << "Service not found: " << service_path
.value();
113 error_callback
.Run("Error.InvalidService", "Invalid Service");
116 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
, callback
);
119 void FakeShillServiceClient::SetProperties(
120 const dbus::ObjectPath
& service_path
,
121 const base::DictionaryValue
& properties
,
122 const base::Closure
& callback
,
123 const ErrorCallback
& error_callback
) {
124 for (base::DictionaryValue::Iterator
iter(properties
);
125 !iter
.IsAtEnd(); iter
.Advance()) {
126 if (!SetServiceProperty(service_path
.value(), iter
.key(), iter
.value())) {
127 LOG(ERROR
) << "Service not found: " << service_path
.value();
128 error_callback
.Run("Error.InvalidService", "Invalid Service");
132 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
, callback
);
135 void FakeShillServiceClient::ClearProperty(
136 const dbus::ObjectPath
& service_path
,
137 const std::string
& name
,
138 const base::Closure
& callback
,
139 const ErrorCallback
& error_callback
) {
140 base::DictionaryValue
* dict
= NULL
;
141 if (!stub_services_
.GetDictionaryWithoutPathExpansion(
142 service_path
.value(), &dict
)) {
143 error_callback
.Run("Error.InvalidService", "Invalid Service");
146 dict
->RemoveWithoutPathExpansion(name
, NULL
);
147 // Note: Shill does not send notifications when properties are cleared.
148 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
, callback
);
151 void FakeShillServiceClient::ClearProperties(
152 const dbus::ObjectPath
& service_path
,
153 const std::vector
<std::string
>& names
,
154 const ListValueCallback
& callback
,
155 const ErrorCallback
& error_callback
) {
156 base::DictionaryValue
* dict
= NULL
;
157 if (!stub_services_
.GetDictionaryWithoutPathExpansion(
158 service_path
.value(), &dict
)) {
159 error_callback
.Run("Error.InvalidService", "Invalid Service");
162 scoped_ptr
<base::ListValue
> results(new base::ListValue
);
163 for (std::vector
<std::string
>::const_iterator iter
= names
.begin();
164 iter
!= names
.end(); ++iter
) {
165 dict
->RemoveWithoutPathExpansion(*iter
, NULL
);
166 // Note: Shill does not send notifications when properties are cleared.
167 results
->AppendBoolean(true);
169 base::ThreadTaskRunnerHandle::Get()->PostTask(
171 base::Bind(&PassStubListValue
, callback
, base::Owned(results
.release())));
174 void FakeShillServiceClient::Connect(const dbus::ObjectPath
& service_path
,
175 const base::Closure
& callback
,
176 const ErrorCallback
& error_callback
) {
177 VLOG(1) << "FakeShillServiceClient::Connect: " << service_path
.value();
178 base::DictionaryValue
* service_properties
= NULL
;
179 if (!stub_services_
.GetDictionary(service_path
.value(),
180 &service_properties
)) {
181 LOG(ERROR
) << "Service not found: " << service_path
.value();
182 error_callback
.Run("Error.InvalidService", "Invalid Service");
186 // Set any other services of the same Type to 'offline' first, before setting
187 // State to Association which will trigger sorting Manager.Services and
188 // sending an update.
189 SetOtherServicesOffline(service_path
.value());
192 service_properties
->SetStringWithoutPathExpansion(shill::kErrorProperty
, "");
195 base::StringValue
associating_value(shill::kStateAssociation
);
196 SetServiceProperty(service_path
.value(), shill::kStateProperty
,
199 // Stay Associating until the state is changed again after a delay.
200 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
202 base::Bind(&FakeShillServiceClient::ContinueConnect
,
203 weak_ptr_factory_
.GetWeakPtr(), service_path
.value()),
204 base::TimeDelta::FromSeconds(GetInteractiveDelay()));
206 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
, callback
);
209 void FakeShillServiceClient::Disconnect(const dbus::ObjectPath
& service_path
,
210 const base::Closure
& callback
,
211 const ErrorCallback
& error_callback
) {
212 base::Value
* service
;
213 if (!stub_services_
.Get(service_path
.value(), &service
)) {
214 error_callback
.Run("Error.InvalidService", "Invalid Service");
217 // Set Idle after a delay
218 base::StringValue
idle_value(shill::kStateIdle
);
219 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
220 FROM_HERE
, base::Bind(&FakeShillServiceClient::SetProperty
,
221 weak_ptr_factory_
.GetWeakPtr(), service_path
,
222 shill::kStateProperty
, idle_value
,
223 base::Bind(&base::DoNothing
), error_callback
),
224 base::TimeDelta::FromSeconds(GetInteractiveDelay()));
228 void FakeShillServiceClient::Remove(const dbus::ObjectPath
& service_path
,
229 const base::Closure
& callback
,
230 const ErrorCallback
& error_callback
) {
231 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
, callback
);
234 void FakeShillServiceClient::ActivateCellularModem(
235 const dbus::ObjectPath
& service_path
,
236 const std::string
& carrier
,
237 const base::Closure
& callback
,
238 const ErrorCallback
& error_callback
) {
239 base::DictionaryValue
* service_properties
=
240 GetModifiableServiceProperties(service_path
.value(), false);
241 if (!service_properties
) {
242 LOG(ERROR
) << "Service not found: " << service_path
.value();
243 error_callback
.Run("Error.InvalidService", "Invalid Service");
245 SetServiceProperty(service_path
.value(),
246 shill::kActivationStateProperty
,
247 base::StringValue(shill::kActivationStateActivating
));
248 // Set Activated after a delay
249 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
251 base::Bind(&FakeShillServiceClient::SetCellularActivated
,
252 weak_ptr_factory_
.GetWeakPtr(), service_path
, error_callback
),
253 base::TimeDelta::FromSeconds(GetInteractiveDelay()));
255 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
, callback
);
258 void FakeShillServiceClient::CompleteCellularActivation(
259 const dbus::ObjectPath
& service_path
,
260 const base::Closure
& callback
,
261 const ErrorCallback
& error_callback
) {
262 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
, callback
);
265 void FakeShillServiceClient::GetLoadableProfileEntries(
266 const dbus::ObjectPath
& service_path
,
267 const DictionaryValueCallback
& callback
) {
268 // Provide a dictionary with a single { profile_path, service_path } entry
269 // if the Profile property is set, or an empty dictionary.
270 scoped_ptr
<base::DictionaryValue
> result_properties(
271 new base::DictionaryValue
);
272 base::DictionaryValue
* service_properties
=
273 GetModifiableServiceProperties(service_path
.value(), false);
274 if (service_properties
) {
275 std::string profile_path
;
276 if (service_properties
->GetStringWithoutPathExpansion(
277 shill::kProfileProperty
, &profile_path
)) {
278 result_properties
->SetStringWithoutPathExpansion(
279 profile_path
, service_path
.value());
282 LOG(WARNING
) << "Service not in profile: " << service_path
.value();
285 DBusMethodCallStatus call_status
= DBUS_METHOD_CALL_SUCCESS
;
286 base::ThreadTaskRunnerHandle::Get()->PostTask(
287 FROM_HERE
, base::Bind(&PassStubServiceProperties
, callback
, call_status
,
288 base::Owned(result_properties
.release())));
291 ShillServiceClient::TestInterface
* FakeShillServiceClient::GetTestInterface() {
295 // ShillServiceClient::TestInterface overrides.
297 void FakeShillServiceClient::AddService(const std::string
& service_path
,
298 const std::string
& guid
,
299 const std::string
& name
,
300 const std::string
& type
,
301 const std::string
& state
,
303 AddServiceWithIPConfig(service_path
, guid
, name
,
304 type
, state
, "" /* ipconfig_path */,
308 void FakeShillServiceClient::AddServiceWithIPConfig(
309 const std::string
& service_path
,
310 const std::string
& guid
,
311 const std::string
& name
,
312 const std::string
& type
,
313 const std::string
& state
,
314 const std::string
& ipconfig_path
,
316 base::DictionaryValue
* properties
= SetServiceProperties(
317 service_path
, guid
, name
, type
, state
, visible
);
319 std::string profile_path
;
320 if (properties
->GetStringWithoutPathExpansion(shill::kProfileProperty
,
322 !profile_path
.empty()) {
323 DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface()->
324 UpdateService(profile_path
, service_path
);
327 if (!ipconfig_path
.empty()) {
328 properties
->SetWithoutPathExpansion(
329 shill::kIPConfigProperty
,
330 new base::StringValue(ipconfig_path
));
333 DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
334 AddManagerService(service_path
, true);
337 base::DictionaryValue
* FakeShillServiceClient::SetServiceProperties(
338 const std::string
& service_path
,
339 const std::string
& guid
,
340 const std::string
& name
,
341 const std::string
& type
,
342 const std::string
& state
,
344 base::DictionaryValue
* properties
=
345 GetModifiableServiceProperties(service_path
, true);
346 connect_behavior_
.erase(service_path
);
348 std::string profile_path
;
349 base::DictionaryValue profile_properties
;
350 if (DBusThreadManager::Get()
351 ->GetShillProfileClient()
353 ->GetService(service_path
, &profile_path
, &profile_properties
)) {
354 properties
->SetStringWithoutPathExpansion(shill::kProfileProperty
,
358 // If |guid| is provided, set Service.GUID to that. Otherwise if a GUID is
359 // stored in a profile entry, use that. Otherwise leave it blank. Shill does
360 // not enforce a valid guid, we do that at the NetworkStateHandler layer.
361 std::string guid_to_set
= guid
;
362 if (guid_to_set
.empty()) {
363 profile_properties
.GetStringWithoutPathExpansion(shill::kGuidProperty
,
366 if (!guid_to_set
.empty()) {
367 properties
->SetStringWithoutPathExpansion(shill::kGuidProperty
,
370 properties
->SetStringWithoutPathExpansion(shill::kSSIDProperty
, name
);
371 shill_property_util::SetSSID(name
, properties
); // Sets kWifiHexSsid
372 properties
->SetStringWithoutPathExpansion(shill::kNameProperty
, name
);
373 std::string device_path
= DBusThreadManager::Get()
374 ->GetShillDeviceClient()
376 ->GetDevicePathForType(type
);
377 properties
->SetStringWithoutPathExpansion(shill::kDeviceProperty
,
379 properties
->SetStringWithoutPathExpansion(shill::kTypeProperty
, type
);
380 properties
->SetStringWithoutPathExpansion(shill::kStateProperty
, state
);
381 properties
->SetBooleanWithoutPathExpansion(shill::kVisibleProperty
, visible
);
382 if (type
== shill::kTypeWifi
) {
383 properties
->SetStringWithoutPathExpansion(shill::kSecurityClassProperty
,
384 shill::kSecurityNone
);
385 properties
->SetStringWithoutPathExpansion(shill::kModeProperty
,
386 shill::kModeManaged
);
391 void FakeShillServiceClient::RemoveService(const std::string
& service_path
) {
392 stub_services_
.RemoveWithoutPathExpansion(service_path
, NULL
);
393 connect_behavior_
.erase(service_path
);
394 DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
395 RemoveManagerService(service_path
);
398 bool FakeShillServiceClient::SetServiceProperty(const std::string
& service_path
,
399 const std::string
& property
,
400 const base::Value
& value
) {
401 base::DictionaryValue
* dict
= NULL
;
402 if (!stub_services_
.GetDictionaryWithoutPathExpansion(service_path
, &dict
))
405 VLOG(1) << "Service.SetProperty: " << property
<< " = " << value
406 << " For: " << service_path
;
408 base::DictionaryValue new_properties
;
409 std::string changed_property
;
410 bool case_sensitive
= true;
411 if (base::StartsWithASCII(property
, "Provider.", case_sensitive
) ||
412 base::StartsWithASCII(property
, "OpenVPN.", case_sensitive
) ||
413 base::StartsWithASCII(property
, "L2TPIPsec.", case_sensitive
)) {
414 // These properties are only nested within the Provider dictionary if read
415 // from Shill. Properties that start with "Provider" need to have that
416 // stripped off, other properties are nested in the "Provider" dictionary
418 std::string key
= property
;
419 if (base::StartsWithASCII(property
, "Provider.", case_sensitive
))
420 key
= property
.substr(strlen("Provider."));
421 base::DictionaryValue
* provider
= new base::DictionaryValue
;
422 provider
->SetWithoutPathExpansion(key
, value
.DeepCopy());
423 new_properties
.SetWithoutPathExpansion(shill::kProviderProperty
, provider
);
424 changed_property
= shill::kProviderProperty
;
425 } else if (value
.GetType() == base::Value::TYPE_DICTIONARY
) {
426 const base::DictionaryValue
* new_dict
= NULL
;
427 value
.GetAsDictionary(&new_dict
);
429 scoped_ptr
<base::Value
> cur_value
;
430 base::DictionaryValue
* cur_dict
;
431 if (dict
->RemoveWithoutPathExpansion(property
, &cur_value
) &&
432 cur_value
->GetAsDictionary(&cur_dict
)) {
434 cur_dict
->MergeDictionary(new_dict
);
435 new_properties
.SetWithoutPathExpansion(property
, cur_value
.release());
437 new_properties
.SetWithoutPathExpansion(property
, value
.DeepCopy());
439 changed_property
= property
;
441 new_properties
.SetWithoutPathExpansion(property
, value
.DeepCopy());
442 changed_property
= property
;
445 dict
->MergeDictionary(&new_properties
);
447 // Add or update the profile entry.
448 ShillProfileClient::TestInterface
* profile_test
=
449 DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface();
450 if (property
== shill::kProfileProperty
) {
451 std::string profile_path
;
452 if (value
.GetAsString(&profile_path
)) {
453 if (!profile_path
.empty())
454 profile_test
->AddService(profile_path
, service_path
);
456 LOG(ERROR
) << "Profile value is not a String!";
459 std::string profile_path
;
460 if (dict
->GetStringWithoutPathExpansion(
461 shill::kProfileProperty
, &profile_path
) && !profile_path
.empty()) {
462 profile_test
->UpdateService(profile_path
, service_path
);
466 // Notify the Manager if the state changed (affects DefaultService).
467 if (property
== shill::kStateProperty
) {
469 value
.GetAsString(&state
);
470 DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
471 ServiceStateChanged(service_path
, state
);
474 // If the State or Visibility changes, the sort order of service lists may
475 // change and the DefaultService property may change.
476 if (property
== shill::kStateProperty
||
477 property
== shill::kVisibleProperty
) {
478 base::ThreadTaskRunnerHandle::Get()->PostTask(
479 FROM_HERE
, base::Bind(&CallSortManagerServices
));
482 // Notifiy Chrome of the property change.
483 base::ThreadTaskRunnerHandle::Get()->PostTask(
485 base::Bind(&FakeShillServiceClient::NotifyObserversPropertyChanged
,
486 weak_ptr_factory_
.GetWeakPtr(), dbus::ObjectPath(service_path
),
491 const base::DictionaryValue
* FakeShillServiceClient::GetServiceProperties(
492 const std::string
& service_path
) const {
493 const base::DictionaryValue
* properties
= NULL
;
494 stub_services_
.GetDictionaryWithoutPathExpansion(service_path
, &properties
);
498 void FakeShillServiceClient::ClearServices() {
499 DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
500 ClearManagerServices();
502 stub_services_
.Clear();
503 connect_behavior_
.clear();
506 void FakeShillServiceClient::SetConnectBehavior(const std::string
& service_path
,
507 const base::Closure
& behavior
) {
508 connect_behavior_
[service_path
] = behavior
;
511 void FakeShillServiceClient::NotifyObserversPropertyChanged(
512 const dbus::ObjectPath
& service_path
,
513 const std::string
& property
) {
514 base::DictionaryValue
* dict
= NULL
;
515 std::string path
= service_path
.value();
516 if (!stub_services_
.GetDictionaryWithoutPathExpansion(path
, &dict
)) {
517 LOG(ERROR
) << "Notify for unknown service: " << path
;
520 base::Value
* value
= NULL
;
521 if (!dict
->GetWithoutPathExpansion(property
, &value
)) {
522 LOG(ERROR
) << "Notify for unknown property: "
523 << path
<< " : " << property
;
526 FOR_EACH_OBSERVER(ShillPropertyChangedObserver
,
527 GetObserverList(service_path
),
528 OnPropertyChanged(property
, *value
));
531 base::DictionaryValue
* FakeShillServiceClient::GetModifiableServiceProperties(
532 const std::string
& service_path
, bool create_if_missing
) {
533 base::DictionaryValue
* properties
= NULL
;
534 if (!stub_services_
.GetDictionaryWithoutPathExpansion(service_path
,
537 properties
= new base::DictionaryValue
;
538 stub_services_
.Set(service_path
, properties
);
543 FakeShillServiceClient::PropertyObserverList
&
544 FakeShillServiceClient::GetObserverList(const dbus::ObjectPath
& device_path
) {
545 std::map
<dbus::ObjectPath
, PropertyObserverList
*>::iterator iter
=
546 observer_list_
.find(device_path
);
547 if (iter
!= observer_list_
.end())
548 return *(iter
->second
);
549 PropertyObserverList
* observer_list
= new PropertyObserverList();
550 observer_list_
[device_path
] = observer_list
;
551 return *observer_list
;
554 void FakeShillServiceClient::SetOtherServicesOffline(
555 const std::string
& service_path
) {
556 const base::DictionaryValue
* service_properties
= GetServiceProperties(
558 if (!service_properties
) {
559 LOG(ERROR
) << "Missing service: " << service_path
;
562 std::string service_type
;
563 service_properties
->GetString(shill::kTypeProperty
, &service_type
);
564 // Set all other services of the same type to offline (Idle).
565 for (base::DictionaryValue::Iterator
iter(stub_services_
);
566 !iter
.IsAtEnd(); iter
.Advance()) {
567 std::string path
= iter
.key();
568 if (path
== service_path
)
570 base::DictionaryValue
* properties
;
571 if (!stub_services_
.GetDictionaryWithoutPathExpansion(path
, &properties
))
575 properties
->GetString(shill::kTypeProperty
, &type
);
576 if (type
!= service_type
)
578 properties
->SetWithoutPathExpansion(
579 shill::kStateProperty
,
580 new base::StringValue(shill::kStateIdle
));
584 void FakeShillServiceClient::SetCellularActivated(
585 const dbus::ObjectPath
& service_path
,
586 const ErrorCallback
& error_callback
) {
587 SetProperty(service_path
,
588 shill::kActivationStateProperty
,
589 base::StringValue(shill::kActivationStateActivated
),
590 base::Bind(&base::DoNothing
),
592 SetProperty(service_path
,
593 shill::kConnectableProperty
,
594 base::FundamentalValue(true),
595 base::Bind(&base::DoNothing
),
599 void FakeShillServiceClient::ContinueConnect(const std::string
& service_path
) {
600 VLOG(1) << "FakeShillServiceClient::ContinueConnect: " << service_path
;
601 base::DictionaryValue
* service_properties
= NULL
;
602 if (!stub_services_
.GetDictionary(service_path
, &service_properties
)) {
603 LOG(ERROR
) << "Service not found: " << service_path
;
607 if (ContainsKey(connect_behavior_
, service_path
)) {
608 const base::Closure
& custom_connect_behavior
=
609 connect_behavior_
[service_path
];
610 VLOG(1) << "Running custom connect behavior for " << service_path
;
611 custom_connect_behavior
.Run();
615 // No custom connect behavior set, continue with the default connect behavior.
616 std::string passphrase
;
617 service_properties
->GetStringWithoutPathExpansion(shill::kPassphraseProperty
,
619 if (passphrase
== "failure") {
620 // Simulate a password failure.
621 SetServiceProperty(service_path
, shill::kErrorProperty
,
622 base::StringValue(shill::kErrorBadPassphrase
));
623 SetServiceProperty(service_path
, shill::kStateProperty
,
624 base::StringValue(shill::kStateFailure
));
625 base::ThreadTaskRunnerHandle::Get()->PostTask(
628 base::IgnoreResult(&FakeShillServiceClient::SetServiceProperty
),
629 weak_ptr_factory_
.GetWeakPtr(), service_path
, shill::kErrorProperty
,
630 base::StringValue(shill::kErrorBadPassphrase
)));
633 VLOG(1) << "Setting state to Online " << service_path
;
634 SetServiceProperty(service_path
, shill::kStateProperty
,
635 base::StringValue(shill::kStateOnline
));
639 } // namespace chromeos