diff options
author | haven@chromium.org <haven@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-09 23:11:14 +0000 |
---|---|---|
committer | haven@chromium.org <haven@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-09 23:11:14 +0000 |
commit | 6f584585d97c0ecc5ec0a5071f6e70cae3291e61 (patch) | |
tree | fd99f5be972768ccf5a54d9a5a4310d8bac9d6b5 | |
parent | 8589e7d6a49c2af9872d84bd8511998b5f436ed3 (diff) | |
download | chromium_src-6f584585d97c0ecc5ec0a5071f6e70cae3291e61.zip chromium_src-6f584585d97c0ecc5ec0a5071f6e70cae3291e61.tar.gz chromium_src-6f584585d97c0ecc5ec0a5071f6e70cae3291e61.tar.bz2 |
Changes Mac removable device listing to include all attached USB drives.
Some drives do not report themselves as removable despite appearing to a user to be a removable drive. Particularly this is the case for some USB sticks. We are fixing this by changing the device listing to list all drives that are either removable or attached via USB. We have already done a similar change for Chrome OS due to some SD card readers listing themselves as non-removable. Chrome OS lists all SD or USB drives. However, we do not have a reliable way to detect SD cards on Windows and Mac so we will continue to use the removable flag.
BUG=391998
Review URL: https://codereview.chromium.org/375703004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@282166 0039d316-1c4b-4281-b951-d872f2087c98
6 files changed, 114 insertions, 32 deletions
diff --git a/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_mac.cc b/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_mac.cc index 67c8ab6..a47c63c 100644 --- a/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_mac.cc +++ b/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_mac.cc @@ -16,6 +16,7 @@ #include "base/mac/scoped_ioobject.h" #include "base/strings/sys_string_conversions.h" #include "base/threading/thread_restrictions.h" +#include "chrome/common/extensions/image_writer/image_writer_util_mac.h" namespace extensions { @@ -23,11 +24,9 @@ namespace extensions { bool RemovableStorageProvider::PopulateDeviceList( scoped_refptr<StorageDeviceList> device_list) { base::ThreadRestrictions::AssertIOAllowed(); - // Match only removable, ejectable, non-internal, whole disks. + // Match only writable whole-disks. CFMutableDictionaryRef matching = IOServiceMatching(kIOMediaClass); CFDictionaryAddValue(matching, CFSTR(kIOMediaWholeKey), kCFBooleanTrue); - CFDictionaryAddValue(matching, CFSTR(kIOMediaEjectableKey), kCFBooleanTrue); - CFDictionaryAddValue(matching, CFSTR(kIOMediaRemovableKey), kCFBooleanTrue); CFDictionaryAddValue(matching, CFSTR(kIOMediaWritableKey), kCFBooleanTrue); io_service_t disk_iterator; @@ -60,6 +59,16 @@ bool RemovableStorageProvider::PopulateDeviceList( if (size_number) CFNumberGetValue(size_number, kCFNumberLongLongType, &size_in_bytes); + CFBooleanRef cf_removable = base::mac::GetValueFromDictionary<CFBooleanRef>( + dict, CFSTR(kIOMediaRemovableKey)); + bool removable = CFBooleanGetValue(cf_removable); + + bool is_usb = IsUsbDevice(disk_obj); + + if (!removable && !is_usb) { + continue; + } + base::ScopedCFTypeRef<CFDictionaryRef> characteristics( static_cast<CFDictionaryRef>(IORegistryEntrySearchCFProperty( disk_obj, diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi index 11a1afc..fd3380d 100644 --- a/chrome/chrome_common.gypi +++ b/chrome/chrome_common.gypi @@ -91,6 +91,8 @@ 'common/extensions/features/chrome_channel_feature_filter.h', 'common/extensions/features/feature_channel.cc', 'common/extensions/features/feature_channel.h', + 'common/extensions/image_writer/image_writer_util_mac.cc', + 'common/extensions/image_writer/image_writer_util_mac.h', 'common/extensions/manifest_handlers/app_isolation_info.cc', 'common/extensions/manifest_handlers/app_isolation_info.h', 'common/extensions/manifest_handlers/app_launch_info.cc', diff --git a/chrome/common/extensions/image_writer/OWNERS b/chrome/common/extensions/image_writer/OWNERS new file mode 100644 index 0000000..0847ff8 --- /dev/null +++ b/chrome/common/extensions/image_writer/OWNERS @@ -0,0 +1,2 @@ +haven@chromium.org +miket@chromium.org diff --git a/chrome/common/extensions/image_writer/image_writer_util_mac.cc b/chrome/common/extensions/image_writer/image_writer_util_mac.cc new file mode 100644 index 0000000..70f4460 --- /dev/null +++ b/chrome/common/extensions/image_writer/image_writer_util_mac.cc @@ -0,0 +1,42 @@ +// Copyright 2014 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 "chrome/common/extensions/image_writer/image_writer_util_mac.h" + +#include <CoreFoundation/CoreFoundation.h> + +#include "base/mac/scoped_cftyperef.h" +#include "base/mac/scoped_ioobject.h" + +namespace extensions { + +bool IsUsbDevice(io_object_t disk_obj) { + io_object_t current_obj = disk_obj; + io_object_t parent_obj = 0; + // Keep scoped object outside the loop so the object lives to the next + // GetParentEntry. + base::mac::ScopedIOObject<io_object_t> parent_obj_ref(parent_obj); + + while ((IORegistryEntryGetParentEntry( + current_obj, kIOServicePlane, &parent_obj)) == KERN_SUCCESS) { + current_obj = parent_obj; + parent_obj_ref.reset(parent_obj); + + base::ScopedCFTypeRef<CFStringRef> class_name( + IOObjectCopyClass(current_obj)); + if (!class_name) { + LOG(ERROR) << "Could not get object class of IO Registry Entry."; + continue; + } + + if (CFStringCompare(class_name.get(), CFSTR("IOUSBMassStorageClass"), 0) == + kCFCompareEqualTo) { + return true; + } + } + + return false; +} + +} // namespace extensions diff --git a/chrome/common/extensions/image_writer/image_writer_util_mac.h b/chrome/common/extensions/image_writer/image_writer_util_mac.h new file mode 100644 index 0000000..5b1c82c --- /dev/null +++ b/chrome/common/extensions/image_writer/image_writer_util_mac.h @@ -0,0 +1,19 @@ +// Copyright 2014 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. + +#ifndef CHROME_COMMON_EXTENSIONS_IMAGE_WRITER_IMAGE_WRITER_UTIL_MAC_H +#define CHROME_COMMON_EXTENSIONS_IMAGE_WRITER_IMAGE_WRITER_UTIL_MAC_H + +#include <IOKit/IOKitLib.h> + +namespace extensions { + +// Determines whether the object from the IO registry is a USB mass storage +// device. It does this by reading the ancestors of the object to see if any +// is of the USB mass-storage class. +bool IsUsbDevice(io_object_t disk_obj); + +} // namespace extensions + +#endif // CHROME_COMMON_EXTENSIONS_IMAGE_WRITER_IMAGE_WRITER_UTIL_MAC_H diff --git a/chrome/utility/image_writer/image_writer_mac.cc b/chrome/utility/image_writer/image_writer_mac.cc index 0935a5a..c572d14 100644 --- a/chrome/utility/image_writer/image_writer_mac.cc +++ b/chrome/utility/image_writer/image_writer_mac.cc @@ -2,15 +2,24 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <CoreFoundation/CoreFoundation.h> +#include <IOKit/IOBSD.h> +#include <IOKit/IOKitLib.h> +#include <IOKit/storage/IOBlockStorageDevice.h> +#include <IOKit/storage/IOMedia.h> #include <IOKit/storage/IOStorageProtocolCharacteristics.h> #include <sys/socket.h> #include "base/command_line.h" #include "base/files/scoped_file.h" +#include "base/mac/scoped_cftyperef.h" +#include "base/mac/scoped_ioobject.h" #include "base/posix/eintr_wrapper.h" #include "base/process/kill.h" #include "base/process/launch.h" #include "base/strings/stringprintf.h" +#include "base/strings/sys_string_conversions.h" +#include "chrome/common/extensions/image_writer/image_writer_util_mac.h" #include "chrome/utility/image_writer/disk_unmounter_mac.h" #include "chrome/utility/image_writer/error_messages.h" #include "chrome/utility/image_writer/image_writer.h" @@ -20,37 +29,36 @@ namespace image_writer { static const char kAuthOpenPath[] = "/usr/libexec/authopen"; bool ImageWriter::IsValidDevice() { - base::ScopedCFTypeRef<DASessionRef> session(DASessionCreate(NULL)); - base::ScopedCFTypeRef<DADiskRef> disk(DADiskCreateFromBSDName( - kCFAllocatorDefault, session, device_path_.value().c_str())); + base::ScopedCFTypeRef<CFStringRef> cf_bsd_name( + base::SysUTF8ToCFStringRef(device_path_.value())); + CFMutableDictionaryRef matching = IOServiceMatching(kIOMediaClass); + CFDictionaryAddValue(matching, CFSTR(kIOMediaWholeKey), kCFBooleanTrue); + CFDictionaryAddValue(matching, CFSTR(kIOMediaWritableKey), kCFBooleanTrue); + CFDictionaryAddValue(matching, CFSTR(kIOBSDNameKey), cf_bsd_name); + + io_service_t disk_obj = + IOServiceGetMatchingService(kIOMasterPortDefault, matching); + base::mac::ScopedIOObject<io_service_t> iterator_ref(disk_obj); + + if (disk_obj) { + CFMutableDictionaryRef dict; + if (IORegistryEntryCreateCFProperties( + disk_obj, &dict, kCFAllocatorDefault, 0) != KERN_SUCCESS) { + LOG(ERROR) << "Unable to get properties of disk object."; + return false; + } + base::ScopedCFTypeRef<CFMutableDictionaryRef> dict_ref(dict); - if (!disk) - return false; + CFBooleanRef cf_removable = base::mac::GetValueFromDictionary<CFBooleanRef>( + dict, CFSTR(kIOMediaRemovableKey)); + bool removable = CFBooleanGetValue(cf_removable); + + bool is_usb = extensions::IsUsbDevice(disk_obj); + + return removable || is_usb; + } - base::ScopedCFTypeRef<CFDictionaryRef> disk_description( - DADiskCopyDescription(disk)); - - CFBooleanRef ejectable = base::mac::GetValueFromDictionary<CFBooleanRef>( - disk_description, kDADiskDescriptionMediaEjectableKey); - CFBooleanRef removable = base::mac::GetValueFromDictionary<CFBooleanRef>( - disk_description, kDADiskDescriptionMediaRemovableKey); - CFBooleanRef writable = base::mac::GetValueFromDictionary<CFBooleanRef>( - disk_description, kDADiskDescriptionMediaWritableKey); - CFBooleanRef whole = base::mac::GetValueFromDictionary<CFBooleanRef>( - disk_description, kDADiskDescriptionMediaWholeKey); - CFStringRef kind = base::mac::GetValueFromDictionary<CFStringRef>( - disk_description, kDADiskDescriptionMediaKindKey); - - // A drive is valid if it is - // - ejectable - // - removable - // - writable - // - a whole drive - // - it is of type IOMedia (external DVD drives and the like are IOCDMedia or - // IODVDMedia) - return CFBooleanGetValue(ejectable) && CFBooleanGetValue(removable) && - CFBooleanGetValue(writable) && CFBooleanGetValue(whole) && - CFStringCompare(kind, CFSTR("IOMedia"), 0) == kCFCompareEqualTo; + return false; } void ImageWriter::UnmountVolumes(const base::Closure& continuation) { |