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 {
- (void)open;
- (void)close;
- (void)eject;
// Download the given file |name| to the provided |local_path|. Completion
// 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.
......
......@@ -92,6 +92,10 @@ base::FilePath PathForCameraItem(ICCameraItem* item) {
listener_.reset();
}
- (void)eject {
[camera_ requestEjectOrDisconnect];
}
- (void)downloadFile:(const std::string&)name
localPath:(const base::FilePath&)localPath {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
......
......@@ -38,6 +38,11 @@ class ImageCaptureDeviceManager {
// TODO(gbillock): Move this to be a constructor argument.
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:
base::scoped_nsobject<ImageCaptureDeviceManagerImpl> device_browser_;
};
......
......@@ -146,6 +146,16 @@ void ImageCaptureDeviceManager::SetNotifications(
[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
ImageCaptureDevice* ImageCaptureDeviceManager::deviceForUUID(
const std::string& uuid) {
......
......@@ -165,6 +165,21 @@ bool MediaTransferProtocolDeviceObserverLinux::GetStorageInfoForPath(
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.
void MediaTransferProtocolDeviceObserverLinux::StorageChanged(
bool is_attached,
......@@ -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
......@@ -42,6 +42,9 @@ class MediaTransferProtocolDeviceObserverLinux
bool GetStorageInfoForPath(const base::FilePath& path,
StorageInfo* storage_info) const;
void EjectDevice(const std::string& device_id,
base::Callback<void(StorageMonitor::EjectStatus)> callback);
protected:
// Only used in unit tests.
MediaTransferProtocolDeviceObserverLinux(
......@@ -61,6 +64,11 @@ class MediaTransferProtocolDeviceObserverLinux
// Enumerate existing mtp storage devices.
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
// manager outlives this object.
device::MediaTransferProtocolManager* mtp_manager_;
......
......@@ -555,7 +555,19 @@ void PortableDeviceWatcherWin::SetNotifications(
void PortableDeviceWatcherWin::EjectDevice(
const std::string& device_id,
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() {
......@@ -623,7 +635,7 @@ void PortableDeviceWatcherWin::OnDidHandleDeviceAttachEvent(
string16 storage_name(name + L" (" + storage_iter->object_temporary_id +
L')');
StorageInfo info(storage_id, storage_name, location,
string16(), string16(), string16(), 0);
storage_name, string16(), string16(), 0);
storage_map_[storage_id] = info;
if (storage_notifications_) {
info.set_location(GetStoragePathFromStorageId(storage_id));
......
......@@ -247,6 +247,17 @@ void NotifyUnmountResult(
void StorageMonitorCros::EjectDevice(
const std::string& device_id,
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;
for (MountMap::const_iterator info_it = mount_map_.begin();
info_it != mount_map_.end(); ++info_it) {
......
......@@ -334,6 +334,17 @@ void StorageMonitorLinux::SetMediaTransferProtocolManagerForTest(
void StorageMonitorLinux::EjectDevice(
const std::string& device_id,
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.
base::FilePath path;
base::FilePath device;
......
......@@ -272,6 +272,19 @@ bool StorageMonitorMac::GetStorageInfoForPath(const base::FilePath& path,
void StorageMonitorMac::EjectDevice(
const std::string& device_id,
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;
for (std::map<std::string, StorageInfo>::iterator
it = disk_info_map_.begin(); it != disk_info_map_.end(); ++it) {
......
......@@ -98,7 +98,6 @@ void StorageMonitorWin::EjectDevice(
const std::string& device_id,
base::Callback<void(EjectStatus)> callback) {
StorageInfo::Type type;
if (!StorageInfo::CrackDeviceId(device_id, &type, NULL)) {
callback.Run(EJECT_FAILURE);
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