• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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 "chrome/browser/extensions/api/image_writer_private/removable_storage_provider.h"
6 
7 #include <CoreFoundation/CoreFoundation.h>
8 #include <IOKit/storage/IOBlockStorageDevice.h>
9 #include <IOKit/IOBSD.h>
10 #include <IOKit/IOKitLib.h>
11 #include <IOKit/storage/IOMedia.h>
12 #include <IOKit/storage/IOStorageProtocolCharacteristics.h>
13 
14 #include "base/mac/foundation_util.h"
15 #include "base/mac/scoped_cftyperef.h"
16 #include "base/mac/scoped_ioobject.h"
17 #include "base/strings/sys_string_conversions.h"
18 #include "base/threading/thread_restrictions.h"
19 
20 namespace extensions {
21 
22 // static
PopulateDeviceList(scoped_refptr<StorageDeviceList> device_list)23 bool RemovableStorageProvider::PopulateDeviceList(
24     scoped_refptr<StorageDeviceList> device_list) {
25   base::ThreadRestrictions::AssertIOAllowed();
26   // Match only removable, ejectable, non-internal, whole disks.
27   CFMutableDictionaryRef matching = IOServiceMatching(kIOMediaClass);
28   CFDictionaryAddValue(matching, CFSTR(kIOMediaWholeKey), kCFBooleanTrue);
29   CFDictionaryAddValue(matching, CFSTR(kIOMediaEjectableKey), kCFBooleanTrue);
30   CFDictionaryAddValue(matching, CFSTR(kIOMediaRemovableKey), kCFBooleanTrue);
31   CFDictionaryAddValue(matching, CFSTR(kIOMediaWritableKey), kCFBooleanTrue);
32 
33   io_service_t disk_iterator;
34   if (IOServiceGetMatchingServices(
35           kIOMasterPortDefault, matching, &disk_iterator) != KERN_SUCCESS) {
36     LOG(ERROR) << "Unable to get disk services.";
37     return false;
38   }
39   base::mac::ScopedIOObject<io_service_t> iterator_ref(disk_iterator);
40 
41   io_object_t disk_obj;
42   while ((disk_obj = IOIteratorNext(disk_iterator))) {
43     base::mac::ScopedIOObject<io_object_t> disk_obj_ref(disk_obj);
44 
45     CFMutableDictionaryRef dict;
46     if (IORegistryEntryCreateCFProperties(
47             disk_obj, &dict, kCFAllocatorDefault, 0) != KERN_SUCCESS) {
48       LOG(ERROR) << "Unable to get properties of disk object.";
49       continue;
50     }
51     base::ScopedCFTypeRef<CFMutableDictionaryRef> dict_ref(dict);
52 
53     CFStringRef cf_bsd_name = base::mac::GetValueFromDictionary<CFStringRef>(
54         dict, CFSTR(kIOBSDNameKey));
55     std::string bsd_name = base::SysCFStringRefToUTF8(cf_bsd_name);
56 
57     CFNumberRef size_number = base::mac::GetValueFromDictionary<CFNumberRef>(
58         dict, CFSTR(kIOMediaSizeKey));
59     uint64 size_in_bytes = 0;
60     if (size_number)
61       CFNumberGetValue(size_number, kCFNumberLongLongType, &size_in_bytes);
62 
63     base::ScopedCFTypeRef<CFDictionaryRef> characteristics(
64         static_cast<CFDictionaryRef>(IORegistryEntrySearchCFProperty(
65             disk_obj,
66             kIOServicePlane,
67             CFSTR(kIOPropertyDeviceCharacteristicsKey),
68             kCFAllocatorDefault,
69             kIORegistryIterateParents | kIORegistryIterateRecursively)));
70 
71     if (characteristics == NULL) {
72       LOG(ERROR) << "Unable to find device characteristics for " << cf_bsd_name;
73       continue;
74     }
75 
76     CFStringRef cf_vendor = base::mac::GetValueFromDictionary<CFStringRef>(
77         characteristics, CFSTR(kIOPropertyVendorNameKey));
78     std::string vendor = base::SysCFStringRefToUTF8(cf_vendor);
79 
80     CFStringRef cf_model = base::mac::GetValueFromDictionary<CFStringRef>(
81         characteristics, CFSTR(kIOPropertyProductNameKey));
82     std::string model = base::SysCFStringRefToUTF8(cf_model);
83 
84     linked_ptr<api::image_writer_private::RemovableStorageDevice> device(
85         new api::image_writer_private::RemovableStorageDevice());
86     device->storage_unit_id = bsd_name;
87     device->capacity = size_in_bytes;
88     device->vendor = vendor;
89     device->model = model;
90     device_list->data.push_back(device);
91   }
92 
93   return true;
94 }
95 
96 } // namespace extensions
97