Commit c1ee74a4 authored by gbillock@chromium.org's avatar gbillock@chromium.org

[StorageMonitor] Handle EjectDevice call for MTP devices

This change includes intercept code to dispatch eject calls on
MTP devices for all platforms. By and large, MTP devices don't need
specific ejection APIs to be called -- the devices are safe to remove
without notice. So the implementations mainly just simulate their
removal and signal OK to the caller. When the device is then actually
removed, the removal will be swallowed without additional notification.

R=thestig@chromium.org
BUG=257179

Review URL: https://chromiumcodereview.appspot.com/23383009

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@222112 0039d316-1c4b-4281-b951-d872f2087c98
parent 88d07de9
...@@ -68,6 +68,8 @@ class ImageCaptureDeviceListener { ...@@ -68,6 +68,8 @@ class ImageCaptureDeviceListener {
- (void)open; - (void)open;
- (void)close; - (void)close;
- (void)eject;
// Download the given file |name| to the provided |local_path|. Completion // Download the given file |name| to the provided |local_path|. Completion
// notice will be sent to the listener's DownloadedFile method. The name // notice will be sent to the listener's DownloadedFile method. The name
// should be of the same form as those sent to the listener's ItemAdded method. // should be of the same form as those sent to the listener's ItemAdded method.
......
...@@ -92,6 +92,10 @@ base::FilePath PathForCameraItem(ICCameraItem* item) { ...@@ -92,6 +92,10 @@ base::FilePath PathForCameraItem(ICCameraItem* item) {
listener_.reset(); listener_.reset();
} }
- (void)eject {
[camera_ requestEjectOrDisconnect];
}
- (void)downloadFile:(const std::string&)name - (void)downloadFile:(const std::string&)name
localPath:(const base::FilePath&)localPath { localPath:(const base::FilePath&)localPath {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
......
...@@ -38,6 +38,11 @@ class ImageCaptureDeviceManager { ...@@ -38,6 +38,11 @@ class ImageCaptureDeviceManager {
// TODO(gbillock): Move this to be a constructor argument. // TODO(gbillock): Move this to be a constructor argument.
void SetNotifications(StorageMonitor::Receiver* notifications); void SetNotifications(StorageMonitor::Receiver* notifications);
// Eject the given device. The ID passed is not the device ID, but the
// ImageCapture UUID.
void EjectDevice(const std::string& uuid,
base::Callback<void(StorageMonitor::EjectStatus)> callback);
private: private:
base::scoped_nsobject<ImageCaptureDeviceManagerImpl> device_browser_; base::scoped_nsobject<ImageCaptureDeviceManagerImpl> device_browser_;
}; };
......
...@@ -146,6 +146,16 @@ void ImageCaptureDeviceManager::SetNotifications( ...@@ -146,6 +146,16 @@ void ImageCaptureDeviceManager::SetNotifications(
[device_browser_ setNotifications:notifications]; [device_browser_ setNotifications:notifications];
} }
void ImageCaptureDeviceManager::EjectDevice(
const std::string& uuid,
base::Callback<void(StorageMonitor::EjectStatus)> callback) {
base::scoped_nsobject<ImageCaptureDevice> camera_device(
[[device_browser_ deviceForUUID:uuid] retain]);
[camera_device eject];
[camera_device close];
callback.Run(StorageMonitor::EJECT_OK);
}
// static // static
ImageCaptureDevice* ImageCaptureDeviceManager::deviceForUUID( ImageCaptureDevice* ImageCaptureDeviceManager::deviceForUUID(
const std::string& uuid) { const std::string& uuid) {
......
...@@ -165,6 +165,21 @@ bool MediaTransferProtocolDeviceObserverLinux::GetStorageInfoForPath( ...@@ -165,6 +165,21 @@ bool MediaTransferProtocolDeviceObserverLinux::GetStorageInfoForPath(
return true; return true;
} }
void MediaTransferProtocolDeviceObserverLinux::EjectDevice(
const std::string& device_id,
base::Callback<void(StorageMonitor::EjectStatus)> callback) {
std::string location;
if (!GetLocationForDeviceId(device_id, &location)) {
callback.Run(StorageMonitor::EJECT_NO_SUCH_DEVICE);
return;
}
// TODO(thestig): Change this to tell the mtp manager to eject the device.
StorageChanged(false, location);
callback.Run(StorageMonitor::EJECT_OK);
}
// device::MediaTransferProtocolManager::Observer override. // device::MediaTransferProtocolManager::Observer override.
void MediaTransferProtocolDeviceObserverLinux::StorageChanged( void MediaTransferProtocolDeviceObserverLinux::StorageChanged(
bool is_attached, bool is_attached,
...@@ -211,4 +226,17 @@ void MediaTransferProtocolDeviceObserverLinux::EnumerateStorages() { ...@@ -211,4 +226,17 @@ void MediaTransferProtocolDeviceObserverLinux::EnumerateStorages() {
} }
} }
bool MediaTransferProtocolDeviceObserverLinux::GetLocationForDeviceId(
const std::string& device_id, std::string* location) const {
for (StorageLocationToInfoMap::const_iterator it = storage_map_.begin();
it != storage_map_.end(); ++it) {
if (it->second.device_id() == device_id) {
*location = it->first;
return true;
}
}
return false;
}
} // namespace chrome } // namespace chrome
...@@ -42,6 +42,9 @@ class MediaTransferProtocolDeviceObserverLinux ...@@ -42,6 +42,9 @@ class MediaTransferProtocolDeviceObserverLinux
bool GetStorageInfoForPath(const base::FilePath& path, bool GetStorageInfoForPath(const base::FilePath& path,
StorageInfo* storage_info) const; StorageInfo* storage_info) const;
void EjectDevice(const std::string& device_id,
base::Callback<void(StorageMonitor::EjectStatus)> callback);
protected: protected:
// Only used in unit tests. // Only used in unit tests.
MediaTransferProtocolDeviceObserverLinux( MediaTransferProtocolDeviceObserverLinux(
...@@ -61,6 +64,11 @@ class MediaTransferProtocolDeviceObserverLinux ...@@ -61,6 +64,11 @@ class MediaTransferProtocolDeviceObserverLinux
// Enumerate existing mtp storage devices. // Enumerate existing mtp storage devices.
void EnumerateStorages(); void EnumerateStorages();
// Find the |storage_map_| key for the record with this |device_id|. Returns
// true on success, false on failure.
bool GetLocationForDeviceId(const std::string& device_id,
std::string* location) const;
// Pointer to the MTP manager. Not owned. Client must ensure the MTP // Pointer to the MTP manager. Not owned. Client must ensure the MTP
// manager outlives this object. // manager outlives this object.
device::MediaTransferProtocolManager* mtp_manager_; device::MediaTransferProtocolManager* mtp_manager_;
......
...@@ -555,7 +555,19 @@ void PortableDeviceWatcherWin::SetNotifications( ...@@ -555,7 +555,19 @@ void PortableDeviceWatcherWin::SetNotifications(
void PortableDeviceWatcherWin::EjectDevice( void PortableDeviceWatcherWin::EjectDevice(
const std::string& device_id, const std::string& device_id,
base::Callback<void(StorageMonitor::EjectStatus)> callback) { base::Callback<void(StorageMonitor::EjectStatus)> callback) {
callback.Run(chrome::StorageMonitor::EJECT_FAILURE); // MTP devices on Windows don't have a detach API needed -- signal
// the object as if the device is gone and tell the caller it is OK
// to remove.
string16 device_location; // The device_map_ key.
string16 storage_object_id;
if (!GetMTPStorageInfoFromDeviceId(device_id,
&device_location, &storage_object_id)) {
callback.Run(chrome::StorageMonitor::EJECT_NO_SUCH_DEVICE);
return;
}
HandleDeviceDetachEvent(device_location);
callback.Run(chrome::StorageMonitor::EJECT_OK);
} }
void PortableDeviceWatcherWin::EnumerateAttachedDevices() { void PortableDeviceWatcherWin::EnumerateAttachedDevices() {
...@@ -623,7 +635,7 @@ void PortableDeviceWatcherWin::OnDidHandleDeviceAttachEvent( ...@@ -623,7 +635,7 @@ void PortableDeviceWatcherWin::OnDidHandleDeviceAttachEvent(
string16 storage_name(name + L" (" + storage_iter->object_temporary_id + string16 storage_name(name + L" (" + storage_iter->object_temporary_id +
L')'); L')');
StorageInfo info(storage_id, storage_name, location, StorageInfo info(storage_id, storage_name, location,
string16(), string16(), string16(), 0); storage_name, string16(), string16(), 0);
storage_map_[storage_id] = info; storage_map_[storage_id] = info;
if (storage_notifications_) { if (storage_notifications_) {
info.set_location(GetStoragePathFromStorageId(storage_id)); info.set_location(GetStoragePathFromStorageId(storage_id));
......
...@@ -247,6 +247,17 @@ void NotifyUnmountResult( ...@@ -247,6 +247,17 @@ void NotifyUnmountResult(
void StorageMonitorCros::EjectDevice( void StorageMonitorCros::EjectDevice(
const std::string& device_id, const std::string& device_id,
base::Callback<void(EjectStatus)> callback) { base::Callback<void(EjectStatus)> callback) {
StorageInfo::Type type;
if (!StorageInfo::CrackDeviceId(device_id, &type, NULL)) {
callback.Run(EJECT_FAILURE);
return;
}
if (type == StorageInfo::MTP_OR_PTP) {
media_transfer_protocol_device_observer_->EjectDevice(device_id, callback);
return;
}
std::string mount_path; std::string mount_path;
for (MountMap::const_iterator info_it = mount_map_.begin(); for (MountMap::const_iterator info_it = mount_map_.begin();
info_it != mount_map_.end(); ++info_it) { info_it != mount_map_.end(); ++info_it) {
......
...@@ -334,6 +334,17 @@ void StorageMonitorLinux::SetMediaTransferProtocolManagerForTest( ...@@ -334,6 +334,17 @@ void StorageMonitorLinux::SetMediaTransferProtocolManagerForTest(
void StorageMonitorLinux::EjectDevice( void StorageMonitorLinux::EjectDevice(
const std::string& device_id, const std::string& device_id,
base::Callback<void(EjectStatus)> callback) { base::Callback<void(EjectStatus)> callback) {
StorageInfo::Type type;
if (!StorageInfo::CrackDeviceId(device_id, &type, NULL)) {
callback.Run(EJECT_FAILURE);
return;
}
if (type == StorageInfo::MTP_OR_PTP) {
media_transfer_protocol_device_observer_->EjectDevice(device_id, callback);
return;
}
// Find the mount point for the given device ID. // Find the mount point for the given device ID.
base::FilePath path; base::FilePath path;
base::FilePath device; base::FilePath device;
......
...@@ -272,6 +272,19 @@ bool StorageMonitorMac::GetStorageInfoForPath(const base::FilePath& path, ...@@ -272,6 +272,19 @@ bool StorageMonitorMac::GetStorageInfoForPath(const base::FilePath& path,
void StorageMonitorMac::EjectDevice( void StorageMonitorMac::EjectDevice(
const std::string& device_id, const std::string& device_id,
base::Callback<void(EjectStatus)> callback) { base::Callback<void(EjectStatus)> callback) {
StorageInfo::Type type;
std::string uuid;
if (!StorageInfo::CrackDeviceId(device_id, &type, &uuid)) {
callback.Run(EJECT_FAILURE);
return;
}
if (type == StorageInfo::MAC_IMAGE_CAPTURE &&
image_capture_device_manager_.get()) {
image_capture_device_manager_->EjectDevice(uuid, callback);
return;
}
std::string bsd_name; std::string bsd_name;
for (std::map<std::string, StorageInfo>::iterator for (std::map<std::string, StorageInfo>::iterator
it = disk_info_map_.begin(); it != disk_info_map_.end(); ++it) { it = disk_info_map_.begin(); it != disk_info_map_.end(); ++it) {
......
...@@ -98,7 +98,6 @@ void StorageMonitorWin::EjectDevice( ...@@ -98,7 +98,6 @@ void StorageMonitorWin::EjectDevice(
const std::string& device_id, const std::string& device_id,
base::Callback<void(EjectStatus)> callback) { base::Callback<void(EjectStatus)> callback) {
StorageInfo::Type type; StorageInfo::Type type;
if (!StorageInfo::CrackDeviceId(device_id, &type, NULL)) { if (!StorageInfo::CrackDeviceId(device_id, &type, NULL)) {
callback.Run(EJECT_FAILURE); callback.Run(EJECT_FAILURE);
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment