summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dbus/bus.cc58
-rw-r--r--dbus/bus.h30
-rw-r--r--dbus/object_proxy.cc82
-rw-r--r--device/media_transfer_protocol/media_transfer_protocol_manager.cc71
4 files changed, 165 insertions, 76 deletions
diff --git a/dbus/bus.cc b/dbus/bus.cc
index ea0497d..0d170ff 100644
--- a/dbus/bus.cc
+++ b/dbus/bus.cc
@@ -832,6 +832,64 @@ void Bus::AssertOnDBusThread() {
}
}
+std::string Bus::GetServiceOwnerAndBlock(const std::string& service_name,
+ GetServiceOwnerOption options) {
+ AssertOnDBusThread();
+
+ MethodCall get_name_owner_call("org.freedesktop.DBus", "GetNameOwner");
+ MessageWriter writer(&get_name_owner_call);
+ writer.AppendString(service_name);
+ VLOG(1) << "Method call: " << get_name_owner_call.ToString();
+
+ const ObjectPath obj_path("/org/freedesktop/DBus");
+ if (!get_name_owner_call.SetDestination("org.freedesktop.DBus") ||
+ !get_name_owner_call.SetPath(obj_path)) {
+ if (options == REPORT_ERRORS)
+ LOG(ERROR) << "Failed to get name owner.";
+ return "";
+ }
+
+ ScopedDBusError error;
+ DBusMessage* response_message =
+ SendWithReplyAndBlock(get_name_owner_call.raw_message(),
+ ObjectProxy::TIMEOUT_USE_DEFAULT,
+ error.get());
+ if (!response_message) {
+ if (options == REPORT_ERRORS) {
+ LOG(ERROR) << "Failed to get name owner. Got " << error.name() << ": "
+ << error.message();
+ }
+ return "";
+ }
+
+ scoped_ptr<Response> response(Response::FromRawMessage(response_message));
+ MessageReader reader(response.get());
+
+ std::string service_owner;
+ if (!reader.PopString(&service_owner))
+ service_owner.clear();
+ return service_owner;
+}
+
+void Bus::GetServiceOwner(const std::string& service_name,
+ const GetServiceOwnerCallback& callback) {
+ AssertOnOriginThread();
+
+ PostTaskToDBusThread(
+ FROM_HERE,
+ base::Bind(&Bus::GetServiceOwnerInternal, this, service_name, callback));
+}
+
+void Bus::GetServiceOwnerInternal(const std::string& service_name,
+ const GetServiceOwnerCallback& callback) {
+ AssertOnDBusThread();
+
+ std::string service_owner;
+ if (Connect())
+ service_owner = GetServiceOwnerAndBlock(service_name, REPORT_ERRORS);
+ PostTaskToOriginThread(FROM_HERE, base::Bind(callback, service_owner));
+}
+
dbus_bool_t Bus::OnAddWatch(DBusWatch* raw_watch) {
AssertOnDBusThread();
diff --git a/dbus/bus.h b/dbus/bus.h
index ec6bef1..5cf73ac 100644
--- a/dbus/bus.h
+++ b/dbus/bus.h
@@ -161,6 +161,13 @@ class CHROME_DBUS_EXPORT Bus : public base::RefCountedThreadSafe<Bus> {
SHARED,
};
+ // Specifies whether the GetServiceOwnerAndBlock call should report or
+ // suppress errors.
+ enum GetServiceOwnerOption {
+ REPORT_ERRORS,
+ SUPPRESS_ERRORS,
+ };
+
// Options used to create a Bus object.
struct CHROME_DBUS_EXPORT Options {
Options();
@@ -211,6 +218,12 @@ class CHROME_DBUS_EXPORT Bus : public base::RefCountedThreadSafe<Bus> {
// - the requested service name.
// - whether ownership has been obtained or not.
typedef base::Callback<void (const std::string&, bool)> OnOwnershipCallback;
+
+ // Called when GetServiceOwner() completes.
+ // |service_owner| is the return value from GetServiceOwnerAndBlock().
+ typedef base::Callback<void (const std::string& service_owner)>
+ GetServiceOwnerCallback;
+
// TODO(satorux): Remove the service name parameter as the caller of
// RequestOwnership() knows the service name.
@@ -530,6 +543,19 @@ class CHROME_DBUS_EXPORT Bus : public base::RefCountedThreadSafe<Bus> {
// AssertOnOriginThread().
virtual void AssertOnDBusThread();
+ // Gets the owner for |service_name| via org.freedesktop.DBus.GetNameOwner.
+ // Returns the owner name, if any, or an empty string on failure.
+ // |options| specifies where to printing error messages or not.
+ //
+ // BLOCKING CALL.
+ virtual std::string GetServiceOwnerAndBlock(const std::string& service_name,
+ GetServiceOwnerOption options);
+
+ // A non-blocking version of GetServiceOwnerAndBlock().
+ // Must be called in the origin thread.
+ virtual void GetServiceOwner(const std::string& service_name,
+ const GetServiceOwnerCallback& callback);
+
// Returns true if the bus is connected to D-Bus.
bool is_connected() { return connection_ != NULL; }
@@ -555,6 +581,10 @@ class CHROME_DBUS_EXPORT Bus : public base::RefCountedThreadSafe<Bus> {
void RequestOwnershipInternal(const std::string& service_name,
OnOwnershipCallback on_ownership_callback);
+ // Helper function used for GetServiceOwner().
+ void GetServiceOwnerInternal(const std::string& service_name,
+ const GetServiceOwnerCallback& callback);
+
// Processes the all incoming data to the connection, if any.
//
// BLOCKING CALL.
diff --git a/dbus/object_proxy.cc b/dbus/object_proxy.cc
index 0e56c7a..53b3539 100644
--- a/dbus/object_proxy.cc
+++ b/dbus/object_proxy.cc
@@ -18,6 +18,8 @@
#include "dbus/object_proxy.h"
#include "dbus/scoped_dbus_error.h"
+namespace dbus {
+
namespace {
const char kErrorServiceUnknown[] = "org.freedesktop.DBus.Error.ServiceUnknown";
@@ -28,6 +30,15 @@ const int kSuccessRatioHistogramMaxValue = 2;
// The path of D-Bus Object sending NameOwnerChanged signal.
const char kDBusSystemObjectPath[] = "/org/freedesktop/DBus";
+// The D-Bus Object interface.
+const char kDBusSystemObjectInterface[] = "org.freedesktop.DBus";
+
+// The D-Bus Object address.
+const char kDBusSystemObjectAddress[] = "org.freedesktop.DBus";
+
+// The NameOwnerChanged member in |kDBusSystemObjectInterface|.
+const char kNameOwnerChangedMember[] = "NameOwnerChanged";
+
// Gets the absolute signal name by concatenating the interface name and
// the signal name. Used for building keys for method_table_ in
// ObjectProxy.
@@ -38,13 +49,11 @@ std::string GetAbsoluteSignalName(
}
// An empty function used for ObjectProxy::EmptyResponseCallback().
-void EmptyResponseCallbackBody(dbus::Response* unused_response) {
+void EmptyResponseCallbackBody(Response* /*response*/) {
}
} // namespace
-namespace dbus {
-
ObjectProxy::ObjectProxy(Bus* bus,
const std::string& service_name,
const ObjectPath& object_path,
@@ -285,18 +294,17 @@ void ObjectProxy::RunResponseCallback(ResponseCallback response_callback,
} else if (dbus_message_get_type(response_message) ==
DBUS_MESSAGE_TYPE_ERROR) {
// This will take |response_message| and release (unref) it.
- scoped_ptr<dbus::ErrorResponse> error_response(
- dbus::ErrorResponse::FromRawMessage(response_message));
+ scoped_ptr<ErrorResponse> error_response(
+ ErrorResponse::FromRawMessage(response_message));
error_callback.Run(error_response.get());
// Delete the message on the D-Bus thread. See below for why.
bus_->PostTaskToDBusThread(
FROM_HERE,
- base::Bind(&base::DeletePointer<dbus::ErrorResponse>,
+ base::Bind(&base::DeletePointer<ErrorResponse>,
error_response.release()));
} else {
// This will take |response_message| and release (unref) it.
- scoped_ptr<dbus::Response> response(
- dbus::Response::FromRawMessage(response_message));
+ scoped_ptr<Response> response(Response::FromRawMessage(response_message));
// The response is successfully received.
response_callback.Run(response.get());
// The message should be deleted on the D-Bus thread for a complicated
@@ -319,8 +327,7 @@ void ObjectProxy::RunResponseCallback(ResponseCallback response_callback,
// thread, not from the current thread here, which is likely UI thread.
bus_->PostTaskToDBusThread(
FROM_HERE,
- base::Bind(&base::DeletePointer<dbus::Response>,
- response.release()));
+ base::Bind(&base::DeletePointer<Response>, response.release()));
method_call_successful = true;
// Record time spent for the method call. Don't include failures.
@@ -439,10 +446,10 @@ DBusHandlerResult ObjectProxy::HandleMessage(
// Verify the signal comes from the object we're proxying for, this is
// our last chance to return DBUS_HANDLER_RESULT_NOT_YET_HANDLED and
// allow other object proxies to handle instead.
- const dbus::ObjectPath path = signal->GetPath();
+ const ObjectPath path = signal->GetPath();
if (path != object_path_) {
if (path.value() == kDBusSystemObjectPath &&
- signal->GetMember() == "NameOwnerChanged") {
+ signal->GetMember() == kNameOwnerChangedMember) {
// Handle NameOwnerChanged separately
return HandleNameOwnerChanged(signal.Pass());
}
@@ -507,7 +514,7 @@ void ObjectProxy::RunMethod(base::TimeTicks start_time,
// RunResponseCallback().
bus_->PostTaskToDBusThread(
FROM_HERE,
- base::Bind(&base::DeletePointer<dbus::Signal>, signal));
+ base::Bind(&base::DeletePointer<Signal>, signal));
// Record time spent for handling the signal.
UMA_HISTOGRAM_TIMES("DBus.SignalHandleTime",
@@ -541,7 +548,7 @@ void ObjectProxy::OnCallMethodError(const std::string& interface_name,
ErrorResponse* error_response) {
if (error_response) {
// Error message may contain the error message as string.
- dbus::MessageReader reader(error_response);
+ MessageReader reader(error_response);
std::string error_message;
reader.PopString(&error_message);
LogMethodCallFailure(interface_name,
@@ -564,8 +571,8 @@ bool ObjectProxy::AddMatchRuleWithCallback(
ScopedDBusError error;
bus_->AddMatch(match_rule, error.get());
if (error.is_set()) {
- LOG(ERROR) << "Failed to add match rule \"" << match_rule << "\". Got " <<
- error.name() << ": " << error.message();
+ LOG(ERROR) << "Failed to add match rule \"" << match_rule << "\". Got "
+ << error.name() << ": " << error.message();
return false;
} else {
// Store the match rule, so that we can remove this in Detach().
@@ -594,8 +601,8 @@ bool ObjectProxy::AddMatchRuleWithoutCallback(
ScopedDBusError error;
bus_->AddMatch(match_rule, error.get());
if (error.is_set()) {
- LOG(ERROR) << "Failed to add match rule \"" << match_rule << "\". Got " <<
- error.name() << ": " << error.message();
+ LOG(ERROR) << "Failed to add match rule \"" << match_rule << "\". Got "
+ << error.name() << ": " << error.message();
return false;
}
// Store the match rule, so that we can remove this in Detach().
@@ -605,37 +612,8 @@ bool ObjectProxy::AddMatchRuleWithoutCallback(
void ObjectProxy::UpdateNameOwnerAndBlock() {
bus_->AssertOnDBusThread();
-
- MethodCall get_name_owner_call("org.freedesktop.DBus", "GetNameOwner");
- MessageWriter writer(&get_name_owner_call);
- writer.AppendString(service_name_);
- VLOG(1) << "Method call: " << get_name_owner_call.ToString();
-
- const dbus::ObjectPath obj_path("/org/freedesktop/DBus");
- ScopedDBusError error;
- if (!get_name_owner_call.SetDestination("org.freedesktop.DBus") ||
- !get_name_owner_call.SetPath(obj_path)) {
- LOG(ERROR) << "Failed to get name owner.";
- return;
- }
-
- DBusMessage* response_message = bus_->SendWithReplyAndBlock(
- get_name_owner_call.raw_message(),
- TIMEOUT_USE_DEFAULT,
- error.get());
- if (!response_message) {
- LOG(ERROR) << "Failed to get name owner. Got " << error.name() << ": " <<
- error.message();
- return;
- }
- scoped_ptr<Response> response(Response::FromRawMessage(response_message));
- MessageReader reader(response.get());
-
- std::string new_service_name_owner;
- if (reader.PopString(&new_service_name_owner))
- service_name_owner_ = new_service_name_owner;
- else
- service_name_owner_.clear();
+ service_name_owner_ =
+ bus_->GetServiceOwnerAndBlock(service_name_, Bus::SUPPRESS_ERRORS);
}
DBusHandlerResult ObjectProxy::HandleNameOwnerChanged(
@@ -644,9 +622,9 @@ DBusHandlerResult ObjectProxy::HandleNameOwnerChanged(
bus_->AssertOnDBusThread();
// Confirm the validity of the NameOwnerChanged signal.
- if (signal->GetMember() == "NameOwnerChanged" &&
- signal->GetInterface() == "org.freedesktop.DBus" &&
- signal->GetSender() == "org.freedesktop.DBus") {
+ if (signal->GetMember() == kNameOwnerChangedMember &&
+ signal->GetInterface() == kDBusSystemObjectInterface &&
+ signal->GetSender() == kDBusSystemObjectAddress) {
MessageReader reader(signal.get());
std::string name, old_owner, new_owner;
if (reader.PopString(&name) &&
diff --git a/device/media_transfer_protocol/media_transfer_protocol_manager.cc b/device/media_transfer_protocol/media_transfer_protocol_manager.cc
index 70871bd..869e924 100644
--- a/device/media_transfer_protocol/media_transfer_protocol_manager.cc
+++ b/device/media_transfer_protocol/media_transfer_protocol_manager.cc
@@ -11,19 +11,20 @@
#include "base/bind.h"
#include "base/command_line.h"
+#include "base/location.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/sequenced_task_runner.h"
#include "base/stl_util.h"
#include "base/threading/thread_checker.h"
+#include "dbus/bus.h"
#include "device/media_transfer_protocol/media_transfer_protocol_daemon_client.h"
#include "device/media_transfer_protocol/mtp_file_entry.pb.h"
#include "device/media_transfer_protocol/mtp_storage_info.pb.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
#if defined(OS_CHROMEOS)
#include "chromeos/dbus/dbus_thread_manager.h"
-#else
-#include "dbus/bus.h"
#endif
namespace device {
@@ -38,14 +39,8 @@ class MediaTransferProtocolManagerImpl : public MediaTransferProtocolManager {
explicit MediaTransferProtocolManagerImpl(
scoped_refptr<base::SequencedTaskRunner> task_runner)
: weak_ptr_factory_(this) {
- dbus::Bus* bus = NULL;
#if defined(OS_CHROMEOS)
DCHECK(!task_runner.get());
- chromeos::DBusThreadManager* dbus_thread_manager =
- chromeos::DBusThreadManager::Get();
- bus = dbus_thread_manager->GetSystemBus();
- if (!bus)
- return;
#else
DCHECK(task_runner.get());
dbus::Bus::Options options;
@@ -53,21 +48,12 @@ class MediaTransferProtocolManagerImpl : public MediaTransferProtocolManager {
options.connection_type = dbus::Bus::PRIVATE;
options.dbus_task_runner = task_runner;
session_bus_ = new dbus::Bus(options);
- bus = session_bus_.get();
#endif
- DCHECK(bus);
- mtp_client_.reset(
- MediaTransferProtocolDaemonClient::Create(bus, false /* not stub */));
-
- // Set up signals and start initializing |storage_info_map_|.
- mtp_client_->SetUpConnections(
- base::Bind(&MediaTransferProtocolManagerImpl::OnStorageChanged,
- weak_ptr_factory_.GetWeakPtr()));
- mtp_client_->EnumerateStorages(
- base::Bind(&MediaTransferProtocolManagerImpl::OnEnumerateStorages,
- weak_ptr_factory_.GetWeakPtr()),
- base::Bind(&base::DoNothing));
+ dbus::Bus::GetServiceOwnerCallback reply_task =
+ base::Bind(&MediaTransferProtocolManagerImpl::FinishSetupOnOriginThread,
+ weak_ptr_factory_.GetWeakPtr());
+ GetBus()->GetServiceOwner(mtpd::kMtpdServiceName, reply_task);
}
virtual ~MediaTransferProtocolManagerImpl() {
@@ -103,9 +89,7 @@ class MediaTransferProtocolManagerImpl : public MediaTransferProtocolManager {
const std::string& storage_name) const OVERRIDE {
DCHECK(thread_checker_.CalledOnValidThread());
StorageInfoMap::const_iterator it = storage_info_map_.find(storage_name);
- if (it == storage_info_map_.end())
- return NULL;
- return &it->second;
+ return it != storage_info_map_.end() ? &it->second : NULL;
}
// MediaTransferProtocolManager override.
@@ -401,6 +385,45 @@ class MediaTransferProtocolManagerImpl : public MediaTransferProtocolManager {
get_file_info_callbacks_.pop();
}
+ // Get the Bus object used to communicate with mtpd.
+ dbus::Bus* GetBus() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+#if defined(OS_CHROMEOS)
+ return chromeos::DBusThreadManager::Get()->GetSystemBus();
+#else
+ return session_bus_.get();
+#endif
+ }
+
+ // Callback to finish initialization after figuring out if the mtp service
+ // has an owner.
+ // |service_owner| contains the name of the current owner, if any.
+ void FinishSetupOnOriginThread(const std::string& service_owner) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (service_owner.empty()) {
+#if !defined(OS_CHROMEOS)
+ // |session_bus_| will not get used. Manually shut it down.
+ session_bus_->PostTaskToDBusThread(
+ FROM_HERE, base::Bind(&dbus::Bus::ShutdownAndBlock, session_bus_));
+#endif
+ return;
+ }
+
+ mtp_client_.reset(
+ MediaTransferProtocolDaemonClient::Create(GetBus(),
+ false /* not stub */));
+
+ // Set up signals and start initializing |storage_info_map_|.
+ mtp_client_->SetUpConnections(
+ base::Bind(&MediaTransferProtocolManagerImpl::OnStorageChanged,
+ weak_ptr_factory_.GetWeakPtr()));
+ mtp_client_->EnumerateStorages(
+ base::Bind(&MediaTransferProtocolManagerImpl::OnEnumerateStorages,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::Bind(&base::DoNothing));
+ }
+
// Mtpd DBus client.
scoped_ptr<MediaTransferProtocolDaemonClient> mtp_client_;