Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(164)

Side by Side Diff: dbus/object_manager.cc

Issue 510863002: dbus::ObjectManager: Add a match rule for properties before GetManagedObjects. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« dbus/bus.cc ('K') | « dbus/object_manager.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "dbus/object_manager.h" 5 #include "dbus/object_manager.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/location.h"
8 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/metrics/histogram.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/task_runner_util.h"
9 #include "dbus/bus.h" 13 #include "dbus/bus.h"
14 #include "dbus/dbus_statistics.h"
10 #include "dbus/message.h" 15 #include "dbus/message.h"
11 #include "dbus/object_proxy.h" 16 #include "dbus/object_proxy.h"
12 #include "dbus/property.h" 17 #include "dbus/property.h"
18 #include "dbus/scoped_dbus_error.h"
13 19
14 namespace dbus { 20 namespace dbus {
15 21
22 namespace {
23
24 // Gets the absolute signal name by concatenating the interface name and
25 // the signal name.
26 std::string GetAbsoluteSignalName(
27 const std::string& interface_name,
28 const std::string& signal_name) {
29 return interface_name + "." + signal_name;
30 }
satorux1 2014/08/28 04:00:01 this is anotner one in object_proxy.cc. I think it
armansito 2014/08/28 04:30:49 Ack. I'll add a TODO for this and do it in another
satorux1 2014/08/29 05:20:53 It's fine to do it in a separate patch, but that c
armansito 2014/08/29 16:17:08 Done.
31
32 } // namespace
33
16 ObjectManager::Object::Object() 34 ObjectManager::Object::Object()
17 : object_proxy(NULL) { 35 : object_proxy(NULL) {
18 } 36 }
19 37
20 ObjectManager::Object::~Object() { 38 ObjectManager::Object::~Object() {
21 } 39 }
22 40
23 ObjectManager::ObjectManager(Bus* bus, 41 ObjectManager::ObjectManager(Bus* bus,
24 const std::string& service_name, 42 const std::string& service_name,
25 const ObjectPath& object_path) 43 const ObjectPath& object_path)
26 : bus_(bus), 44 : bus_(bus),
27 service_name_(service_name), 45 service_name_(service_name),
28 object_path_(object_path), 46 object_path_(object_path),
47 setup_success_(false),
29 weak_ptr_factory_(this) { 48 weak_ptr_factory_(this) {
30 DVLOG(1) << "Creating ObjectManager for " << service_name_ 49 DVLOG(1) << "Creating ObjectManager for " << service_name_
31 << " " << object_path_.value(); 50 << " " << object_path_.value();
32
33 DCHECK(bus_); 51 DCHECK(bus_);
52 bus_->AssertOnOriginThread();
34 object_proxy_ = bus_->GetObjectProxy(service_name_, object_path_); 53 object_proxy_ = bus_->GetObjectProxy(service_name_, object_path_);
35 object_proxy_->SetNameOwnerChangedCallback( 54 object_proxy_->SetNameOwnerChangedCallback(
36 base::Bind(&ObjectManager::NameOwnerChanged, 55 base::Bind(&ObjectManager::NameOwnerChanged,
37 weak_ptr_factory_.GetWeakPtr())); 56 weak_ptr_factory_.GetWeakPtr()));
38 57
39 object_proxy_->ConnectToSignal( 58 // Set up a match rule and a filter function to handle PropertiesChanged
40 kObjectManagerInterface, 59 // signals from the service. This is important to avoid any race conditions
41 kObjectManagerInterfacesAdded, 60 // that might cause us to miss PropertiesChanged signals once all objects are
42 base::Bind(&ObjectManager::InterfacesAddedReceived, 61 // initialized via GetManagedObjects.
43 weak_ptr_factory_.GetWeakPtr()), 62 base::PostTaskAndReplyWithResult(
44 base::Bind(&ObjectManager::InterfacesAddedConnected, 63 bus_->GetDBusTaskRunner(),
45 weak_ptr_factory_.GetWeakPtr())); 64 FROM_HERE,
46 65 base::Bind(&ObjectManager::SetupMatchRuleAndFilter, this),
47 object_proxy_->ConnectToSignal( 66 base::Bind(&ObjectManager::OnSetupMatchRuleAndFilterComplete, this));
48 kObjectManagerInterface,
49 kObjectManagerInterfacesRemoved,
50 base::Bind(&ObjectManager::InterfacesRemovedReceived,
51 weak_ptr_factory_.GetWeakPtr()),
52 base::Bind(&ObjectManager::InterfacesRemovedConnected,
53 weak_ptr_factory_.GetWeakPtr()));
54
55 GetManagedObjects();
56 } 67 }
57 68
58 ObjectManager::~ObjectManager() { 69 ObjectManager::~ObjectManager() {
59 // Clean up Object structures 70 // Clean up Object structures
60 for (ObjectMap::iterator iter = object_map_.begin(); 71 for (ObjectMap::iterator iter = object_map_.begin();
61 iter != object_map_.end(); ++iter) { 72 iter != object_map_.end(); ++iter) {
62 Object* object = iter->second; 73 Object* object = iter->second;
63 74
64 for (Object::PropertiesMap::iterator piter = object->properties_map.begin(); 75 for (Object::PropertiesMap::iterator piter = object->properties_map.begin();
65 piter != object->properties_map.end(); ++piter) { 76 piter != object->properties_map.end(); ++piter) {
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 MethodCall method_call(kObjectManagerInterface, 148 MethodCall method_call(kObjectManagerInterface,
138 kObjectManagerGetManagedObjects); 149 kObjectManagerGetManagedObjects);
139 150
140 object_proxy_->CallMethod( 151 object_proxy_->CallMethod(
141 &method_call, 152 &method_call,
142 ObjectProxy::TIMEOUT_USE_DEFAULT, 153 ObjectProxy::TIMEOUT_USE_DEFAULT,
143 base::Bind(&ObjectManager::OnGetManagedObjects, 154 base::Bind(&ObjectManager::OnGetManagedObjects,
144 weak_ptr_factory_.GetWeakPtr())); 155 weak_ptr_factory_.GetWeakPtr()));
145 } 156 }
146 157
158 void ObjectManager::CleanUp() {
159 DCHECK(bus_);
160 bus_->AssertOnDBusThread();
161
162 if (!setup_success_)
163 return;
164
165 if (!bus_->RemoveFilterFunction(&ObjectManager::HandleMessageThunk, this))
166 LOG(ERROR) << "Failed to remove filter function";
167
168 ScopedDBusError error;
169 bus_->RemoveMatch(match_rule_, error.get());
170 if (error.is_set())
171 LOG(ERROR) << "Failed to remove match rule: " << match_rule_;
172
173 match_rule_.clear();
174 }
175
176 void ObjectManager::InitializeObjects() {
177 DCHECK(bus_);
178 object_proxy_->ConnectToSignal(
179 kObjectManagerInterface,
180 kObjectManagerInterfacesAdded,
181 base::Bind(&ObjectManager::InterfacesAddedReceived,
182 weak_ptr_factory_.GetWeakPtr()),
183 base::Bind(&ObjectManager::InterfacesAddedConnected,
184 weak_ptr_factory_.GetWeakPtr()));
185
186 object_proxy_->ConnectToSignal(
187 kObjectManagerInterface,
188 kObjectManagerInterfacesRemoved,
189 base::Bind(&ObjectManager::InterfacesRemovedReceived,
190 weak_ptr_factory_.GetWeakPtr()),
191 base::Bind(&ObjectManager::InterfacesRemovedConnected,
192 weak_ptr_factory_.GetWeakPtr()));
193
194 GetManagedObjects();
195 }
196
197 bool ObjectManager::SetupMatchRuleAndFilter() {
198 DCHECK(bus_);
199 DCHECK(!setup_success_);
200 bus_->AssertOnDBusThread();
201
202 if (!bus_->Connect() || !bus_->SetUpAsyncOperations())
203 return false;
204
205 service_name_owner_ =
206 bus_->GetServiceOwnerAndBlock(service_name_, Bus::SUPPRESS_ERRORS);
207
208 const std::string match_rule =
209 base::StringPrintf(
210 "type='signal', sender='%s', interface='%s', member='%s'",
211 service_name_.c_str(),
212 kPropertiesInterface,
213 kPropertiesChanged);
214
215 if (!bus_->AddFilterFunction(&ObjectManager::HandleMessageThunk, this)) {
216 LOG(ERROR) << "ObjectManager failed to add filter function";
217 return false;
218 }
219
220 ScopedDBusError error;
221 bus_->AddMatch(match_rule, error.get());
222 if (error.is_set()) {
223 LOG(ERROR) << "ObjectManager failed to add match rule \"" << match_rule
224 << "\". Got " << error.name() << ": " << error.message();
225 bus_->RemoveFilterFunction(&ObjectManager::HandleMessageThunk, this);
226 return false;
227 }
228
229 match_rule_ = match_rule;
230 setup_success_ = true;
231
232 return true;
233 }
234
235 void ObjectManager::OnSetupMatchRuleAndFilterComplete(bool success) {
236 LOG_IF(WARNING, !success) << service_name_ << " " << object_path_.value()
237 << ": Failed to set up match rule.";
238 if (success)
239 InitializeObjects();
240 }
241
242 // static
243 DBusHandlerResult ObjectManager::HandleMessageThunk(DBusConnection* connection,
244 DBusMessage* raw_message,
245 void* user_data) {
246 ObjectManager* self = reinterpret_cast<ObjectManager*>(user_data);
247 return self->HandleMessage(connection, raw_message);
248 }
249
250 DBusHandlerResult ObjectManager::HandleMessage(DBusConnection* connection,
251 DBusMessage* raw_message) {
252 DCHECK(bus_);
253 bus_->AssertOnDBusThread();
254
255 if (dbus_message_get_type(raw_message) != DBUS_MESSAGE_TYPE_SIGNAL)
256 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
257
258 // raw_message will be unrefed on exit of the function. Increment the
259 // reference so we can use it in Signal.
260 dbus_message_ref(raw_message);
261 scoped_ptr<Signal> signal(
262 Signal::FromRawMessage(raw_message));
263
264 const std::string interface = signal->GetInterface();
265 const std::string member = signal->GetMember();
266
267 statistics::AddReceivedSignal(service_name_, interface, member);
268
269 // Only handle the PropertiesChanged signal.
270 const std::string absolute_signal_name =
271 GetAbsoluteSignalName(interface, member);
272 const std::string properties_changed_signal_name =
273 GetAbsoluteSignalName(kPropertiesInterface, kPropertiesChanged);
274 if (absolute_signal_name != properties_changed_signal_name)
275 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
276
277 VLOG(1) << "Signal received: " << signal->ToString();
278
279 // Make sure that the signal originated from the correct sender.
280 std::string sender = signal->GetSender();
281 if (service_name_owner_ != sender) {
282 LOG(ERROR) << "Rejecting a message from a wrong sender.";
283 UMA_HISTOGRAM_COUNTS("DBus.RejectedSignalCount", 1);
284 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
285 }
286
287 const ObjectPath path = signal->GetPath();
288
289 if (bus_->HasDBusThread()) {
290 // Post a task to run the method in the origin thread. Transfer ownership of
291 // |signal| to NotifyPropertiesChanged, which will handle the clean up.
292 Signal* released_signal = signal.release();
293 bus_->GetOriginTaskRunner()->PostTask(
294 FROM_HERE,
295 base::Bind(&ObjectManager::NotifyPropertiesChanged,
296 this, path,
297 released_signal));
298 } else {
299 // If the D-Bus thread is not used, just call the callback on the
300 // current thread. Transfer the ownership of |signal| to
301 // NotifyPropertiesChanged.
302 NotifyPropertiesChanged(path, signal.release());
303 }
304
305 // We don't return DBUS_HANDLER_RESULT_HANDLED for signals because other
306 // objects may be interested in them. (e.g. Signals from org.freedesktop.DBus)
307 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
308 }
309
310 void ObjectManager::NotifyPropertiesChanged(
311 const dbus::ObjectPath object_path,
312 Signal* signal) {
satorux1 2014/08/28 04:00:01 add bus_->AssertOnOriginThread(); to be consiste
armansito 2014/08/28 15:37:59 Done.
313 NotifyPropertiesChangedHelper(object_path, signal);
314
315 // Delete the message on the D-Bus thread. See comments in HandleMessage.
316 bus_->GetDBusTaskRunner()->PostTask(
317 FROM_HERE,
318 base::Bind(&base::DeletePointer<Signal>, signal));
319 }
320
321 void ObjectManager::NotifyPropertiesChangedHelper(
322 const dbus::ObjectPath object_path,
323 Signal* signal) {
324 DCHECK(bus_);
325 bus_->AssertOnOriginThread();
satorux1 2014/08/29 05:20:53 let's keep them. a bit verbose, but good to have t
armansito 2014/08/29 16:17:08 Done.
326
327 MessageReader reader(signal);
328 std::string interface;
329 if (!reader.PopString(&interface)) {
330 LOG(WARNING) << "Property changed signal has wrong parameters: "
331 << "expected interface name: " << signal->ToString();
332 return;
333 }
334
335 PropertySet* properties = GetProperties(object_path, interface);
336 if (properties)
337 properties->ChangedReceived(signal);
338 }
339
147 void ObjectManager::OnGetManagedObjects(Response* response) { 340 void ObjectManager::OnGetManagedObjects(Response* response) {
148 if (response != NULL) { 341 if (response != NULL) {
149 MessageReader reader(response); 342 MessageReader reader(response);
150 MessageReader array_reader(NULL); 343 MessageReader array_reader(NULL);
151 if (!reader.PopArray(&array_reader)) 344 if (!reader.PopArray(&array_reader))
152 return; 345 return;
153 346
154 while (array_reader.HasMoreData()) { 347 while (array_reader.HasMoreData()) {
155 MessageReader dict_entry_reader(NULL); 348 MessageReader dict_entry_reader(NULL);
156 ObjectPath object_path; 349 ObjectPath object_path;
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 object = oiter->second; 443 object = oiter->second;
251 444
252 Object::PropertiesMap::iterator piter = 445 Object::PropertiesMap::iterator piter =
253 object->properties_map.find(interface_name); 446 object->properties_map.find(interface_name);
254 PropertySet* property_set; 447 PropertySet* property_set;
255 const bool interface_added = (piter == object->properties_map.end()); 448 const bool interface_added = (piter == object->properties_map.end());
256 if (interface_added) { 449 if (interface_added) {
257 property_set = object->properties_map[interface_name] = 450 property_set = object->properties_map[interface_name] =
258 interface->CreateProperties(object->object_proxy, 451 interface->CreateProperties(object->object_proxy,
259 object_path, interface_name); 452 object_path, interface_name);
260 property_set->ConnectSignals();
261 } else 453 } else
262 property_set = piter->second; 454 property_set = piter->second;
263 455
264 property_set->UpdatePropertiesFromReader(reader); 456 property_set->UpdatePropertiesFromReader(reader);
265 457
266 if (interface_added) 458 if (interface_added)
267 interface->ObjectAdded(object_path, interface_name); 459 interface->ObjectAdded(object_path, interface_name);
268 } 460 }
269 461
270 void ObjectManager::RemoveInterface(const ObjectPath& object_path, 462 void ObjectManager::RemoveInterface(const ObjectPath& object_path,
(...skipping 19 matching lines...) Expand all
290 object->properties_map.erase(piter); 482 object->properties_map.erase(piter);
291 483
292 if (object->properties_map.empty()) { 484 if (object->properties_map.empty()) {
293 object_map_.erase(oiter); 485 object_map_.erase(oiter);
294 delete object; 486 delete object;
295 } 487 }
296 } 488 }
297 489
298 void ObjectManager::NameOwnerChanged(const std::string& old_owner, 490 void ObjectManager::NameOwnerChanged(const std::string& old_owner,
299 const std::string& new_owner) { 491 const std::string& new_owner) {
492 service_name_owner_ = new_owner;
493
300 if (!old_owner.empty()) { 494 if (!old_owner.empty()) {
301 ObjectMap::iterator iter = object_map_.begin(); 495 ObjectMap::iterator iter = object_map_.begin();
302 while (iter != object_map_.end()) { 496 while (iter != object_map_.end()) {
303 ObjectMap::iterator tmp = iter; 497 ObjectMap::iterator tmp = iter;
304 ++iter; 498 ++iter;
305 499
306 // PropertiesMap is mutated by RemoveInterface, and also Object is 500 // PropertiesMap is mutated by RemoveInterface, and also Object is
307 // destroyed; easier to collect the object path and interface names 501 // destroyed; easier to collect the object path and interface names
308 // and remove them safely. 502 // and remove them safely.
309 const dbus::ObjectPath object_path = tmp->first; 503 const dbus::ObjectPath object_path = tmp->first;
(...skipping 10 matching lines...) Expand all
320 RemoveInterface(object_path, *iiter); 514 RemoveInterface(object_path, *iiter);
321 } 515 }
322 516
323 } 517 }
324 518
325 if (!new_owner.empty()) 519 if (!new_owner.empty())
326 GetManagedObjects(); 520 GetManagedObjects();
327 } 521 }
328 522
329 } // namespace dbus 523 } // namespace dbus
OLDNEW
« dbus/bus.cc ('K') | « dbus/object_manager.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698