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

Revert 175938

> [Media Galleries] Add an ImageCaptureCore listener for Mac. (part 2)
> 
> This listener uses the ImageCapture API to watch for attach and detach
> events of PTP devices and other devices which can be read through the
> library. It forwards such notifications through the SystemMonitor.
> 
> Also provides an API for clients to access such devices directly and
> retrieve the media contents from them.
> 
> R=thestig@chromium.org,sail@chromium.org
> BUG=151681
> 
> 
> Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=175471
> 
> Review URL: https://chromiumcodereview.appspot.com/11442057

TBR=gbillock@chromium.org
Review URL: https://codereview.chromium.org/11817036

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@175943 0039d316-1c4b-4281-b951-d872f2087c98
parent d9eed90a
......@@ -26,7 +26,6 @@
MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
DEFINE_EMPTY_PROTOCOL(NSDraggingDestination)
DEFINE_EMPTY_PROTOCOL(ICCameraDeviceDownloadDelegate)
#endif // MAC_OS_X_VERSION_10_7
......
......@@ -9,7 +9,6 @@
#include "base/memory/ref_counted.h"
namespace chrome {
class ImageCaptureDeviceManager;
class RemovableDeviceNotificationsMac;
}
......@@ -32,8 +31,6 @@ class ChromeBrowserMainPartsMac : public ChromeBrowserMainPartsPosix {
scoped_refptr<chrome::RemovableDeviceNotificationsMac>
removable_device_notifications_mac_;
scoped_ptr<chrome::ImageCaptureDeviceManager> image_capture_device_manager_;
DISALLOW_COPY_AND_ASSIGN(ChromeBrowserMainPartsMac);
};
......
......@@ -22,7 +22,6 @@
#include "chrome/browser/mac/keychain_reauthorize.h"
#import "chrome/browser/mac/keystone_glue.h"
#include "chrome/browser/metrics/metrics_service.h"
#include "chrome/browser/system_monitor/image_capture_device_manager.h"
#include "chrome/browser/system_monitor/removable_device_notifications_mac.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
......@@ -284,7 +283,6 @@ void ChromeBrowserMainPartsMac::PreMainMessageLoopStart() {
void ChromeBrowserMainPartsMac::PreProfileInit() {
removable_device_notifications_mac_ =
new chrome::RemovableDeviceNotificationsMac();
image_capture_device_manager_.reset(new chrome::ImageCaptureDeviceManager);
ChromeBrowserMainPartsPosix::PreProfileInit();
}
......
......@@ -22,6 +22,11 @@ class DiskInfoMac {
// dictionary. This function must be called on the file thread.
static DiskInfoMac BuildDiskInfoOnFileThread(CFDictionaryRef dict);
// Construct a disk info object from info from an ImageCature device.
static DiskInfoMac BuildDiskInfoFromICDevice(std::string device_id,
string16 device_name,
FilePath mount_point);
const std::string& bsd_name() const { return bsd_name_; }
const std::string& device_id() const { return device_id_; }
const std::string& model_name() const { return model_name_; }
......
......@@ -114,4 +114,17 @@ DiskInfoMac DiskInfoMac::BuildDiskInfoOnFileThread(CFDictionaryRef dict) {
return info;
}
// TODO(gbillock): Make sure this gets test coverage.
// static
DiskInfoMac DiskInfoMac::BuildDiskInfoFromICDevice(std::string device_id,
string16 device_name,
FilePath mount_point) {
DiskInfoMac info;
info.device_id_ = device_id;
info.device_name_ = device_name;
info.mount_point_ = mount_point;
info.type_ = MediaStorageUtil::MAC_IMAGE_CAPTURE;
return info;
}
} // namesapce chrome
// 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.
#ifndef CHROME_BROWSER_SYSTEM_MONITOR_IMAGE_CAPTURE_DEVICE_H_
#define CHROME_BROWSER_SYSTEM_MONITOR_IMAGE_CAPTURE_DEVICE_H_
#import <Foundation/Foundation.h>
#import <ImageCaptureCore/ImageCaptureCore.h>
#include "base/file_path.h"
#include "base/mac/cocoa_protocols.h"
#include "base/mac/foundation_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_nsobject.h"
#include "base/memory/weak_ptr.h"
#include "base/platform_file.h"
#include "base/string_util.h"
#include "base/synchronization/lock.h"
#include "base/sys_string_conversions.h"
// Clients use this listener interface to get notifications about
// events happening as a particular ImageCapture device is interacted with.
// Clients drive the interaction through the ImageCaptureDeviceManager
// and the ImageCaptureDevice classes, and get notifications of
// events through this interface.
class ImageCaptureDeviceListener {
public:
virtual ~ImageCaptureDeviceListener() {}
// Get a notification that a particular item has been found on the device.
// These calls will come automatically after a new device is initialized.
virtual void ItemAdded(const std::string& name,
const base::PlatformFileInfo& info) = 0;
// Called when there are no more items to retrieve.
virtual void NoMoreItems() = 0;
// Called upon completion of a file download request. The |path| is the
// requested download file. Note: in NOT_FOUND error case, can be called
// inline with the download request.
virtual void DownloadedFile(const std::string& name,
base::PlatformFileError error) = 0;
// Called to let the client know the device is removed. The client should
// set the ImageCaptureDevice listener to null upon receiving this call.
virtual void DeviceRemoved() = 0;
};
// Interface to a camera device found by ImageCaptureCore. This class manages a
// session to the camera and provides the backing interactions to present the
// media files on it to the filesystem delegate. FilePaths will be artificial,
// like "/$device_id/" + name.
// Note that all interactions with this class must happen on the UI thread.
@interface ImageCaptureDevice
: NSObject<ICCameraDeviceDelegate, ICCameraDeviceDownloadDelegate> {
@private
scoped_nsobject<ICCameraDevice> camera_;
base::WeakPtr<ImageCaptureDeviceListener> listener_;
}
- (id)initWithCameraDevice:(ICCameraDevice*)cameraDevice;
- (void)setListener:(base::WeakPtr<ImageCaptureDeviceListener>)listener;
- (void)open;
- (void)close;
// Download the given |file| to the provided |local_path|. Completion notice
// will be sent to the listener's DownloadedFile method.
- (void)downloadFile:(const std::string&)name
localPath:(const FilePath&)localPath;
@end
#endif // CHROME_BROWSER_SYSTEM_MONITOR_IMAGE_CAPTURE_DEVICE_H_
// 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.
#import "chrome/browser/system_monitor/image_capture_device.h"
#include "base/file_util.h"
#include "base/mac/mac_util.h"
#include "base/system_monitor/system_monitor.h"
#include "chrome/browser/system_monitor/media_storage_util.h"
#include "content/public/browser/browser_thread.h"
namespace {
void RenameFile(const FilePath& downloaded_filename,
const FilePath& desired_filename,
base::PlatformFileError* result) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
bool success = file_util::ReplaceFile(downloaded_filename, desired_filename);
*result = success ? base::PLATFORM_FILE_OK
: base::PLATFORM_FILE_ERROR_NOT_FOUND;
}
void ReturnRenameResultToListener(
base::WeakPtr<ImageCaptureDeviceListener> listener,
const std::string& name,
base::PlatformFileError* result) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
scoped_ptr<base::PlatformFileError> result_deleter(result);
if (listener)
listener->DownloadedFile(name, *result);
}
base::Time NSDateToBaseTime(NSDate* date) {
return base::Time::FromDoubleT([date timeIntervalSince1970]);
}
} // namespace
@implementation ImageCaptureDevice
- (id)initWithCameraDevice:(ICCameraDevice*)cameraDevice {
if ((self = [super init])) {
camera_.reset([cameraDevice retain]);
[camera_ setDelegate:self];
}
return self;
}
- (void)dealloc {
// Make sure the session was closed and listener set to null
// before destruction.
DCHECK(![camera_ delegate]);
DCHECK(!listener_);
[super dealloc];
}
- (void)setListener:(base::WeakPtr<ImageCaptureDeviceListener>)listener {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
listener_ = listener;
}
- (void)open {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
DCHECK(listener_);
[camera_ requestOpenSession];
}
- (void)close {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
[camera_ requestCloseSession];
[camera_ setDelegate:nil];
listener_.reset();
}
- (void)downloadFile:(const std::string&)name
localPath:(const FilePath&)localPath {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
// Find the file with that name and start download.
for (ICCameraItem* item in [camera_ mediaFiles]) {
std::string itemName = base::SysNSStringToUTF8([item name]);
if (itemName == name) {
// To create save options for ImageCapture, we need to
// split the target filename into directory/name
// and encode the directory as a URL.
NSString* saveDirectory =
base::mac::FilePathToNSString(localPath.DirName());
NSString* saveFilename =
base::mac::FilePathToNSString(localPath.BaseName());
NSMutableDictionary* options =
[NSMutableDictionary dictionaryWithCapacity:3];
[options setObject:[NSURL fileURLWithPath:saveDirectory isDirectory:YES]
forKey:ICDownloadsDirectoryURL];
[options setObject:saveFilename forKey:ICSaveAsFilename];
[options setObject:[NSNumber numberWithBool:YES] forKey:ICOverwrite];
[camera_ requestDownloadFile:base::mac::ObjCCastStrict<ICCameraFile>(item)
options:options
downloadDelegate:self
didDownloadSelector:
@selector(didDownloadFile:error:options:contextInfo:)
contextInfo:NULL];
return;
}
}
if (listener_)
listener_->DownloadedFile(name, base::PLATFORM_FILE_ERROR_NOT_FOUND);
}
- (void)cameraDevice:(ICCameraDevice*)camera didAddItem:(ICCameraItem*)item {
std::string name = base::SysNSStringToUTF8([item name]);
base::PlatformFileInfo info;
if ([[item UTI] isEqualToString:base::mac::CFToNSCast(kUTTypeFolder)])
info.is_directory = true;
else
info.size = [base::mac::ObjCCastStrict<ICCameraFile>(item) fileSize];
info.last_modified = NSDateToBaseTime([item modificationDate]);
info.creation_time = NSDateToBaseTime([item creationDate]);
info.last_accessed = info.last_modified;
if (listener_)
listener_->ItemAdded(name, info);
}
- (void)cameraDevice:(ICCameraDevice*)camera didAddItems:(NSArray*)items {
for (ICCameraItem* item in items)
[self cameraDevice:camera didAddItem:item];
}
- (void)didRemoveDevice:(ICDevice*)device {
device.delegate = NULL;
if (listener_)
listener_->DeviceRemoved();
}
// Notifies that a session was opened with the given device; potentially
// with an error.
- (void)device:(ICDevice*)device didOpenSessionWithError:(NSError*)error {
if (error)
[self didRemoveDevice:camera_];
}
- (void)device:(ICDevice*)device didEncounterError:(NSError*)error {
if (error && listener_)
listener_->DeviceRemoved();
}
// When this message is received, all media metadata is now loaded.
- (void)deviceDidBecomeReadyWithCompleteContentCatalog:(ICDevice*)device {
if (listener_)
listener_->NoMoreItems();
}
// For 10.7 and earlier, this method has the semantics of
// deviceDidBecomeReadyWithCompleteContentCatalog. For 10.8++, it has
// the semantics of notifying that the device can receive commands.
- (void)deviceDidBecomeReady:(ICDevice*)device {
if (listener_ && base::mac::IsOSLionOrEarlier())
listener_->NoMoreItems();
}
- (void)didDownloadFile:(ICCameraFile*)file
error:(NSError*)error
options:(NSDictionary*)options
contextInfo:(void*)contextInfo {
std::string name = base::SysNSStringToUTF8([file name]);
if (error) {
if (listener_)
listener_->DownloadedFile(name, base::PLATFORM_FILE_ERROR_FAILED);
return;
}
std::string savedFilename =
base::SysNSStringToUTF8([options objectForKey:ICSavedFilename]);
std::string saveAsFilename =
base::SysNSStringToUTF8([options objectForKey:ICSaveAsFilename]);
if (savedFilename == saveAsFilename) {
if (listener_)
listener_->DownloadedFile(name, base::PLATFORM_FILE_OK);
return;
}
// ImageCapture did not save the file into the name we gave it in the
// options. It picks a new name according to its best lights, so we need
// to rename the file.
FilePath saveDir(base::SysNSStringToUTF8(
[[options objectForKey:ICDownloadsDirectoryURL] path]));
FilePath saveAsPath = saveDir.Append(saveAsFilename);
FilePath savedPath = saveDir.Append(savedFilename);
// Shared result value from file-copy closure to tell-listener closure.
base::PlatformFileError* copyResult = new base::PlatformFileError();
content::BrowserThread::PostTaskAndReply(
content::BrowserThread::FILE,
FROM_HERE,
base::Bind(&RenameFile, savedPath, saveAsPath, copyResult),
base::Bind(&ReturnRenameResultToListener, listener_, name, copyResult));
}
@end // ImageCaptureDevice
// 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.
#ifndef CHROME_BROWSER_SYSTEM_MONITOR_IMAGE_CAPTURE_DEVICE_MANAGER_H_
#define CHROME_BROWSER_SYSTEM_MONITOR_IMAGE_CAPTURE_DEVICE_MANAGER_H_
#import <Foundation/Foundation.h>
#include <string>
#include "base/memory/scoped_nsobject.h"
@protocol ICDeviceBrowserDelegate;
@class ImageCaptureDevice;
@class ImageCaptureDeviceManagerImpl;
namespace chrome {
// Upon creation, begins monitoring for any attached devices using the
// ImageCapture API. Notifies clients of the presence of such devices
// (i.e. cameras, USB cards) using the SystemMonitor and makes them
// available using |deviceForUUID|.
class ImageCaptureDeviceManager {
public:
ImageCaptureDeviceManager();
~ImageCaptureDeviceManager();
// The UUIDs passed here are available in the device attach notifications
// given through SystemMonitor. They're gotten by cracking the device ID
// and taking the unique ID output.
static ImageCaptureDevice* deviceForUUID(const std::string& uuid);
// Returns a weak pointer to the internal ImageCapture interface protocol.
id<ICDeviceBrowserDelegate> device_browser();
private:
scoped_nsobject<ImageCaptureDeviceManagerImpl> device_browser_;
};
} // namespace chrome
#endif // CHROME_BROWSER_SYSTEM_MONITOR_IMAGE_CAPTURE_DEVICE_MANAGER_H_
// 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/system_monitor/image_capture_device_manager.h"
#import <ImageCaptureCore/ImageCaptureCore.h>
#include "base/file_util.h"
#include "base/system_monitor/system_monitor.h"
#include "chrome/browser/system_monitor/disk_info_mac.h"
#import "chrome/browser/system_monitor/image_capture_device.h"
#include "chrome/browser/system_monitor/media_storage_util.h"
#include "content/public/browser/browser_thread.h"
namespace {
chrome::ImageCaptureDeviceManager* g_image_capture_device_manager = NULL;
} // namespace
// This class is the surface for the Mac ICDeviceBrowser ImageCaptureCore API.
// Owned by the ChromeBrowserParts and has browser process lifetime. Upon
// creation, it gets a list of attached media volumes (asynchronously) which
// it will eventually forward to the SystemMonitor as removable storage
// notifications. It will also set up an ImageCaptureCore listener to be
// told when new devices/volumes are discovered and existing ones are removed.
@interface ImageCaptureDeviceManagerImpl
: NSObject<ICDeviceBrowserDelegate> {
@private
scoped_nsobject<ICDeviceBrowser> deviceBrowser_;
scoped_nsobject<NSMutableArray> cameras_;
}
- (void)close;
// The UUIDs passed here are available in the device attach notifications
// given through SystemMonitor. They're gotten by cracking the device ID
// and taking the unique ID output.
- (ImageCaptureDevice*)deviceForUUID:(const std::string&)uuid;
@end
@implementation ImageCaptureDeviceManagerImpl
- (id)init {
if ((self = [super init])) {
cameras_.reset([[NSMutableArray alloc] init]);
deviceBrowser_.reset([[ICDeviceBrowser alloc] init]);
[deviceBrowser_ setDelegate:self];
[deviceBrowser_ setBrowsedDeviceTypeMask:
[deviceBrowser_ browsedDeviceTypeMask] |
ICDeviceTypeMaskCamera | ICDeviceLocationTypeMaskLocal];
[deviceBrowser_ start];
}
return self;
}
- (void)close {
[deviceBrowser_ setDelegate:nil];
[deviceBrowser_ stop];
deviceBrowser_.reset();
cameras_.reset();
}
- (ImageCaptureDevice*) deviceForUUID:(const std::string&)uuid {
for (ICCameraDevice* camera in cameras_.get()) {
NSString* camera_id = [camera UUIDString];
if (base::SysNSStringToUTF8(camera_id) == uuid) {
return [[[ImageCaptureDevice alloc]
initWithCameraDevice:camera] autorelease];
}
}
return nil;
}
- (void)deviceBrowser:(ICDeviceBrowser*)browser
didAddDevice:(ICDevice*)addedDevice
moreComing:(BOOL)moreComing {
if (!(addedDevice.type & ICDeviceTypeCamera))
return;
ICCameraDevice* cameraDevice =
base::mac::ObjCCastStrict<ICCameraDevice>(addedDevice);
[cameras_ addObject:addedDevice];
// TODO(gbillock): use [cameraDevice mountPoint] here when possible.
base::SystemMonitor::Get()->ProcessRemovableStorageAttached(
chrome::MediaStorageUtil::MakeDeviceId(
chrome::MediaStorageUtil::MAC_IMAGE_CAPTURE,
base::SysNSStringToUTF8([cameraDevice UUIDString])),
base::SysNSStringToUTF16([cameraDevice name]), "");
}
- (void)deviceBrowser:(ICDeviceBrowser*)browser
didRemoveDevice:(ICDevice*)device
moreGoing:(BOOL)moreGoing {
if (!(device.type & ICDeviceTypeCamera))
return;
std::string uuid = base::SysNSStringToUTF8([device UUIDString]);
// May delete |device|.
[cameras_ removeObject:device];
base::SystemMonitor::Get()->ProcessRemovableStorageDetached(
chrome::MediaStorageUtil::MakeDeviceId(
chrome::MediaStorageUtil::MAC_IMAGE_CAPTURE, uuid));
}
@end // ImageCaptureDeviceManagerImpl
namespace chrome {
ImageCaptureDeviceManager::ImageCaptureDeviceManager() {
device_browser_.reset([[ImageCaptureDeviceManagerImpl alloc] init]);
g_image_capture_device_manager = this;
}
ImageCaptureDeviceManager::~ImageCaptureDeviceManager() {
g_image_capture_device_manager = NULL;
[device_browser_ close];
}
// static
ImageCaptureDevice* ImageCaptureDeviceManager::deviceForUUID(
const std::string& uuid) {
ImageCaptureDeviceManagerImpl* manager =
g_image_capture_device_manager->device_browser_;
return [manager deviceForUUID:uuid];
}
id<ICDeviceBrowserDelegate> ImageCaptureDeviceManager::device_browser() {
return device_browser_.get();
}
} // namespace chrome
......@@ -2046,10 +2046,6 @@
'browser/sync_file_system/sync_file_system_service.h',
'browser/system_monitor/disk_info_mac.h',
'browser/system_monitor/disk_info_mac.mm',
'browser/system_monitor/image_capture_device.h',
'browser/system_monitor/image_capture_device.mm',
'browser/system_monitor/image_capture_device_manager.h',
'browser/system_monitor/image_capture_device_manager.mm',
'browser/system_monitor/media_device_notifications_utils.cc',
'browser/system_monitor/media_device_notifications_utils.h',
'browser/system_monitor/media_storage_util.cc',
......@@ -2836,7 +2832,6 @@
'$(SDKROOT)/System/Library/Frameworks/AudioUnit.framework',
'$(SDKROOT)/System/Library/Frameworks/DiskArbitration.framework',
'$(SDKROOT)/System/Library/Frameworks/IOKit.framework',
'$(SDKROOT)/System/Library/Frameworks/ImageCaptureCore.framework',
'$(SDKROOT)/System/Library/Frameworks/OpenGL.framework',
'$(SDKROOT)/System/Library/Frameworks/QuartzCore.framework',
'$(SDKROOT)/System/Library/Frameworks/SecurityInterface.framework',
......
......@@ -1142,7 +1142,6 @@
'browser/sync_file_system/sync_file_system_service_unittest.cc',
'browser/sync_file_system/sync_file_system_test_util.cc',
'browser/sync_file_system/sync_file_system_test_util.h',
'browser/system_monitor/image_capture_device_manager_unittest.mm',
'browser/system_monitor/media_device_notifications_utils_unittest.cc',
'browser/system_monitor/media_storage_util_unittest.cc',
'browser/system_monitor/media_transfer_protocol_device_observer_linux_unittest.cc',
......
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