• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_service_client.h"
6 
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/command_line.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/stl_util.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_manager_client.h"
17 #include "chromeos/dbus/shill_property_changed_observer.h"
18 #include "chromeos/dbus/shill_stub_helper.h"
19 #include "chromeos/network/shill_property_util.h"
20 #include "dbus/bus.h"
21 #include "dbus/message.h"
22 #include "dbus/object_path.h"
23 #include "third_party/cros_system_api/dbus/service_constants.h"
24 
25 namespace chromeos {
26 
27 namespace {
28 
PassStubListValue(const ShillServiceClient::ListValueCallback & callback,base::ListValue * value)29 void PassStubListValue(const ShillServiceClient::ListValueCallback& callback,
30                        base::ListValue* value) {
31   callback.Run(*value);
32 }
33 
PassStubServiceProperties(const ShillServiceClient::DictionaryValueCallback & callback,DBusMethodCallStatus call_status,const base::DictionaryValue * properties)34 void PassStubServiceProperties(
35     const ShillServiceClient::DictionaryValueCallback& callback,
36     DBusMethodCallStatus call_status,
37     const base::DictionaryValue* properties) {
38   callback.Run(call_status, *properties);
39 }
40 
41 }  // namespace
42 
FakeShillServiceClient()43 FakeShillServiceClient::FakeShillServiceClient() : weak_ptr_factory_(this) {
44 }
45 
~FakeShillServiceClient()46 FakeShillServiceClient::~FakeShillServiceClient() {
47   STLDeleteContainerPairSecondPointers(
48       observer_list_.begin(), observer_list_.end());
49 }
50 
51 
52 // ShillServiceClient overrides.
53 
Init(dbus::Bus * bus)54 void FakeShillServiceClient::Init(dbus::Bus* bus) {
55 }
56 
AddPropertyChangedObserver(const dbus::ObjectPath & service_path,ShillPropertyChangedObserver * observer)57 void FakeShillServiceClient::AddPropertyChangedObserver(
58     const dbus::ObjectPath& service_path,
59     ShillPropertyChangedObserver* observer) {
60   GetObserverList(service_path).AddObserver(observer);
61 }
62 
RemovePropertyChangedObserver(const dbus::ObjectPath & service_path,ShillPropertyChangedObserver * observer)63 void FakeShillServiceClient::RemovePropertyChangedObserver(
64     const dbus::ObjectPath& service_path,
65     ShillPropertyChangedObserver* observer) {
66   GetObserverList(service_path).RemoveObserver(observer);
67 }
68 
GetProperties(const dbus::ObjectPath & service_path,const DictionaryValueCallback & callback)69 void FakeShillServiceClient::GetProperties(
70     const dbus::ObjectPath& service_path,
71     const DictionaryValueCallback& callback) {
72   base::DictionaryValue* nested_dict = NULL;
73   scoped_ptr<base::DictionaryValue> result_properties;
74   DBusMethodCallStatus call_status;
75   stub_services_.GetDictionaryWithoutPathExpansion(service_path.value(),
76                                                    &nested_dict);
77   if (nested_dict) {
78     result_properties.reset(nested_dict->DeepCopy());
79     // Remove credentials that Shill wouldn't send.
80     result_properties->RemoveWithoutPathExpansion(shill::kPassphraseProperty,
81                                                   NULL);
82     call_status = DBUS_METHOD_CALL_SUCCESS;
83   } else {
84     LOG(ERROR) << "Properties not found for: " << service_path.value();
85     result_properties.reset(new base::DictionaryValue);
86     call_status = DBUS_METHOD_CALL_FAILURE;
87   }
88 
89   base::MessageLoop::current()->PostTask(
90       FROM_HERE,
91       base::Bind(&PassStubServiceProperties,
92                  callback,
93                  call_status,
94                  base::Owned(result_properties.release())));
95 }
96 
SetProperty(const dbus::ObjectPath & service_path,const std::string & name,const base::Value & value,const base::Closure & callback,const ErrorCallback & error_callback)97 void FakeShillServiceClient::SetProperty(const dbus::ObjectPath& service_path,
98                                          const std::string& name,
99                                          const base::Value& value,
100                                          const base::Closure& callback,
101                                          const ErrorCallback& error_callback) {
102   if (!SetServiceProperty(service_path.value(), name, value)) {
103     LOG(ERROR) << "Service not found: " << service_path.value();
104     error_callback.Run("Error.InvalidService", "Invalid Service");
105     return;
106   }
107   base::MessageLoop::current()->PostTask(FROM_HERE, callback);
108 }
109 
SetProperties(const dbus::ObjectPath & service_path,const base::DictionaryValue & properties,const base::Closure & callback,const ErrorCallback & error_callback)110 void FakeShillServiceClient::SetProperties(
111     const dbus::ObjectPath& service_path,
112     const base::DictionaryValue& properties,
113     const base::Closure& callback,
114     const ErrorCallback& error_callback) {
115   for (base::DictionaryValue::Iterator iter(properties);
116        !iter.IsAtEnd(); iter.Advance()) {
117     if (!SetServiceProperty(service_path.value(), iter.key(), iter.value())) {
118       LOG(ERROR) << "Service not found: " << service_path.value();
119       error_callback.Run("Error.InvalidService", "Invalid Service");
120       return;
121     }
122   }
123   base::MessageLoop::current()->PostTask(FROM_HERE, callback);
124 }
125 
ClearProperty(const dbus::ObjectPath & service_path,const std::string & name,const base::Closure & callback,const ErrorCallback & error_callback)126 void FakeShillServiceClient::ClearProperty(
127     const dbus::ObjectPath& service_path,
128     const std::string& name,
129     const base::Closure& callback,
130     const ErrorCallback& error_callback) {
131   base::DictionaryValue* dict = NULL;
132   if (!stub_services_.GetDictionaryWithoutPathExpansion(
133       service_path.value(), &dict)) {
134     error_callback.Run("Error.InvalidService", "Invalid Service");
135     return;
136   }
137   dict->RemoveWithoutPathExpansion(name, NULL);
138   // Note: Shill does not send notifications when properties are cleared.
139   base::MessageLoop::current()->PostTask(FROM_HERE, callback);
140 }
141 
ClearProperties(const dbus::ObjectPath & service_path,const std::vector<std::string> & names,const ListValueCallback & callback,const ErrorCallback & error_callback)142 void FakeShillServiceClient::ClearProperties(
143     const dbus::ObjectPath& service_path,
144     const std::vector<std::string>& names,
145     const ListValueCallback& callback,
146     const ErrorCallback& error_callback) {
147   base::DictionaryValue* dict = NULL;
148   if (!stub_services_.GetDictionaryWithoutPathExpansion(
149       service_path.value(), &dict)) {
150     error_callback.Run("Error.InvalidService", "Invalid Service");
151     return;
152   }
153   scoped_ptr<base::ListValue> results(new base::ListValue);
154   for (std::vector<std::string>::const_iterator iter = names.begin();
155       iter != names.end(); ++iter) {
156     dict->RemoveWithoutPathExpansion(*iter, NULL);
157     // Note: Shill does not send notifications when properties are cleared.
158     results->AppendBoolean(true);
159   }
160   base::MessageLoop::current()->PostTask(
161       FROM_HERE,
162       base::Bind(&PassStubListValue,
163                  callback, base::Owned(results.release())));
164 }
165 
Connect(const dbus::ObjectPath & service_path,const base::Closure & callback,const ErrorCallback & error_callback)166 void FakeShillServiceClient::Connect(const dbus::ObjectPath& service_path,
167                                      const base::Closure& callback,
168                                      const ErrorCallback& error_callback) {
169   VLOG(1) << "FakeShillServiceClient::Connect: " << service_path.value();
170   base::DictionaryValue* service_properties = NULL;
171   if (!stub_services_.GetDictionary(
172           service_path.value(), &service_properties)) {
173     LOG(ERROR) << "Service not found: " << service_path.value();
174     error_callback.Run("Error.InvalidService", "Invalid Service");
175     return;
176   }
177 
178   // Set any other services of the same Type to 'offline' first, before setting
179   // State to Association which will trigger sorting Manager.Services and
180   // sending an update.
181   SetOtherServicesOffline(service_path.value());
182 
183   // Set Associating.
184   base::StringValue associating_value(shill::kStateAssociation);
185   SetServiceProperty(service_path.value(),
186                      shill::kStateProperty,
187                      associating_value);
188 
189   // Stay Associating until the state is changed again after a delay.
190   base::TimeDelta delay;
191   if (CommandLine::ForCurrentProcess()->HasSwitch(
192           chromeos::switches::kEnableStubInteractive)) {
193     const int kConnectDelaySeconds = 5;
194     delay = base::TimeDelta::FromSeconds(kConnectDelaySeconds);
195   }
196   base::MessageLoop::current()->PostDelayedTask(
197       FROM_HERE,
198       base::Bind(&FakeShillServiceClient::ContinueConnect,
199                  weak_ptr_factory_.GetWeakPtr(),
200                  service_path.value()),
201       delay);
202 
203   callback.Run();
204 }
205 
Disconnect(const dbus::ObjectPath & service_path,const base::Closure & callback,const ErrorCallback & error_callback)206 void FakeShillServiceClient::Disconnect(const dbus::ObjectPath& service_path,
207                                         const base::Closure& callback,
208                                         const ErrorCallback& error_callback) {
209   base::Value* service;
210   if (!stub_services_.Get(service_path.value(), &service)) {
211     error_callback.Run("Error.InvalidService", "Invalid Service");
212     return;
213   }
214   base::TimeDelta delay;
215   if (CommandLine::ForCurrentProcess()->HasSwitch(
216           chromeos::switches::kEnableStubInteractive)) {
217     const int kConnectDelaySeconds = 2;
218     delay = base::TimeDelta::FromSeconds(kConnectDelaySeconds);
219   }
220   // Set Idle after a delay
221   base::StringValue idle_value(shill::kStateIdle);
222   base::MessageLoop::current()->PostDelayedTask(
223       FROM_HERE,
224       base::Bind(&FakeShillServiceClient::SetProperty,
225                  weak_ptr_factory_.GetWeakPtr(),
226                  service_path,
227                  shill::kStateProperty,
228                  idle_value,
229                  base::Bind(&base::DoNothing),
230                  error_callback),
231       delay);
232   callback.Run();
233 }
234 
Remove(const dbus::ObjectPath & service_path,const base::Closure & callback,const ErrorCallback & error_callback)235 void FakeShillServiceClient::Remove(const dbus::ObjectPath& service_path,
236                                     const base::Closure& callback,
237                                     const ErrorCallback& error_callback) {
238   base::MessageLoop::current()->PostTask(FROM_HERE, callback);
239 }
240 
ActivateCellularModem(const dbus::ObjectPath & service_path,const std::string & carrier,const base::Closure & callback,const ErrorCallback & error_callback)241 void FakeShillServiceClient::ActivateCellularModem(
242     const dbus::ObjectPath& service_path,
243     const std::string& carrier,
244     const base::Closure& callback,
245     const ErrorCallback& error_callback) {
246   base::DictionaryValue* service_properties =
247       GetModifiableServiceProperties(service_path.value(), false);
248   if (!service_properties) {
249     LOG(ERROR) << "Service not found: " << service_path.value();
250     error_callback.Run("Error.InvalidService", "Invalid Service");
251   }
252   SetServiceProperty(service_path.value(),
253                      shill::kActivationStateProperty,
254                      base::StringValue(shill::kActivationStateActivating));
255   base::TimeDelta delay;
256   if (CommandLine::ForCurrentProcess()->HasSwitch(
257           chromeos::switches::kEnableStubInteractive)) {
258     const int kConnectDelaySeconds = 2;
259     delay = base::TimeDelta::FromSeconds(kConnectDelaySeconds);
260   }
261   // Set Activated after a delay
262   base::MessageLoop::current()->PostDelayedTask(
263       FROM_HERE,
264       base::Bind(&FakeShillServiceClient::SetCellularActivated,
265                  weak_ptr_factory_.GetWeakPtr(),
266                  service_path,
267                  error_callback),
268       delay);
269 
270   base::MessageLoop::current()->PostTask(FROM_HERE, callback);
271 }
272 
CompleteCellularActivation(const dbus::ObjectPath & service_path,const base::Closure & callback,const ErrorCallback & error_callback)273 void FakeShillServiceClient::CompleteCellularActivation(
274     const dbus::ObjectPath& service_path,
275     const base::Closure& callback,
276     const ErrorCallback& error_callback) {
277   base::MessageLoop::current()->PostTask(FROM_HERE, callback);
278 }
279 
GetLoadableProfileEntries(const dbus::ObjectPath & service_path,const DictionaryValueCallback & callback)280 void FakeShillServiceClient::GetLoadableProfileEntries(
281     const dbus::ObjectPath& service_path,
282     const DictionaryValueCallback& callback) {
283   // Provide a dictionary with a single { profile_path, service_path } entry
284   // if the Profile property is set, or an empty dictionary.
285   scoped_ptr<base::DictionaryValue> result_properties(
286       new base::DictionaryValue);
287   base::DictionaryValue* service_properties =
288       GetModifiableServiceProperties(service_path.value(), false);
289   if (service_properties) {
290     std::string profile_path;
291     if (service_properties->GetStringWithoutPathExpansion(
292             shill::kProfileProperty, &profile_path)) {
293       result_properties->SetStringWithoutPathExpansion(
294           profile_path, service_path.value());
295     }
296   } else {
297     LOG(WARNING) << "Service not in profile: " << service_path.value();
298   }
299 
300   DBusMethodCallStatus call_status = DBUS_METHOD_CALL_SUCCESS;
301   base::MessageLoop::current()->PostTask(
302       FROM_HERE,
303       base::Bind(&PassStubServiceProperties,
304                  callback,
305                  call_status,
306                  base::Owned(result_properties.release())));
307 }
308 
GetTestInterface()309 ShillServiceClient::TestInterface* FakeShillServiceClient::GetTestInterface() {
310   return this;
311 }
312 
313 // ShillServiceClient::TestInterface overrides.
314 
AddService(const std::string & service_path,const std::string & name,const std::string & type,const std::string & state,bool add_to_visible_list,bool add_to_watch_list)315 void FakeShillServiceClient::AddService(const std::string& service_path,
316                                         const std::string& name,
317                                         const std::string& type,
318                                         const std::string& state,
319                                         bool add_to_visible_list,
320                                         bool add_to_watch_list) {
321   std::string nstate = state;
322   if (CommandLine::ForCurrentProcess()->HasSwitch(
323           chromeos::switches::kDefaultStubNetworkStateIdle)) {
324     nstate = shill::kStateIdle;
325   }
326   AddServiceWithIPConfig(service_path, name, type, nstate, "",
327                          add_to_visible_list, add_to_watch_list);
328 }
329 
AddServiceWithIPConfig(const std::string & service_path,const std::string & name,const std::string & type,const std::string & state,const std::string & ipconfig_path,bool add_to_visible_list,bool add_to_watch_list)330 void FakeShillServiceClient::AddServiceWithIPConfig(
331     const std::string& service_path,
332     const std::string& name,
333     const std::string& type,
334     const std::string& state,
335     const std::string& ipconfig_path,
336     bool add_to_visible_list,
337     bool add_to_watch_list) {
338   DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
339       AddManagerService(service_path, add_to_visible_list, add_to_watch_list);
340 
341   base::DictionaryValue* properties =
342       GetModifiableServiceProperties(service_path, true);
343   connect_behavior_.erase(service_path);
344   shill_property_util::SetSSID(name, properties);
345   properties->SetWithoutPathExpansion(
346       shill::kNameProperty,
347       base::Value::CreateStringValue(name));
348   properties->SetWithoutPathExpansion(
349       shill::kDeviceProperty,
350       base::Value::CreateStringValue(
351           shill_stub_helper::DevicePathForType(type)));
352   properties->SetWithoutPathExpansion(
353       shill::kTypeProperty,
354       base::Value::CreateStringValue(type));
355   properties->SetWithoutPathExpansion(
356       shill::kStateProperty,
357       base::Value::CreateStringValue(state));
358   if (!ipconfig_path.empty())
359     properties->SetWithoutPathExpansion(
360         shill::kIPConfigProperty,
361         base::Value::CreateStringValue(ipconfig_path));
362 }
363 
RemoveService(const std::string & service_path)364 void FakeShillServiceClient::RemoveService(const std::string& service_path) {
365   DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
366       RemoveManagerService(service_path);
367 
368   stub_services_.RemoveWithoutPathExpansion(service_path, NULL);
369   connect_behavior_.erase(service_path);
370 }
371 
SetServiceProperty(const std::string & service_path,const std::string & property,const base::Value & value)372 bool FakeShillServiceClient::SetServiceProperty(const std::string& service_path,
373                                                 const std::string& property,
374                                                 const base::Value& value) {
375   base::DictionaryValue* dict = NULL;
376   if (!stub_services_.GetDictionaryWithoutPathExpansion(service_path, &dict))
377     return false;
378 
379   VLOG(1) << "Service.SetProperty: " << property << " = " << value
380           << " For: " << service_path;
381 
382   base::DictionaryValue new_properties;
383   std::string changed_property;
384   bool case_sensitive = true;
385   if (StartsWithASCII(property, "Provider.", case_sensitive) ||
386       StartsWithASCII(property, "OpenVPN.", case_sensitive) ||
387       StartsWithASCII(property, "L2TPIPsec.", case_sensitive)) {
388     // These properties are only nested within the Provider dictionary if read
389     // from Shill.
390     base::DictionaryValue* provider = new base::DictionaryValue;
391     provider->SetWithoutPathExpansion(property, value.DeepCopy());
392     new_properties.SetWithoutPathExpansion(shill::kProviderProperty, provider);
393     changed_property = shill::kProviderProperty;
394   } else {
395     new_properties.SetWithoutPathExpansion(property, value.DeepCopy());
396     changed_property = property;
397   }
398 
399   dict->MergeDictionary(&new_properties);
400 
401   if (property == shill::kStateProperty) {
402     // When State changes the sort order of Services may change.
403     DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
404         SortManagerServices();
405   }
406 
407   base::MessageLoop::current()->PostTask(
408       FROM_HERE,
409       base::Bind(&FakeShillServiceClient::NotifyObserversPropertyChanged,
410                  weak_ptr_factory_.GetWeakPtr(),
411                  dbus::ObjectPath(service_path), changed_property));
412   return true;
413 }
414 
GetServiceProperties(const std::string & service_path) const415 const base::DictionaryValue* FakeShillServiceClient::GetServiceProperties(
416     const std::string& service_path) const {
417   const base::DictionaryValue* properties = NULL;
418   stub_services_.GetDictionaryWithoutPathExpansion(service_path, &properties);
419   return properties;
420 }
421 
ClearServices()422 void FakeShillServiceClient::ClearServices() {
423   DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
424       ClearManagerServices();
425 
426   stub_services_.Clear();
427   connect_behavior_.clear();
428 }
429 
SetConnectBehavior(const std::string & service_path,const base::Closure & behavior)430 void FakeShillServiceClient::SetConnectBehavior(const std::string& service_path,
431                                 const base::Closure& behavior) {
432   connect_behavior_[service_path] = behavior;
433 }
434 
NotifyObserversPropertyChanged(const dbus::ObjectPath & service_path,const std::string & property)435 void FakeShillServiceClient::NotifyObserversPropertyChanged(
436     const dbus::ObjectPath& service_path,
437     const std::string& property) {
438   base::DictionaryValue* dict = NULL;
439   std::string path = service_path.value();
440   if (!stub_services_.GetDictionaryWithoutPathExpansion(path, &dict)) {
441     LOG(ERROR) << "Notify for unknown service: " << path;
442     return;
443   }
444   base::Value* value = NULL;
445   if (!dict->GetWithoutPathExpansion(property, &value)) {
446     LOG(ERROR) << "Notify for unknown property: "
447                << path << " : " << property;
448     return;
449   }
450   FOR_EACH_OBSERVER(ShillPropertyChangedObserver,
451                     GetObserverList(service_path),
452                     OnPropertyChanged(property, *value));
453 }
454 
GetModifiableServiceProperties(const std::string & service_path,bool create_if_missing)455 base::DictionaryValue* FakeShillServiceClient::GetModifiableServiceProperties(
456     const std::string& service_path, bool create_if_missing) {
457   base::DictionaryValue* properties = NULL;
458   if (!stub_services_.GetDictionaryWithoutPathExpansion(service_path,
459                                                         &properties) &&
460       create_if_missing) {
461     properties = new base::DictionaryValue;
462     stub_services_.Set(service_path, properties);
463   }
464   return properties;
465 }
466 
467 FakeShillServiceClient::PropertyObserverList&
GetObserverList(const dbus::ObjectPath & device_path)468 FakeShillServiceClient::GetObserverList(const dbus::ObjectPath& device_path) {
469   std::map<dbus::ObjectPath, PropertyObserverList*>::iterator iter =
470       observer_list_.find(device_path);
471   if (iter != observer_list_.end())
472     return *(iter->second);
473   PropertyObserverList* observer_list = new PropertyObserverList();
474   observer_list_[device_path] = observer_list;
475   return *observer_list;
476 }
477 
SetOtherServicesOffline(const std::string & service_path)478 void FakeShillServiceClient::SetOtherServicesOffline(
479     const std::string& service_path) {
480   const base::DictionaryValue* service_properties = GetServiceProperties(
481       service_path);
482   if (!service_properties) {
483     LOG(ERROR) << "Missing service: " << service_path;
484     return;
485   }
486   std::string service_type;
487   service_properties->GetString(shill::kTypeProperty, &service_type);
488   // Set all other services of the same type to offline (Idle).
489   for (base::DictionaryValue::Iterator iter(stub_services_);
490        !iter.IsAtEnd(); iter.Advance()) {
491     std::string path = iter.key();
492     if (path == service_path)
493       continue;
494     base::DictionaryValue* properties;
495     if (!stub_services_.GetDictionaryWithoutPathExpansion(path, &properties))
496       NOTREACHED();
497 
498     std::string type;
499     properties->GetString(shill::kTypeProperty, &type);
500     if (type != service_type)
501       continue;
502     properties->SetWithoutPathExpansion(
503         shill::kStateProperty,
504         base::Value::CreateStringValue(shill::kStateIdle));
505   }
506 }
507 
SetCellularActivated(const dbus::ObjectPath & service_path,const ErrorCallback & error_callback)508 void FakeShillServiceClient::SetCellularActivated(
509     const dbus::ObjectPath& service_path,
510     const ErrorCallback& error_callback) {
511   SetProperty(service_path,
512               shill::kActivationStateProperty,
513               base::StringValue(shill::kActivationStateActivated),
514               base::Bind(&base::DoNothing),
515               error_callback);
516   SetProperty(service_path,
517               shill::kConnectableProperty,
518               base::FundamentalValue(true),
519               base::Bind(&base::DoNothing),
520               error_callback);
521 }
522 
ContinueConnect(const std::string & service_path)523 void FakeShillServiceClient::ContinueConnect(
524     const std::string& service_path) {
525   VLOG(1) << "FakeShillServiceClient::ContinueConnect: " << service_path;
526   base::DictionaryValue* service_properties = NULL;
527   if (!stub_services_.GetDictionary(service_path, &service_properties)) {
528     LOG(ERROR) << "Service not found: " << service_path;
529     return;
530   }
531 
532   if (ContainsKey(connect_behavior_, service_path)) {
533     const base::Closure& custom_connect_behavior =
534         connect_behavior_[service_path];
535     custom_connect_behavior.Run();
536     return;
537   }
538 
539   // No custom connect behavior set, continue with the default connect behavior.
540   std::string passphrase;
541   service_properties->GetStringWithoutPathExpansion(
542       shill::kPassphraseProperty, &passphrase);
543   if (passphrase == "failure") {
544     // Simulate a password failure.
545     SetServiceProperty(service_path,
546                        shill::kStateProperty,
547                        base::StringValue(shill::kStateFailure));
548     base::MessageLoop::current()->PostTask(
549         FROM_HERE,
550         base::Bind(
551             base::IgnoreResult(&FakeShillServiceClient::SetServiceProperty),
552             weak_ptr_factory_.GetWeakPtr(),
553             service_path,
554             shill::kErrorProperty,
555             base::StringValue(shill::kErrorBadPassphrase)));
556   } else {
557     // Set Online.
558     SetServiceProperty(service_path,
559                        shill::kStateProperty,
560                        base::StringValue(shill::kStateOnline));
561   }
562 }
563 
564 }  // namespace chromeos
565