Chromium Code Reviews| Index: content/browser/device_monitor_mac.mm |
| diff --git a/content/browser/device_monitor_mac.mm b/content/browser/device_monitor_mac.mm |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..e5d40d52c82ee8f9fb5e6c771e595884dc894e66 |
| --- /dev/null |
| +++ b/content/browser/device_monitor_mac.mm |
| @@ -0,0 +1,148 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
|
Mark Mentovai
2012/08/07 18:39:10
Why is this a .mm file? You haven’t used any Objec
no longer working on chromium
2012/08/08 08:42:42
It is a following design from gamepad/platform_dat
|
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "content/browser/device_monitor_mac.h" |
| + |
| +#include <IOKit/usb/IOUSBLib.h> |
| + |
| +#include "base/logging.h" |
| +#include "base/mac/scoped_cftyperef.h" |
| +#include "base/mac/scoped_ioobject.h" |
| + |
| +namespace content { |
| + |
| +namespace { |
| + |
| +struct { |
|
Mark Mentovai
2012/08/07 18:39:10
const?
no longer working on chromium
2012/08/08 08:42:42
Done.
|
| + base::SystemMonitor::DeviceType device_type; |
| + const io_name_t service_type; |
|
Mark Mentovai
2012/08/07 18:39:10
…but this doesn’t really need to be const
no longer working on chromium
2012/08/08 08:42:42
I think it is a c_string, isn't it better to put i
|
| +} kDeviceServices[] = { |
| + // Add new services here if needed. |
| + { base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE, kIOMatchedNotification }, |
| + { base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE, kIOTerminatedNotification }, |
| + { base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE, kIOMatchedNotification }, |
| + { base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE, kIOTerminatedNotification }, |
| +}; |
| + |
| +CFMutableDictionaryRef CreateMatchingDictionary( |
| + SInt32 interface_class_code, SInt32 interface_subclass_code) { |
| + CFMutableDictionaryRef matching_dictionary = IOServiceMatching( |
| + kIOUSBInterfaceClassName); |
| + base::mac::ScopedCFTypeRef<CFNumberRef> number_ref(CFNumberCreate( |
| + kCFAllocatorDefault, kCFNumberSInt32Type, &interface_class_code)); |
| + DCHECK(number_ref); |
| + CFDictionaryAddValue(matching_dictionary, CFSTR(kUSBInterfaceClass), |
| + number_ref); |
| + |
| + number_ref.reset(CFNumberCreate(kCFAllocatorDefault, |
| + kCFNumberSInt32Type, |
| + &interface_subclass_code)); |
| + DCHECK(number_ref); |
| + CFDictionaryAddValue(matching_dictionary, CFSTR(kUSBInterfaceSubClass), |
| + number_ref); |
| + |
| + return matching_dictionary; |
| +} |
| + |
| +void AddCallbackToIOService(IONotificationPortRef port, |
| + const io_name_t type, |
| + CFMutableDictionaryRef dictionary, |
| + IOServiceMatchingCallback callback, |
| + void* context, |
| + io_iterator_t* notification) { |
| + kern_return_t err = IOServiceAddMatchingNotification(port, |
|
Mark Mentovai
2012/08/07 18:39:10
Weird indentation.
no longer working on chromium
2012/08/08 08:42:42
thanks.
|
| + type, |
| + dictionary, |
| + callback, |
| + context, |
| + notification); |
| + if (err) { |
| + NOTREACHED() << "Failed to register the IO matched notification for type " |
| + << type; |
| + return; |
| + } |
| + DCHECK(*notification); |
| + |
| + // Iterate over set of matching devices to access already-present devices |
| + // and to arm the notification. |
| + base::mac::ScopedIOObject<io_service_t> this_object( |
| + IOIteratorNext(*notification)); |
| + for (; this_object; this_object.reset(IOIteratorNext(*notification))); |
|
Mark Mentovai
2012/08/07 18:39:10
Use {} to show an empty body. Also see the comment
no longer working on chromium
2012/08/08 08:42:42
Done.
I replied the comment at line 136.
|
| +} |
| + |
| +} // namespace |
| + |
| +DeviceMonitorMac::DeviceMonitorMac() { |
| + CFRunLoopRef runloop = CFRunLoopGetCurrent(); |
|
Mark Mentovai
2012/08/07 18:39:10
You can save doing this until you’re ready to add
no longer working on chromium
2012/08/08 08:42:42
Done.
|
| + |
| + // Add the notification port to the run loop. |
| + notification_port_ = IONotificationPortCreate(kIOMasterPortDefault); |
| + DCHECK(notification_port_); |
| + CFRunLoopSourceRef notification_cfsource = |
| + IONotificationPortGetRunLoopSource(notification_port_); |
| + |
| + RegisterServices(); |
| + |
| + CFRunLoopAddSource(runloop, notification_cfsource, kCFRunLoopCommonModes); |
| +} |
| + |
| +DeviceMonitorMac::~DeviceMonitorMac() { |
| + // Stop the notifications and free the objects. |
| + for (size_t i = 0; i < arraysize(kDeviceServices); ++i) { |
|
Mark Mentovai
2012/08/07 18:39:10
This looks a little freaky. Why don’t you use a st
no longer working on chromium
2012/08/08 08:42:42
a scoped_array is much more suitable here because
Mark Mentovai
2012/08/08 12:32:57
Aside from the ability to resize a std::vector (wh
|
| + IOObjectRelease(notification_iterators_[i]); |
|
Avi (use Gerrit)
2012/08/06 20:29:47
Aha, cool.
|
| + } |
| + |
| + // Remove the sleep notification port from the application runloop. |
| + CFRunLoopRemoveSource(CFRunLoopGetCurrent(), |
| + IONotificationPortGetRunLoopSource(notification_port_), |
| + kCFRunLoopCommonModes); |
| + |
| + // Destroy the notification port allocated by IONotificationPortCreate. |
| + IONotificationPortDestroy(notification_port_); |
| +} |
| + |
| +void DeviceMonitorMac::RegisterServices() { |
| + notification_iterators_.reset(new io_iterator_t[arraysize(kDeviceServices)]); |
| + CFMutableDictionaryRef matching_dictionary; |
| + for (size_t i = 0; i < arraysize(kDeviceServices); ++i) { |
| + switch (kDeviceServices[i].device_type) { |
|
wjia(left Chromium)
2012/08/07 20:57:27
After chatting with mmentovai@, my understanding i
no longer working on chromium
2012/08/08 08:42:42
NO.
I thought I had already explained clearly abou
|
| + case base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE: |
| + matching_dictionary = CreateMatchingDictionary( |
| + kUSBAudioInterfaceClass, kUSBAudioControlSubClass); |
| + break; |
| + case base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE: |
| + matching_dictionary = CreateMatchingDictionary( |
| + kUSBVideoInterfaceClass, kUSBVideoControlSubClass); |
| + break; |
| + default: |
| + NOTREACHED(); |
| + return; |
| + } |
| + |
| + // Add callback to the service. |
| + AddCallbackToIOService(notification_port_, |
| + kDeviceServices[i].service_type, |
| + matching_dictionary, |
| + &DeviceChangedCallback, |
| + static_cast<void*>(&kDeviceServices[i].device_type), |
| + ¬ification_iterators_[i]); |
| + } |
| +} |
| + |
| +void DeviceMonitorMac::DeviceChangedCallback(void *context, |
| + io_iterator_t iterator) { |
| + base::mac::ScopedIOObject<io_service_t> this_object(IOIteratorNext(iterator)); |
| + for (; this_object; this_object.reset(IOIteratorNext(iterator))) { |
|
Mark Mentovai
2012/08/07 18:39:10
I’d write the initialization inside the body of th
no longer working on chromium
2012/08/08 08:42:42
:) I think I have got different opinions on this s
Mark Mentovai
2012/08/08 12:32:57
Whoever’s opinion you got in the past on this was
|
| + if (context) { |
| + base::SystemMonitor::DeviceType device_type = |
| + *reinterpret_cast<base::SystemMonitor::DeviceType*>(context); |
| + DCHECK(device_type == base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE || |
| + device_type == base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE); |
| + // TODO(xians): Remove the global variable for SystemMonitor. |
| + base::SystemMonitor::Get()->ProcessDevicesChanged(device_type); |
| + } |
| + } |
| +} |
| + |
| +} // namespace content |