diff options
-rw-r--r-- | dbus/bus.cc | 58 | ||||
-rw-r--r-- | dbus/bus.h | 30 | ||||
-rw-r--r-- | dbus/object_proxy.cc | 82 | ||||
-rw-r--r-- | device/media_transfer_protocol/media_transfer_protocol_manager.cc | 71 |
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(); @@ -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_; |