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