OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2012 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 | |
5 #include "content/browser/mac/media_device_notifications.h" | |
6 | |
7 #include <Carbon/Carbon.h> | |
8 #include <CoreFoundation/CoreFoundation.h> | |
9 | |
10 #include "base/file_path.h" | |
11 #include "base/mac/foundation_util.h" | |
12 #include "base/mac/scoped_cftyperef.h" | |
13 #include "base/sys_string_conversions.h" | |
14 #include "base/system_monitor/system_monitor.h" | |
15 | |
16 namespace content { | |
17 | |
18 namespace { | |
19 | |
20 const CFStringRef kICAUserAssignedDeviceNameKey = | |
21 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.
| |
22 const CFStringRef kICDeviceNameKey = base::mac::NSToCFCast(@"ifil"); | |
23 const CFStringRef kICDeviceBSDNameKey = base::mac::NSToCFCast(@"bsdName"); | |
24 | |
25 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.
| |
26 base::mac::ScopedCFTypeRef<DASessionRef> session( | |
27 DASessionCreate(kCFAllocatorDefault)); | |
28 if (!session.get()) | |
29 return NULL; | |
30 | |
31 base::mac::ScopedCFTypeRef<DADiskRef> disk( | |
32 DADiskCreateFromBSDName(kCFAllocatorDefault, session.get(), bsd_name)); | |
33 if (!disk.get()) | |
34 return NULL; | |
35 | |
36 base::mac::ScopedCFTypeRef<CFDictionaryRef> description( | |
37 DADiskCopyDescription(disk)); | |
38 if (!description.get()) | |
39 return NULL; | |
40 | |
41 CFURLRef mount_point = base::mac::GetValueFromDictionary<CFURLRef>( | |
42 description, kDADiskDescriptionVolumePathKey); | |
43 if (!mount_point) | |
44 return NULL; | |
45 | |
46 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.
| |
47 } | |
48 | |
49 bool GetDeviceInfo(unsigned long device_number, std::string* name, | |
50 FilePath* location) { | |
51 ICACopyObjectPropertyDictionaryPB properties_request; | |
52 properties_request.object = device_number; | |
53 CFDictionaryRef device_properties; | |
54 properties_request.theDict = &device_properties; | |
55 OSErr ret = ICACopyObjectPropertyDictionary(&properties_request, NULL); | |
56 base::mac::ScopedCFTypeRef<CFDictionaryRef> scoped_device_properties( | |
57 device_properties); | |
58 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.
| |
59 | |
60 CFStringRef device_name = base::mac::GetValueFromDictionary<CFStringRef>( | |
61 device_properties, kICAUserAssignedDeviceNameKey); | |
62 if (device_name == NULL) { | |
63 device_name = base::mac::GetValueFromDictionary<CFStringRef>( | |
64 device_properties, kICDeviceNameKey); | |
65 } | |
66 if (device_name == NULL) | |
67 return false; | |
68 *name = base::SysCFStringRefToUTF8(device_name); | |
69 | |
70 // TODO(vandebo) Support all media device, for now we only support mass | |
71 // storage media devices. | |
72 CFStringRef device = base::mac::GetValueFromDictionary<CFStringRef>( | |
73 device_properties, kICDeviceBSDNameKey); | |
74 if (device == NULL) | |
75 return false; | |
76 base::mac::ScopedCFTypeRef<CFStringRef> path( | |
77 CopyMountPointFromBSDName(base::SysCFStringRefToUTF8(device).c_str())); | |
78 if (path.get() == NULL) | |
79 return false; | |
80 | |
81 *location = FilePath(base::SysCFStringRefToUTF8(path).c_str()); | |
82 | |
83 return true; | |
84 } | |
85 | |
86 void MediaDeviceNotificationCallback(CFStringRef notification_type, | |
87 CFDictionaryRef notification_dictionary) { | |
88 bool attach = false; | |
89 if (CFEqual(notification_type, kICANotificationTypeDeviceAdded)) { | |
90 attach = true; | |
91 } else if (CFEqual(notification_type, kICANotificationTypeDeviceRemoved)) { | |
92 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
| |
93 } | |
94 | |
95 base::SystemMonitor* system_monitor = base::SystemMonitor::Get(); | |
96 | |
97 CFNumberRef device_number_object = | |
98 base::mac::GetValueFromDictionary<CFNumberRef>( | |
99 notification_dictionary, kICANotificationDeviceICAObjectKey); | |
100 unsigned long device_number = | |
101 [base::mac::CFToNSCast(device_number_object) unsignedLongValue]; | |
102 if (attach) { | |
103 std::string device_name; | |
104 FilePath location; | |
105 if (GetDeviceInfo(device_number, &device_name, &location)) { | |
106 system_monitor->ProcessMediaDeviceAttached(device_number, device_name, | |
107 location); | |
108 } | |
109 } else { | |
110 system_monitor->ProcessMediaDeviceDetached(device_number); | |
111 } | |
112 } | |
113 | |
114 } // namespace | |
115 | |
116 void StartMediaDeviceNotifications() { | |
117 NSArray* events_of_interest = [NSArray arrayWithObjects: | |
118 (id)kICANotificationTypeDeviceAdded, | |
119 (id)kICANotificationTypeDeviceRemoved, | |
120 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.
| |
121 | |
122 ICARegisterForEventNotificationPB notification_request; | |
123 notification_request.objectOfInterest = 0; // Zero means all objects | |
124 notification_request.eventsOfInterest = | |
125 base::mac::NSToCFCast(events_of_interest); | |
126 notification_request.notificationProc = &MediaDeviceNotificationCallback; | |
127 notification_request.options = NULL; | |
128 OSErr err = ICARegisterForEventNotification(¬ification_request, NULL); | |
129 CHECK_EQ(err, noErr); | |
130 } | |
131 | |
132 } // namespace content | |
OLD | NEW |