diff options
Diffstat (limited to 'chrome/browser')
17 files changed, 513 insertions, 83 deletions
diff --git a/chrome/browser/chromeos/file_manager/volume_manager.cc b/chrome/browser/chromeos/file_manager/volume_manager.cc index 7c2dde6..6820aab 100644 --- a/chrome/browser/chromeos/file_manager/volume_manager.cc +++ b/chrome/browser/chromeos/file_manager/volume_manager.cc @@ -661,18 +661,23 @@ void VolumeManager::OnRemovableStorageAttached( storage::FileSystemMountOption(), path); DCHECK(result); + + // TODO(yawano) A variable to switch MTP write support. This variable should + // be false until MTP write operation is implemented and shipped. + bool write_supported = false; + content::BrowserThread::PostTask( - content::BrowserThread::IO, FROM_HERE, base::Bind( - &MTPDeviceMapService::RegisterMTPFileSystem, - base::Unretained(MTPDeviceMapService::GetInstance()), - info.location(), fsid)); + content::BrowserThread::IO, FROM_HERE, + base::Bind(&MTPDeviceMapService::RegisterMTPFileSystem, + base::Unretained(MTPDeviceMapService::GetInstance()), + info.location(), fsid, !write_supported /* read_only */)); VolumeInfo volume_info; volume_info.type = VOLUME_TYPE_MTP; volume_info.mount_path = path; volume_info.mount_condition = chromeos::disks::MOUNT_CONDITION_NONE; volume_info.is_parent = true; - volume_info.is_read_only = true; + volume_info.is_read_only = !write_supported; volume_info.volume_id = kMtpVolumeIdPrefix + label; volume_info.volume_label = label; volume_info.source_path = path; diff --git a/chrome/browser/media_galleries/fileapi/device_media_async_file_util.cc b/chrome/browser/media_galleries/fileapi/device_media_async_file_util.cc index 2245ba6..c106f65 100644 --- a/chrome/browser/media_galleries/fileapi/device_media_async_file_util.cc +++ b/chrome/browser/media_galleries/fileapi/device_media_async_file_util.cc @@ -79,6 +79,13 @@ void OnReadDirectoryError(const AsyncFileUtil::ReadDirectoryCallback& callback, callback.Run(error, AsyncFileUtil::EntryList(), false /*no more*/); } +// Called when CopyInForeignFile method call failed. +void OnCopyInForeignFileError(const AsyncFileUtil::StatusCallback& callback, + base::File::Error error) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + callback.Run(error); +} + // Called on a blocking pool thread to create a snapshot file to hold the // contents of |device_file_path|. The snapshot file is created in the // "profile_path/kDeviceMediaAsyncFileUtilTempDir" directory. Return the @@ -330,6 +337,7 @@ void DeviceMediaAsyncFileUtil::ReadDirectory( OnReadDirectoryError(callback, base::File::FILE_ERROR_NOT_FOUND); return; } + delegate->ReadDirectory( url.path(), base::Bind(&DeviceMediaAsyncFileUtil::OnDidReadDirectory, @@ -389,8 +397,22 @@ void DeviceMediaAsyncFileUtil::CopyInForeignFile( const FileSystemURL& dest_url, const StatusCallback& callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - NOTIMPLEMENTED(); - callback.Run(base::File::FILE_ERROR_SECURITY); + + MTPDeviceAsyncDelegate* delegate = GetMTPDeviceDelegate(dest_url); + if (!delegate) { + OnCopyInForeignFileError(callback, base::File::FILE_ERROR_NOT_FOUND); + return; + } + if (delegate->IsReadOnly()) { + OnCopyInForeignFileError(callback, base::File::FILE_ERROR_SECURITY); + return; + } + + delegate->CopyFileFromLocal( + src_file_path, dest_url.path(), + base::Bind(&DeviceMediaAsyncFileUtil::OnDidCopyInForeignFile, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&OnCopyInForeignFileError, callback)); } void DeviceMediaAsyncFileUtil::DeleteFile( @@ -511,6 +533,13 @@ void DeviceMediaAsyncFileUtil::OnDidReadDirectory( base::Bind(&OnDidCheckMediaForReadDirectory, callback, has_more)); } +void DeviceMediaAsyncFileUtil::OnDidCopyInForeignFile( + const StatusCallback& callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + callback.Run(base::File::FILE_OK); +} + bool DeviceMediaAsyncFileUtil::validate_media_files() const { return media_path_filter_wrapper_.get() != NULL; } diff --git a/chrome/browser/media_galleries/fileapi/device_media_async_file_util.h b/chrome/browser/media_galleries/fileapi/device_media_async_file_util.h index 3716c44..96c6b1d 100644 --- a/chrome/browser/media_galleries/fileapi/device_media_async_file_util.h +++ b/chrome/browser/media_galleries/fileapi/device_media_async_file_util.h @@ -141,6 +141,10 @@ class DeviceMediaAsyncFileUtil : public storage::AsyncFileUtil { const EntryList& file_list, bool has_more); + // Called when CopyInForeignFile method call succeeds. |callback| is invoked + // to complete the CopyInForeignFile request. + void OnDidCopyInForeignFile(const StatusCallback& callback); + bool validate_media_files() const; // Profile path. diff --git a/chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h b/chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h index f73c3f7..79555a3 100644 --- a/chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h +++ b/chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h @@ -63,6 +63,9 @@ class MTPDeviceAsyncDelegate { ErrorCallback error_callback; }; + // A callback to be called when CopyFileFromLocal method call succeeds. + typedef base::Closure CopyFileFromLocalSuccessCallback; + // Gets information about the given |file_path| and invokes the appropriate // callback asynchronously when complete. virtual void GetFileInfo( @@ -99,6 +102,16 @@ class MTPDeviceAsyncDelegate { const ReadBytesSuccessCallback& success_callback, const ErrorCallback& error_callback) = 0; + // Returns true if storage is opened for read only. + virtual bool IsReadOnly() = 0; + + // Copies a file from |source_file_path| to |device_file_path|. + virtual void CopyFileFromLocal( + const base::FilePath& source_file_path, + const base::FilePath& device_file_path, + const CopyFileFromLocalSuccessCallback& success_callback, + const ErrorCallback& error_callback) = 0; + // Called when the // (1) Browser application is in shutdown mode (or) // (2) Last extension using this MTP device is destroyed (or) @@ -119,6 +132,7 @@ typedef base::Callback<void(MTPDeviceAsyncDelegate*)> void CreateMTPDeviceAsyncDelegate( const base::FilePath::StringType& device_location, + const bool read_only, const CreateMTPDeviceAsyncDelegateCallback& callback); #endif // CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_MTP_DEVICE_ASYNC_DELEGATE_H_ diff --git a/chrome/browser/media_galleries/fileapi/mtp_device_map_service.cc b/chrome/browser/media_galleries/fileapi/mtp_device_map_service.cc index b85a9bb..6941878 100644 --- a/chrome/browser/media_galleries/fileapi/mtp_device_map_service.cc +++ b/chrome/browser/media_galleries/fileapi/mtp_device_map_service.cc @@ -26,64 +26,101 @@ MTPDeviceMapService* MTPDeviceMapService::GetInstance() { void MTPDeviceMapService::RegisterMTPFileSystem( const base::FilePath::StringType& device_location, - const std::string& fsid) { + const std::string& filesystem_id, + const bool read_only) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK(!device_location.empty()); + DCHECK(!filesystem_id.empty()); - if (!ContainsKey(mtp_device_usage_map_, device_location)) { + const AsyncDelegateKey key = GetAsyncDelegateKey(device_location, read_only); + if (!ContainsKey(mtp_device_usage_map_, key)) { // Note that this initializes the delegate asynchronously, but since // the delegate will only be used from the IO thread, it is guaranteed // to be created before use of it expects it to be there. - CreateMTPDeviceAsyncDelegate(device_location, + CreateMTPDeviceAsyncDelegate( + device_location, read_only, base::Bind(&MTPDeviceMapService::AddAsyncDelegate, - base::Unretained(this), device_location)); - mtp_device_usage_map_[device_location] = 0; + base::Unretained(this), device_location, read_only)); + mtp_device_usage_map_[key] = 0; } - mtp_device_usage_map_[device_location]++; - mtp_device_map_[fsid] = device_location; + mtp_device_usage_map_[key]++; + mtp_device_map_[filesystem_id] = make_pair(device_location, read_only); } -void MTPDeviceMapService::RevokeMTPFileSystem(const std::string& fsid) { +void MTPDeviceMapService::RevokeMTPFileSystem( + const std::string& filesystem_id) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK(!filesystem_id.empty()); - MTPDeviceFileSystemMap::iterator it = mtp_device_map_.find(fsid); + MTPDeviceFileSystemMap::iterator it = mtp_device_map_.find(filesystem_id); if (it != mtp_device_map_.end()) { - base::FilePath::StringType device_location = it->second; + const base::FilePath::StringType device_location = it->second.first; + const bool read_only = it->second.second; + mtp_device_map_.erase(it); - MTPDeviceUsageMap::iterator delegate_it = - mtp_device_usage_map_.find(device_location); + + const AsyncDelegateKey key = + GetAsyncDelegateKey(device_location, read_only); + MTPDeviceUsageMap::iterator delegate_it = mtp_device_usage_map_.find(key); DCHECK(delegate_it != mtp_device_usage_map_.end()); - mtp_device_usage_map_[device_location]--; - if (mtp_device_usage_map_[device_location] == 0) { + + mtp_device_usage_map_[key]--; + if (mtp_device_usage_map_[key] == 0) { mtp_device_usage_map_.erase(delegate_it); - RemoveAsyncDelegate(device_location); + RemoveAsyncDelegate(device_location, read_only); } } } void MTPDeviceMapService::AddAsyncDelegate( const base::FilePath::StringType& device_location, + const bool read_only, MTPDeviceAsyncDelegate* delegate) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK(delegate); DCHECK(!device_location.empty()); - if (ContainsKey(async_delegate_map_, device_location)) + + const AsyncDelegateKey key = GetAsyncDelegateKey(device_location, read_only); + if (ContainsKey(async_delegate_map_, key)) return; - async_delegate_map_[device_location] = delegate; + async_delegate_map_[key] = delegate; } void MTPDeviceMapService::RemoveAsyncDelegate( - const base::FilePath::StringType& device_location) { + const base::FilePath::StringType& device_location, + const bool read_only) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - AsyncDelegateMap::iterator it = async_delegate_map_.find(device_location); + DCHECK(!device_location.empty()); + + const AsyncDelegateKey key = GetAsyncDelegateKey(device_location, read_only); + AsyncDelegateMap::iterator it = async_delegate_map_.find(key); DCHECK(it != async_delegate_map_.end()); it->second->CancelPendingTasksAndDeleteDelegate(); async_delegate_map_.erase(it); } +// static +MTPDeviceMapService::AsyncDelegateKey MTPDeviceMapService::GetAsyncDelegateKey( + const base::FilePath::StringType& device_location, + const bool read_only) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + base::FilePath::StringType key; + key.append(read_only ? FILE_PATH_LITERAL("ReadOnly") + : FILE_PATH_LITERAL("ReadWrite")); + key.append(FILE_PATH_LITERAL("|")); + key.append(device_location); + return key; +} + MTPDeviceAsyncDelegate* MTPDeviceMapService::GetMTPDeviceAsyncDelegate( const std::string& filesystem_id) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK(!filesystem_id.empty()); + + // File system may be already revoked on ExternalMountPoints side, we check + // here that the file system is still valid. base::FilePath device_path; if (!storage::ExternalMountPoints::GetSystemInstance()->GetRegisteredPath( filesystem_id, &device_path)) { @@ -91,10 +128,21 @@ MTPDeviceAsyncDelegate* MTPDeviceMapService::GetMTPDeviceAsyncDelegate( } const base::FilePath::StringType& device_location = device_path.value(); - DCHECK(!device_location.empty()); - AsyncDelegateMap::const_iterator it = - async_delegate_map_.find(device_location); - return (it != async_delegate_map_.end()) ? it->second : NULL; + + MTPDeviceFileSystemMap::const_iterator mtp_device_map_it = + mtp_device_map_.find(filesystem_id); + if (mtp_device_map_it == mtp_device_map_.end()) + return NULL; + + DCHECK_EQ(device_path.value(), mtp_device_map_it->second.first); + const bool read_only = mtp_device_map_it->second.second; + const AsyncDelegateKey key = GetAsyncDelegateKey(device_location, read_only); + + AsyncDelegateMap::const_iterator async_delegate_map_it = + async_delegate_map_.find(key); + return (async_delegate_map_it != async_delegate_map_.end()) + ? async_delegate_map_it->second + : NULL; } MTPDeviceMapService::MTPDeviceMapService() { diff --git a/chrome/browser/media_galleries/fileapi/mtp_device_map_service.h b/chrome/browser/media_galleries/fileapi/mtp_device_map_service.h index d64742e..0f24b14 100644 --- a/chrome/browser/media_galleries/fileapi/mtp_device_map_service.h +++ b/chrome/browser/media_galleries/fileapi/mtp_device_map_service.h @@ -29,14 +29,14 @@ class MTPDeviceMapService { const std::string& filesystem_id); // Register that an MTP filesystem is in use for the given |device_location|. - void RegisterMTPFileSystem( - const base::FilePath::StringType& device_location, - const std::string& fsid); + void RegisterMTPFileSystem(const base::FilePath::StringType& device_location, + const std::string& filesystem_id, + const bool read_only); // Removes the MTP entry associated with the given // |device_location|. Signals the MTPDeviceMapService to destroy the // delegate if there are no more uses of it. - void RevokeMTPFileSystem(const std::string& fsid); + void RevokeMTPFileSystem(const std::string& filesystem_id); private: friend struct base::DefaultLazyInstanceTraits<MTPDeviceMapService>; @@ -45,27 +45,34 @@ class MTPDeviceMapService { // specifies the mount location of the MTP device. // Called on the IO thread. void AddAsyncDelegate(const base::FilePath::StringType& device_location, + const bool read_only, MTPDeviceAsyncDelegate* delegate); // Removes the MTP device delegate from the map service. |device_location| // specifies the mount location of the MTP device. // Called on the IO thread. - void RemoveAsyncDelegate(const base::FilePath::StringType& device_location); + void RemoveAsyncDelegate(const base::FilePath::StringType& device_location, + const bool read_only); + + // A key to be used in AsyncDelegateMap and MTPDeviceUsageMap. + typedef base::FilePath::StringType AsyncDelegateKey; + + // Gets a key from |device_location| and |read_only|. + static AsyncDelegateKey GetAsyncDelegateKey( + const base::FilePath::StringType& device_location, + const bool read_only); // Mapping of device_location and MTPDeviceAsyncDelegate* object. It is safe // to store and access the raw pointer. This class operates on the IO thread. - typedef std::map<base::FilePath::StringType, MTPDeviceAsyncDelegate*> - AsyncDelegateMap; + typedef std::map<AsyncDelegateKey, MTPDeviceAsyncDelegate*> AsyncDelegateMap; // Map a filesystem id (fsid) to an MTP device location. - typedef std::map<std::string, base::FilePath::StringType> - MTPDeviceFileSystemMap; + typedef std::pair<base::FilePath::StringType, bool> MTPDeviceInfo; + typedef std::map<std::string, MTPDeviceInfo> MTPDeviceFileSystemMap; // Map a MTP or PTP device location to a count of current uses of that // location. - typedef std::map<const base::FilePath::StringType, int> - MTPDeviceUsageMap; - + typedef std::map<AsyncDelegateKey, int> MTPDeviceUsageMap; // Get access to this class using GetInstance() method. MTPDeviceMapService(); diff --git a/chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.cc b/chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.cc index b1cd91c..b742eea8 100644 --- a/chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.cc +++ b/chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.cc @@ -4,11 +4,13 @@ #include "chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.h" +#include <fcntl.h> #include <algorithm> #include <vector> #include "base/bind.h" #include "base/numerics/safe_conversions.h" +#include "base/posix/eintr_wrapper.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" @@ -51,13 +53,16 @@ std::string GetDeviceRelativePath(const base::FilePath& registered_dev_path, // storage. // // |storage_name| specifies the name of the storage device. +// |read_only| specifies the mode of the storage device. // Returns NULL if the |storage_name| is no longer valid (e.g. because the // corresponding storage device is detached, etc). MTPDeviceTaskHelper* GetDeviceTaskHelperForStorage( - const std::string& storage_name) { + const std::string& storage_name, + const bool read_only) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); return MTPDeviceTaskHelperMapService::GetInstance()->GetDeviceTaskHelper( - storage_name); + storage_name, + read_only); } // Opens the storage device for communication. @@ -66,20 +71,22 @@ MTPDeviceTaskHelper* GetDeviceTaskHelperForStorage( // MediaTransferProtocolManager. // // |storage_name| specifies the name of the storage device. +// |read_only| specifies the mode of the storage device. // |reply_callback| is called when the OpenStorage request completes. // |reply_callback| runs on the IO thread. void OpenStorageOnUIThread( const std::string& storage_name, + const bool read_only, const MTPDeviceTaskHelper::OpenStorageCallback& reply_callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); MTPDeviceTaskHelper* task_helper = - GetDeviceTaskHelperForStorage(storage_name); + GetDeviceTaskHelperForStorage(storage_name, read_only); if (!task_helper) { task_helper = MTPDeviceTaskHelperMapService::GetInstance()->CreateDeviceTaskHelper( - storage_name); + storage_name, read_only); } - task_helper->OpenStorage(storage_name, reply_callback); + task_helper->OpenStorage(storage_name, read_only, reply_callback); } // Enumerates the |dir_id| directory file entries. @@ -88,17 +95,19 @@ void OpenStorageOnUIThread( // MediaTransferProtocolManager. // // |storage_name| specifies the name of the storage device. +// |read_only| specifies the mode of the storage device. // |success_callback| is called when the ReadDirectory request succeeds. // |error_callback| is called when the ReadDirectory request fails. // |success_callback| and |error_callback| runs on the IO thread. void ReadDirectoryOnUIThread( const std::string& storage_name, + const bool read_only, uint32 dir_id, const MTPDeviceTaskHelper::ReadDirectorySuccessCallback& success_callback, const MTPDeviceTaskHelper::ErrorCallback& error_callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); MTPDeviceTaskHelper* task_helper = - GetDeviceTaskHelperForStorage(storage_name); + GetDeviceTaskHelperForStorage(storage_name, read_only); if (!task_helper) return; task_helper->ReadDirectory(dir_id, success_callback, error_callback); @@ -110,17 +119,19 @@ void ReadDirectoryOnUIThread( // MediaTransferProtocolManager. // // |storage_name| specifies the name of the storage device. +// |read_only| specifies the mode of the storage device. // |success_callback| is called when the GetFileInfo request succeeds. // |error_callback| is called when the GetFileInfo request fails. // |success_callback| and |error_callback| runs on the IO thread. void GetFileInfoOnUIThread( const std::string& storage_name, + const bool read_only, uint32 file_id, const MTPDeviceTaskHelper::GetFileInfoSuccessCallback& success_callback, const MTPDeviceTaskHelper::ErrorCallback& error_callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); MTPDeviceTaskHelper* task_helper = - GetDeviceTaskHelperForStorage(storage_name); + GetDeviceTaskHelperForStorage(storage_name, read_only); if (!task_helper) return; task_helper->GetFileInfo(file_id, success_callback, error_callback); @@ -132,6 +143,7 @@ void GetFileInfoOnUIThread( // MediaTransferProtocolManager. // // |storage_name| specifies the name of the storage device. +// |read_only| specifies the mode of the storage device. // |device_file_path| specifies the media device file path. // |snapshot_file_path| specifies the platform path of the snapshot file. // |file_size| specifies the number of bytes that will be written to the @@ -141,11 +153,12 @@ void GetFileInfoOnUIThread( // |success_callback| and |error_callback| runs on the IO thread. void WriteDataIntoSnapshotFileOnUIThread( const std::string& storage_name, + const bool read_only, const SnapshotRequestInfo& request_info, const base::File::Info& snapshot_file_info) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); MTPDeviceTaskHelper* task_helper = - GetDeviceTaskHelperForStorage(storage_name); + GetDeviceTaskHelperForStorage(storage_name, read_only); if (!task_helper) return; task_helper->WriteDataIntoSnapshotFile(request_info, snapshot_file_info); @@ -157,33 +170,80 @@ void WriteDataIntoSnapshotFileOnUIThread( // MediaTransferProtocolManager. // // |storage_name| specifies the name of the storage device. +// |read_only| specifies the mode of the storage device. // |request| is a struct containing details about the byte read request. void ReadBytesOnUIThread( const std::string& storage_name, + const bool read_only, const MTPDeviceAsyncDelegate::ReadBytesRequest& request) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); MTPDeviceTaskHelper* task_helper = - GetDeviceTaskHelperForStorage(storage_name); + GetDeviceTaskHelperForStorage(storage_name, read_only); if (!task_helper) return; task_helper->ReadBytes(request); } +// Copies the file |source_file_descriptor| to |file_name| in |parent_id|. +// +// |storage_name| specifies the name of the storage device. +// |read_only| specifies the mode of the storage device. +// |source_file_descriptor| file descriptor of source file. +// |parent_id| object id of a target directory. +// |file_name| file name of a target file. +// |success_callback| is called when the file is copied successfully. +// |error_callback| is called when it fails to copy file. +// Since this method does not close the file descriptor, callbacks are +// responsible for closing it. +void CopyFileFromLocalOnUIThread( + const std::string& storage_name, + const bool read_only, + const int source_file_descriptor, + const uint32 parent_id, + const std::string& file_name, + const MTPDeviceTaskHelper::CopyFileFromLocalSuccessCallback& + success_callback, + const MTPDeviceTaskHelper::ErrorCallback& error_callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + MTPDeviceTaskHelper* task_helper = + GetDeviceTaskHelperForStorage(storage_name, read_only); + if (!task_helper) + return; + task_helper->CopyFileFromLocal(storage_name, source_file_descriptor, + parent_id, file_name, success_callback, + error_callback); +} + // Closes the device storage specified by the |storage_name| and destroys the // MTPDeviceTaskHelper object associated with the device storage. // // Called on the UI thread to dispatch the request to the // MediaTransferProtocolManager. void CloseStorageAndDestroyTaskHelperOnUIThread( - const std::string& storage_name) { + const std::string& storage_name, + const bool read_only) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); MTPDeviceTaskHelper* task_helper = - GetDeviceTaskHelperForStorage(storage_name); + GetDeviceTaskHelperForStorage(storage_name, read_only); if (!task_helper) return; task_helper->CloseStorage(); MTPDeviceTaskHelperMapService::GetInstance()->DestroyDeviceTaskHelper( - storage_name); + storage_name, read_only); +} + +// Opens |file_path| with |flags|. +int OpenFileDescriptor(const char* file_path, const int flags) { + DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); + + return open(file_path, flags); +} + +// Closes |file_descriptor| on file thread. +void CloseFileDescriptor(const int file_descriptor) { + DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); + + IGNORE_EINTR(close(file_descriptor)); } } // namespace @@ -310,10 +370,12 @@ bool MTPDeviceDelegateImplLinux::MTPFileNode::DeleteChild(uint32 file_id) { } MTPDeviceDelegateImplLinux::MTPDeviceDelegateImplLinux( - const std::string& device_location) + const std::string& device_location, + const bool read_only) : init_state_(UNINITIALIZED), task_in_progress_(false), device_path_(device_location), + read_only_(read_only), root_node_(new MTPFileNode(mtpd::kRootFileId, "", // Root node has no name. NULL, // And no parent node. @@ -432,13 +494,41 @@ void MTPDeviceDelegateImplLinux::ReadBytes( closure)); } +bool MTPDeviceDelegateImplLinux::IsReadOnly() { + return read_only_; +} + +void MTPDeviceDelegateImplLinux::CopyFileFromLocal( + const base::FilePath& source_file_path, + const base::FilePath& device_file_path, + const CopyFileFromLocalSuccessCallback& success_callback, + const ErrorCallback& error_callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK(!source_file_path.empty()); + DCHECK(!device_file_path.empty()); + + content::BrowserThread::PostTaskAndReplyWithResult( + content::BrowserThread::FILE, + FROM_HERE, + base::Bind(&OpenFileDescriptor, + source_file_path.value().c_str(), + O_RDONLY), + base::Bind(&MTPDeviceDelegateImplLinux::CopyFileFromLocalInternal, + weak_ptr_factory_.GetWeakPtr(), + device_file_path, + success_callback, + error_callback)); +} + void MTPDeviceDelegateImplLinux::CancelPendingTasksAndDeleteDelegate() { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); // To cancel all the pending tasks, destroy the MTPDeviceTaskHelper object. content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, - base::Bind(&CloseStorageAndDestroyTaskHelperOnUIThread, storage_name_)); + base::Bind(&CloseStorageAndDestroyTaskHelperOnUIThread, + storage_name_, + read_only_)); delete this; } @@ -463,6 +553,7 @@ void MTPDeviceDelegateImplLinux::GetFileInfoInternal( base::Closure closure = base::Bind(&GetFileInfoOnUIThread, storage_name_, + read_only_, file_id, success_callback_wrapper, error_callback_wrapper); @@ -497,6 +588,7 @@ void MTPDeviceDelegateImplLinux::ReadDirectoryInternal( dir_id); base::Closure closure = base::Bind(&GetFileInfoOnUIThread, storage_name_, + read_only_, dir_id, success_callback_wrapper, error_callback_wrapper); @@ -536,6 +628,7 @@ void MTPDeviceDelegateImplLinux::CreateSnapshotFileInternal( file_id); base::Closure closure = base::Bind(&GetFileInfoOnUIThread, storage_name_, + read_only_, file_id, success_callback_wrapper, error_callback_wrapper); @@ -569,7 +662,7 @@ void MTPDeviceDelegateImplLinux::ReadBytesInternal( file_id)); base::Closure closure = - base::Bind(base::Bind(&ReadBytesOnUIThread, storage_name_, request)); + base::Bind(&ReadBytesOnUIThread, storage_name_, read_only_, request); EnsureInitAndRunTask(PendingTaskInfo(base::FilePath(), content::BrowserThread::UI, FROM_HERE, @@ -580,6 +673,49 @@ void MTPDeviceDelegateImplLinux::ReadBytesInternal( PendingRequestDone(); } +void MTPDeviceDelegateImplLinux::CopyFileFromLocalInternal( + const base::FilePath& device_file_path, + const CopyFileFromLocalSuccessCallback& success_callback, + const ErrorCallback& error_callback, + const int source_file_descriptor) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + if (source_file_descriptor < 0) { + error_callback.Run(base::File::FILE_ERROR_INVALID_OPERATION); + PendingRequestDone(); + return; + } + + uint32 parent_id; + if (CachedPathToId(device_file_path.DirName(), &parent_id)) { + CopyFileFromLocalSuccessCallback success_callback_wrapper = + base::Bind(&MTPDeviceDelegateImplLinux::OnDidCopyFileFromLocal, + weak_ptr_factory_.GetWeakPtr(), success_callback, + source_file_descriptor); + + ErrorCallback error_callback_wrapper = base::Bind( + &MTPDeviceDelegateImplLinux::HandleCopyFileFromLocalError, + weak_ptr_factory_.GetWeakPtr(), error_callback, source_file_descriptor); + + base::Closure closure = base::Bind(&CopyFileFromLocalOnUIThread, + storage_name_, + read_only_, + source_file_descriptor, + parent_id, + device_file_path.BaseName().value(), + success_callback_wrapper, + error_callback_wrapper); + + EnsureInitAndRunTask(PendingTaskInfo( + base::FilePath(), content::BrowserThread::UI, FROM_HERE, closure)); + } else { + HandleCopyFileFromLocalError(error_callback, source_file_descriptor, + base::File::FILE_ERROR_INVALID_OPERATION); + } + + PendingRequestDone(); +} + void MTPDeviceDelegateImplLinux::EnsureInitAndRunTask( const PendingTaskInfo& task_info) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); @@ -599,10 +735,8 @@ void MTPDeviceDelegateImplLinux::EnsureInitAndRunTask( init_state_ = PENDING_INIT; task_in_progress_ = true; content::BrowserThread::PostTask( - content::BrowserThread::UI, - FROM_HERE, - base::Bind(&OpenStorageOnUIThread, - storage_name_, + content::BrowserThread::UI, FROM_HERE, + base::Bind(&OpenStorageOnUIThread, storage_name_, read_only_, base::Bind(&MTPDeviceDelegateImplLinux::OnInitCompleted, weak_ptr_factory_.GetWeakPtr()))); } @@ -649,6 +783,7 @@ void MTPDeviceDelegateImplLinux::WriteDataIntoSnapshotFile( base::Closure task_closure = base::Bind(&WriteDataIntoSnapshotFileOnUIThread, storage_name_, + read_only_, request_info, file_info); content::BrowserThread::PostTask(content::BrowserThread::UI, @@ -657,6 +792,7 @@ void MTPDeviceDelegateImplLinux::WriteDataIntoSnapshotFile( } void MTPDeviceDelegateImplLinux::PendingRequestDone() { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK(task_in_progress_); task_in_progress_ = false; ProcessNextPendingRequest(); @@ -703,6 +839,7 @@ void MTPDeviceDelegateImplLinux::OnDidGetFileInfoToReadDirectory( base::Closure task_closure = base::Bind(&ReadDirectoryOnUIThread, storage_name_, + read_only_, dir_id, base::Bind(&MTPDeviceDelegateImplLinux::OnDidReadDirectory, weak_ptr_factory_.GetWeakPtr(), @@ -854,6 +991,37 @@ void MTPDeviceDelegateImplLinux::OnFillFileCacheFailed( pending_tasks_.front().path.clear(); } +void MTPDeviceDelegateImplLinux::OnDidCopyFileFromLocal( + const CopyFileFromLocalSuccessCallback& success_callback, + const int source_file_descriptor) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + const base::Closure closure = base::Bind(&CloseFileDescriptor, + source_file_descriptor); + + content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE, + closure); + + success_callback.Run(); + PendingRequestDone(); +} + +void MTPDeviceDelegateImplLinux::HandleCopyFileFromLocalError( + const ErrorCallback& error_callback, + const int source_file_descriptor, + base::File::Error error) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + const base::Closure closure = base::Bind(&CloseFileDescriptor, + source_file_descriptor); + + content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE, + closure); + + error_callback.Run(error); + PendingRequestDone(); +} + void MTPDeviceDelegateImplLinux::HandleDeviceFileError( const ErrorCallback& error_callback, uint32 file_id, @@ -943,7 +1111,8 @@ bool MTPDeviceDelegateImplLinux::CachedPathToId(const base::FilePath& path, void CreateMTPDeviceAsyncDelegate( const std::string& device_location, + const bool read_only, const CreateMTPDeviceAsyncDelegateCallback& callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - callback.Run(new MTPDeviceDelegateImplLinux(device_location)); + callback.Run(new MTPDeviceDelegateImplLinux(device_location, read_only)); } diff --git a/chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.h b/chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.h index 0b9a7725..eba3703 100644 --- a/chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.h +++ b/chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.h @@ -32,6 +32,7 @@ class MTPDeviceDelegateImplLinux : public MTPDeviceAsyncDelegate { private: friend void CreateMTPDeviceAsyncDelegate( const std::string&, + const bool read_only, const CreateMTPDeviceAsyncDelegateCallback&); enum InitializationState { @@ -66,7 +67,8 @@ class MTPDeviceDelegateImplLinux : public MTPDeviceAsyncDelegate { // Should only be called by CreateMTPDeviceAsyncDelegate() factory call. // Defer the device initializations until the first file operation request. // Do all the initializations in EnsureInitAndRunTask() function. - explicit MTPDeviceDelegateImplLinux(const std::string& device_location); + MTPDeviceDelegateImplLinux(const std::string& device_location, + const bool read_only); // Destructed via CancelPendingTasksAndDeleteDelegate(). ~MTPDeviceDelegateImplLinux() override; @@ -90,6 +92,12 @@ class MTPDeviceDelegateImplLinux : public MTPDeviceAsyncDelegate { int buf_len, const ReadBytesSuccessCallback& success_callback, const ErrorCallback& error_callback) override; + bool IsReadOnly() override; + void CopyFileFromLocal( + const base::FilePath& source_file_path, + const base::FilePath& device_file_path, + const CopyFileFromLocalSuccessCallback& success_callback, + const ErrorCallback& error_callback) override; void CancelPendingTasksAndDeleteDelegate() override; // The internal methods correspond to the similarly named methods above. @@ -112,6 +120,11 @@ class MTPDeviceDelegateImplLinux : public MTPDeviceAsyncDelegate { net::IOBuffer* buf, int64 offset, int buf_len, const ReadBytesSuccessCallback& success_callback, const ErrorCallback& error_callback); + virtual void CopyFileFromLocalInternal( + const base::FilePath& device_file_path, + const CopyFileFromLocalSuccessCallback& success_callback, + const ErrorCallback& error_callback, + const int source_file_descriptor); // Ensures the device is initialized for communication. // If the device is already initialized, call RunTask(). @@ -222,6 +235,16 @@ class MTPDeviceDelegateImplLinux : public MTPDeviceAsyncDelegate { // Called when FillFileCache() fails. void OnFillFileCacheFailed(base::File::Error error); + // Called when CopyFileFromLocal() succeeds. + void OnDidCopyFileFromLocal( + const CopyFileFromLocalSuccessCallback& success_callback, + const int source_file_descriptor); + + // Called when CopyFileFromLocal() fails. + void HandleCopyFileFromLocalError(const ErrorCallback& error_callback, + const int source_file_descriptor, + base::File::Error error); + // Handles the device file |error| while operating on |file_id|. // |error_callback| is invoked to notify the caller about the file error. void HandleDeviceFileError(const ErrorCallback& error_callback, @@ -257,6 +280,9 @@ class MTPDeviceDelegateImplLinux : public MTPDeviceAsyncDelegate { // MTP device storage name (e.g. "usb:2,2:81282"). std::string storage_name_; + // Mode for opening storage. + const bool read_only_; + // A list of pending tasks that needs to be run when the device is // initialized or when the current task in progress is complete. std::deque<PendingTaskInfo> pending_tasks_; diff --git a/chrome/browser/media_galleries/linux/mtp_device_task_helper.cc b/chrome/browser/media_galleries/linux/mtp_device_task_helper.cc index e19ce18..5fb766f 100644 --- a/chrome/browser/media_galleries/linux/mtp_device_task_helper.cc +++ b/chrome/browser/media_galleries/linux/mtp_device_task_helper.cc @@ -59,6 +59,7 @@ MTPDeviceTaskHelper::~MTPDeviceTaskHelper() { } void MTPDeviceTaskHelper::OpenStorage(const std::string& storage_name, + const bool read_only, const OpenStorageCallback& callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(!storage_name.empty()); @@ -68,11 +69,12 @@ void MTPDeviceTaskHelper::OpenStorage(const std::string& storage_name, base::Bind(callback, true)); return; } + + const std::string mode = + read_only ? mtpd::kReadOnlyMode : mtpd::kReadWriteMode; GetMediaTransferProtocolManager()->OpenStorage( - storage_name, mtpd::kReadOnlyMode, - base::Bind(&MTPDeviceTaskHelper::OnDidOpenStorage, - weak_ptr_factory_.GetWeakPtr(), - callback)); + storage_name, mode, base::Bind(&MTPDeviceTaskHelper::OnDidOpenStorage, + weak_ptr_factory_.GetWeakPtr(), callback)); } void MTPDeviceTaskHelper::GetFileInfo( @@ -136,6 +138,22 @@ void MTPDeviceTaskHelper::ReadBytes( weak_ptr_factory_.GetWeakPtr(), request)); } +void MTPDeviceTaskHelper::CopyFileFromLocal( + const std::string& storage_name, + const int source_file_descriptor, + const uint32 parent_id, + const std::string& file_name, + const CopyFileFromLocalSuccessCallback& success_callback, + const ErrorCallback& error_callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + GetMediaTransferProtocolManager()->CopyFileFromLocal( + device_handle_, source_file_descriptor, parent_id, file_name, + base::Bind(&MTPDeviceTaskHelper::OnCopyFileFromLocal, + weak_ptr_factory_.GetWeakPtr(), success_callback, + error_callback)); +} + void MTPDeviceTaskHelper::CloseStorage() const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (device_handle_.empty()) @@ -266,6 +284,22 @@ void MTPDeviceTaskHelper::OnDidReadBytes( file_info, data.length())); } +void MTPDeviceTaskHelper::OnCopyFileFromLocal( + const CopyFileFromLocalSuccessCallback& success_callback, + const ErrorCallback& error_callback, + const bool error) const { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (error) { + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::Bind(error_callback, base::File::FILE_ERROR_FAILED)); + return; + } + + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(success_callback)); +} + void MTPDeviceTaskHelper::HandleDeviceError( const ErrorCallback& error_callback, base::File::Error error) const { diff --git a/chrome/browser/media_galleries/linux/mtp_device_task_helper.h b/chrome/browser/media_galleries/linux/mtp_device_task_helper.h index 31ac534..df284a1 100644 --- a/chrome/browser/media_galleries/linux/mtp_device_task_helper.h +++ b/chrome/browser/media_galleries/linux/mtp_device_task_helper.h @@ -36,6 +36,8 @@ class MTPDeviceTaskHelper { typedef base::Callback<void(const storage::AsyncFileUtil::EntryList& entries, bool has_more)> ReadDirectorySuccessCallback; + typedef base::Closure CopyFileFromLocalSuccessCallback; + typedef MTPDeviceAsyncDelegate::ErrorCallback ErrorCallback; MTPDeviceTaskHelper(); @@ -48,6 +50,7 @@ class MTPDeviceTaskHelper { // |callback| is called when the OpenStorage request completes. |callback| // runs on the IO thread. void OpenStorage(const std::string& storage_name, + const bool read_only, const OpenStorageCallback& callback); // Dispatches the GetFileInfo request to the MediaTransferProtocolManager. @@ -95,6 +98,15 @@ class MTPDeviceTaskHelper { // called on the IO thread to notify the caller about success or failure. void ReadBytes(const MTPDeviceAsyncDelegate::ReadBytesRequest& request); + // Forwards CopyFileFromLocal request to the MediaTransferProtocolManager. + void CopyFileFromLocal( + const std::string& storage_name, + const int source_file_descriptor, + const uint32 parent_id, + const std::string& file_name, + const CopyFileFromLocalSuccessCallback& success_callback, + const ErrorCallback& error_callback); + // Dispatches the CloseStorage request to the MediaTransferProtocolManager. void CloseStorage() const; @@ -159,6 +171,13 @@ class MTPDeviceTaskHelper { const std::string& data, bool error) const; + // Called when CopyFileFromLocal completed no matter if it succeeded or + // failed. + void OnCopyFileFromLocal( + const CopyFileFromLocalSuccessCallback& success_callback, + const ErrorCallback& error_callback, + const bool error) const; + // Called when the device is uninitialized. // // Runs |error_callback| on the IO thread to notify the caller about the diff --git a/chrome/browser/media_galleries/linux/mtp_device_task_helper_map_service.cc b/chrome/browser/media_galleries/linux/mtp_device_task_helper_map_service.cc index ce923aa..dfa85e3 100644 --- a/chrome/browser/media_galleries/linux/mtp_device_task_helper_map_service.cc +++ b/chrome/browser/media_galleries/linux/mtp_device_task_helper_map_service.cc @@ -22,19 +22,25 @@ MTPDeviceTaskHelperMapService* MTPDeviceTaskHelperMapService::GetInstance() { } MTPDeviceTaskHelper* MTPDeviceTaskHelperMapService::CreateDeviceTaskHelper( - const std::string& storage_name) { + const std::string& storage_name, + const bool read_only) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(!storage_name.empty()); - DCHECK(!ContainsKey(task_helper_map_, storage_name)); + const MTPDeviceTaskHelperKey key = + GetMTPDeviceTaskHelperKey(storage_name, read_only); + DCHECK(!ContainsKey(task_helper_map_, key)); MTPDeviceTaskHelper* task_helper = new MTPDeviceTaskHelper(); - task_helper_map_[storage_name] = task_helper; + task_helper_map_[key] = task_helper; return task_helper; } void MTPDeviceTaskHelperMapService::DestroyDeviceTaskHelper( - const std::string& storage_name) { + const std::string& storage_name, + const bool read_only) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - TaskHelperMap::iterator it = task_helper_map_.find(storage_name); + const MTPDeviceTaskHelperKey key = + GetMTPDeviceTaskHelperKey(storage_name, read_only); + TaskHelperMap::iterator it = task_helper_map_.find(key); if (it == task_helper_map_.end()) return; delete it->second; @@ -42,13 +48,25 @@ void MTPDeviceTaskHelperMapService::DestroyDeviceTaskHelper( } MTPDeviceTaskHelper* MTPDeviceTaskHelperMapService::GetDeviceTaskHelper( - const std::string& storage_name) { + const std::string& storage_name, + const bool read_only) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(!storage_name.empty()); - TaskHelperMap::const_iterator it = task_helper_map_.find(storage_name); + const MTPDeviceTaskHelperKey key = + GetMTPDeviceTaskHelperKey(storage_name, read_only); + TaskHelperMap::const_iterator it = task_helper_map_.find(key); return (it != task_helper_map_.end()) ? it->second : NULL; } +// static +MTPDeviceTaskHelperMapService::MTPDeviceTaskHelperKey +MTPDeviceTaskHelperMapService::GetMTPDeviceTaskHelperKey( + const std::string& storage_name, + const bool read_only) { + return (read_only ? "ReadOnly" : "ReadWrite") + std::string("|") + + storage_name; +} + MTPDeviceTaskHelperMapService::MTPDeviceTaskHelperMapService() { } diff --git a/chrome/browser/media_galleries/linux/mtp_device_task_helper_map_service.h b/chrome/browser/media_galleries/linux/mtp_device_task_helper_map_service.h index d13920c..6b02b09 100644 --- a/chrome/browser/media_galleries/linux/mtp_device_task_helper_map_service.h +++ b/chrome/browser/media_galleries/linux/mtp_device_task_helper_map_service.h @@ -20,25 +20,36 @@ class MTPDeviceTaskHelperMapService { // Creates and returns the MTPDeviceTaskHelper object for the storage device // specified by the |storage_name|. - MTPDeviceTaskHelper* CreateDeviceTaskHelper(const std::string& storage_name); + MTPDeviceTaskHelper* CreateDeviceTaskHelper(const std::string& storage_name, + const bool read_only); // Destroys the MTPDeviceTaskHelper object created by // CreateDeviceTaskHelper(). // |storage_name| specifies the name of the storage device. - void DestroyDeviceTaskHelper(const std::string& storage_name); + void DestroyDeviceTaskHelper(const std::string& storage_name, + const bool read_only); // Gets the MTPDeviceTaskHelper object associated with the device storage. // |storage_name| specifies the name of the storage device. // Return NULL if the |storage_name| is no longer valid (e.g. because the // corresponding storage device is detached, etc). - MTPDeviceTaskHelper* GetDeviceTaskHelper(const std::string& storage_name); + MTPDeviceTaskHelper* GetDeviceTaskHelper(const std::string& storage_name, + const bool read_only); private: friend struct base::DefaultLazyInstanceTraits<MTPDeviceTaskHelperMapService>; - // Key: Storage name. + // A key to be used in TaskHelperMap. + typedef std::string MTPDeviceTaskHelperKey; + + // Gets a key from |storage_name| and |read_only|. + static MTPDeviceTaskHelperKey GetMTPDeviceTaskHelperKey( + const std::string& storage_name, + const bool read_only); + + // Key: A combined value with storage_name and read_only. // Value: MTPDeviceTaskHelper object. - typedef std::map<std::string, MTPDeviceTaskHelper*> TaskHelperMap; + typedef std::map<MTPDeviceTaskHelperKey, MTPDeviceTaskHelper*> TaskHelperMap; // Get access to this class using GetInstance() method. MTPDeviceTaskHelperMapService(); diff --git a/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac.h b/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac.h index 0440fbd..f770834 100644 --- a/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac.h +++ b/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac.h @@ -54,6 +54,12 @@ class MTPDeviceDelegateImplMac : public MTPDeviceAsyncDelegate { int buf_len, const ReadBytesSuccessCallback& success_callback, const ErrorCallback& error_callback) override; + bool IsReadOnly() override; + void CopyFileFromLocal( + const base::FilePath& source_file_path, + const base::FilePath& device_file_path, + const CopyFileFromLocalSuccessCallback& success_callback, + const ErrorCallback& error_callback) override; void CancelPendingTasksAndDeleteDelegate() override; // Forward delegates for ImageCaptureDeviceListener. These are diff --git a/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac.mm b/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac.mm index 9c54cc7..a8781bc 100644 --- a/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac.mm +++ b/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac.mm @@ -209,6 +209,18 @@ void MTPDeviceDelegateImplMac::ReadBytes( NOTREACHED(); } +bool MTPDeviceDelegateImplMac::IsReadOnly() { + return true; +} + +void MTPDeviceDelegateImplMac::CopyFileFromLocal( + const base::FilePath& source_file_path, + const base::FilePath& device_file_path, + const CopyFileFromLocalSuccessCallback& success_callback, + const ErrorCallback& error_callback) { + NOTREACHED(); +} + void MTPDeviceDelegateImplMac::CancelPendingTasksAndDeleteDelegate() { content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, base::Bind(&MTPDeviceDelegateImplMac::CancelAndDelete, @@ -480,7 +492,11 @@ MTPDeviceDelegateImplMac::ReadDirectoryRequest::~ReadDirectoryRequest() {} void CreateMTPDeviceAsyncDelegate( const base::FilePath::StringType& device_location, + const bool read_only, const CreateMTPDeviceAsyncDelegateCallback& cb) { + // Write operation is not supported on Mac. + DCHECK(read_only); + std::string device_name = base::FilePath(device_location).BaseName().value(); std::string device_id; storage_monitor::StorageInfo::Type type; diff --git a/chrome/browser/media_galleries/media_file_system_registry.cc b/chrome/browser/media_galleries/media_file_system_registry.cc index a01845e..85bd095 100644 --- a/chrome/browser/media_galleries/media_file_system_registry.cc +++ b/chrome/browser/media_galleries/media_file_system_registry.cc @@ -722,10 +722,11 @@ class MediaFileSystemRegistry::MediaFileSystemContextImpl storage::FileSystemMountOption(), path); CHECK(result); - BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind( - &MTPDeviceMapService::RegisterMTPFileSystem, - base::Unretained(MTPDeviceMapService::GetInstance()), - path.value(), fs_name)); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&MTPDeviceMapService::RegisterMTPFileSystem, + base::Unretained(MTPDeviceMapService::GetInstance()), + path.value(), fs_name, true /* read only */)); return result; } diff --git a/chrome/browser/media_galleries/win/mtp_device_delegate_impl_win.cc b/chrome/browser/media_galleries/win/mtp_device_delegate_impl_win.cc index 21aa95e..5f1234c 100644 --- a/chrome/browser/media_galleries/win/mtp_device_delegate_impl_win.cc +++ b/chrome/browser/media_galleries/win/mtp_device_delegate_impl_win.cc @@ -315,8 +315,13 @@ void OnGetStorageInfoCreateDelegate( void CreateMTPDeviceAsyncDelegate( const base::string16& device_location, + const bool read_only, const CreateMTPDeviceAsyncDelegateCallback& callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + // Write operation is not supported on Windows. + DCHECK(read_only); + DCHECK(!device_location.empty()); base::string16* pnp_device_id = new base::string16; base::string16* storage_object_id = new base::string16; @@ -456,6 +461,18 @@ void MTPDeviceDelegateImplWin::ReadBytes( NOTREACHED(); } +bool MTPDeviceDelegateImplWin::IsReadOnly() { + return true; +} + +void MTPDeviceDelegateImplWin::CopyFileFromLocal( + const base::FilePath& source_file_path, + const base::FilePath& device_file_path, + const CopyFileFromLocalSuccessCallback& success_callback, + const ErrorCallback& error_callback) { + NOTREACHED(); +} + void MTPDeviceDelegateImplWin::CancelPendingTasksAndDeleteDelegate() { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); PortableDeviceMapService::GetInstance()->MarkPortableDeviceForDeletion( diff --git a/chrome/browser/media_galleries/win/mtp_device_delegate_impl_win.h b/chrome/browser/media_galleries/win/mtp_device_delegate_impl_win.h index f1ca860..f0da938 100644 --- a/chrome/browser/media_galleries/win/mtp_device_delegate_impl_win.h +++ b/chrome/browser/media_galleries/win/mtp_device_delegate_impl_win.h @@ -110,6 +110,12 @@ class MTPDeviceDelegateImplWin : public MTPDeviceAsyncDelegate { int buf_len, const ReadBytesSuccessCallback& success_callback, const ErrorCallback& error_callback) override; + bool IsReadOnly() override; + void CopyFileFromLocal( + const base::FilePath& source_file_path, + const base::FilePath& device_file_path, + const CopyFileFromLocalSuccessCallback& success_callback, + const ErrorCallback& error_callback) override; virtual void CancelPendingTasksAndDeleteDelegate() override; // Ensures the device is initialized for communication by doing a |