Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(538)

Unified Diff: content/browser/mac/media_device_notifications.mm

Issue 9363008: Add Media device notification to SystemMonitor and Mac impl (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address comments Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/mac/media_device_notifications.mm
diff --git a/content/browser/mac/media_device_notifications.mm b/content/browser/mac/media_device_notifications.mm
new file mode 100644
index 0000000000000000000000000000000000000000..7e50e20912064ff95fa61589d6edca569f4f71c5
--- /dev/null
+++ b/content/browser/mac/media_device_notifications.mm
@@ -0,0 +1,132 @@
+// 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 "content/browser/mac/media_device_notifications.h"
+
+#include <Carbon/Carbon.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "base/file_path.h"
+#include "base/mac/foundation_util.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "base/sys_string_conversions.h"
+#include "base/system_monitor/system_monitor.h"
+
+namespace content {
+
+namespace {
+
+const CFStringRef kICAUserAssignedDeviceNameKey =
+ base::mac::NSToCFCast(@"ICAUserAssignedDeviceNameKey");
Avi (use Gerrit) 2012/02/28 01:26:46 CFSTR() here and the next two lines.
vandebo (ex-Chrome) 2012/02/28 18:35:05 Done.
+const CFStringRef kICDeviceNameKey = base::mac::NSToCFCast(@"ifil");
+const CFStringRef kICDeviceBSDNameKey = base::mac::NSToCFCast(@"bsdName");
+
+CFStringRef CopyMountPointFromBSDName(const char* bsd_name) {
Avi (use Gerrit) 2012/02/28 01:26:46 It's weird that this doesn't take a CF argument bu
vandebo (ex-Chrome) 2012/02/28 18:35:05 Done.
+ base::mac::ScopedCFTypeRef<DASessionRef> session(
+ DASessionCreate(kCFAllocatorDefault));
+ if (!session.get())
+ return NULL;
+
+ base::mac::ScopedCFTypeRef<DADiskRef> disk(
+ DADiskCreateFromBSDName(kCFAllocatorDefault, session.get(), bsd_name));
+ if (!disk.get())
+ return NULL;
+
+ base::mac::ScopedCFTypeRef<CFDictionaryRef> description(
+ DADiskCopyDescription(disk));
+ if (!description.get())
+ return NULL;
+
+ CFURLRef mount_point = base::mac::GetValueFromDictionary<CFURLRef>(
+ description, kDADiskDescriptionVolumePathKey);
+ if (!mount_point)
+ return NULL;
+
+ return CFURLCopyFileSystemPath(mount_point, kCFURLComponentPath);
Avi (use Gerrit) 2012/02/28 01:26:46 You mean kCFURLPOSIXPathStyle. (kCFURLComponentPat
vandebo (ex-Chrome) 2012/02/28 18:35:05 Done.
+}
+
+bool GetDeviceInfo(unsigned long device_number, std::string* name,
+ FilePath* location) {
+ ICACopyObjectPropertyDictionaryPB properties_request;
+ properties_request.object = device_number;
+ CFDictionaryRef device_properties;
+ properties_request.theDict = &device_properties;
+ OSErr ret = ICACopyObjectPropertyDictionary(&properties_request, NULL);
+ base::mac::ScopedCFTypeRef<CFDictionaryRef> scoped_device_properties(
+ device_properties);
+ CHECK_EQ(ret, noErr);
Avi (use Gerrit) 2012/02/28 01:26:46 Everywhere else, if a null is returned you return
vandebo (ex-Chrome) 2012/02/28 18:35:05 Done.
+
+ CFStringRef device_name = base::mac::GetValueFromDictionary<CFStringRef>(
+ device_properties, kICAUserAssignedDeviceNameKey);
+ if (device_name == NULL) {
+ device_name = base::mac::GetValueFromDictionary<CFStringRef>(
+ device_properties, kICDeviceNameKey);
+ }
+ if (device_name == NULL)
+ return false;
+ *name = base::SysCFStringRefToUTF8(device_name);
+
+ // TODO(vandebo) Support all media device, for now we only support mass
+ // storage media devices.
+ CFStringRef device = base::mac::GetValueFromDictionary<CFStringRef>(
+ device_properties, kICDeviceBSDNameKey);
+ if (device == NULL)
+ return false;
+ base::mac::ScopedCFTypeRef<CFStringRef> path(
+ CopyMountPointFromBSDName(base::SysCFStringRefToUTF8(device).c_str()));
+ if (path.get() == NULL)
+ return false;
+
+ *location = FilePath(base::SysCFStringRefToUTF8(path).c_str());
+
+ return true;
+}
+
+void MediaDeviceNotificationCallback(CFStringRef notification_type,
+ CFDictionaryRef notification_dictionary) {
+ bool attach = false;
+ if (CFEqual(notification_type, kICANotificationTypeDeviceAdded)) {
+ attach = true;
+ } else if (CFEqual(notification_type, kICANotificationTypeDeviceRemoved)) {
+ return;
Avi (use Gerrit) 2012/02/28 01:26:46 A little confused; why the return here? If you don
vandebo (ex-Chrome) 2012/02/28 18:35:05 A conversion bug, from CFStringCompare. I would h
+ }
+
+ base::SystemMonitor* system_monitor = base::SystemMonitor::Get();
+
+ CFNumberRef device_number_object =
+ base::mac::GetValueFromDictionary<CFNumberRef>(
+ notification_dictionary, kICANotificationDeviceICAObjectKey);
+ unsigned long device_number =
+ [base::mac::CFToNSCast(device_number_object) unsignedLongValue];
+ if (attach) {
+ std::string device_name;
+ FilePath location;
+ if (GetDeviceInfo(device_number, &device_name, &location)) {
+ system_monitor->ProcessMediaDeviceAttached(device_number, device_name,
+ location);
+ }
+ } else {
+ system_monitor->ProcessMediaDeviceDetached(device_number);
+ }
+}
+
+} // namespace
+
+void StartMediaDeviceNotifications() {
+ NSArray* events_of_interest = [NSArray arrayWithObjects:
+ (id)kICANotificationTypeDeviceAdded,
+ (id)kICANotificationTypeDeviceRemoved,
+ NULL];
Avi (use Gerrit) 2012/02/28 01:26:46 nil (not NULL) is used when referring to an ObjC o
vandebo (ex-Chrome) 2012/02/28 18:35:05 Done.
+
+ ICARegisterForEventNotificationPB notification_request;
+ notification_request.objectOfInterest = 0; // Zero means all objects
+ notification_request.eventsOfInterest =
+ base::mac::NSToCFCast(events_of_interest);
+ notification_request.notificationProc = &MediaDeviceNotificationCallback;
+ notification_request.options = NULL;
+ OSErr err = ICARegisterForEventNotification(&notification_request, NULL);
+ CHECK_EQ(err, noErr);
+}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698