• 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_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 
22 namespace chromeos {
23 
24 struct FakeShillProfileClient::ProfileProperties {
25   base::DictionaryValue entries;  // Dictionary of Service Dictionaries
26   base::DictionaryValue properties;  // Dictionary of Profile properties
27 };
28 
29 namespace {
30 
PassDictionary(const ShillProfileClient::DictionaryValueCallbackWithoutStatus & callback,const base::DictionaryValue * dictionary)31 void PassDictionary(
32     const ShillProfileClient::DictionaryValueCallbackWithoutStatus& callback,
33     const base::DictionaryValue* dictionary) {
34   callback.Run(*dictionary);
35 }
36 
37 }  // namespace
38 
FakeShillProfileClient()39 FakeShillProfileClient::FakeShillProfileClient() {
40 }
41 
~FakeShillProfileClient()42 FakeShillProfileClient::~FakeShillProfileClient() {
43   STLDeleteValues(&profiles_);
44 }
45 
Init(dbus::Bus * bus)46 void FakeShillProfileClient::Init(dbus::Bus* bus) {
47 }
48 
AddPropertyChangedObserver(const dbus::ObjectPath & profile_path,ShillPropertyChangedObserver * observer)49 void FakeShillProfileClient::AddPropertyChangedObserver(
50     const dbus::ObjectPath& profile_path,
51     ShillPropertyChangedObserver* observer) {
52 }
53 
RemovePropertyChangedObserver(const dbus::ObjectPath & profile_path,ShillPropertyChangedObserver * observer)54 void FakeShillProfileClient::RemovePropertyChangedObserver(
55     const dbus::ObjectPath& profile_path,
56     ShillPropertyChangedObserver* observer) {
57 }
58 
GetProperties(const dbus::ObjectPath & profile_path,const DictionaryValueCallbackWithoutStatus & callback,const ErrorCallback & error_callback)59 void 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 
GetEntry(const dbus::ObjectPath & profile_path,const std::string & entry_path,const DictionaryValueCallbackWithoutStatus & callback,const ErrorCallback & error_callback)80 void 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 
DeleteEntry(const dbus::ObjectPath & profile_path,const std::string & entry_path,const base::Closure & callback,const ErrorCallback & error_callback)101 void 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 
GetTestInterface()123 ShillProfileClient::TestInterface* FakeShillProfileClient::GetTestInterface() {
124   return this;
125 }
126 
AddProfile(const std::string & profile_path,const std::string & userhash)127 void 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 
AddEntry(const std::string & profile_path,const std::string & entry_path,const base::DictionaryValue & properties)140 void 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, true);
149 }
150 
AddService(const std::string & profile_path,const std::string & service_path)151 bool 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                << " for: " << service_path;
158     return false;
159   }
160   if (profile->entries.HasKey(service_path))
161     return false;
162   return AddOrUpdateServiceImpl(profile_path, service_path, profile);
163 }
164 
UpdateService(const std::string & profile_path,const std::string & service_path)165 bool FakeShillProfileClient::UpdateService(const std::string& profile_path,
166                                            const std::string& service_path) {
167   ProfileProperties* profile = GetProfile(dbus::ObjectPath(profile_path),
168                                           ErrorCallback());
169   if (!profile) {
170     LOG(ERROR) << "UpdateService: No matching profile: " << profile_path
171                << " for: " << service_path;
172     return false;
173   }
174   if (!profile->entries.HasKey(service_path)) {
175     LOG(ERROR) << "UpdateService: Profile: " << profile_path
176                << " does not contain Service: " << service_path;
177     return false;
178   }
179   return AddOrUpdateServiceImpl(profile_path, service_path, profile);
180 }
181 
AddOrUpdateServiceImpl(const std::string & profile_path,const std::string & service_path,ProfileProperties * profile)182 bool FakeShillProfileClient::AddOrUpdateServiceImpl(
183     const std::string& profile_path,
184     const std::string& service_path,
185     ProfileProperties* profile) {
186   ShillServiceClient::TestInterface* service_test =
187       DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
188   const base::DictionaryValue* service_properties =
189       service_test->GetServiceProperties(service_path);
190   if (!service_properties) {
191     LOG(ERROR) << "No matching service: " << service_path;
192     return false;
193   }
194   std::string service_profile_path;
195   service_properties->GetStringWithoutPathExpansion(shill::kProfileProperty,
196                                                     &service_profile_path);
197   if (service_profile_path.empty()) {
198     base::StringValue profile_path_value(profile_path);
199     service_test->SetServiceProperty(service_path,
200                                      shill::kProfileProperty,
201                                      profile_path_value);
202   } else if (service_profile_path != profile_path) {
203     LOG(ERROR) << "Service has non matching profile path: "
204                << service_profile_path;
205     return false;
206   }
207 
208   profile->entries.SetWithoutPathExpansion(service_path,
209                                            service_properties->DeepCopy());
210   return true;
211 }
212 
GetProfilePaths(std::vector<std::string> * profiles)213 void FakeShillProfileClient::GetProfilePaths(
214     std::vector<std::string>* profiles) {
215   for (ProfileMap::iterator iter = profiles_.begin();
216        iter != profiles_.end(); ++iter) {
217     profiles->push_back(iter->first);
218   }
219 }
220 
GetService(const std::string & service_path,std::string * profile_path,base::DictionaryValue * properties)221 bool FakeShillProfileClient::GetService(const std::string& service_path,
222                                         std::string* profile_path,
223                                         base::DictionaryValue* properties) {
224   properties->Clear();
225   for (ProfileMap::const_iterator iter = profiles_.begin();
226        iter != profiles_.end(); ++iter) {
227     const ProfileProperties* profile = iter->second;
228     const base::DictionaryValue* entry;
229     if (!profile->entries.GetDictionaryWithoutPathExpansion(
230             service_path, &entry)) {
231       continue;
232     }
233     *profile_path = iter->first;
234     properties->MergeDictionary(entry);
235     return true;
236   }
237   return false;
238 }
239 
ClearProfiles()240 void FakeShillProfileClient::ClearProfiles() {
241   STLDeleteValues(&profiles_);
242 }
243 
GetProfile(const dbus::ObjectPath & profile_path,const ErrorCallback & error_callback)244 FakeShillProfileClient::ProfileProperties* FakeShillProfileClient::GetProfile(
245     const dbus::ObjectPath& profile_path,
246     const ErrorCallback& error_callback) {
247   ProfileMap::const_iterator found = profiles_.find(profile_path.value());
248   if (found == profiles_.end()) {
249     if (!error_callback.is_null())
250       error_callback.Run("Error.InvalidProfile", "Invalid profile");
251     return NULL;
252   }
253 
254   return found->second;
255 }
256 
257 }  // namespace chromeos
258