158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// found in the LICENSE file. 458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 5d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "chrome/browser/extensions/api/image_writer_private/removable_storage_provider.h" 658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <CoreFoundation/CoreFoundation.h> 8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <IOKit/storage/IOBlockStorageDevice.h> 9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <IOKit/IOBSD.h> 10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <IOKit/IOKitLib.h> 11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <IOKit/storage/IOMedia.h> 12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <IOKit/storage/IOStorageProtocolCharacteristics.h> 13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/mac/foundation_util.h" 15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/mac/scoped_cftyperef.h" 16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/mac/scoped_ioobject.h" 17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/strings/sys_string_conversions.h" 18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/threading/thread_restrictions.h" 19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/common/extensions/image_writer/image_writer_util_mac.h" 20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 2158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace extensions { 2258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// static 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool RemovableStorageProvider::PopulateDeviceList( 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_refptr<StorageDeviceList> device_list) { 26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Match only writable whole-disks. 28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CFMutableDictionaryRef matching = IOServiceMatching(kIOMediaClass); 29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CFDictionaryAddValue(matching, CFSTR(kIOMediaWholeKey), kCFBooleanTrue); 30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CFDictionaryAddValue(matching, CFSTR(kIOMediaWritableKey), kCFBooleanTrue); 31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) io_service_t disk_iterator; 33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (IOServiceGetMatchingServices( 34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) kIOMasterPortDefault, matching, &disk_iterator) != KERN_SUCCESS) { 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LOG(ERROR) << "Unable to get disk services."; 36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::mac::ScopedIOObject<io_service_t> iterator_ref(disk_iterator); 39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) io_object_t disk_obj; 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) while ((disk_obj = IOIteratorNext(disk_iterator))) { 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::mac::ScopedIOObject<io_object_t> disk_obj_ref(disk_obj); 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CFMutableDictionaryRef dict; 45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (IORegistryEntryCreateCFProperties( 46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) disk_obj, &dict, kCFAllocatorDefault, 0) != KERN_SUCCESS) { 47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LOG(ERROR) << "Unable to get properties of disk object."; 48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) continue; 49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::ScopedCFTypeRef<CFMutableDictionaryRef> dict_ref(dict); 51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CFStringRef cf_bsd_name = base::mac::GetValueFromDictionary<CFStringRef>( 53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dict, CFSTR(kIOBSDNameKey)); 54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string bsd_name = base::SysCFStringRefToUTF8(cf_bsd_name); 55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CFNumberRef size_number = base::mac::GetValueFromDictionary<CFNumberRef>( 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dict, CFSTR(kIOMediaSizeKey)); 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) uint64 size_in_bytes = 0; 59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (size_number) 60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CFNumberGetValue(size_number, kCFNumberLongLongType, &size_in_bytes); 61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CFBooleanRef cf_removable = base::mac::GetValueFromDictionary<CFBooleanRef>( 63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch dict, CFSTR(kIOMediaRemovableKey)); 64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool removable = CFBooleanGetValue(cf_removable); 65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool is_usb = IsUsbDevice(disk_obj); 67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!removable && !is_usb) { 69116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch continue; 70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::ScopedCFTypeRef<CFDictionaryRef> characteristics( 73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) static_cast<CFDictionaryRef>(IORegistryEntrySearchCFProperty( 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) disk_obj, 75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) kIOServicePlane, 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CFSTR(kIOPropertyDeviceCharacteristicsKey), 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) kCFAllocatorDefault, 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) kIORegistryIterateParents | kIORegistryIterateRecursively))); 79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (characteristics == NULL) { 81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LOG(ERROR) << "Unable to find device characteristics for " << cf_bsd_name; 82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) continue; 83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CFStringRef cf_vendor = base::mac::GetValueFromDictionary<CFStringRef>( 86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) characteristics, CFSTR(kIOPropertyVendorNameKey)); 87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string vendor = base::SysCFStringRefToUTF8(cf_vendor); 88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CFStringRef cf_model = base::mac::GetValueFromDictionary<CFStringRef>( 90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) characteristics, CFSTR(kIOPropertyProductNameKey)); 91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string model = base::SysCFStringRefToUTF8(cf_model); 92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) linked_ptr<api::image_writer_private::RemovableStorageDevice> device( 94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) new api::image_writer_private::RemovableStorageDevice()); 95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) device->storage_unit_id = bsd_name; 96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) device->capacity = size_in_bytes; 97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) device->vendor = vendor; 98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) device->model = model; 996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) device->removable = removable; 100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) device_list->data.push_back(device); 101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} // namespace extensions 107