18bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
58bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chromeos/dbus/fake_shill_service_client.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/bind_helpers.h"
99ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "base/strings/string_util.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h"
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chromeos/dbus/shill_device_client.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/dbus/shill_manager_client.h"
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chromeos/dbus/shill_profile_client.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/dbus/shill_property_changed_observer.h"
184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/network/shill_property_util.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "dbus/bus.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "dbus/message.h"
2168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "dbus/object_path.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace chromeos {
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PassStubListValue(const ShillServiceClient::ListValueCallback& callback,
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       base::ListValue* value) {
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run(*value);
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void PassStubServiceProperties(
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ShillServiceClient::DictionaryValueCallback& callback,
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DBusMethodCallStatus call_status,
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue* properties) {
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run(call_status, *properties);
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void CallSortManagerServices() {
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      SortManagerServices(true);
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int GetInteractiveDelay() {
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      GetInteractiveDelay();
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)FakeShillServiceClient::FakeShillServiceClient() : weak_ptr_factory_(this) {
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)FakeShillServiceClient::~FakeShillServiceClient() {
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STLDeleteContainerPairSecondPointers(
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      observer_list_.begin(), observer_list_.end());
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
60c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ShillServiceClient overrides.
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void FakeShillServiceClient::Init(dbus::Bus* bus) {
64424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
65424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void FakeShillServiceClient::AddPropertyChangedObserver(
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const dbus::ObjectPath& service_path,
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ShillPropertyChangedObserver* observer) {
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GetObserverList(service_path).AddObserver(observer);
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void FakeShillServiceClient::RemovePropertyChangedObserver(
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const dbus::ObjectPath& service_path,
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ShillPropertyChangedObserver* observer) {
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GetObserverList(service_path).RemoveObserver(observer);
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void FakeShillServiceClient::GetProperties(
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const dbus::ObjectPath& service_path,
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const DictionaryValueCallback& callback) {
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::DictionaryValue* nested_dict = NULL;
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> result_properties;
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DBusMethodCallStatus call_status;
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stub_services_.GetDictionaryWithoutPathExpansion(service_path.value(),
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                   &nested_dict);
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (nested_dict) {
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    result_properties.reset(nested_dict->DeepCopy());
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Remove credentials that Shill wouldn't send.
8968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    result_properties->RemoveWithoutPathExpansion(shill::kPassphraseProperty,
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                  NULL);
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    call_status = DBUS_METHOD_CALL_SUCCESS;
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // This may happen if we remove services from the list.
94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    VLOG(2) << "Properties not found for: " << service_path.value();
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    result_properties.reset(new base::DictionaryValue);
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    call_status = DBUS_METHOD_CALL_FAILURE;
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::MessageLoop::current()->PostTask(
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&PassStubServiceProperties,
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 callback,
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 call_status,
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Owned(result_properties.release())));
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void FakeShillServiceClient::SetProperty(const dbus::ObjectPath& service_path,
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         const std::string& name,
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         const base::Value& value,
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         const base::Closure& callback,
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         const ErrorCallback& error_callback) {
1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!SetServiceProperty(service_path.value(), name, value)) {
1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    LOG(ERROR) << "Service not found: " << service_path.value();
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    error_callback.Run("Error.InvalidService", "Invalid Service");
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  base::MessageLoop::current()->PostTask(FROM_HERE, callback);
1187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void FakeShillServiceClient::SetProperties(
1217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const dbus::ObjectPath& service_path,
1227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const base::DictionaryValue& properties,
1237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const base::Closure& callback,
1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const ErrorCallback& error_callback) {
1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  for (base::DictionaryValue::Iterator iter(properties);
1267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch       !iter.IsAtEnd(); iter.Advance()) {
1277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (!SetServiceProperty(service_path.value(), iter.key(), iter.value())) {
1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      LOG(ERROR) << "Service not found: " << service_path.value();
1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      error_callback.Run("Error.InvalidService", "Invalid Service");
1307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return;
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::MessageLoop::current()->PostTask(FROM_HERE, callback);
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void FakeShillServiceClient::ClearProperty(
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const dbus::ObjectPath& service_path,
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& name,
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Closure& callback,
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ErrorCallback& error_callback) {
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue* dict = NULL;
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!stub_services_.GetDictionaryWithoutPathExpansion(
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      service_path.value(), &dict)) {
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    error_callback.Run("Error.InvalidService", "Invalid Service");
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
147a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  dict->RemoveWithoutPathExpansion(name, NULL);
148a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Note: Shill does not send notifications when properties are cleared.
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::MessageLoop::current()->PostTask(FROM_HERE, callback);
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void FakeShillServiceClient::ClearProperties(
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const dbus::ObjectPath& service_path,
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<std::string>& names,
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ListValueCallback& callback,
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ErrorCallback& error_callback) {
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue* dict = NULL;
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!stub_services_.GetDictionaryWithoutPathExpansion(
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      service_path.value(), &dict)) {
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    error_callback.Run("Error.InvalidService", "Invalid Service");
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::ListValue> results(new base::ListValue);
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::vector<std::string>::const_iterator iter = names.begin();
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      iter != names.end(); ++iter) {
166a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    dict->RemoveWithoutPathExpansion(*iter, NULL);
167a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // Note: Shill does not send notifications when properties are cleared.
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    results->AppendBoolean(true);
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::MessageLoop::current()->PostTask(
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&PassStubListValue,
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 callback, base::Owned(results.release())));
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void FakeShillServiceClient::Connect(const dbus::ObjectPath& service_path,
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     const base::Closure& callback,
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     const ErrorCallback& error_callback) {
1798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  VLOG(1) << "FakeShillServiceClient::Connect: " << service_path.value();
18068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  base::DictionaryValue* service_properties = NULL;
181ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!stub_services_.GetDictionary(
182ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          service_path.value(), &service_properties)) {
1837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    LOG(ERROR) << "Service not found: " << service_path.value();
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    error_callback.Run("Error.InvalidService", "Invalid Service");
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Set any other services of the same Type to 'offline' first, before setting
1893240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // State to Association which will trigger sorting Manager.Services and
1903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // sending an update.
1913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  SetOtherServicesOffline(service_path.value());
1923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Set Associating.
19468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  base::StringValue associating_value(shill::kStateAssociation);
195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SetServiceProperty(service_path.value(),
19668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                     shill::kStateProperty,
197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     associating_value);
1983240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
19968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Stay Associating until the state is changed again after a delay.
200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::MessageLoop::current()->PostDelayedTask(
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
2028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      base::Bind(&FakeShillServiceClient::ContinueConnect,
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
20468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                 service_path.value()),
205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::TimeDelta::FromSeconds(GetInteractiveDelay()));
20668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run();
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void FakeShillServiceClient::Disconnect(const dbus::ObjectPath& service_path,
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        const base::Closure& callback,
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        const ErrorCallback& error_callback) {
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Value* service;
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!stub_services_.Get(service_path.value(), &service)) {
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    error_callback.Run("Error.InvalidService", "Invalid Service");
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Set Idle after a delay
21968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  base::StringValue idle_value(shill::kStateIdle);
220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::MessageLoop::current()->PostDelayedTask(
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
2228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      base::Bind(&FakeShillServiceClient::SetProperty,
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 service_path,
22568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                 shill::kStateProperty,
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 idle_value,
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Bind(&base::DoNothing),
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 error_callback),
229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::TimeDelta::FromSeconds(GetInteractiveDelay()));
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run();
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void FakeShillServiceClient::Remove(const dbus::ObjectPath& service_path,
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    const base::Closure& callback,
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    const ErrorCallback& error_callback) {
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::MessageLoop::current()->PostTask(FROM_HERE, callback);
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void FakeShillServiceClient::ActivateCellularModem(
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const dbus::ObjectPath& service_path,
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& carrier,
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Closure& callback,
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ErrorCallback& error_callback) {
2443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::DictionaryValue* service_properties =
24568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      GetModifiableServiceProperties(service_path.value(), false);
2463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!service_properties) {
2473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    LOG(ERROR) << "Service not found: " << service_path.value();
2483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    error_callback.Run("Error.InvalidService", "Invalid Service");
2493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  SetServiceProperty(service_path.value(),
25168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                     shill::kActivationStateProperty,
25268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                     base::StringValue(shill::kActivationStateActivating));
2533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Set Activated after a delay
2543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::MessageLoop::current()->PostDelayedTask(
2553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      FROM_HERE,
2568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      base::Bind(&FakeShillServiceClient::SetCellularActivated,
2573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
2583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 service_path,
2593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 error_callback),
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::TimeDelta::FromSeconds(GetInteractiveDelay()));
2613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::MessageLoop::current()->PostTask(FROM_HERE, callback);
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void FakeShillServiceClient::CompleteCellularActivation(
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const dbus::ObjectPath& service_path,
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Closure& callback,
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ErrorCallback& error_callback) {
269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::MessageLoop::current()->PostTask(FROM_HERE, callback);
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void FakeShillServiceClient::GetLoadableProfileEntries(
273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const dbus::ObjectPath& service_path,
274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const DictionaryValueCallback& callback) {
275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Provide a dictionary with a single { profile_path, service_path } entry
276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // if the Profile property is set, or an empty dictionary.
277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<base::DictionaryValue> result_properties(
278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new base::DictionaryValue);
279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::DictionaryValue* service_properties =
28068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      GetModifiableServiceProperties(service_path.value(), false);
281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (service_properties) {
282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::string profile_path;
283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (service_properties->GetStringWithoutPathExpansion(
28468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            shill::kProfileProperty, &profile_path)) {
285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      result_properties->SetStringWithoutPathExpansion(
286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          profile_path, service_path.value());
287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  } else {
289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    LOG(WARNING) << "Service not in profile: " << service_path.value();
290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DBusMethodCallStatus call_status = DBUS_METHOD_CALL_SUCCESS;
293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::MessageLoop::current()->PostTask(
294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      FROM_HERE,
295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::Bind(&PassStubServiceProperties,
296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 callback,
297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 call_status,
298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 base::Owned(result_properties.release())));
299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)ShillServiceClient::TestInterface* FakeShillServiceClient::GetTestInterface() {
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return this;
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ShillServiceClient::TestInterface overrides.
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void FakeShillServiceClient::AddService(const std::string& service_path,
308116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                        const std::string& guid,
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        const std::string& name,
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        const std::string& type,
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        const std::string& state,
3126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                        bool visible) {
313116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  AddServiceWithIPConfig(service_path, guid, name,
314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                         type, state, "" /* ipconfig_path */,
3156d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                         visible);
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void FakeShillServiceClient::AddServiceWithIPConfig(
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& service_path,
320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::string& guid,
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& name,
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& type,
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& state,
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& ipconfig_path,
3256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    bool visible) {
3266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  base::DictionaryValue* properties = SetServiceProperties(
3276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      service_path, guid, name, type, state, visible);
3286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
3296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  std::string profile_path;
3306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (properties->GetStringWithoutPathExpansion(shill::kProfileProperty,
3316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                                &profile_path) &&
3326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      !profile_path.empty()) {
3336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface()->
3346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        UpdateService(profile_path, service_path);
3356d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3376d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (!ipconfig_path.empty()) {
3386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    properties->SetWithoutPathExpansion(
3396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        shill::kIPConfigProperty,
3406d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        new base::StringValue(ipconfig_path));
3416d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
3426d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
3436d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
3446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      AddManagerService(service_path, true);
3456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
3466d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
3476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
3486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)base::DictionaryValue* FakeShillServiceClient::SetServiceProperties(
3496d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const std::string& service_path,
3506d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const std::string& guid,
3516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const std::string& name,
3526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const std::string& type,
3536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const std::string& state,
3546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    bool visible) {
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue* properties =
35668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      GetModifiableServiceProperties(service_path, true);
35768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  connect_behavior_.erase(service_path);
358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::string profile_path;
360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::DictionaryValue profile_properties;
361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface()->
362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      GetService(service_path, &profile_path, &profile_properties)) {
363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    properties->SetWithoutPathExpansion(
364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        shill::kProfileProperty,
365cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        new base::StringValue(profile_path));
366cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
367cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // If |guid| is provided, set Service.GUID to that. Otherwise if a GUID is
369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // stored in a profile entry, use that. Otherwise leave it blank. Shill does
370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // not enforce a valid guid, we do that at the NetworkStateHandler layer.
371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::string guid_to_set = guid;
372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (guid_to_set.empty()) {
373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    profile_properties.GetStringWithoutPathExpansion(
374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        shill::kGuidProperty, &guid_to_set);
375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!guid_to_set.empty()) {
377cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    properties->SetWithoutPathExpansion(shill::kGuidProperty,
378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                        new base::StringValue(guid_to_set));
379cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
3804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  shill_property_util::SetSSID(name, properties);
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  properties->SetWithoutPathExpansion(
38268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      shill::kNameProperty,
383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new base::StringValue(name));
3846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  std::string device_path =
3856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface()->
3866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      GetDevicePathForType(type);
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  properties->SetWithoutPathExpansion(
3884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      shill::kDeviceProperty,
389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new base::StringValue(device_path));
3904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  properties->SetWithoutPathExpansion(
39168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      shill::kTypeProperty,
392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new base::StringValue(type));
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  properties->SetWithoutPathExpansion(
39468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      shill::kStateProperty,
395cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new base::StringValue(state));
396f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  properties->SetWithoutPathExpansion(
397f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      shill::kVisibleProperty,
3986d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      new base::FundamentalValue(visible));
399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (type == shill::kTypeWifi) {
400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    properties->SetWithoutPathExpansion(
401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        shill::kSecurityProperty,
402cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        new base::StringValue(shill::kSecurityNone));
403a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
4046d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  return properties;
405f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
407f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void FakeShillServiceClient::RemoveService(const std::string& service_path) {
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stub_services_.RemoveWithoutPathExpansion(service_path, NULL);
40968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  connect_behavior_.erase(service_path);
410f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
411f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      RemoveManagerService(service_path);
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool FakeShillServiceClient::SetServiceProperty(const std::string& service_path,
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                const std::string& property,
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                const base::Value& value) {
4177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  base::DictionaryValue* dict = NULL;
4187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!stub_services_.GetDictionaryWithoutPathExpansion(service_path, &dict))
4197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
4207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  VLOG(1) << "Service.SetProperty: " << property << " = " << value
4227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          << " For: " << service_path;
4233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
4243240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  base::DictionaryValue new_properties;
4253240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  std::string changed_property;
4263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  bool case_sensitive = true;
4273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (StartsWithASCII(property, "Provider.", case_sensitive) ||
4283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      StartsWithASCII(property, "OpenVPN.", case_sensitive) ||
4293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      StartsWithASCII(property, "L2TPIPsec.", case_sensitive)) {
4303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // These properties are only nested within the Provider dictionary if read
4313240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // from Shill.
4323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    base::DictionaryValue* provider = new base::DictionaryValue;
4333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    provider->SetWithoutPathExpansion(property, value.DeepCopy());
43468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    new_properties.SetWithoutPathExpansion(shill::kProviderProperty, provider);
43568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    changed_property = shill::kProviderProperty;
4363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  } else {
4373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    new_properties.SetWithoutPathExpansion(property, value.DeepCopy());
4383240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    changed_property = property;
4393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
4403240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
4413240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  dict->MergeDictionary(&new_properties);
4423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
443cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Add or update the profile entry.
444cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (property == shill::kProfileProperty) {
445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    std::string profile_path;
446cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (value.GetAsString(&profile_path)) {
447cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface()->
448cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          AddService(profile_path, service_path);
449cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    } else {
450cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      LOG(ERROR) << "Profile value is not a String!";
451cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
452cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
453cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    std::string profile_path;
454cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (dict->GetStringWithoutPathExpansion(
455cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            shill::kProfileProperty, &profile_path) && !profile_path.empty()) {
456cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface()->
457cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          UpdateService(profile_path, service_path);
458cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
459cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
460cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
461a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Notify the Manager if the state changed (affects DefaultService).
46268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (property == shill::kStateProperty) {
463a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    std::string state;
464a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    value.GetAsString(&state);
4653240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
466a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        ServiceStateChanged(service_path, state);
467a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
468a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
469f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // If the State or Visibility changes, the sort order of service lists may
470f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // change and the DefaultService property may change.
471f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (property == shill::kStateProperty ||
472f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      property == shill::kVisibleProperty) {
473a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::MessageLoop::current()->PostTask(
474a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        FROM_HERE, base::Bind(&CallSortManagerServices));
4757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
4763240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
477a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Notifiy Chrome of the property change.
4787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  base::MessageLoop::current()->PostTask(
4797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      FROM_HERE,
4808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      base::Bind(&FakeShillServiceClient::NotifyObserversPropertyChanged,
4817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                 weak_ptr_factory_.GetWeakPtr(),
4823240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                 dbus::ObjectPath(service_path), changed_property));
4837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)const base::DictionaryValue* FakeShillServiceClient::GetServiceProperties(
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& service_path) const {
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::DictionaryValue* properties = NULL;
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stub_services_.GetDictionaryWithoutPathExpansion(service_path, &properties);
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return properties;
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void FakeShillServiceClient::ClearServices() {
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
495a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      ClearManagerServices();
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stub_services_.Clear();
49868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  connect_behavior_.clear();
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void FakeShillServiceClient::SetConnectBehavior(const std::string& service_path,
50268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                const base::Closure& behavior) {
50368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  connect_behavior_[service_path] = behavior;
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void FakeShillServiceClient::NotifyObserversPropertyChanged(
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const dbus::ObjectPath& service_path,
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& property) {
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue* dict = NULL;
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string path = service_path.value();
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!stub_services_.GetDictionaryWithoutPathExpansion(path, &dict)) {
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "Notify for unknown service: " << path;
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Value* value = NULL;
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!dict->GetWithoutPathExpansion(property, &value)) {
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "Notify for unknown property: "
518a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)               << path << " : " << property;
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(ShillPropertyChangedObserver,
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    GetObserverList(service_path),
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    OnPropertyChanged(property, *value));
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)base::DictionaryValue* FakeShillServiceClient::GetModifiableServiceProperties(
52768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& service_path, bool create_if_missing) {
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue* properties = NULL;
52968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!stub_services_.GetDictionaryWithoutPathExpansion(service_path,
53068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                                        &properties) &&
53168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      create_if_missing) {
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    properties = new base::DictionaryValue;
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    stub_services_.Set(service_path, properties);
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return properties;
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)FakeShillServiceClient::PropertyObserverList&
5398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)FakeShillServiceClient::GetObserverList(const dbus::ObjectPath& device_path) {
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::map<dbus::ObjectPath, PropertyObserverList*>::iterator iter =
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      observer_list_.find(device_path);
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (iter != observer_list_.end())
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return *(iter->second);
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PropertyObserverList* observer_list = new PropertyObserverList();
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  observer_list_[device_path] = observer_list;
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return *observer_list;
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void FakeShillServiceClient::SetOtherServicesOffline(
5503240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const std::string& service_path) {
5513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  const base::DictionaryValue* service_properties = GetServiceProperties(
5523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      service_path);
5533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (!service_properties) {
5543240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    LOG(ERROR) << "Missing service: " << service_path;
5553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    return;
5563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
5573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  std::string service_type;
55868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  service_properties->GetString(shill::kTypeProperty, &service_type);
5593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Set all other services of the same type to offline (Idle).
5603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  for (base::DictionaryValue::Iterator iter(stub_services_);
5613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch       !iter.IsAtEnd(); iter.Advance()) {
5623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    std::string path = iter.key();
5633240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (path == service_path)
5643240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
5653240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    base::DictionaryValue* properties;
5663240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (!stub_services_.GetDictionaryWithoutPathExpansion(path, &properties))
5673240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      NOTREACHED();
5683240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
5693240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    std::string type;
57068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    properties->GetString(shill::kTypeProperty, &type);
5713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (type != service_type)
5723240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
5733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    properties->SetWithoutPathExpansion(
57468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        shill::kStateProperty,
575cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        new base::StringValue(shill::kStateIdle));
5763240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
5773240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
5783240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
5798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void FakeShillServiceClient::SetCellularActivated(
5803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const dbus::ObjectPath& service_path,
5813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const ErrorCallback& error_callback) {
5823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  SetProperty(service_path,
58368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)              shill::kActivationStateProperty,
58468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)              base::StringValue(shill::kActivationStateActivated),
5853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)              base::Bind(&base::DoNothing),
5863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)              error_callback);
5873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  SetProperty(service_path,
58868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)              shill::kConnectableProperty,
5893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)              base::FundamentalValue(true),
5903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)              base::Bind(&base::DoNothing),
5913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)              error_callback);
5923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void FakeShillServiceClient::ContinueConnect(
59568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& service_path) {
5968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  VLOG(1) << "FakeShillServiceClient::ContinueConnect: " << service_path;
59768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  base::DictionaryValue* service_properties = NULL;
59868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!stub_services_.GetDictionary(service_path, &service_properties)) {
59968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    LOG(ERROR) << "Service not found: " << service_path;
60068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
60168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
60268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
60368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (ContainsKey(connect_behavior_, service_path)) {
60468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const base::Closure& custom_connect_behavior =
60568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        connect_behavior_[service_path];
606116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    VLOG(1) << "Running custom connect behavior for " << service_path;
60768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    custom_connect_behavior.Run();
60868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
60968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
61068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
61168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // No custom connect behavior set, continue with the default connect behavior.
61268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::string passphrase;
61368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  service_properties->GetStringWithoutPathExpansion(
61468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      shill::kPassphraseProperty, &passphrase);
61568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (passphrase == "failure") {
61668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Simulate a password failure.
61768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    SetServiceProperty(service_path,
61868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                       shill::kStateProperty,
61968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                       base::StringValue(shill::kStateFailure));
62068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    base::MessageLoop::current()->PostTask(
62168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        FROM_HERE,
62268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        base::Bind(
6238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            base::IgnoreResult(&FakeShillServiceClient::SetServiceProperty),
62468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            weak_ptr_factory_.GetWeakPtr(),
62568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            service_path,
62668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            shill::kErrorProperty,
62768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            base::StringValue(shill::kErrorBadPassphrase)));
62868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  } else {
62968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Set Online.
630116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    VLOG(1) << "Setting state to Online " << service_path;
63168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    SetServiceProperty(service_path,
63268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                       shill::kStateProperty,
63368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                       base::StringValue(shill::kStateOnline));
63468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
63568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
63668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace chromeos
638