xref: /aosp_15_r20/external/libchrome/dbus/object_manager.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
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