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

Unified Diff: chrome/browser/extensions/api/image_writer_private/removable_storage_provider_mac.cc

Issue 291333006: Adds removable-drive listing for OS X. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Removes unnecessary changes. Created 6 years, 7 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: chrome/browser/extensions/api/image_writer_private/removable_storage_provider_mac.cc
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 f227dde49e3e4ad9c34922be154df2c1b82a80ba..98b4e568eb91adfff1a4c2efc1638c372e5a4153 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
@@ -2,13 +2,190 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <IOKit/storage/IOStorageProtocolCharacteristics.h>
+
+#include "base/strings/sys_string_conversions.h"
#include "chrome/browser/extensions/api/image_writer_private/removable_storage_provider.h"
+#include "content/public/browser/browser_thread.h"
namespace extensions {
-bool RemovableStorageProvider::PopulateDeviceList(
+void RemovableStorageProvider::GetAllDevicesImpl(
+ const DeviceListReadyCallback& callback) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+ DAWrapper* da_wrapper = new DAWrapper();
Robert Sesek 2014/06/02 19:56:05 Comment about ownership.
Drew Haven 2014/06/03 02:03:23 I wasn't sure how to address this exactly. We get
+ da_wrapper->GetDeviceList(
+ base::Bind(DAWrapper::WrapperDeleter, da_wrapper, callback));
+}
+
+DAWrapper::DAWrapper() : updates_pending_(0), callback_() {
+}
+
+DAWrapper::~DAWrapper() {
+ if (session_.get()) {
+ DASessionUnscheduleFromRunLoop(
+ session_, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
+ }
+}
+
+void DAWrapper::GetDeviceList(const DeviceListReadyCallback& callback) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+ device_list_ = new StorageDeviceList;
+ callback_ = callback;
+
+ session_.reset(DASessionCreate(NULL));
+
+ DARegisterDiskAppearedCallback(
+ session_, kDADiskDescriptionMatchMediaWhole, DiskAppearedCallback, this);
+ DARegisterDiskDisappearedCallback(session_,
+ kDADiskDescriptionMatchMediaWhole,
+ DiskDisappearedCallback,
+ this);
+ DASessionScheduleWithRunLoop(
+ session_, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
Robert Sesek 2014/06/02 19:56:05 Really? I thought you said this was going to execu
Drew Haven 2014/06/03 02:03:23 Discussed out of band. See general comment.
+}
+
+void DAWrapper::ProcessDisk(base::ScopedCFTypeRef<CFDictionaryRef> dict) {
+ updates_pending_++;
+ content::BrowserThread::PostTask(
Robert Sesek 2014/06/02 19:56:05 Why are you using message passing here? It's all b
Drew Haven 2014/06/03 02:03:23 The reason is because we get a bunch of DiskAppear
Robert Sesek 2014/06/04 19:10:43 But does that actually work as you describe? There
Drew Haven 2014/06/05 01:52:50 As far as I can tell this is entirely undocumented
Drew Haven 2014/06/09 23:13:02 I talked with Greg Billock who did the similar wor
Robert Sesek 2014/06/10 20:52:22 Then what is the rationale for not using storage m
+ content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&DAWrapper::AddDisk, AsWeakPtr(), dict));
+}
+
+void DAWrapper::AddDisk(base::ScopedCFTypeRef<CFDictionaryRef> dict) {
+ if (DiskIsValidTarget(dict.get())) {
+ CFStringRef cf_bsd_name = base::mac::GetValueFromDictionary<CFStringRef>(
+ dict, kDADiskDescriptionMediaBSDNameKey);
+ CFStringRef cf_vendor = base::mac::GetValueFromDictionary<CFStringRef>(
+ dict, kDADiskDescriptionDeviceVendorKey);
+ CFStringRef cf_model = base::mac::GetValueFromDictionary<CFStringRef>(
+ dict, kDADiskDescriptionDeviceModelKey);
+
+ std::string bsd_name = base::SysCFStringRefToUTF8(cf_bsd_name);
+ std::string vendor = base::SysCFStringRefToUTF8(cf_vendor);
+ std::string model = base::SysCFStringRefToUTF8(cf_model);
+
+ CFNumberRef size_number = base::mac::GetValueFromDictionary<CFNumberRef>(
+ dict, kDADiskDescriptionMediaSizeKey);
+ uint64 size_in_bytes = 0;
+ if (size_number)
+ CFNumberGetValue(size_number, kCFNumberLongLongType, &size_in_bytes);
+
+ linked_ptr<api::image_writer_private::RemovableStorageDevice> device(
+ new api::image_writer_private::RemovableStorageDevice());
+ device->storage_unit_id = bsd_name;
+ device->capacity = size_in_bytes;
+ device->vendor = vendor;
+ device->model = model;
+ device_list_->data.push_back(device);
+ }
+
+ updates_pending_--;
+
+ if (updates_pending_ == 0) {
+ callback_.Run(device_list_, true);
+ }
+}
+
+// static
+void DAWrapper::DiskAppearedCallback(DADiskRef disk, void* context) {
+ DAWrapper* wrapper = static_cast<DAWrapper*>(context);
+ base::ScopedCFTypeRef<CFDictionaryRef> dict(DADiskCopyDescription(disk));
+ wrapper->ProcessDisk(dict);
+}
+
+// static
+void DAWrapper::DiskDisappearedCallback(DADiskRef disk, void* context) {
+}
+
+// static
+bool DAWrapper::DiskIsValidTarget(CFDictionaryRef dict) {
+ CFBooleanRef internal = (CFBooleanRef)CFDictionaryGetValue(
Robert Sesek 2014/06/02 19:56:05 C-style casts are banned. Use GetValueFromDictiona
Drew Haven 2014/06/03 02:03:23 Done.
+ dict, kDADiskDescriptionDeviceInternalKey);
+ CFStringRef protocol = (CFStringRef)CFDictionaryGetValue(
+ dict, kDADiskDescriptionDeviceProtocolKey);
+ CFStringRef io_reg_path =
+ (CFStringRef)CFDictionaryGetValue(dict, kDADiskDescriptionDevicePathKey);
+ CFBooleanRef ejectable = (CFBooleanRef)CFDictionaryGetValue(
+ dict, kDADiskDescriptionMediaEjectableKey);
+ CFBooleanRef removable = (CFBooleanRef)CFDictionaryGetValue(
+ dict, kDADiskDescriptionMediaRemovableKey);
+ CFBooleanRef whole =
+ (CFBooleanRef)CFDictionaryGetValue(dict, kDADiskDescriptionMediaWholeKey);
+ CFStringRef kind =
+ (CFStringRef)CFDictionaryGetValue(dict, kDADiskDescriptionMediaKindKey);
+
+ // A drive is a USB stick iff:
+ // - it is not internal
+ // - it is attached to the USB bus
+ // - it is ejectable (because it will be ejected after written to)
+ // - it is removable
+ // - it is the whole drive (although the use of
+ // kDADiskDescriptionMatchMediaWhole should have ensured this)
+ // - it is of type IOMedia (external DVD drives and the like are IOCDMedia
+ // or
+ // IODVDMedia)
+ bool isUSBStick =
Robert Sesek 2014/06/02 19:56:05 naming: is_usb_stick
Drew Haven 2014/06/03 02:03:23 Done.
+ !CFBooleanGetValue(internal) &&
+ CFEqual(protocol, CFSTR(kIOPropertyPhysicalInterconnectTypeUSB)) &&
+ CFBooleanGetValue(ejectable) && CFBooleanGetValue(removable) &&
+ CFBooleanGetValue(whole) &&
+ CFStringCompare(kind, CFSTR("IOMedia"), 0) == kCFCompareEqualTo;
+
+ // A drive is an SD card iff:
+ // - it is attached to the USB bus
+ // - it is ejectable (because it will be ejected after written to)
+ // - it is removable
+ // - it is the whole drive (although the use of
+ // kDADiskDescriptionMatchMediaWhole should have ensured this)
+ // - it is of type IOMedia (external DVD drives and the like are IOCDMedia
+ // or
+ // IODVDMedia)
+ // - the IORegistry device path contains "AppleUSBCardReader"
+ bool isSDCard =
Robert Sesek 2014/06/02 19:56:05 naming: is_sd_card
Drew Haven 2014/06/03 02:03:23 Done.
+ CFEqual(protocol, CFSTR(kIOPropertyPhysicalInterconnectTypeUSB)) &&
+ CFBooleanGetValue(ejectable) && CFBooleanGetValue(removable) &&
+ CFBooleanGetValue(whole) &&
+ CFStringCompare(kind, CFSTR("IOMedia"), 0) == kCFCompareEqualTo &&
+ CFStringFind(io_reg_path, CFSTR("AppleUSBCardReader"), 0).location !=
+ kCFNotFound;
+
+ return isUSBStick || isSDCard;
+}
+
+// static
+void DAWrapper::WrapperDeleter(DAWrapper* wrapper,
+ const DeviceListReadyCallback& callback,
+ scoped_refptr<StorageDeviceList> device_list,
+ bool success) {
+ delete wrapper;
+ callback.Run(device_list, success);
+}
+
+DAWrapperSpouse::DAWrapperSpouse(DAWrapper* spouse) : spouse_(spouse) {
+}
+DAWrapperSpouse::~DAWrapperSpouse() {
+}
+
+void DAWrapperSpouse::SetCallback(const DeviceListReadyCallback& callback) {
+ spouse_->callback_ = callback;
+}
+
+void DAWrapperSpouse::SetDeviceList(
scoped_refptr<StorageDeviceList> device_list) {
- return false;
+ spouse_->device_list_ = device_list;
+}
+
+void DAWrapperSpouse::ProcessDisk(base::ScopedCFTypeRef<CFDictionaryRef> disk) {
+ spouse_->ProcessDisk(disk);
+}
+
+// static
+bool DAWrapperSpouse::DiskIsValidTarget(CFDictionaryRef dict) {
+ return DAWrapper::DiskIsValidTarget(dict);
}
} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698