fake_shill_profile_client.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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_profile_client.h"
6
7#include "base/bind.h"
8#include "base/bind_helpers.h"
9#include "base/message_loop/message_loop.h"
10#include "base/stl_util.h"
11#include "base/values.h"
12#include "chromeos/dbus/dbus_thread_manager.h"
13#include "chromeos/dbus/shill_manager_client.h"
14#include "chromeos/dbus/shill_property_changed_observer.h"
15#include "chromeos/dbus/shill_service_client.h"
16#include "dbus/bus.h"
17#include "dbus/message.h"
18#include "dbus/object_path.h"
19#include "dbus/values_util.h"
20#include "third_party/cros_system_api/dbus/service_constants.h"
21
22namespace chromeos {
23
24struct FakeShillProfileClient::ProfileProperties {
25  base::DictionaryValue entries;  // Dictionary of Service Dictionaries
26  base::DictionaryValue properties;  // Dictionary of Profile properties
27};
28
29namespace {
30
31void PassDictionary(
32    const ShillProfileClient::DictionaryValueCallbackWithoutStatus& callback,
33    const base::DictionaryValue* dictionary) {
34  callback.Run(*dictionary);
35}
36
37}  // namespace
38
39FakeShillProfileClient::FakeShillProfileClient() {
40}
41
42FakeShillProfileClient::~FakeShillProfileClient() {
43  STLDeleteValues(&profiles_);
44}
45
46void FakeShillProfileClient::Init(dbus::Bus* bus) {
47}
48
49void FakeShillProfileClient::AddPropertyChangedObserver(
50    const dbus::ObjectPath& profile_path,
51    ShillPropertyChangedObserver* observer) {
52}
53
54void FakeShillProfileClient::RemovePropertyChangedObserver(
55    const dbus::ObjectPath& profile_path,
56    ShillPropertyChangedObserver* observer) {
57}
58
59void FakeShillProfileClient::GetProperties(
60    const dbus::ObjectPath& profile_path,
61    const DictionaryValueCallbackWithoutStatus& callback,
62    const ErrorCallback& error_callback) {
63  ProfileProperties* profile = GetProfile(profile_path, error_callback);
64  if (!profile)
65    return;
66
67  scoped_ptr<base::DictionaryValue> properties(profile->properties.DeepCopy());
68  base::ListValue* entry_paths = new base::ListValue;
69  properties->SetWithoutPathExpansion(shill::kEntriesProperty, entry_paths);
70  for (base::DictionaryValue::Iterator it(profile->entries); !it.IsAtEnd();
71       it.Advance()) {
72    entry_paths->AppendString(it.key());
73  }
74
75  base::MessageLoop::current()->PostTask(
76      FROM_HERE,
77      base::Bind(&PassDictionary, callback, base::Owned(properties.release())));
78}
79
80void FakeShillProfileClient::GetEntry(
81    const dbus::ObjectPath& profile_path,
82    const std::string& entry_path,
83    const DictionaryValueCallbackWithoutStatus& callback,
84    const ErrorCallback& error_callback) {
85  ProfileProperties* profile = GetProfile(profile_path, error_callback);
86  if (!profile)
87    return;
88
89  base::DictionaryValue* entry = NULL;
90  profile->entries.GetDictionaryWithoutPathExpansion(entry_path, &entry);
91  if (!entry) {
92    error_callback.Run("Error.InvalidProfileEntry", "Invalid profile entry");
93    return;
94  }
95
96  base::MessageLoop::current()->PostTask(
97      FROM_HERE,
98      base::Bind(&PassDictionary, callback, base::Owned(entry->DeepCopy())));
99}
100
101void FakeShillProfileClient::DeleteEntry(const dbus::ObjectPath& profile_path,
102                                         const std::string& entry_path,
103                                         const base::Closure& callback,
104                                         const ErrorCallback& error_callback) {
105  ProfileProperties* profile = GetProfile(profile_path, error_callback);
106  if (!profile)
107    return;
108
109  if (!profile->entries.RemoveWithoutPathExpansion(entry_path, NULL)) {
110    error_callback.Run("Error.InvalidProfileEntry", entry_path);
111    return;
112  }
113
114  base::StringValue profile_path_value("");
115  DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface()->
116      SetServiceProperty(entry_path,
117                         shill::kProfileProperty,
118                         profile_path_value);
119
120  base::MessageLoop::current()->PostTask(FROM_HERE, callback);
121}
122
123ShillProfileClient::TestInterface* FakeShillProfileClient::GetTestInterface() {
124  return this;
125}
126
127void FakeShillProfileClient::AddProfile(const std::string& profile_path,
128                                        const std::string& userhash) {
129  if (GetProfile(dbus::ObjectPath(profile_path), ErrorCallback()))
130    return;
131
132  ProfileProperties* profile = new ProfileProperties;
133  profile->properties.SetStringWithoutPathExpansion(shill::kUserHashProperty,
134                                                    userhash);
135  profiles_[profile_path] = profile;
136  DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
137      AddProfile(profile_path);
138}
139
140void FakeShillProfileClient::AddEntry(const std::string& profile_path,
141                                      const std::string& entry_path,
142                                      const base::DictionaryValue& properties) {
143  ProfileProperties* profile = GetProfile(dbus::ObjectPath(profile_path),
144                                          ErrorCallback());
145  DCHECK(profile);
146  profile->entries.SetWithoutPathExpansion(entry_path, properties.DeepCopy());
147  DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
148      AddManagerService(entry_path, false /* visible */, false /* watch */);
149}
150
151bool FakeShillProfileClient::AddService(const std::string& profile_path,
152                                        const std::string& service_path) {
153  ProfileProperties* profile = GetProfile(dbus::ObjectPath(profile_path),
154                                          ErrorCallback());
155  if (!profile) {
156    LOG(ERROR) << "AddService: No matching profile: " << profile_path;
157    return false;
158  }
159  if (profile->entries.HasKey(service_path)) {
160    LOG(ERROR) << "AddService: Profile: " << profile_path
161               << " already contains Service: " << service_path;
162    return false;
163  }
164  return AddOrUpdateServiceImpl(profile_path, service_path, profile);
165}
166
167bool FakeShillProfileClient::UpdateService(const std::string& profile_path,
168                                           const std::string& service_path) {
169  ProfileProperties* profile = GetProfile(dbus::ObjectPath(profile_path),
170                                          ErrorCallback());
171  if (!profile) {
172    LOG(ERROR) << "UpdateService: No matching profile: " << profile_path;
173    return false;
174  }
175  if (!profile->entries.HasKey(service_path)) {
176    LOG(ERROR) << "UpdateService: Profile: " << profile_path
177               << " does not contain Service: " << service_path;
178    return false;
179  }
180  return AddOrUpdateServiceImpl(profile_path, service_path, profile);
181}
182
183bool FakeShillProfileClient::AddOrUpdateServiceImpl(
184    const std::string& profile_path,
185    const std::string& service_path,
186    ProfileProperties* profile) {
187  ShillServiceClient::TestInterface* service_test =
188      DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
189  const base::DictionaryValue* service_properties =
190      service_test->GetServiceProperties(service_path);
191  if (!service_properties) {
192    LOG(ERROR) << "No matching service: " << service_path;
193    return false;
194  }
195  std::string service_profile_path;
196  service_properties->GetStringWithoutPathExpansion(shill::kProfileProperty,
197                                                    &service_profile_path);
198  if (service_profile_path.empty()) {
199    base::StringValue profile_path_value(profile_path);
200    service_test->SetServiceProperty(service_path,
201                                     shill::kProfileProperty,
202                                     profile_path_value);
203  } else if (service_profile_path != profile_path) {
204    LOG(ERROR) << "Service has non matching profile path: "
205               << service_profile_path;
206    return false;
207  }
208
209  profile->entries.SetWithoutPathExpansion(service_path,
210                                           service_properties->DeepCopy());
211  return true;
212}
213
214void FakeShillProfileClient::GetProfilePaths(
215    std::vector<std::string>* profiles) {
216  for (ProfileMap::iterator iter = profiles_.begin();
217       iter != profiles_.end(); ++iter) {
218    profiles->push_back(iter->first);
219  }
220}
221
222bool FakeShillProfileClient::GetService(const std::string& service_path,
223                                        std::string* profile_path,
224                                        base::DictionaryValue* properties) {
225  properties->Clear();
226  for (ProfileMap::const_iterator iter = profiles_.begin();
227       iter != profiles_.end(); ++iter) {
228    const ProfileProperties* profile = iter->second;
229    const base::DictionaryValue* entry;
230    if (!profile->entries.GetDictionaryWithoutPathExpansion(
231            service_path, &entry)) {
232      continue;
233    }
234    *profile_path = iter->first;
235    properties->MergeDictionary(entry);
236    return true;
237  }
238  return false;
239}
240
241void FakeShillProfileClient::ClearProfiles() {
242  STLDeleteValues(&profiles_);
243}
244
245FakeShillProfileClient::ProfileProperties* FakeShillProfileClient::GetProfile(
246    const dbus::ObjectPath& profile_path,
247    const ErrorCallback& error_callback) {
248  ProfileMap::const_iterator found = profiles_.find(profile_path.value());
249  if (found == profiles_.end()) {
250    if (!error_callback.is_null())
251      error_callback.Run("Error.InvalidProfile", "Invalid profile");
252    return NULL;
253  }
254
255  return found->second;
256}
257
258}  // namespace chromeos
259