1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker
5*635a8641SAndroid Build Coastguard Worker #include "dbus/object_manager.h"
6*635a8641SAndroid Build Coastguard Worker
7*635a8641SAndroid Build Coastguard Worker #include <stddef.h>
8*635a8641SAndroid Build Coastguard Worker
9*635a8641SAndroid Build Coastguard Worker #include "base/bind.h"
10*635a8641SAndroid Build Coastguard Worker #include "base/location.h"
11*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/metrics/histogram.h"
13*635a8641SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
14*635a8641SAndroid Build Coastguard Worker #include "base/task_runner_util.h"
15*635a8641SAndroid Build Coastguard Worker #include "dbus/bus.h"
16*635a8641SAndroid Build Coastguard Worker #include "dbus/dbus_statistics.h"
17*635a8641SAndroid Build Coastguard Worker #include "dbus/message.h"
18*635a8641SAndroid Build Coastguard Worker #include "dbus/object_proxy.h"
19*635a8641SAndroid Build Coastguard Worker #include "dbus/property.h"
20*635a8641SAndroid Build Coastguard Worker #include "dbus/scoped_dbus_error.h"
21*635a8641SAndroid Build Coastguard Worker #include "dbus/util.h"
22*635a8641SAndroid Build Coastguard Worker
23*635a8641SAndroid Build Coastguard Worker namespace dbus {
24*635a8641SAndroid Build Coastguard Worker
Object()25*635a8641SAndroid Build Coastguard Worker ObjectManager::Object::Object()
26*635a8641SAndroid Build Coastguard Worker : object_proxy(nullptr) {
27*635a8641SAndroid Build Coastguard Worker }
28*635a8641SAndroid Build Coastguard Worker
29*635a8641SAndroid Build Coastguard Worker ObjectManager::Object::~Object() = default;
30*635a8641SAndroid Build Coastguard Worker
ObjectManager(Bus * bus,const std::string & service_name,const ObjectPath & object_path)31*635a8641SAndroid Build Coastguard Worker ObjectManager::ObjectManager(Bus* bus,
32*635a8641SAndroid Build Coastguard Worker const std::string& service_name,
33*635a8641SAndroid Build Coastguard Worker const ObjectPath& object_path)
34*635a8641SAndroid Build Coastguard Worker : bus_(bus),
35*635a8641SAndroid Build Coastguard Worker service_name_(service_name),
36*635a8641SAndroid Build Coastguard Worker object_path_(object_path),
37*635a8641SAndroid Build Coastguard Worker setup_success_(false),
38*635a8641SAndroid Build Coastguard Worker cleanup_called_(false),
39*635a8641SAndroid Build Coastguard Worker weak_ptr_factory_(this) {
40*635a8641SAndroid Build Coastguard Worker LOG_IF(FATAL, !object_path_.IsValid()) << object_path_.value();
41*635a8641SAndroid Build Coastguard Worker DVLOG(1) << "Creating ObjectManager for " << service_name_
42*635a8641SAndroid Build Coastguard Worker << " " << object_path_.value();
43*635a8641SAndroid Build Coastguard Worker DCHECK(bus_);
44*635a8641SAndroid Build Coastguard Worker bus_->AssertOnOriginThread();
45*635a8641SAndroid Build Coastguard Worker object_proxy_ = bus_->GetObjectProxy(service_name_, object_path_);
46*635a8641SAndroid Build Coastguard Worker object_proxy_->SetNameOwnerChangedCallback(
47*635a8641SAndroid Build Coastguard Worker base::Bind(&ObjectManager::NameOwnerChanged,
48*635a8641SAndroid Build Coastguard Worker weak_ptr_factory_.GetWeakPtr()));
49*635a8641SAndroid Build Coastguard Worker
50*635a8641SAndroid Build Coastguard Worker // Set up a match rule and a filter function to handle PropertiesChanged
51*635a8641SAndroid Build Coastguard Worker // signals from the service. This is important to avoid any race conditions
52*635a8641SAndroid Build Coastguard Worker // that might cause us to miss PropertiesChanged signals once all objects are
53*635a8641SAndroid Build Coastguard Worker // initialized via GetManagedObjects.
54*635a8641SAndroid Build Coastguard Worker base::PostTaskAndReplyWithResult(
55*635a8641SAndroid Build Coastguard Worker bus_->GetDBusTaskRunner(),
56*635a8641SAndroid Build Coastguard Worker FROM_HERE,
57*635a8641SAndroid Build Coastguard Worker base::Bind(&ObjectManager::SetupMatchRuleAndFilter, this),
58*635a8641SAndroid Build Coastguard Worker base::Bind(&ObjectManager::OnSetupMatchRuleAndFilterComplete, this));
59*635a8641SAndroid Build Coastguard Worker }
60*635a8641SAndroid Build Coastguard Worker
~ObjectManager()61*635a8641SAndroid Build Coastguard Worker ObjectManager::~ObjectManager() {
62*635a8641SAndroid Build Coastguard Worker // Clean up Object structures
63*635a8641SAndroid Build Coastguard Worker for (ObjectMap::iterator iter = object_map_.begin();
64*635a8641SAndroid Build Coastguard Worker iter != object_map_.end(); ++iter) {
65*635a8641SAndroid Build Coastguard Worker Object* object = iter->second;
66*635a8641SAndroid Build Coastguard Worker
67*635a8641SAndroid Build Coastguard Worker for (Object::PropertiesMap::iterator piter = object->properties_map.begin();
68*635a8641SAndroid Build Coastguard Worker piter != object->properties_map.end(); ++piter) {
69*635a8641SAndroid Build Coastguard Worker PropertySet* properties = piter->second;
70*635a8641SAndroid Build Coastguard Worker delete properties;
71*635a8641SAndroid Build Coastguard Worker }
72*635a8641SAndroid Build Coastguard Worker
73*635a8641SAndroid Build Coastguard Worker delete object;
74*635a8641SAndroid Build Coastguard Worker }
75*635a8641SAndroid Build Coastguard Worker }
76*635a8641SAndroid Build Coastguard Worker
RegisterInterface(const std::string & interface_name,Interface * interface)77*635a8641SAndroid Build Coastguard Worker void ObjectManager::RegisterInterface(const std::string& interface_name,
78*635a8641SAndroid Build Coastguard Worker Interface* interface) {
79*635a8641SAndroid Build Coastguard Worker interface_map_[interface_name] = interface;
80*635a8641SAndroid Build Coastguard Worker }
81*635a8641SAndroid Build Coastguard Worker
UnregisterInterface(const std::string & interface_name)82*635a8641SAndroid Build Coastguard Worker void ObjectManager::UnregisterInterface(const std::string& interface_name) {
83*635a8641SAndroid Build Coastguard Worker InterfaceMap::iterator iter = interface_map_.find(interface_name);
84*635a8641SAndroid Build Coastguard Worker if (iter != interface_map_.end())
85*635a8641SAndroid Build Coastguard Worker interface_map_.erase(iter);
86*635a8641SAndroid Build Coastguard Worker }
87*635a8641SAndroid Build Coastguard Worker
GetObjects()88*635a8641SAndroid Build Coastguard Worker std::vector<ObjectPath> ObjectManager::GetObjects() {
89*635a8641SAndroid Build Coastguard Worker std::vector<ObjectPath> object_paths;
90*635a8641SAndroid Build Coastguard Worker
91*635a8641SAndroid Build Coastguard Worker for (ObjectMap::iterator iter = object_map_.begin();
92*635a8641SAndroid Build Coastguard Worker iter != object_map_.end(); ++iter)
93*635a8641SAndroid Build Coastguard Worker object_paths.push_back(iter->first);
94*635a8641SAndroid Build Coastguard Worker
95*635a8641SAndroid Build Coastguard Worker return object_paths;
96*635a8641SAndroid Build Coastguard Worker }
97*635a8641SAndroid Build Coastguard Worker
GetObjectsWithInterface(const std::string & interface_name)98*635a8641SAndroid Build Coastguard Worker std::vector<ObjectPath> ObjectManager::GetObjectsWithInterface(
99*635a8641SAndroid Build Coastguard Worker const std::string& interface_name) {
100*635a8641SAndroid Build Coastguard Worker std::vector<ObjectPath> object_paths;
101*635a8641SAndroid Build Coastguard Worker
102*635a8641SAndroid Build Coastguard Worker for (ObjectMap::iterator oiter = object_map_.begin();
103*635a8641SAndroid Build Coastguard Worker oiter != object_map_.end(); ++oiter) {
104*635a8641SAndroid Build Coastguard Worker Object* object = oiter->second;
105*635a8641SAndroid Build Coastguard Worker
106*635a8641SAndroid Build Coastguard Worker Object::PropertiesMap::iterator piter =
107*635a8641SAndroid Build Coastguard Worker object->properties_map.find(interface_name);
108*635a8641SAndroid Build Coastguard Worker if (piter != object->properties_map.end())
109*635a8641SAndroid Build Coastguard Worker object_paths.push_back(oiter->first);
110*635a8641SAndroid Build Coastguard Worker }
111*635a8641SAndroid Build Coastguard Worker
112*635a8641SAndroid Build Coastguard Worker return object_paths;
113*635a8641SAndroid Build Coastguard Worker }
114*635a8641SAndroid Build Coastguard Worker
GetObjectProxy(const ObjectPath & object_path)115*635a8641SAndroid Build Coastguard Worker ObjectProxy* ObjectManager::GetObjectProxy(const ObjectPath& object_path) {
116*635a8641SAndroid Build Coastguard Worker ObjectMap::iterator iter = object_map_.find(object_path);
117*635a8641SAndroid Build Coastguard Worker if (iter == object_map_.end())
118*635a8641SAndroid Build Coastguard Worker return nullptr;
119*635a8641SAndroid Build Coastguard Worker
120*635a8641SAndroid Build Coastguard Worker Object* object = iter->second;
121*635a8641SAndroid Build Coastguard Worker return object->object_proxy;
122*635a8641SAndroid Build Coastguard Worker }
123*635a8641SAndroid Build Coastguard Worker
GetProperties(const ObjectPath & object_path,const std::string & interface_name)124*635a8641SAndroid Build Coastguard Worker PropertySet* ObjectManager::GetProperties(const ObjectPath& object_path,
125*635a8641SAndroid Build Coastguard Worker const std::string& interface_name) {
126*635a8641SAndroid Build Coastguard Worker ObjectMap::iterator iter = object_map_.find(object_path);
127*635a8641SAndroid Build Coastguard Worker if (iter == object_map_.end())
128*635a8641SAndroid Build Coastguard Worker return nullptr;
129*635a8641SAndroid Build Coastguard Worker
130*635a8641SAndroid Build Coastguard Worker Object* object = iter->second;
131*635a8641SAndroid Build Coastguard Worker Object::PropertiesMap::iterator piter =
132*635a8641SAndroid Build Coastguard Worker object->properties_map.find(interface_name);
133*635a8641SAndroid Build Coastguard Worker if (piter == object->properties_map.end())
134*635a8641SAndroid Build Coastguard Worker return nullptr;
135*635a8641SAndroid Build Coastguard Worker
136*635a8641SAndroid Build Coastguard Worker return piter->second;
137*635a8641SAndroid Build Coastguard Worker }
138*635a8641SAndroid Build Coastguard Worker
GetManagedObjects()139*635a8641SAndroid Build Coastguard Worker void ObjectManager::GetManagedObjects() {
140*635a8641SAndroid Build Coastguard Worker MethodCall method_call(kObjectManagerInterface,
141*635a8641SAndroid Build Coastguard Worker kObjectManagerGetManagedObjects);
142*635a8641SAndroid Build Coastguard Worker
143*635a8641SAndroid Build Coastguard Worker object_proxy_->CallMethod(
144*635a8641SAndroid Build Coastguard Worker &method_call,
145*635a8641SAndroid Build Coastguard Worker ObjectProxy::TIMEOUT_USE_DEFAULT,
146*635a8641SAndroid Build Coastguard Worker base::Bind(&ObjectManager::OnGetManagedObjects,
147*635a8641SAndroid Build Coastguard Worker weak_ptr_factory_.GetWeakPtr()));
148*635a8641SAndroid Build Coastguard Worker }
149*635a8641SAndroid Build Coastguard Worker
CleanUp()150*635a8641SAndroid Build Coastguard Worker void ObjectManager::CleanUp() {
151*635a8641SAndroid Build Coastguard Worker DCHECK(bus_);
152*635a8641SAndroid Build Coastguard Worker bus_->AssertOnDBusThread();
153*635a8641SAndroid Build Coastguard Worker DCHECK(!cleanup_called_);
154*635a8641SAndroid Build Coastguard Worker
155*635a8641SAndroid Build Coastguard Worker cleanup_called_ = true;
156*635a8641SAndroid Build Coastguard Worker
157*635a8641SAndroid Build Coastguard Worker if (!setup_success_)
158*635a8641SAndroid Build Coastguard Worker return;
159*635a8641SAndroid Build Coastguard Worker
160*635a8641SAndroid Build Coastguard Worker bus_->RemoveFilterFunction(&ObjectManager::HandleMessageThunk, this);
161*635a8641SAndroid Build Coastguard Worker
162*635a8641SAndroid Build Coastguard Worker ScopedDBusError error;
163*635a8641SAndroid Build Coastguard Worker bus_->RemoveMatch(match_rule_, error.get());
164*635a8641SAndroid Build Coastguard Worker if (error.is_set())
165*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to remove match rule: " << match_rule_;
166*635a8641SAndroid Build Coastguard Worker
167*635a8641SAndroid Build Coastguard Worker match_rule_.clear();
168*635a8641SAndroid Build Coastguard Worker }
169*635a8641SAndroid Build Coastguard Worker
SetupMatchRuleAndFilter()170*635a8641SAndroid Build Coastguard Worker bool ObjectManager::SetupMatchRuleAndFilter() {
171*635a8641SAndroid Build Coastguard Worker DCHECK(bus_);
172*635a8641SAndroid Build Coastguard Worker DCHECK(!setup_success_);
173*635a8641SAndroid Build Coastguard Worker bus_->AssertOnDBusThread();
174*635a8641SAndroid Build Coastguard Worker
175*635a8641SAndroid Build Coastguard Worker if (cleanup_called_)
176*635a8641SAndroid Build Coastguard Worker return false;
177*635a8641SAndroid Build Coastguard Worker
178*635a8641SAndroid Build Coastguard Worker if (!bus_->Connect() || !bus_->SetUpAsyncOperations())
179*635a8641SAndroid Build Coastguard Worker return false;
180*635a8641SAndroid Build Coastguard Worker
181*635a8641SAndroid Build Coastguard Worker service_name_owner_ =
182*635a8641SAndroid Build Coastguard Worker bus_->GetServiceOwnerAndBlock(service_name_, Bus::SUPPRESS_ERRORS);
183*635a8641SAndroid Build Coastguard Worker
184*635a8641SAndroid Build Coastguard Worker const std::string match_rule =
185*635a8641SAndroid Build Coastguard Worker base::StringPrintf(
186*635a8641SAndroid Build Coastguard Worker "type='signal', sender='%s', interface='%s', member='%s'",
187*635a8641SAndroid Build Coastguard Worker service_name_.c_str(),
188*635a8641SAndroid Build Coastguard Worker kPropertiesInterface,
189*635a8641SAndroid Build Coastguard Worker kPropertiesChanged);
190*635a8641SAndroid Build Coastguard Worker
191*635a8641SAndroid Build Coastguard Worker bus_->AddFilterFunction(&ObjectManager::HandleMessageThunk, this);
192*635a8641SAndroid Build Coastguard Worker
193*635a8641SAndroid Build Coastguard Worker ScopedDBusError error;
194*635a8641SAndroid Build Coastguard Worker bus_->AddMatch(match_rule, error.get());
195*635a8641SAndroid Build Coastguard Worker if (error.is_set()) {
196*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "ObjectManager failed to add match rule \"" << match_rule
197*635a8641SAndroid Build Coastguard Worker << "\". Got " << error.name() << ": " << error.message();
198*635a8641SAndroid Build Coastguard Worker bus_->RemoveFilterFunction(&ObjectManager::HandleMessageThunk, this);
199*635a8641SAndroid Build Coastguard Worker return false;
200*635a8641SAndroid Build Coastguard Worker }
201*635a8641SAndroid Build Coastguard Worker
202*635a8641SAndroid Build Coastguard Worker match_rule_ = match_rule;
203*635a8641SAndroid Build Coastguard Worker setup_success_ = true;
204*635a8641SAndroid Build Coastguard Worker
205*635a8641SAndroid Build Coastguard Worker return true;
206*635a8641SAndroid Build Coastguard Worker }
207*635a8641SAndroid Build Coastguard Worker
OnSetupMatchRuleAndFilterComplete(bool success)208*635a8641SAndroid Build Coastguard Worker void ObjectManager::OnSetupMatchRuleAndFilterComplete(bool success) {
209*635a8641SAndroid Build Coastguard Worker if (!success) {
210*635a8641SAndroid Build Coastguard Worker LOG(WARNING) << service_name_ << " " << object_path_.value()
211*635a8641SAndroid Build Coastguard Worker << ": Failed to set up match rule.";
212*635a8641SAndroid Build Coastguard Worker return;
213*635a8641SAndroid Build Coastguard Worker }
214*635a8641SAndroid Build Coastguard Worker
215*635a8641SAndroid Build Coastguard Worker DCHECK(bus_);
216*635a8641SAndroid Build Coastguard Worker DCHECK(object_proxy_);
217*635a8641SAndroid Build Coastguard Worker DCHECK(setup_success_);
218*635a8641SAndroid Build Coastguard Worker
219*635a8641SAndroid Build Coastguard Worker // |object_proxy_| is no longer valid if the Bus was shut down before this
220*635a8641SAndroid Build Coastguard Worker // call. Don't initiate any other action from the origin thread.
221*635a8641SAndroid Build Coastguard Worker if (cleanup_called_)
222*635a8641SAndroid Build Coastguard Worker return;
223*635a8641SAndroid Build Coastguard Worker
224*635a8641SAndroid Build Coastguard Worker object_proxy_->ConnectToSignal(
225*635a8641SAndroid Build Coastguard Worker kObjectManagerInterface,
226*635a8641SAndroid Build Coastguard Worker kObjectManagerInterfacesAdded,
227*635a8641SAndroid Build Coastguard Worker base::Bind(&ObjectManager::InterfacesAddedReceived,
228*635a8641SAndroid Build Coastguard Worker weak_ptr_factory_.GetWeakPtr()),
229*635a8641SAndroid Build Coastguard Worker base::Bind(&ObjectManager::InterfacesAddedConnected,
230*635a8641SAndroid Build Coastguard Worker weak_ptr_factory_.GetWeakPtr()));
231*635a8641SAndroid Build Coastguard Worker
232*635a8641SAndroid Build Coastguard Worker object_proxy_->ConnectToSignal(
233*635a8641SAndroid Build Coastguard Worker kObjectManagerInterface,
234*635a8641SAndroid Build Coastguard Worker kObjectManagerInterfacesRemoved,
235*635a8641SAndroid Build Coastguard Worker base::Bind(&ObjectManager::InterfacesRemovedReceived,
236*635a8641SAndroid Build Coastguard Worker weak_ptr_factory_.GetWeakPtr()),
237*635a8641SAndroid Build Coastguard Worker base::Bind(&ObjectManager::InterfacesRemovedConnected,
238*635a8641SAndroid Build Coastguard Worker weak_ptr_factory_.GetWeakPtr()));
239*635a8641SAndroid Build Coastguard Worker
240*635a8641SAndroid Build Coastguard Worker if (!service_name_owner_.empty())
241*635a8641SAndroid Build Coastguard Worker GetManagedObjects();
242*635a8641SAndroid Build Coastguard Worker }
243*635a8641SAndroid Build Coastguard Worker
244*635a8641SAndroid Build Coastguard Worker // static
HandleMessageThunk(DBusConnection * connection,DBusMessage * raw_message,void * user_data)245*635a8641SAndroid Build Coastguard Worker DBusHandlerResult ObjectManager::HandleMessageThunk(DBusConnection* connection,
246*635a8641SAndroid Build Coastguard Worker DBusMessage* raw_message,
247*635a8641SAndroid Build Coastguard Worker void* user_data) {
248*635a8641SAndroid Build Coastguard Worker ObjectManager* self = reinterpret_cast<ObjectManager*>(user_data);
249*635a8641SAndroid Build Coastguard Worker return self->HandleMessage(connection, raw_message);
250*635a8641SAndroid Build Coastguard Worker }
251*635a8641SAndroid Build Coastguard Worker
HandleMessage(DBusConnection * connection,DBusMessage * raw_message)252*635a8641SAndroid Build Coastguard Worker DBusHandlerResult ObjectManager::HandleMessage(DBusConnection* connection,
253*635a8641SAndroid Build Coastguard Worker DBusMessage* raw_message) {
254*635a8641SAndroid Build Coastguard Worker DCHECK(bus_);
255*635a8641SAndroid Build Coastguard Worker bus_->AssertOnDBusThread();
256*635a8641SAndroid Build Coastguard Worker
257*635a8641SAndroid Build Coastguard Worker // Handle the message only if it is a signal.
258*635a8641SAndroid Build Coastguard Worker // Note that the match rule in SetupMatchRuleAndFilter() is configured to
259*635a8641SAndroid Build Coastguard Worker // only accept signals, but we check here just in case.
260*635a8641SAndroid Build Coastguard Worker if (dbus_message_get_type(raw_message) != DBUS_MESSAGE_TYPE_SIGNAL)
261*635a8641SAndroid Build Coastguard Worker return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
262*635a8641SAndroid Build Coastguard Worker
263*635a8641SAndroid Build Coastguard Worker // raw_message will be unrefed on exit of the function. Increment the
264*635a8641SAndroid Build Coastguard Worker // reference so we can use it in Signal.
265*635a8641SAndroid Build Coastguard Worker dbus_message_ref(raw_message);
266*635a8641SAndroid Build Coastguard Worker std::unique_ptr<Signal> signal(Signal::FromRawMessage(raw_message));
267*635a8641SAndroid Build Coastguard Worker
268*635a8641SAndroid Build Coastguard Worker const std::string interface = signal->GetInterface();
269*635a8641SAndroid Build Coastguard Worker const std::string member = signal->GetMember();
270*635a8641SAndroid Build Coastguard Worker
271*635a8641SAndroid Build Coastguard Worker statistics::AddReceivedSignal(service_name_, interface, member);
272*635a8641SAndroid Build Coastguard Worker
273*635a8641SAndroid Build Coastguard Worker // Handle the signal only if it is PropertiesChanged.
274*635a8641SAndroid Build Coastguard Worker // Note that the match rule in SetupMatchRuleAndFilter() is configured to
275*635a8641SAndroid Build Coastguard Worker // only accept PropertiesChanged signals, but we check here just in case.
276*635a8641SAndroid Build Coastguard Worker const std::string absolute_signal_name =
277*635a8641SAndroid Build Coastguard Worker GetAbsoluteMemberName(interface, member);
278*635a8641SAndroid Build Coastguard Worker const std::string properties_changed_signal_name =
279*635a8641SAndroid Build Coastguard Worker GetAbsoluteMemberName(kPropertiesInterface, kPropertiesChanged);
280*635a8641SAndroid Build Coastguard Worker if (absolute_signal_name != properties_changed_signal_name)
281*635a8641SAndroid Build Coastguard Worker return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
282*635a8641SAndroid Build Coastguard Worker
283*635a8641SAndroid Build Coastguard Worker VLOG(1) << "Signal received: " << signal->ToString();
284*635a8641SAndroid Build Coastguard Worker
285*635a8641SAndroid Build Coastguard Worker // Handle the signal only if it is from the service that the ObjectManager
286*635a8641SAndroid Build Coastguard Worker // instance is interested in.
287*635a8641SAndroid Build Coastguard Worker // Note that the match rule in SetupMatchRuleAndFilter() is configured to
288*635a8641SAndroid Build Coastguard Worker // only accept messages from the service name of our interest. However, the
289*635a8641SAndroid Build Coastguard Worker // service='...' filter does not work as intended. See crbug.com/507206#14
290*635a8641SAndroid Build Coastguard Worker // and #15 for details, hence it's necessary to check the sender here.
291*635a8641SAndroid Build Coastguard Worker std::string sender = signal->GetSender();
292*635a8641SAndroid Build Coastguard Worker if (service_name_owner_ != sender)
293*635a8641SAndroid Build Coastguard Worker return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
294*635a8641SAndroid Build Coastguard Worker
295*635a8641SAndroid Build Coastguard Worker const ObjectPath path = signal->GetPath();
296*635a8641SAndroid Build Coastguard Worker
297*635a8641SAndroid Build Coastguard Worker if (bus_->HasDBusThread()) {
298*635a8641SAndroid Build Coastguard Worker // Post a task to run the method in the origin thread. Transfer ownership of
299*635a8641SAndroid Build Coastguard Worker // |signal| to NotifyPropertiesChanged, which will handle the clean up.
300*635a8641SAndroid Build Coastguard Worker Signal* released_signal = signal.release();
301*635a8641SAndroid Build Coastguard Worker bus_->GetOriginTaskRunner()->PostTask(
302*635a8641SAndroid Build Coastguard Worker FROM_HERE,
303*635a8641SAndroid Build Coastguard Worker base::Bind(&ObjectManager::NotifyPropertiesChanged,
304*635a8641SAndroid Build Coastguard Worker this, path,
305*635a8641SAndroid Build Coastguard Worker released_signal));
306*635a8641SAndroid Build Coastguard Worker } else {
307*635a8641SAndroid Build Coastguard Worker // If the D-Bus thread is not used, just call the callback on the
308*635a8641SAndroid Build Coastguard Worker // current thread. Transfer the ownership of |signal| to
309*635a8641SAndroid Build Coastguard Worker // NotifyPropertiesChanged.
310*635a8641SAndroid Build Coastguard Worker NotifyPropertiesChanged(path, signal.release());
311*635a8641SAndroid Build Coastguard Worker }
312*635a8641SAndroid Build Coastguard Worker
313*635a8641SAndroid Build Coastguard Worker // We don't return DBUS_HANDLER_RESULT_HANDLED for signals because other
314*635a8641SAndroid Build Coastguard Worker // objects may be interested in them. (e.g. Signals from org.freedesktop.DBus)
315*635a8641SAndroid Build Coastguard Worker return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
316*635a8641SAndroid Build Coastguard Worker }
317*635a8641SAndroid Build Coastguard Worker
NotifyPropertiesChanged(const dbus::ObjectPath object_path,Signal * signal)318*635a8641SAndroid Build Coastguard Worker void ObjectManager::NotifyPropertiesChanged(
319*635a8641SAndroid Build Coastguard Worker const dbus::ObjectPath object_path,
320*635a8641SAndroid Build Coastguard Worker Signal* signal) {
321*635a8641SAndroid Build Coastguard Worker DCHECK(bus_);
322*635a8641SAndroid Build Coastguard Worker bus_->AssertOnOriginThread();
323*635a8641SAndroid Build Coastguard Worker
324*635a8641SAndroid Build Coastguard Worker NotifyPropertiesChangedHelper(object_path, signal);
325*635a8641SAndroid Build Coastguard Worker
326*635a8641SAndroid Build Coastguard Worker // Delete the message on the D-Bus thread. See comments in HandleMessage.
327*635a8641SAndroid Build Coastguard Worker bus_->GetDBusTaskRunner()->PostTask(
328*635a8641SAndroid Build Coastguard Worker FROM_HERE,
329*635a8641SAndroid Build Coastguard Worker base::Bind(&base::DeletePointer<Signal>, signal));
330*635a8641SAndroid Build Coastguard Worker }
331*635a8641SAndroid Build Coastguard Worker
NotifyPropertiesChangedHelper(const dbus::ObjectPath object_path,Signal * signal)332*635a8641SAndroid Build Coastguard Worker void ObjectManager::NotifyPropertiesChangedHelper(
333*635a8641SAndroid Build Coastguard Worker const dbus::ObjectPath object_path,
334*635a8641SAndroid Build Coastguard Worker Signal* signal) {
335*635a8641SAndroid Build Coastguard Worker DCHECK(bus_);
336*635a8641SAndroid Build Coastguard Worker bus_->AssertOnOriginThread();
337*635a8641SAndroid Build Coastguard Worker
338*635a8641SAndroid Build Coastguard Worker MessageReader reader(signal);
339*635a8641SAndroid Build Coastguard Worker std::string interface;
340*635a8641SAndroid Build Coastguard Worker if (!reader.PopString(&interface)) {
341*635a8641SAndroid Build Coastguard Worker LOG(WARNING) << "Property changed signal has wrong parameters: "
342*635a8641SAndroid Build Coastguard Worker << "expected interface name: " << signal->ToString();
343*635a8641SAndroid Build Coastguard Worker return;
344*635a8641SAndroid Build Coastguard Worker }
345*635a8641SAndroid Build Coastguard Worker
346*635a8641SAndroid Build Coastguard Worker PropertySet* properties = GetProperties(object_path, interface);
347*635a8641SAndroid Build Coastguard Worker if (properties)
348*635a8641SAndroid Build Coastguard Worker properties->ChangedReceived(signal);
349*635a8641SAndroid Build Coastguard Worker }
350*635a8641SAndroid Build Coastguard Worker
OnGetManagedObjects(Response * response)351*635a8641SAndroid Build Coastguard Worker void ObjectManager::OnGetManagedObjects(Response* response) {
352*635a8641SAndroid Build Coastguard Worker if (response != nullptr) {
353*635a8641SAndroid Build Coastguard Worker MessageReader reader(response);
354*635a8641SAndroid Build Coastguard Worker MessageReader array_reader(nullptr);
355*635a8641SAndroid Build Coastguard Worker if (!reader.PopArray(&array_reader))
356*635a8641SAndroid Build Coastguard Worker return;
357*635a8641SAndroid Build Coastguard Worker
358*635a8641SAndroid Build Coastguard Worker while (array_reader.HasMoreData()) {
359*635a8641SAndroid Build Coastguard Worker MessageReader dict_entry_reader(nullptr);
360*635a8641SAndroid Build Coastguard Worker ObjectPath object_path;
361*635a8641SAndroid Build Coastguard Worker if (!array_reader.PopDictEntry(&dict_entry_reader) ||
362*635a8641SAndroid Build Coastguard Worker !dict_entry_reader.PopObjectPath(&object_path))
363*635a8641SAndroid Build Coastguard Worker continue;
364*635a8641SAndroid Build Coastguard Worker
365*635a8641SAndroid Build Coastguard Worker UpdateObject(object_path, &dict_entry_reader);
366*635a8641SAndroid Build Coastguard Worker }
367*635a8641SAndroid Build Coastguard Worker
368*635a8641SAndroid Build Coastguard Worker } else {
369*635a8641SAndroid Build Coastguard Worker LOG(WARNING) << service_name_ << " " << object_path_.value()
370*635a8641SAndroid Build Coastguard Worker << ": Failed to get managed objects";
371*635a8641SAndroid Build Coastguard Worker }
372*635a8641SAndroid Build Coastguard Worker }
373*635a8641SAndroid Build Coastguard Worker
InterfacesAddedReceived(Signal * signal)374*635a8641SAndroid Build Coastguard Worker void ObjectManager::InterfacesAddedReceived(Signal* signal) {
375*635a8641SAndroid Build Coastguard Worker DCHECK(signal);
376*635a8641SAndroid Build Coastguard Worker MessageReader reader(signal);
377*635a8641SAndroid Build Coastguard Worker ObjectPath object_path;
378*635a8641SAndroid Build Coastguard Worker if (!reader.PopObjectPath(&object_path)) {
379*635a8641SAndroid Build Coastguard Worker LOG(WARNING) << service_name_ << " " << object_path_.value()
380*635a8641SAndroid Build Coastguard Worker << ": InterfacesAdded signal has incorrect parameters: "
381*635a8641SAndroid Build Coastguard Worker << signal->ToString();
382*635a8641SAndroid Build Coastguard Worker return;
383*635a8641SAndroid Build Coastguard Worker }
384*635a8641SAndroid Build Coastguard Worker
385*635a8641SAndroid Build Coastguard Worker UpdateObject(object_path, &reader);
386*635a8641SAndroid Build Coastguard Worker }
387*635a8641SAndroid Build Coastguard Worker
InterfacesAddedConnected(const std::string & interface_name,const std::string & signal_name,bool success)388*635a8641SAndroid Build Coastguard Worker void ObjectManager::InterfacesAddedConnected(const std::string& interface_name,
389*635a8641SAndroid Build Coastguard Worker const std::string& signal_name,
390*635a8641SAndroid Build Coastguard Worker bool success) {
391*635a8641SAndroid Build Coastguard Worker LOG_IF(WARNING, !success) << service_name_ << " " << object_path_.value()
392*635a8641SAndroid Build Coastguard Worker << ": Failed to connect to InterfacesAdded signal.";
393*635a8641SAndroid Build Coastguard Worker }
394*635a8641SAndroid Build Coastguard Worker
InterfacesRemovedReceived(Signal * signal)395*635a8641SAndroid Build Coastguard Worker void ObjectManager::InterfacesRemovedReceived(Signal* signal) {
396*635a8641SAndroid Build Coastguard Worker DCHECK(signal);
397*635a8641SAndroid Build Coastguard Worker MessageReader reader(signal);
398*635a8641SAndroid Build Coastguard Worker ObjectPath object_path;
399*635a8641SAndroid Build Coastguard Worker std::vector<std::string> interface_names;
400*635a8641SAndroid Build Coastguard Worker if (!reader.PopObjectPath(&object_path) ||
401*635a8641SAndroid Build Coastguard Worker !reader.PopArrayOfStrings(&interface_names)) {
402*635a8641SAndroid Build Coastguard Worker LOG(WARNING) << service_name_ << " " << object_path_.value()
403*635a8641SAndroid Build Coastguard Worker << ": InterfacesRemoved signal has incorrect parameters: "
404*635a8641SAndroid Build Coastguard Worker << signal->ToString();
405*635a8641SAndroid Build Coastguard Worker return;
406*635a8641SAndroid Build Coastguard Worker }
407*635a8641SAndroid Build Coastguard Worker
408*635a8641SAndroid Build Coastguard Worker for (size_t i = 0; i < interface_names.size(); ++i)
409*635a8641SAndroid Build Coastguard Worker RemoveInterface(object_path, interface_names[i]);
410*635a8641SAndroid Build Coastguard Worker }
411*635a8641SAndroid Build Coastguard Worker
InterfacesRemovedConnected(const std::string & interface_name,const std::string & signal_name,bool success)412*635a8641SAndroid Build Coastguard Worker void ObjectManager::InterfacesRemovedConnected(
413*635a8641SAndroid Build Coastguard Worker const std::string& interface_name,
414*635a8641SAndroid Build Coastguard Worker const std::string& signal_name,
415*635a8641SAndroid Build Coastguard Worker bool success) {
416*635a8641SAndroid Build Coastguard Worker LOG_IF(WARNING, !success) << service_name_ << " " << object_path_.value()
417*635a8641SAndroid Build Coastguard Worker << ": Failed to connect to "
418*635a8641SAndroid Build Coastguard Worker << "InterfacesRemoved signal.";
419*635a8641SAndroid Build Coastguard Worker }
420*635a8641SAndroid Build Coastguard Worker
UpdateObject(const ObjectPath & object_path,MessageReader * reader)421*635a8641SAndroid Build Coastguard Worker void ObjectManager::UpdateObject(const ObjectPath& object_path,
422*635a8641SAndroid Build Coastguard Worker MessageReader* reader) {
423*635a8641SAndroid Build Coastguard Worker DCHECK(reader);
424*635a8641SAndroid Build Coastguard Worker MessageReader array_reader(nullptr);
425*635a8641SAndroid Build Coastguard Worker if (!reader->PopArray(&array_reader))
426*635a8641SAndroid Build Coastguard Worker return;
427*635a8641SAndroid Build Coastguard Worker
428*635a8641SAndroid Build Coastguard Worker while (array_reader.HasMoreData()) {
429*635a8641SAndroid Build Coastguard Worker MessageReader dict_entry_reader(nullptr);
430*635a8641SAndroid Build Coastguard Worker std::string interface_name;
431*635a8641SAndroid Build Coastguard Worker if (!array_reader.PopDictEntry(&dict_entry_reader) ||
432*635a8641SAndroid Build Coastguard Worker !dict_entry_reader.PopString(&interface_name))
433*635a8641SAndroid Build Coastguard Worker continue;
434*635a8641SAndroid Build Coastguard Worker
435*635a8641SAndroid Build Coastguard Worker AddInterface(object_path, interface_name, &dict_entry_reader);
436*635a8641SAndroid Build Coastguard Worker }
437*635a8641SAndroid Build Coastguard Worker }
438*635a8641SAndroid Build Coastguard Worker
439*635a8641SAndroid Build Coastguard Worker
AddInterface(const ObjectPath & object_path,const std::string & interface_name,MessageReader * reader)440*635a8641SAndroid Build Coastguard Worker void ObjectManager::AddInterface(const ObjectPath& object_path,
441*635a8641SAndroid Build Coastguard Worker const std::string& interface_name,
442*635a8641SAndroid Build Coastguard Worker MessageReader* reader) {
443*635a8641SAndroid Build Coastguard Worker InterfaceMap::iterator iiter = interface_map_.find(interface_name);
444*635a8641SAndroid Build Coastguard Worker if (iiter == interface_map_.end())
445*635a8641SAndroid Build Coastguard Worker return;
446*635a8641SAndroid Build Coastguard Worker Interface* interface = iiter->second;
447*635a8641SAndroid Build Coastguard Worker
448*635a8641SAndroid Build Coastguard Worker ObjectMap::iterator oiter = object_map_.find(object_path);
449*635a8641SAndroid Build Coastguard Worker Object* object;
450*635a8641SAndroid Build Coastguard Worker if (oiter == object_map_.end()) {
451*635a8641SAndroid Build Coastguard Worker object = object_map_[object_path] = new Object;
452*635a8641SAndroid Build Coastguard Worker object->object_proxy = bus_->GetObjectProxy(service_name_, object_path);
453*635a8641SAndroid Build Coastguard Worker } else
454*635a8641SAndroid Build Coastguard Worker object = oiter->second;
455*635a8641SAndroid Build Coastguard Worker
456*635a8641SAndroid Build Coastguard Worker Object::PropertiesMap::iterator piter =
457*635a8641SAndroid Build Coastguard Worker object->properties_map.find(interface_name);
458*635a8641SAndroid Build Coastguard Worker PropertySet* property_set;
459*635a8641SAndroid Build Coastguard Worker const bool interface_added = (piter == object->properties_map.end());
460*635a8641SAndroid Build Coastguard Worker if (interface_added) {
461*635a8641SAndroid Build Coastguard Worker property_set = object->properties_map[interface_name] =
462*635a8641SAndroid Build Coastguard Worker interface->CreateProperties(object->object_proxy,
463*635a8641SAndroid Build Coastguard Worker object_path, interface_name);
464*635a8641SAndroid Build Coastguard Worker } else
465*635a8641SAndroid Build Coastguard Worker property_set = piter->second;
466*635a8641SAndroid Build Coastguard Worker
467*635a8641SAndroid Build Coastguard Worker property_set->UpdatePropertiesFromReader(reader);
468*635a8641SAndroid Build Coastguard Worker
469*635a8641SAndroid Build Coastguard Worker if (interface_added)
470*635a8641SAndroid Build Coastguard Worker interface->ObjectAdded(object_path, interface_name);
471*635a8641SAndroid Build Coastguard Worker }
472*635a8641SAndroid Build Coastguard Worker
RemoveInterface(const ObjectPath & object_path,const std::string & interface_name)473*635a8641SAndroid Build Coastguard Worker void ObjectManager::RemoveInterface(const ObjectPath& object_path,
474*635a8641SAndroid Build Coastguard Worker const std::string& interface_name) {
475*635a8641SAndroid Build Coastguard Worker ObjectMap::iterator oiter = object_map_.find(object_path);
476*635a8641SAndroid Build Coastguard Worker if (oiter == object_map_.end())
477*635a8641SAndroid Build Coastguard Worker return;
478*635a8641SAndroid Build Coastguard Worker Object* object = oiter->second;
479*635a8641SAndroid Build Coastguard Worker
480*635a8641SAndroid Build Coastguard Worker Object::PropertiesMap::iterator piter =
481*635a8641SAndroid Build Coastguard Worker object->properties_map.find(interface_name);
482*635a8641SAndroid Build Coastguard Worker if (piter == object->properties_map.end())
483*635a8641SAndroid Build Coastguard Worker return;
484*635a8641SAndroid Build Coastguard Worker
485*635a8641SAndroid Build Coastguard Worker // Inform the interface before removing the properties structure or object
486*635a8641SAndroid Build Coastguard Worker // in case it needs details from them to make its own decisions.
487*635a8641SAndroid Build Coastguard Worker InterfaceMap::iterator iiter = interface_map_.find(interface_name);
488*635a8641SAndroid Build Coastguard Worker if (iiter != interface_map_.end()) {
489*635a8641SAndroid Build Coastguard Worker Interface* interface = iiter->second;
490*635a8641SAndroid Build Coastguard Worker interface->ObjectRemoved(object_path, interface_name);
491*635a8641SAndroid Build Coastguard Worker }
492*635a8641SAndroid Build Coastguard Worker
493*635a8641SAndroid Build Coastguard Worker delete piter->second;
494*635a8641SAndroid Build Coastguard Worker object->properties_map.erase(piter);
495*635a8641SAndroid Build Coastguard Worker
496*635a8641SAndroid Build Coastguard Worker if (object->properties_map.empty()) {
497*635a8641SAndroid Build Coastguard Worker object_map_.erase(oiter);
498*635a8641SAndroid Build Coastguard Worker delete object;
499*635a8641SAndroid Build Coastguard Worker }
500*635a8641SAndroid Build Coastguard Worker }
501*635a8641SAndroid Build Coastguard Worker
NameOwnerChanged(const std::string & old_owner,const std::string & new_owner)502*635a8641SAndroid Build Coastguard Worker void ObjectManager::NameOwnerChanged(const std::string& old_owner,
503*635a8641SAndroid Build Coastguard Worker const std::string& new_owner) {
504*635a8641SAndroid Build Coastguard Worker service_name_owner_ = new_owner;
505*635a8641SAndroid Build Coastguard Worker
506*635a8641SAndroid Build Coastguard Worker if (!old_owner.empty()) {
507*635a8641SAndroid Build Coastguard Worker ObjectMap::iterator iter = object_map_.begin();
508*635a8641SAndroid Build Coastguard Worker while (iter != object_map_.end()) {
509*635a8641SAndroid Build Coastguard Worker ObjectMap::iterator tmp = iter;
510*635a8641SAndroid Build Coastguard Worker ++iter;
511*635a8641SAndroid Build Coastguard Worker
512*635a8641SAndroid Build Coastguard Worker // PropertiesMap is mutated by RemoveInterface, and also Object is
513*635a8641SAndroid Build Coastguard Worker // destroyed; easier to collect the object path and interface names
514*635a8641SAndroid Build Coastguard Worker // and remove them safely.
515*635a8641SAndroid Build Coastguard Worker const dbus::ObjectPath object_path = tmp->first;
516*635a8641SAndroid Build Coastguard Worker Object* object = tmp->second;
517*635a8641SAndroid Build Coastguard Worker std::vector<std::string> interfaces;
518*635a8641SAndroid Build Coastguard Worker
519*635a8641SAndroid Build Coastguard Worker for (Object::PropertiesMap::iterator piter =
520*635a8641SAndroid Build Coastguard Worker object->properties_map.begin();
521*635a8641SAndroid Build Coastguard Worker piter != object->properties_map.end(); ++piter)
522*635a8641SAndroid Build Coastguard Worker interfaces.push_back(piter->first);
523*635a8641SAndroid Build Coastguard Worker
524*635a8641SAndroid Build Coastguard Worker for (std::vector<std::string>::iterator iiter = interfaces.begin();
525*635a8641SAndroid Build Coastguard Worker iiter != interfaces.end(); ++iiter)
526*635a8641SAndroid Build Coastguard Worker RemoveInterface(object_path, *iiter);
527*635a8641SAndroid Build Coastguard Worker }
528*635a8641SAndroid Build Coastguard Worker
529*635a8641SAndroid Build Coastguard Worker }
530*635a8641SAndroid Build Coastguard Worker
531*635a8641SAndroid Build Coastguard Worker if (!new_owner.empty())
532*635a8641SAndroid Build Coastguard Worker GetManagedObjects();
533*635a8641SAndroid Build Coastguard Worker }
534*635a8641SAndroid Build Coastguard Worker
535*635a8641SAndroid Build Coastguard Worker } // namespace dbus
536