1 //
2 // Copyright (C) 2015 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include "shill/dbus/chromeos_dbus_objectmanager_proxy.h"
18
19 #include <memory>
20
21 #include "shill/cellular/cellular_error.h"
22 #include "shill/event_dispatcher.h"
23 #include "shill/logging.h"
24
25 using std::string;
26
27 namespace shill {
28
29 namespace Logging {
30 static auto kModuleLogScope = ScopeLogger::kDBus;
ObjectID(const dbus::ObjectPath * p)31 static string ObjectID(const dbus::ObjectPath* p) { return p->value(); }
32 }
33
ChromeosDBusObjectManagerProxy(EventDispatcher * dispatcher,const scoped_refptr<dbus::Bus> & bus,const std::string & path,const std::string & service,const base::Closure & service_appeared_callback,const base::Closure & service_vanished_callback)34 ChromeosDBusObjectManagerProxy::ChromeosDBusObjectManagerProxy(
35 EventDispatcher* dispatcher,
36 const scoped_refptr<dbus::Bus>& bus,
37 const std::string& path,
38 const std::string& service,
39 const base::Closure& service_appeared_callback,
40 const base::Closure& service_vanished_callback)
41 : proxy_(
42 new org::freedesktop::DBus::ObjectManagerProxy(
43 bus, service, dbus::ObjectPath(path))),
44 dispatcher_(dispatcher),
45 service_appeared_callback_(service_appeared_callback),
46 service_vanished_callback_(service_vanished_callback),
47 service_available_(false) {
48 // Register signal handlers.
49 proxy_->RegisterInterfacesAddedSignalHandler(
50 base::Bind(&ChromeosDBusObjectManagerProxy::InterfacesAdded,
51 weak_factory_.GetWeakPtr()),
52 base::Bind(&ChromeosDBusObjectManagerProxy::OnSignalConnected,
53 weak_factory_.GetWeakPtr()));
54 proxy_->RegisterInterfacesRemovedSignalHandler(
55 base::Bind(&ChromeosDBusObjectManagerProxy::InterfacesRemoved,
56 weak_factory_.GetWeakPtr()),
57 base::Bind(&ChromeosDBusObjectManagerProxy::OnSignalConnected,
58 weak_factory_.GetWeakPtr()));
59
60 // Monitor service owner changes. This callback lives for the lifetime of
61 // the ObjectProxy.
62 proxy_->GetObjectProxy()->SetNameOwnerChangedCallback(
63 base::Bind(&ChromeosDBusObjectManagerProxy::OnServiceOwnerChanged,
64 weak_factory_.GetWeakPtr()));
65
66 // One time callback when service becomes available.
67 proxy_->GetObjectProxy()->WaitForServiceToBeAvailable(
68 base::Bind(&ChromeosDBusObjectManagerProxy::OnServiceAvailable,
69 weak_factory_.GetWeakPtr()));
70 }
71
~ChromeosDBusObjectManagerProxy()72 ChromeosDBusObjectManagerProxy::~ChromeosDBusObjectManagerProxy() {}
73
GetManagedObjects(Error * error,const ManagedObjectsCallback & callback,int timeout)74 void ChromeosDBusObjectManagerProxy::GetManagedObjects(
75 Error* error,
76 const ManagedObjectsCallback& callback,
77 int timeout) {
78 if (!service_available_) {
79 Error::PopulateAndLog(FROM_HERE, error, Error::kInternalError,
80 "Service not available");
81 return;
82 }
83 proxy_->GetManagedObjectsAsync(
84 base::Bind(&ChromeosDBusObjectManagerProxy::OnGetManagedObjectsSuccess,
85 weak_factory_.GetWeakPtr(),
86 callback),
87 base::Bind(&ChromeosDBusObjectManagerProxy::OnGetManagedObjectsFailure,
88 weak_factory_.GetWeakPtr(),
89 callback));
90 }
91
OnServiceAvailable(bool available)92 void ChromeosDBusObjectManagerProxy::OnServiceAvailable(bool available) {
93 LOG(INFO) << __func__ << ": " << available;
94
95 // The callback might invoke calls to the ObjectProxy, so defer the callback
96 // to event loop.
97 if (available && !service_appeared_callback_.is_null()) {
98 dispatcher_->PostTask(service_appeared_callback_);
99 } else if (!available && !service_vanished_callback_.is_null()) {
100 dispatcher_->PostTask(service_vanished_callback_);
101 }
102 service_available_ = available;
103 }
104
OnServiceOwnerChanged(const string & old_owner,const string & new_owner)105 void ChromeosDBusObjectManagerProxy::OnServiceOwnerChanged(
106 const string& old_owner, const string& new_owner) {
107 LOG(INFO) << __func__ << " old: " << old_owner << " new: " << new_owner;
108 if (new_owner.empty()) {
109 OnServiceAvailable(false);
110 } else {
111 OnServiceAvailable(true);
112 }
113 }
114
OnSignalConnected(const string & interface_name,const string & signal_name,bool success)115 void ChromeosDBusObjectManagerProxy::OnSignalConnected(
116 const string& interface_name, const string& signal_name, bool success) {
117 SLOG(&proxy_->GetObjectPath(), 2) << __func__
118 << "interface: " << interface_name
119 << " signal: " << signal_name << "success: " << success;
120 if (!success) {
121 LOG(ERROR) << "Failed to connect signal " << signal_name
122 << " to interface " << interface_name;
123 }
124 }
125
InterfacesAdded(const dbus::ObjectPath & object_path,const DBusInterfaceToProperties & dbus_interface_to_properties)126 void ChromeosDBusObjectManagerProxy::InterfacesAdded(
127 const dbus::ObjectPath& object_path,
128 const DBusInterfaceToProperties& dbus_interface_to_properties) {
129 SLOG(&proxy_->GetObjectPath(), 2) << __func__ << "("
130 << object_path.value() << ")";
131 InterfaceToProperties interface_to_properties;
132 ConvertDBusInterfaceProperties(dbus_interface_to_properties,
133 &interface_to_properties);
134 interfaces_added_callback_.Run(object_path.value(), interface_to_properties);
135 }
136
InterfacesRemoved(const dbus::ObjectPath & object_path,const std::vector<std::string> & interfaces)137 void ChromeosDBusObjectManagerProxy::InterfacesRemoved(
138 const dbus::ObjectPath& object_path,
139 const std::vector<std::string>& interfaces) {
140 SLOG(&proxy_->GetObjectPath(), 2) << __func__ << "("
141 << object_path.value() << ")";
142 interfaces_removed_callback_.Run(object_path.value(), interfaces);
143 }
144
OnGetManagedObjectsSuccess(const ManagedObjectsCallback & callback,const DBusObjectsWithProperties & dbus_objects_with_properties)145 void ChromeosDBusObjectManagerProxy::OnGetManagedObjectsSuccess(
146 const ManagedObjectsCallback& callback,
147 const DBusObjectsWithProperties& dbus_objects_with_properties) {
148 SLOG(&proxy_->GetObjectPath(), 2) << __func__;
149 ObjectsWithProperties objects_with_properties;
150 for (const auto& object : dbus_objects_with_properties) {
151 InterfaceToProperties interface_to_properties;
152 ConvertDBusInterfaceProperties(object.second, &interface_to_properties);
153 objects_with_properties.emplace(object.first.value(),
154 interface_to_properties);
155 }
156 callback.Run(objects_with_properties, Error());
157 }
158
OnGetManagedObjectsFailure(const ManagedObjectsCallback & callback,brillo::Error * dbus_error)159 void ChromeosDBusObjectManagerProxy::OnGetManagedObjectsFailure(
160 const ManagedObjectsCallback& callback,
161 brillo::Error* dbus_error) {
162 Error error;
163 CellularError::FromChromeosDBusError(dbus_error, &error);
164 callback.Run(ObjectsWithProperties(), error);
165 }
166
ConvertDBusInterfaceProperties(const DBusInterfaceToProperties & dbus_interface_to_properties,InterfaceToProperties * interface_to_properties)167 void ChromeosDBusObjectManagerProxy::ConvertDBusInterfaceProperties(
168 const DBusInterfaceToProperties& dbus_interface_to_properties,
169 InterfaceToProperties* interface_to_properties) {
170 for (const auto& interface : dbus_interface_to_properties) {
171 KeyValueStore properties;
172 KeyValueStore::ConvertFromVariantDictionary(interface.second, &properties);
173 interface_to_properties->emplace(interface.first, properties);
174 }
175 }
176
177 } // namespace shill
178