[Extensions UI] Fix another chrome://extensions commands bug
[chromium-blink-merge.git] / chromeos / dbus / fake_shill_service_client.cc
blob990a37b559d99ba41421e83acb89c70235a44185
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"
7 #include "base/bind.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"
21 #include "dbus/bus.h"
22 #include "dbus/message.h"
23 #include "dbus/object_path.h"
24 #include "third_party/cros_system_api/dbus/service_constants.h"
26 namespace chromeos {
28 namespace {
30 void PassStubListValue(const ShillServiceClient::ListValueCallback& callback,
31 base::ListValue* value) {
32 callback.Run(*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();
52 } // namespace
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(),
87 &nested_dict);
88 if (nested_dict) {
89 result_properties.reset(nested_dict->DeepCopy());
90 // Remove credentials that Shill wouldn't send.
91 result_properties->RemoveWithoutPathExpansion(shill::kPassphraseProperty,
92 NULL);
93 call_status = DBUS_METHOD_CALL_SUCCESS;
94 } else {
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");
114 return;
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");
129 return;
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");
144 return;
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");
160 return;
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(
170 FROM_HERE,
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");
183 return;
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());
191 // Clear Error.
192 service_properties->SetStringWithoutPathExpansion(shill::kErrorProperty, "");
194 // Set Associating.
195 base::StringValue associating_value(shill::kStateAssociation);
196 SetServiceProperty(service_path.value(), shill::kStateProperty,
197 associating_value);
199 // Stay Associating until the state is changed again after a delay.
200 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
201 FROM_HERE,
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");
215 return;
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()));
225 callback.Run();
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(
250 FROM_HERE,
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());
281 } else {
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() {
292 return this;
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,
302 bool visible) {
303 AddServiceWithIPConfig(service_path, guid, name,
304 type, state, "" /* ipconfig_path */,
305 visible);
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,
315 bool visible) {
316 base::DictionaryValue* properties = SetServiceProperties(
317 service_path, guid, name, type, state, visible);
319 std::string profile_path;
320 if (properties->GetStringWithoutPathExpansion(shill::kProfileProperty,
321 &profile_path) &&
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,
343 bool visible) {
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()
352 ->GetTestInterface()
353 ->GetService(service_path, &profile_path, &profile_properties)) {
354 properties->SetStringWithoutPathExpansion(shill::kProfileProperty,
355 profile_path);
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,
364 &guid_to_set);
366 if (!guid_to_set.empty()) {
367 properties->SetStringWithoutPathExpansion(shill::kGuidProperty,
368 guid_to_set);
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()
375 ->GetTestInterface()
376 ->GetDevicePathForType(type);
377 properties->SetStringWithoutPathExpansion(shill::kDeviceProperty,
378 device_path);
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);
388 return properties;
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))
403 return false;
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
417 // as-is.
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);
428 CHECK(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)) {
433 cur_dict->Clear();
434 cur_dict->MergeDictionary(new_dict);
435 new_properties.SetWithoutPathExpansion(property, cur_value.release());
436 } else {
437 new_properties.SetWithoutPathExpansion(property, value.DeepCopy());
439 changed_property = property;
440 } else {
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);
455 } else {
456 LOG(ERROR) << "Profile value is not a String!";
458 } else {
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) {
468 std::string state;
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(
484 FROM_HERE,
485 base::Bind(&FakeShillServiceClient::NotifyObserversPropertyChanged,
486 weak_ptr_factory_.GetWeakPtr(), dbus::ObjectPath(service_path),
487 changed_property));
488 return true;
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);
495 return 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;
518 return;
520 base::Value* value = NULL;
521 if (!dict->GetWithoutPathExpansion(property, &value)) {
522 LOG(ERROR) << "Notify for unknown property: "
523 << path << " : " << property;
524 return;
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,
535 &properties) &&
536 create_if_missing) {
537 properties = new base::DictionaryValue;
538 stub_services_.Set(service_path, properties);
540 return 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(
557 service_path);
558 if (!service_properties) {
559 LOG(ERROR) << "Missing service: " << service_path;
560 return;
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)
569 continue;
570 base::DictionaryValue* properties;
571 if (!stub_services_.GetDictionaryWithoutPathExpansion(path, &properties))
572 NOTREACHED();
574 std::string type;
575 properties->GetString(shill::kTypeProperty, &type);
576 if (type != service_type)
577 continue;
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),
591 error_callback);
592 SetProperty(service_path,
593 shill::kConnectableProperty,
594 base::FundamentalValue(true),
595 base::Bind(&base::DoNothing),
596 error_callback);
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;
604 return;
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();
612 return;
615 // No custom connect behavior set, continue with the default connect behavior.
616 std::string passphrase;
617 service_properties->GetStringWithoutPathExpansion(shill::kPassphraseProperty,
618 &passphrase);
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(
626 FROM_HERE,
627 base::Bind(
628 base::IgnoreResult(&FakeShillServiceClient::SetServiceProperty),
629 weak_ptr_factory_.GetWeakPtr(), service_path, shill::kErrorProperty,
630 base::StringValue(shill::kErrorBadPassphrase)));
631 } else {
632 // Set Online.
633 VLOG(1) << "Setting state to Online " << service_path;
634 SetServiceProperty(service_path, shill::kStateProperty,
635 base::StringValue(shill::kStateOnline));
639 } // namespace chromeos