image_capture_device_manager.mm 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/storage_monitor/image_capture_device_manager.h"
  5. #include "base/memory/raw_ptr.h"
  6. #import <ImageCaptureCore/ImageCaptureCore.h>
  7. #import "components/storage_monitor/image_capture_device.h"
  8. #include "components/storage_monitor/storage_info.h"
  9. namespace {
  10. storage_monitor::ImageCaptureDeviceManager* g_image_capture_device_manager =
  11. NULL;
  12. } // namespace
  13. // This class is the surface for the Mac ICDeviceBrowser ImageCaptureCore API.
  14. // Owned by the ChromeBrowserParts and has browser process lifetime. Upon
  15. // creation, it gets a list of attached media volumes (asynchronously) which
  16. // it will eventually forward to StorageMonitor. It will also
  17. // set up an ImageCaptureCore listener to be told when new devices/volumes
  18. // are discovered and existing ones are removed.
  19. @interface ImageCaptureDeviceManagerImpl
  20. : NSObject<ICDeviceBrowserDelegate> {
  21. @private
  22. base::scoped_nsobject<ICDeviceBrowser> _deviceBrowser;
  23. base::scoped_nsobject<NSMutableArray> _cameras;
  24. // Guaranteed to outlive this class.
  25. // TODO(gbillock): Update when ownership chains go up through
  26. // a StorageMonitor subclass.
  27. raw_ptr<storage_monitor::StorageMonitor::Receiver> _notifications;
  28. }
  29. - (void)setNotifications:
  30. (storage_monitor::StorageMonitor::Receiver*)notifications;
  31. - (void)close;
  32. // The UUIDs passed here are available in the device attach notifications.
  33. // They're gotten by cracking the device ID and taking the unique ID output.
  34. - (ImageCaptureDevice*)deviceForUUID:(const std::string&)uuid;
  35. - (ICDeviceBrowser*)deviceBrowserForTest;
  36. @end
  37. @implementation ImageCaptureDeviceManagerImpl
  38. - (instancetype)init {
  39. if ((self = [super init])) {
  40. _cameras.reset([[NSMutableArray alloc] init]);
  41. _notifications = nullptr;
  42. _deviceBrowser.reset([[ICDeviceBrowser alloc] init]);
  43. [_deviceBrowser setDelegate:self];
  44. [_deviceBrowser
  45. setBrowsedDeviceTypeMask:ICDeviceTypeMask{
  46. ICDeviceTypeMaskCamera |
  47. UInt{ICDeviceLocationTypeMaskLocal}}];
  48. [_deviceBrowser start];
  49. }
  50. return self;
  51. }
  52. - (void)setNotifications:
  53. (storage_monitor::StorageMonitor::Receiver*)notifications {
  54. _notifications = notifications;
  55. }
  56. - (void)close {
  57. [_deviceBrowser setDelegate:nil];
  58. [_deviceBrowser stop];
  59. _deviceBrowser.reset();
  60. _cameras.reset();
  61. }
  62. - (ImageCaptureDevice*) deviceForUUID:(const std::string&)uuid {
  63. for (ICCameraDevice* camera in _cameras.get()) {
  64. NSString* camera_id = [camera UUIDString];
  65. if (base::SysNSStringToUTF8(camera_id) == uuid) {
  66. return [[[ImageCaptureDevice alloc]
  67. initWithCameraDevice:camera] autorelease];
  68. }
  69. }
  70. return nil;
  71. }
  72. - (void)deviceBrowser:(ICDeviceBrowser*)browser
  73. didAddDevice:(ICDevice*)addedDevice
  74. moreComing:(BOOL)moreComing {
  75. if (!(addedDevice.type & ICDeviceTypeCamera))
  76. return;
  77. // Ignore mass storage attaches -- those will be handled
  78. // by Mac's removable storage watcher.
  79. if ([addedDevice.transportType isEqualToString:ICTransportTypeMassStorage])
  80. return;
  81. ICCameraDevice* cameraDevice =
  82. base::mac::ObjCCastStrict<ICCameraDevice>(addedDevice);
  83. [_cameras addObject:addedDevice];
  84. // TODO(gbillock): use [cameraDevice mountPoint] here when possible.
  85. storage_monitor::StorageInfo info(
  86. storage_monitor::StorageInfo::MakeDeviceId(
  87. storage_monitor::StorageInfo::MAC_IMAGE_CAPTURE,
  88. base::SysNSStringToUTF8([cameraDevice UUIDString])),
  89. std::string(), base::SysNSStringToUTF16([cameraDevice name]),
  90. std::u16string(), std::u16string(), 0);
  91. _notifications->ProcessAttach(info);
  92. }
  93. - (void)deviceBrowser:(ICDeviceBrowser*)browser
  94. didRemoveDevice:(ICDevice*)device
  95. moreGoing:(BOOL)moreGoing {
  96. if (!(device.type & ICDeviceTypeCamera))
  97. return;
  98. std::string uuid = base::SysNSStringToUTF8([device UUIDString]);
  99. // May delete |device|.
  100. [_cameras removeObject:device];
  101. _notifications->ProcessDetach(storage_monitor::StorageInfo::MakeDeviceId(
  102. storage_monitor::StorageInfo::MAC_IMAGE_CAPTURE, uuid));
  103. }
  104. - (ICDeviceBrowser*)deviceBrowserForTest {
  105. return _deviceBrowser.get();
  106. }
  107. @end // ImageCaptureDeviceManagerImpl
  108. namespace storage_monitor {
  109. ImageCaptureDeviceManager::ImageCaptureDeviceManager() {
  110. device_browser_.reset([[ImageCaptureDeviceManagerImpl alloc] init]);
  111. g_image_capture_device_manager = this;
  112. }
  113. ImageCaptureDeviceManager::~ImageCaptureDeviceManager() {
  114. g_image_capture_device_manager = NULL;
  115. [device_browser_ close];
  116. }
  117. void ImageCaptureDeviceManager::SetNotifications(
  118. StorageMonitor::Receiver* notifications) {
  119. [device_browser_ setNotifications:notifications];
  120. }
  121. void ImageCaptureDeviceManager::EjectDevice(
  122. const std::string& uuid,
  123. base::OnceCallback<void(StorageMonitor::EjectStatus)> callback) {
  124. base::scoped_nsobject<ImageCaptureDevice> camera_device(
  125. [[device_browser_ deviceForUUID:uuid] retain]);
  126. [camera_device eject];
  127. [camera_device close];
  128. std::move(callback).Run(StorageMonitor::EJECT_OK);
  129. }
  130. // static
  131. ImageCaptureDevice* ImageCaptureDeviceManager::deviceForUUID(
  132. const std::string& uuid) {
  133. ImageCaptureDeviceManagerImpl* manager =
  134. g_image_capture_device_manager->device_browser_;
  135. return [manager deviceForUUID:uuid];
  136. }
  137. id<ICDeviceBrowserDelegate>
  138. ImageCaptureDeviceManager::device_browser_delegate() {
  139. return device_browser_.get();
  140. }
  141. ICDeviceBrowser* ImageCaptureDeviceManager::device_browser_for_test() {
  142. return [device_browser_ deviceBrowserForTest];
  143. }
  144. } // namespace storage_monitor