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

Unified Diff: dbus/bus.cc

Issue 15741025: Linux/CrOS: Retry connecting to mtpd. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: address nits Created 7 years, 6 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « dbus/bus.h ('k') | dbus/bus_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: dbus/bus.cc
===================================================================
--- dbus/bus.cc (revision 204929)
+++ dbus/bus.cc (working copy)
@@ -9,10 +9,12 @@
#include "base/message_loop.h"
#include "base/message_loop_proxy.h"
#include "base/stl_util.h"
+#include "base/stringprintf.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "base/time.h"
#include "dbus/exported_object.h"
+#include "dbus/message.h"
#include "dbus/object_manager.h"
#include "dbus/object_path.h"
#include "dbus/object_proxy.h"
@@ -27,6 +29,15 @@
"type='signal', path='/org/freedesktop/DBus/Local',"
"interface='org.freedesktop.DBus.Local', member='Disconnected'";
+// The NameOwnerChanged member in org.freedesktop.DBus
+const char kNameOwnerChangedSignal[] = "NameOwnerChanged";
+
+// The match rule used to filter for changes to a given service name owner.
+const char kServiceNameOwnerChangeMatchRule[] =
+ "type='signal',interface='org.freedesktop.DBus',"
+ "member='NameOwnerChanged',path='/org/freedesktop/DBus',"
+ "sender='org.freedesktop.DBus',arg0='%s'";
+
// The class is used for watching the file descriptor used for D-Bus
// communication.
class Watch : public base::MessagePumpLibevent::Watcher {
@@ -908,6 +919,112 @@
PostTaskToOriginThread(FROM_HERE, base::Bind(callback, service_owner));
}
+void Bus::ListenForServiceOwnerChange(
+ const std::string& service_name,
+ const GetServiceOwnerCallback& callback) {
+ AssertOnOriginThread();
+ DCHECK(!service_name.empty());
+ DCHECK(!callback.is_null());
+
+ PostTaskToDBusThread(FROM_HERE,
+ base::Bind(&Bus::ListenForServiceOwnerChangeInternal,
+ this, service_name, callback));
+}
+
+void Bus::ListenForServiceOwnerChangeInternal(
+ const std::string& service_name,
+ const GetServiceOwnerCallback& callback) {
+ AssertOnDBusThread();
+ DCHECK(!service_name.empty());
+ DCHECK(!callback.is_null());
+
+ if (!Connect() || !SetUpAsyncOperations())
+ return;
+
+ if (service_owner_changed_listener_map_.empty()) {
+ bool filter_added =
+ AddFilterFunction(Bus::OnServiceOwnerChangedFilter, this);
+ DCHECK(filter_added);
+ }
+
+ ServiceOwnerChangedListenerMap::iterator it =
+ service_owner_changed_listener_map_.find(service_name);
+ if (it == service_owner_changed_listener_map_.end()) {
+ // Add a match rule for the new service name.
+ const std::string name_owner_changed_match_rule =
+ base::StringPrintf(kServiceNameOwnerChangeMatchRule,
+ service_name.c_str());
+ ScopedDBusError error;
+ AddMatch(name_owner_changed_match_rule, error.get());
+ if (error.is_set()) {
+ LOG(ERROR) << "Failed to add match rule for " << service_name
+ << ". Got " << error.name() << ": " << error.message();
+ return;
+ }
+
+ service_owner_changed_listener_map_[service_name].push_back(callback);
+ return;
+ }
+
+ // Check if the callback has already been added.
+ std::vector<GetServiceOwnerCallback>& callbacks = it->second;
+ for (size_t i = 0; i < callbacks.size(); ++i) {
+ if (callbacks[i].Equals(callback))
+ return;
+ }
+ callbacks.push_back(callback);
+}
+
+void Bus::UnlistenForServiceOwnerChange(
+ const std::string& service_name,
+ const GetServiceOwnerCallback& callback) {
+ AssertOnOriginThread();
+ DCHECK(!service_name.empty());
+ DCHECK(!callback.is_null());
+
+ PostTaskToDBusThread(FROM_HERE,
+ base::Bind(&Bus::UnlistenForServiceOwnerChangeInternal,
+ this, service_name, callback));
+}
+
+void Bus::UnlistenForServiceOwnerChangeInternal(
+ const std::string& service_name,
+ const GetServiceOwnerCallback& callback) {
+ AssertOnDBusThread();
+ DCHECK(!service_name.empty());
+ DCHECK(!callback.is_null());
+
+ ServiceOwnerChangedListenerMap::iterator it =
+ service_owner_changed_listener_map_.find(service_name);
+ if (it == service_owner_changed_listener_map_.end())
+ return;
+
+ std::vector<GetServiceOwnerCallback>& callbacks = it->second;
+ for (size_t i = 0; i < callbacks.size(); ++i) {
+ if (callbacks[i].Equals(callback)) {
+ callbacks.erase(callbacks.begin() + i);
+ break; // There can be only one.
+ }
+ }
+ if (!callbacks.empty())
+ return;
+
+ // Last callback for |service_name| has been removed, remove match rule.
+ const std::string name_owner_changed_match_rule =
+ base::StringPrintf(kServiceNameOwnerChangeMatchRule,
+ service_name.c_str());
+ ScopedDBusError error;
+ RemoveMatch(name_owner_changed_match_rule, error.get());
+ // And remove |service_owner_changed_listener_map_| entry.
+ service_owner_changed_listener_map_.erase(it);
+
+ if (service_owner_changed_listener_map_.empty()) {
+ bool filter_removed =
+ RemoveFilterFunction(Bus::OnServiceOwnerChangedFilter, this);
+ DCHECK(filter_removed);
+ }
+}
+
dbus_bool_t Bus::OnAddWatch(DBusWatch* raw_watch) {
AssertOnDBusThread();
@@ -1000,36 +1117,81 @@
ShutdownAndBlock();
}
+void Bus::OnServiceOwnerChanged(DBusMessage* message) {
+ DCHECK(message);
+ AssertOnDBusThread();
+
+ // |message| will be unrefed on exit of the function. Increment the
+ // reference so we can use it in Signal::FromRawMessage() below.
+ dbus_message_ref(message);
+ scoped_ptr<Signal> signal(Signal::FromRawMessage(message));
+
+ // Confirm the validity of the NameOwnerChanged signal.
+ if (signal->GetMember() != kNameOwnerChangedSignal ||
+ signal->GetInterface() != DBUS_INTERFACE_DBUS ||
+ signal->GetSender() != DBUS_SERVICE_DBUS) {
+ return;
+ }
+
+ MessageReader reader(signal.get());
+ std::string service_name;
+ std::string old_owner;
+ std::string new_owner;
+ if (!reader.PopString(&service_name) ||
+ !reader.PopString(&old_owner) ||
+ !reader.PopString(&new_owner)) {
+ return;
+ }
+
+ ServiceOwnerChangedListenerMap::const_iterator it =
+ service_owner_changed_listener_map_.find(service_name);
+ if (it == service_owner_changed_listener_map_.end())
+ return;
+
+ const std::vector<GetServiceOwnerCallback>& callbacks = it->second;
+ for (size_t i = 0; i < callbacks.size(); ++i) {
+ PostTaskToOriginThread(FROM_HERE,
+ base::Bind(callbacks[i], new_owner));
+ }
+}
+
+// static
dbus_bool_t Bus::OnAddWatchThunk(DBusWatch* raw_watch, void* data) {
Bus* self = static_cast<Bus*>(data);
return self->OnAddWatch(raw_watch);
}
+// static
void Bus::OnRemoveWatchThunk(DBusWatch* raw_watch, void* data) {
Bus* self = static_cast<Bus*>(data);
self->OnRemoveWatch(raw_watch);
}
+// static
void Bus::OnToggleWatchThunk(DBusWatch* raw_watch, void* data) {
Bus* self = static_cast<Bus*>(data);
self->OnToggleWatch(raw_watch);
}
+// static
dbus_bool_t Bus::OnAddTimeoutThunk(DBusTimeout* raw_timeout, void* data) {
Bus* self = static_cast<Bus*>(data);
return self->OnAddTimeout(raw_timeout);
}
+// static
void Bus::OnRemoveTimeoutThunk(DBusTimeout* raw_timeout, void* data) {
Bus* self = static_cast<Bus*>(data);
self->OnRemoveTimeout(raw_timeout);
}
+// static
void Bus::OnToggleTimeoutThunk(DBusTimeout* raw_timeout, void* data) {
Bus* self = static_cast<Bus*>(data);
self->OnToggleTimeout(raw_timeout);
}
+// static
void Bus::OnDispatchStatusChangedThunk(DBusConnection* connection,
DBusDispatchStatus status,
void* data) {
@@ -1037,6 +1199,7 @@
self->OnDispatchStatusChanged(connection, status);
}
+// static
DBusHandlerResult Bus::OnConnectionDisconnectedFilter(
DBusConnection* connection,
DBusMessage* message,
@@ -1045,11 +1208,26 @@
DBUS_INTERFACE_LOCAL,
kDisconnectedSignal)) {
Bus* self = static_cast<Bus*>(data);
- self->AssertOnDBusThread();
self->OnConnectionDisconnected(connection);
return DBUS_HANDLER_RESULT_HANDLED;
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
+// static
+DBusHandlerResult Bus::OnServiceOwnerChangedFilter(
+ DBusConnection* connection,
+ DBusMessage* message,
+ void* data) {
+ if (dbus_message_is_signal(message,
+ DBUS_INTERFACE_DBUS,
+ kNameOwnerChangedSignal)) {
+ Bus* self = static_cast<Bus*>(data);
+ self->OnServiceOwnerChanged(message);
+ }
+ // Always return unhandled to let others, e.g. ObjectProxies, handle the same
+ // signal.
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
} // namespace dbus
« no previous file with comments | « dbus/bus.h ('k') | dbus/bus_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698