| 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
|
|
|
|
|