Index: chrome/browser/chromeos/mtp/media_transfer_protocol_manager.cc |
=================================================================== |
--- chrome/browser/chromeos/mtp/media_transfer_protocol_manager.cc (revision 0) |
+++ chrome/browser/chromeos/mtp/media_transfer_protocol_manager.cc (revision 0) |
@@ -0,0 +1,417 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/chromeos/mtp/media_transfer_protocol_manager.h" |
+ |
+#include <map> |
+#include <queue> |
+#include <set> |
+#include <utility> |
+ |
+#include "base/bind.h" |
+#include "base/memory/weak_ptr.h" |
+#include "base/observer_list.h" |
+#include "base/stl_util.h" |
+#include "chromeos/dbus/dbus_thread_manager.h" |
+#include "content/public/browser/browser_thread.h" |
+ |
+using content::BrowserThread; |
+ |
+namespace chromeos { |
+namespace mtp { |
+ |
+namespace { |
+ |
+MediaTransferProtocolManager* g_media_transfer_protocol_manager = NULL; |
+ |
+// The MediaTransferProtocolManager implementation. |
+class MediaTransferProtocolManagerImpl : public MediaTransferProtocolManager { |
+ public: |
+ MediaTransferProtocolManagerImpl() : weak_ptr_factory_(this) { |
+ DBusThreadManager* dbus_thread_manager = DBusThreadManager::Get(); |
+ mtp_client_ = dbus_thread_manager->GetMediaTransferProtocolDaemonClient(); |
+ |
+ // Set up signals and start initializing |storage_info_map_|. |
+ mtp_client_->SetUpConnections( |
+ base::Bind(&MediaTransferProtocolManagerImpl::OnStorageChanged, |
+ weak_ptr_factory_.GetWeakPtr())); |
+ mtp_client_->EnumerateStorage( |
+ base::Bind(&MediaTransferProtocolManagerImpl::OnEnumerateStorage, |
+ weak_ptr_factory_.GetWeakPtr()), |
+ base::Bind(&base::DoNothing)); |
+ } |
+ |
+ virtual ~MediaTransferProtocolManagerImpl() { |
+ } |
+ |
+ // MediaTransferProtocolManager override. |
+ virtual void AddObserver(Observer* observer) OVERRIDE { |
+ observers_.AddObserver(observer); |
+ } |
+ |
+ // MediaTransferProtocolManager override. |
+ virtual void RemoveObserver(Observer* observer) OVERRIDE { |
+ observers_.RemoveObserver(observer); |
+ } |
+ |
+ // MediaTransferProtocolManager override. |
+ const std::vector<std::string> GetStorages() const OVERRIDE { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ std::vector<std::string> storages; |
+ for (StorageInfoMap::const_iterator it = storage_info_map_.begin(); |
+ it != storage_info_map_.end(); |
+ ++it) { |
+ storages.push_back(it->first); |
+ } |
+ return storages; |
+ } |
+ |
+ // MediaTransferProtocolManager override. |
+ virtual const StorageInfo* GetStorageInfo( |
+ const std::string& storage_name) const OVERRIDE { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ StorageInfoMap::const_iterator it = storage_info_map_.find(storage_name); |
+ if (it == storage_info_map_.end()) |
+ return NULL; |
+ return &it->second; |
+ } |
+ |
+ // MediaTransferProtocolManager override. |
+ virtual void OpenStorage(const std::string& storage_name, |
+ OpenStorageMode mode, |
+ const OpenStorageCallback& callback) OVERRIDE { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ if (!ContainsKey(storage_info_map_, storage_name)) { |
+ callback.Run("", true); |
+ return; |
+ } |
+ open_storage_callbacks_.push(callback); |
+ mtp_client_->OpenStorage( |
+ storage_name, |
+ mode, |
+ base::Bind(&MediaTransferProtocolManagerImpl::OnOpenStorage, |
+ weak_ptr_factory_.GetWeakPtr()), |
+ base::Bind(&MediaTransferProtocolManagerImpl::OnOpenStorageError, |
+ weak_ptr_factory_.GetWeakPtr())); |
+ } |
+ |
+ // MediaTransferProtocolManager override. |
+ virtual void CloseStorage(const std::string& storage_handle, |
+ const CloseStorageCallback& callback) OVERRIDE { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ if (!ContainsKey(handles_, storage_handle)) { |
+ callback.Run(true); |
+ return; |
+ } |
+ close_storage_callbacks_.push(std::make_pair(callback, storage_handle)); |
+ mtp_client_->CloseStorage( |
+ storage_handle, |
+ base::Bind(&MediaTransferProtocolManagerImpl::OnCloseStorage, |
+ weak_ptr_factory_.GetWeakPtr()), |
+ base::Bind(&MediaTransferProtocolManagerImpl::OnCloseStorageError, |
+ weak_ptr_factory_.GetWeakPtr())); |
+ } |
+ |
+ // MediaTransferProtocolManager override. |
+ virtual void ReadDirectoryByPath( |
+ const std::string& storage_handle, |
+ const std::string& path, |
+ const ReadDirectoryCallback& callback) OVERRIDE { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ if (!ContainsKey(handles_, storage_handle)) { |
+ callback.Run(std::vector<FileEntry>(), true); |
+ return; |
+ } |
+ read_directory_callbacks_.push(callback); |
+ mtp_client_->ReadDirectoryByPath( |
+ storage_handle, |
+ path, |
+ base::Bind(&MediaTransferProtocolManagerImpl::OnReadDirectory, |
+ weak_ptr_factory_.GetWeakPtr()), |
+ base::Bind(&MediaTransferProtocolManagerImpl::OnReadDirectoryError, |
+ weak_ptr_factory_.GetWeakPtr())); |
+ } |
+ |
+ // MediaTransferProtocolManager override. |
+ virtual void ReadDirectoryById( |
+ const std::string& storage_handle, |
+ uint32 file_id, |
+ const ReadDirectoryCallback& callback) OVERRIDE { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ if (!ContainsKey(handles_, storage_handle)) { |
+ callback.Run(std::vector<FileEntry>(), true); |
+ return; |
+ } |
+ read_directory_callbacks_.push(callback); |
+ mtp_client_->ReadDirectoryById( |
+ storage_handle, |
+ file_id, |
+ base::Bind(&MediaTransferProtocolManagerImpl::OnReadDirectory, |
+ weak_ptr_factory_.GetWeakPtr()), |
+ base::Bind(&MediaTransferProtocolManagerImpl::OnReadDirectoryError, |
+ weak_ptr_factory_.GetWeakPtr())); |
+ } |
+ |
+ // MediaTransferProtocolManager override. |
+ virtual void ReadFileByPath(const std::string& storage_handle, |
+ const std::string& path, |
+ const ReadFileCallback& callback) OVERRIDE { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ if (!ContainsKey(handles_, storage_handle)) { |
+ callback.Run(std::string(), true); |
+ return; |
+ } |
+ read_file_callbacks_.push(callback); |
+ mtp_client_->ReadFileByPath( |
+ storage_handle, |
+ path, |
+ base::Bind(&MediaTransferProtocolManagerImpl::OnReadFile, |
+ weak_ptr_factory_.GetWeakPtr()), |
+ base::Bind(&MediaTransferProtocolManagerImpl::OnReadFileError, |
+ weak_ptr_factory_.GetWeakPtr())); |
+ } |
+ |
+ // MediaTransferProtocolManager override. |
+ virtual void ReadFileById(const std::string& storage_handle, |
+ uint32 file_id, |
+ const ReadFileCallback& callback) OVERRIDE { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ if (!ContainsKey(handles_, storage_handle)) { |
+ callback.Run(std::string(), true); |
+ return; |
+ } |
+ read_file_callbacks_.push(callback); |
+ mtp_client_->ReadFileById( |
+ storage_handle, |
+ file_id, |
+ base::Bind(&MediaTransferProtocolManagerImpl::OnReadFile, |
+ weak_ptr_factory_.GetWeakPtr()), |
+ base::Bind(&MediaTransferProtocolManagerImpl::OnReadFileError, |
+ weak_ptr_factory_.GetWeakPtr())); |
+ } |
+ |
+ virtual void GetFileInfoByPath(const std::string& storage_handle, |
+ const std::string& path, |
+ const GetFileInfoCallback& callback) OVERRIDE { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ if (!ContainsKey(handles_, storage_handle)) { |
+ callback.Run(FileEntry(), true); |
+ return; |
+ } |
+ get_file_info_callbacks_.push(callback); |
+ mtp_client_->GetFileInfoByPath( |
+ storage_handle, |
+ path, |
+ base::Bind(&MediaTransferProtocolManagerImpl::OnGetFileInfo, |
+ weak_ptr_factory_.GetWeakPtr()), |
+ base::Bind(&MediaTransferProtocolManagerImpl::OnGetFileInfoError, |
+ weak_ptr_factory_.GetWeakPtr())); |
+ } |
+ |
+ virtual void GetFileInfoById(const std::string& storage_handle, |
+ uint32 file_id, |
+ const GetFileInfoCallback& callback) OVERRIDE { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ if (!ContainsKey(handles_, storage_handle)) { |
+ callback.Run(FileEntry(), true); |
+ return; |
+ } |
+ get_file_info_callbacks_.push(callback); |
+ mtp_client_->GetFileInfoById( |
+ storage_handle, |
+ file_id, |
+ base::Bind(&MediaTransferProtocolManagerImpl::OnGetFileInfo, |
+ weak_ptr_factory_.GetWeakPtr()), |
+ base::Bind(&MediaTransferProtocolManagerImpl::OnGetFileInfoError, |
+ weak_ptr_factory_.GetWeakPtr())); |
+ } |
+ |
+ private: |
+ // Map of storage names to storage info. |
+ typedef std::map<std::string, StorageInfo> StorageInfoMap; |
+ // Callback queues - DBus communication is in-order, thus callbacks are |
+ // received in the same order as the requests. |
+ typedef std::queue<OpenStorageCallback> OpenStorageCallbackQueue; |
+ // (callback, handle) |
+ typedef std::queue<std::pair<CloseStorageCallback, std::string> |
+ > CloseStorageCallbackQueue; |
+ typedef std::queue<ReadDirectoryCallback> ReadDirectoryCallbackQueue; |
+ typedef std::queue<ReadFileCallback> ReadFileCallbackQueue; |
+ typedef std::queue<GetFileInfoCallback> GetFileInfoCallbackQueue; |
+ |
+ void OnStorageChanged(bool is_attach, const std::string& storage_name) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ if (is_attach) { |
+ mtp_client_->GetStorageInfo( |
+ storage_name, |
+ base::Bind(&MediaTransferProtocolManagerImpl::OnGetStorageInfo, |
+ weak_ptr_factory_.GetWeakPtr()), |
+ base::Bind(&base::DoNothing)); |
+ return; |
+ } |
+ |
+ // Detach case. |
+ StorageInfoMap::iterator it = storage_info_map_.find(storage_name); |
+ if (it == storage_info_map_.end()) { |
+ // This might happen during initialization when |storage_info_map_| has |
+ // not been fully populated yet? |
+ return; |
+ } |
+ storage_info_map_.erase(it); |
+ FOR_EACH_OBSERVER(Observer, |
+ observers_, |
+ StorageChanged(false /* detach */, storage_name)); |
+ } |
+ |
+ void OnEnumerateStorage(const std::vector<std::string>& storage_names) { |
+ for (size_t i = 0; i < storage_names.size(); ++i) { |
+ mtp_client_->GetStorageInfo( |
+ storage_names[i], |
+ base::Bind(&MediaTransferProtocolManagerImpl::OnGetStorageInfo, |
+ weak_ptr_factory_.GetWeakPtr()), |
+ base::Bind(&base::DoNothing)); |
+ } |
+ } |
+ |
+ void OnGetStorageInfo(const StorageInfo& storage_info) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ const std::string& storage_name = storage_info.storage_name(); |
+ if (ContainsKey(storage_info_map_, storage_name)) { |
+ // This should not happen, since MediaTransferProtocolManagerImpl should |
+ // only call EnumerateStorage() once, which populates |storage_info_map_| |
+ // with the already-attached devices. |
+ // After that, all incoming signals are either for new storage |
+ // attachments, which should not be in |storage_info_map_|, or for |
+ // storage detachements, which do not add to |storage_info_map_|. |
+ NOTREACHED(); |
+ return; |
+ } |
+ |
+ // New storage. Add it and let the observers know. |
+ storage_info_map_.insert(std::make_pair(storage_name, storage_info)); |
+ FOR_EACH_OBSERVER(Observer, |
+ observers_, |
+ StorageChanged(true /* is attach */, storage_name)); |
+ } |
+ |
+ void OnOpenStorage(const std::string& handle) { |
+ if (!ContainsKey(handles_, handle)) { |
+ handles_.insert(handle); |
+ open_storage_callbacks_.front().Run(handle, false); |
+ } else { |
+ NOTREACHED(); |
+ open_storage_callbacks_.front().Run("", true); |
+ } |
+ open_storage_callbacks_.pop(); |
+ } |
+ |
+ void OnOpenStorageError() { |
+ open_storage_callbacks_.front().Run("", true); |
+ open_storage_callbacks_.pop(); |
+ } |
+ |
+ void OnCloseStorage() { |
+ const std::string& handle = close_storage_callbacks_.front().second; |
+ if (ContainsKey(handles_, handle)) { |
+ handles_.erase(handle); |
+ close_storage_callbacks_.front().first.Run(false); |
+ } else { |
+ NOTREACHED(); |
+ close_storage_callbacks_.front().first.Run(true); |
+ } |
+ close_storage_callbacks_.pop(); |
+ } |
+ |
+ void OnCloseStorageError() { |
+ close_storage_callbacks_.front().first.Run(true); |
+ close_storage_callbacks_.pop(); |
+ } |
+ |
+ void OnReadDirectory(const std::vector<FileEntry>& file_entries) { |
+ read_directory_callbacks_.front().Run(file_entries, false); |
+ read_directory_callbacks_.pop(); |
+ } |
+ |
+ void OnReadDirectoryError() { |
+ read_directory_callbacks_.front().Run(std::vector<FileEntry>(), true); |
+ read_directory_callbacks_.pop(); |
+ } |
+ |
+ void OnReadFile(const std::string& data) { |
+ read_file_callbacks_.front().Run(data, false); |
+ read_file_callbacks_.pop(); |
+ } |
+ |
+ void OnReadFileError() { |
+ read_file_callbacks_.front().Run(std::string(), true); |
+ read_file_callbacks_.pop(); |
+ } |
+ |
+ void OnGetFileInfo(const FileEntry& entry) { |
+ get_file_info_callbacks_.front().Run(entry, false); |
+ get_file_info_callbacks_.pop(); |
+ } |
+ |
+ void OnGetFileInfoError() { |
+ get_file_info_callbacks_.front().Run(FileEntry(), true); |
+ get_file_info_callbacks_.pop(); |
+ } |
+ |
+ // Mtpd DBus client. |
+ MediaTransferProtocolDaemonClient* mtp_client_; |
+ |
+ // Device attachment / detachment observers. |
+ ObserverList<Observer> observers_; |
+ |
+ base::WeakPtrFactory<MediaTransferProtocolManagerImpl> weak_ptr_factory_; |
+ |
+ // Everything below is only accessed on the UI thread. |
+ |
+ // Map to keep track of attached storages by name. |
+ StorageInfoMap storage_info_map_; |
+ |
+ // Set of open storage handles. |
+ std::set<std::string> handles_; |
+ |
+ // Queued callbacks. |
+ OpenStorageCallbackQueue open_storage_callbacks_; |
+ CloseStorageCallbackQueue close_storage_callbacks_; |
+ ReadDirectoryCallbackQueue read_directory_callbacks_; |
+ ReadFileCallbackQueue read_file_callbacks_; |
+ GetFileInfoCallbackQueue get_file_info_callbacks_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(MediaTransferProtocolManagerImpl); |
+}; |
+ |
+} // namespace |
+ |
+// static |
+void MediaTransferProtocolManager::Initialize() { |
+ if (g_media_transfer_protocol_manager) { |
+ LOG(WARNING) << "MediaTransferProtocolManager was already initialized"; |
+ return; |
+ } |
+ g_media_transfer_protocol_manager = new MediaTransferProtocolManagerImpl(); |
+ VLOG(1) << "MediaTransferProtocolManager initialized"; |
+} |
+ |
+// static |
+void MediaTransferProtocolManager::Shutdown() { |
+ if (!g_media_transfer_protocol_manager) { |
+ LOG(WARNING) << "MediaTransferProtocolManager::Shutdown() called with " |
+ << "NULL manager"; |
+ return; |
+ } |
+ delete g_media_transfer_protocol_manager; |
+ g_media_transfer_protocol_manager = NULL; |
+ VLOG(1) << "MediaTransferProtocolManager Shutdown completed"; |
+} |
+ |
+// static |
+MediaTransferProtocolManager* MediaTransferProtocolManager::GetInstance() { |
+ return g_media_transfer_protocol_manager; |
+} |
+ |
+} // namespace mtp |
+} // namespace chromeos |
Property changes on: chrome/browser/chromeos/mtp/media_transfer_protocol_manager.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |