Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / chromeos / dbus / shill_manager_client_stub.cc
blobf19c5a5d2de8209759cc5ff623349f409562625c
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chromeos/dbus/shill_manager_client_stub.h"
7 #include "base/bind.h"
8 #include "base/chromeos/chromeos_version.h"
9 #include "base/command_line.h"
10 #include "base/message_loop.h"
11 #include "base/values.h"
12 #include "chromeos/chromeos_switches.h"
13 #include "chromeos/dbus/dbus_thread_manager.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/object_proxy.h"
20 #include "dbus/values_util.h"
21 #include "third_party/cros_system_api/dbus/service_constants.h"
23 namespace chromeos {
25 namespace {
27 // Used to compare values for finding entries to erase in a ListValue.
28 // (ListValue only implements a const_iterator version of Find).
29 struct ValueEquals {
30 explicit ValueEquals(const Value* first) : first_(first) {}
31 bool operator()(const Value* second) const {
32 return first_->Equals(second);
34 const Value* first_;
37 } // namespace
39 ShillManagerClientStub::ShillManagerClientStub()
40 : weak_ptr_factory_(this) {
41 SetDefaultProperties();
44 ShillManagerClientStub::~ShillManagerClientStub() {}
46 // ShillManagerClient overrides.
48 void ShillManagerClientStub::AddPropertyChangedObserver(
49 ShillPropertyChangedObserver* observer) {
50 observer_list_.AddObserver(observer);
53 void ShillManagerClientStub::RemovePropertyChangedObserver(
54 ShillPropertyChangedObserver* observer) {
55 observer_list_.RemoveObserver(observer);
58 void ShillManagerClientStub::GetProperties(
59 const DictionaryValueCallback& callback) {
60 if (callback.is_null())
61 return;
62 MessageLoop::current()->PostTask(
63 FROM_HERE, base::Bind(
64 &ShillManagerClientStub::PassStubProperties,
65 weak_ptr_factory_.GetWeakPtr(),
66 callback));
69 base::DictionaryValue* ShillManagerClientStub::CallGetPropertiesAndBlock() {
70 return stub_properties_.DeepCopy();
73 void ShillManagerClientStub::GetNetworksForGeolocation(
74 const DictionaryValueCallback& callback) {
75 if (callback.is_null())
76 return;
77 MessageLoop::current()->PostTask(
78 FROM_HERE, base::Bind(
79 &ShillManagerClientStub::PassStubGeoNetworks,
80 weak_ptr_factory_.GetWeakPtr(),
81 callback));
84 void ShillManagerClientStub::SetProperty(const std::string& name,
85 const base::Value& value,
86 const base::Closure& callback,
87 const ErrorCallback& error_callback) {
88 stub_properties_.SetWithoutPathExpansion(name, value.DeepCopy());
89 if (callback.is_null())
90 return;
91 MessageLoop::current()->PostTask(FROM_HERE, callback);
94 void ShillManagerClientStub::RequestScan(const std::string& type,
95 const base::Closure& callback,
96 const ErrorCallback& error_callback) {
97 const int kScanDelayMilliseconds = 3000;
98 CallNotifyObserversPropertyChanged(
99 flimflam::kServicesProperty, kScanDelayMilliseconds);
100 if (callback.is_null())
101 return;
102 MessageLoop::current()->PostTask(FROM_HERE, callback);
105 void ShillManagerClientStub::EnableTechnology(
106 const std::string& type,
107 const base::Closure& callback,
108 const ErrorCallback& error_callback) {
109 base::ListValue* enabled_list = NULL;
110 if (!stub_properties_.GetListWithoutPathExpansion(
111 flimflam::kEnabledTechnologiesProperty, &enabled_list)) {
112 if (!error_callback.is_null()) {
113 MessageLoop::current()->PostTask(FROM_HERE, callback);
114 MessageLoop::current()->PostTask(
115 FROM_HERE,
116 base::Bind(error_callback, "StubError", "Property not found"));
118 return;
120 enabled_list->AppendIfNotPresent(new base::StringValue(type));
121 CallNotifyObserversPropertyChanged(
122 flimflam::kEnabledTechnologiesProperty, 0);
123 if (!callback.is_null())
124 MessageLoop::current()->PostTask(FROM_HERE, callback);
125 // May affect available services
126 CallNotifyObserversPropertyChanged(flimflam::kServicesProperty, 0);
127 CallNotifyObserversPropertyChanged(flimflam::kServiceWatchListProperty, 0);
130 void ShillManagerClientStub::DisableTechnology(
131 const std::string& type,
132 const base::Closure& callback,
133 const ErrorCallback& error_callback) {
134 base::ListValue* enabled_list = NULL;
135 if (!stub_properties_.GetListWithoutPathExpansion(
136 flimflam::kEnabledTechnologiesProperty, &enabled_list)) {
137 if (!error_callback.is_null()) {
138 MessageLoop::current()->PostTask(
139 FROM_HERE,
140 base::Bind(error_callback, "StubError", "Property not found"));
142 return;
144 base::StringValue type_value(type);
145 enabled_list->Remove(type_value, NULL);
146 CallNotifyObserversPropertyChanged(
147 flimflam::kEnabledTechnologiesProperty, 0);
148 if (!callback.is_null())
149 MessageLoop::current()->PostTask(FROM_HERE, callback);
150 // May affect available services
151 CallNotifyObserversPropertyChanged(flimflam::kServicesProperty, 0);
152 CallNotifyObserversPropertyChanged(flimflam::kServiceWatchListProperty, 0);
155 void ShillManagerClientStub::ConfigureService(
156 const base::DictionaryValue& properties,
157 const ObjectPathCallback& callback,
158 const ErrorCallback& error_callback) {
159 if (callback.is_null())
160 return;
162 // For the purposes of this stub, we're going to assume that the GUID property
163 // is set to the service path because we don't want to re-implement Shill's
164 // property matching magic here.
165 ShillServiceClient::TestInterface* service_client =
166 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
168 std::string guid;
169 std::string type;
170 if (!properties.GetString(flimflam::kGuidProperty, &guid) ||
171 !properties.GetString(flimflam::kTypeProperty, &type)) {
172 // If the properties aren't filled out completely, then just return an empty
173 // object path.
174 MessageLoop::current()->PostTask(
175 FROM_HERE, base::Bind(callback, dbus::ObjectPath()));
176 return;
179 std::string ipconfig_path;
180 properties.GetString(shill::kIPConfigProperty, &ipconfig_path);
182 // Add the service to the service client stub if not already there.
183 service_client->AddServiceWithIPConfig(guid, guid, type, flimflam::kStateIdle,
184 ipconfig_path, true);
186 // Merge the new properties with existing properties, if any.
187 scoped_ptr<base::DictionaryValue> merged_properties;
188 const base::DictionaryValue* existing_properties =
189 service_client->GetServiceProperties(guid);
190 if (existing_properties) {
191 merged_properties.reset(existing_properties->DeepCopy());
192 } else {
193 merged_properties.reset(new base::DictionaryValue);
195 merged_properties->MergeDictionary(&properties);
197 // Now set all the properties.
198 for (base::DictionaryValue::Iterator iter(*merged_properties);
199 !iter.IsAtEnd(); iter.Advance()) {
200 service_client->SetServiceProperty(guid, iter.key(), iter.value());
203 MessageLoop::current()->PostTask(
204 FROM_HERE, base::Bind(callback, dbus::ObjectPath(guid)));
207 void ShillManagerClientStub::GetService(
208 const base::DictionaryValue& properties,
209 const ObjectPathCallback& callback,
210 const ErrorCallback& error_callback) {
211 if (callback.is_null())
212 return;
213 MessageLoop::current()->PostTask(
214 FROM_HERE, base::Bind(callback, dbus::ObjectPath()));
217 void ShillManagerClientStub::VerifyDestination(
218 const std::string& certificate,
219 const std::string& public_key,
220 const std::string& nonce,
221 const std::string& signed_data,
222 const std::string& device_serial,
223 const BooleanCallback& callback,
224 const ErrorCallback& error_callback) {
225 if (callback.is_null())
226 return;
227 MessageLoop::current()->PostTask(
228 FROM_HERE, base::Bind(callback, true));
231 void ShillManagerClientStub::VerifyAndEncryptCredentials(
232 const std::string& certificate,
233 const std::string& public_key,
234 const std::string& nonce,
235 const std::string& signed_data,
236 const std::string& device_serial,
237 const std::string& service_path,
238 const StringCallback& callback,
239 const ErrorCallback& error_callback) {
240 if (callback.is_null())
241 return;
242 MessageLoop::current()->PostTask(
243 FROM_HERE, base::Bind(callback, "encrypted_credentials"));
246 void ShillManagerClientStub::VerifyAndEncryptData(
247 const std::string& certificate,
248 const std::string& public_key,
249 const std::string& nonce,
250 const std::string& signed_data,
251 const std::string& device_serial,
252 const std::string& data,
253 const StringCallback& callback,
254 const ErrorCallback& error_callback) {
255 if (callback.is_null())
256 return;
257 MessageLoop::current()->PostTask(
258 FROM_HERE, base::Bind(callback, "encrypted_data"));
261 void ShillManagerClientStub::ConnectToBestServices(
262 const base::Closure& callback,
263 const ErrorCallback& error_callback) {
266 ShillManagerClient::TestInterface* ShillManagerClientStub::GetTestInterface() {
267 return this;
270 // ShillManagerClient::TestInterface overrides.
272 void ShillManagerClientStub::AddDevice(const std::string& device_path) {
273 if (GetListProperty(flimflam::kDevicesProperty)->AppendIfNotPresent(
274 base::Value::CreateStringValue(device_path))) {
275 CallNotifyObserversPropertyChanged(flimflam::kDevicesProperty, 0);
279 void ShillManagerClientStub::RemoveDevice(const std::string& device_path) {
280 base::StringValue device_path_value(device_path);
281 if (GetListProperty(flimflam::kDevicesProperty)->Remove(
282 device_path_value, NULL)) {
283 CallNotifyObserversPropertyChanged(flimflam::kDevicesProperty, 0);
287 void ShillManagerClientStub::ClearDevices() {
288 stub_properties_.Remove(flimflam::kDevicesProperty, NULL);
291 void ShillManagerClientStub::ClearServices() {
292 stub_properties_.Remove(flimflam::kServicesProperty, NULL);
293 stub_properties_.Remove(flimflam::kServiceWatchListProperty, NULL);
296 void ShillManagerClientStub::AddService(const std::string& service_path,
297 bool add_to_watch_list) {
298 if (GetListProperty(flimflam::kServicesProperty)->AppendIfNotPresent(
299 base::Value::CreateStringValue(service_path))) {
300 CallNotifyObserversPropertyChanged(flimflam::kServicesProperty, 0);
302 if (add_to_watch_list)
303 AddServiceToWatchList(service_path);
306 void ShillManagerClientStub::AddServiceAtIndex(const std::string& service_path,
307 size_t index,
308 bool add_to_watch_list) {
309 base::StringValue path_value(service_path);
310 base::ListValue* service_list =
311 GetListProperty(flimflam::kServicesProperty);
312 base::ListValue::iterator iter =
313 std::find_if(service_list->begin(), service_list->end(),
314 ValueEquals(&path_value));
315 service_list->Find(path_value);
316 if (iter != service_list->end())
317 service_list->Erase(iter, NULL);
318 service_list->Insert(index, path_value.DeepCopy());
319 CallNotifyObserversPropertyChanged(flimflam::kServicesProperty, 0);
320 if (add_to_watch_list)
321 AddServiceToWatchList(service_path);
324 void ShillManagerClientStub::RemoveService(const std::string& service_path) {
325 base::StringValue service_path_value(service_path);
326 if (GetListProperty(flimflam::kServicesProperty)->Remove(
327 service_path_value, NULL)) {
328 CallNotifyObserversPropertyChanged(flimflam::kServicesProperty, 0);
330 if (GetListProperty(flimflam::kServiceWatchListProperty)->Remove(
331 service_path_value, NULL)) {
332 CallNotifyObserversPropertyChanged(
333 flimflam::kServiceWatchListProperty, 0);
337 void ShillManagerClientStub::AddTechnology(const std::string& type,
338 bool enabled) {
339 if (GetListProperty(flimflam::kAvailableTechnologiesProperty)->
340 AppendIfNotPresent(base::Value::CreateStringValue(type))) {
341 CallNotifyObserversPropertyChanged(
342 flimflam::kAvailableTechnologiesProperty, 0);
344 if (enabled &&
345 GetListProperty(flimflam::kEnabledTechnologiesProperty)->
346 AppendIfNotPresent(base::Value::CreateStringValue(type))) {
347 CallNotifyObserversPropertyChanged(
348 flimflam::kEnabledTechnologiesProperty, 0);
352 void ShillManagerClientStub::RemoveTechnology(const std::string& type) {
353 base::StringValue type_value(type);
354 if (GetListProperty(flimflam::kAvailableTechnologiesProperty)->Remove(
355 type_value, NULL)) {
356 CallNotifyObserversPropertyChanged(
357 flimflam::kAvailableTechnologiesProperty, 0);
359 if (GetListProperty(flimflam::kEnabledTechnologiesProperty)->Remove(
360 type_value, NULL)) {
361 CallNotifyObserversPropertyChanged(
362 flimflam::kEnabledTechnologiesProperty, 0);
366 void ShillManagerClientStub::ClearProperties() {
367 stub_properties_.Clear();
370 void ShillManagerClientStub::AddGeoNetwork(
371 const std::string& technology,
372 const base::DictionaryValue& network) {
373 base::ListValue* list_value = NULL;
374 if (!stub_geo_networks_.GetListWithoutPathExpansion(
375 technology, &list_value)) {
376 list_value = new base::ListValue;
377 stub_geo_networks_.SetWithoutPathExpansion(technology, list_value);
379 list_value->Append(network.DeepCopy());
382 void ShillManagerClientStub::AddServiceToWatchList(
383 const std::string& service_path) {
384 if (GetListProperty(
385 flimflam::kServiceWatchListProperty)->AppendIfNotPresent(
386 base::Value::CreateStringValue(service_path))) {
387 CallNotifyObserversPropertyChanged(
388 flimflam::kServiceWatchListProperty, 0);
392 void ShillManagerClientStub::SetDefaultProperties() {
393 // Stub Technologies.
394 if (!CommandLine::ForCurrentProcess()->HasSwitch(
395 chromeos::switches::kDisableStubEthernet)) {
396 AddTechnology(flimflam::kTypeEthernet, true);
398 AddTechnology(flimflam::kTypeWifi, true);
399 AddTechnology(flimflam::kTypeCellular, true);
402 void ShillManagerClientStub::PassStubProperties(
403 const DictionaryValueCallback& callback) const {
404 scoped_ptr<base::DictionaryValue> stub_properties(
405 stub_properties_.DeepCopy());
406 // Remove disabled services from the list
407 stub_properties->SetWithoutPathExpansion(
408 flimflam::kServicesProperty,
409 GetEnabledServiceList(flimflam::kServicesProperty));
410 stub_properties->SetWithoutPathExpansion(
411 flimflam::kServiceWatchListProperty,
412 GetEnabledServiceList(flimflam::kServiceWatchListProperty));
413 callback.Run(DBUS_METHOD_CALL_SUCCESS, *stub_properties);
416 void ShillManagerClientStub::PassStubGeoNetworks(
417 const DictionaryValueCallback& callback) const {
418 callback.Run(DBUS_METHOD_CALL_SUCCESS, stub_geo_networks_);
421 void ShillManagerClientStub::CallNotifyObserversPropertyChanged(
422 const std::string& property,
423 int delay_ms) {
424 // Avoid unnecessary delayed task if we have no observers (e.g. during
425 // initial setup).
426 if (observer_list_.size() == 0)
427 return;
428 MessageLoop::current()->PostDelayedTask(
429 FROM_HERE,
430 base::Bind(&ShillManagerClientStub::NotifyObserversPropertyChanged,
431 weak_ptr_factory_.GetWeakPtr(),
432 property),
433 base::TimeDelta::FromMilliseconds(delay_ms));
436 void ShillManagerClientStub::NotifyObserversPropertyChanged(
437 const std::string& property) {
438 if (property == flimflam::kServicesProperty ||
439 property == flimflam::kServiceWatchListProperty) {
440 scoped_ptr<base::ListValue> services(GetEnabledServiceList(property));
441 FOR_EACH_OBSERVER(ShillPropertyChangedObserver,
442 observer_list_,
443 OnPropertyChanged(property, *(services.get())));
444 return;
446 base::Value* value = NULL;
447 if (!stub_properties_.GetWithoutPathExpansion(property, &value)) {
448 LOG(ERROR) << "Notify for unknown property: " << property;
449 return;
451 FOR_EACH_OBSERVER(ShillPropertyChangedObserver,
452 observer_list_,
453 OnPropertyChanged(property, *value));
456 base::ListValue* ShillManagerClientStub::GetListProperty(
457 const std::string& property) {
458 base::ListValue* list_property = NULL;
459 if (!stub_properties_.GetListWithoutPathExpansion(
460 property, &list_property)) {
461 list_property = new base::ListValue;
462 stub_properties_.SetWithoutPathExpansion(property, list_property);
464 return list_property;
467 bool ShillManagerClientStub::TechnologyEnabled(const std::string& type) const {
468 if (type == flimflam::kTypeVPN)
469 return true; // VPN is always "enabled" since there is no associated device
470 bool enabled = false;
471 const base::ListValue* technologies;
472 if (stub_properties_.GetListWithoutPathExpansion(
473 flimflam::kEnabledTechnologiesProperty, &technologies)) {
474 base::StringValue type_value(type);
475 if (technologies->Find(type_value) != technologies->end())
476 enabled = true;
478 return enabled;
481 base::ListValue* ShillManagerClientStub::GetEnabledServiceList(
482 const std::string& property) const {
483 base::ListValue* new_service_list = new base::ListValue;
484 const base::ListValue* service_list;
485 if (stub_properties_.GetListWithoutPathExpansion(property, &service_list)) {
486 ShillServiceClient::TestInterface* service_client =
487 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
488 for (base::ListValue::const_iterator iter = service_list->begin();
489 iter != service_list->end(); ++iter) {
490 std::string service_path;
491 if (!(*iter)->GetAsString(&service_path))
492 continue;
493 const base::DictionaryValue* properties =
494 service_client->GetServiceProperties(service_path);
495 if (!properties) {
496 LOG(ERROR) << "Properties not found for service: " << service_path;
497 continue;
499 std::string name;
500 properties->GetString(flimflam::kNameProperty, &name);
501 std::string type;
502 properties->GetString(flimflam::kTypeProperty, &type);
503 if (TechnologyEnabled(type))
504 new_service_list->Append((*iter)->DeepCopy());
507 return new_service_list;
510 } // namespace chromeos