| Index: chrome/browser/metrics/drive_metrics_provider_mac.mm
|
| diff --git a/chrome/browser/metrics/drive_metrics_provider_mac.mm b/chrome/browser/metrics/drive_metrics_provider_mac.mm
|
| index ff98485df15b23257a75939ac01e4370e79ad3e6..565acd8c3e3f7da17f0465b089096d443c792761 100644
|
| --- a/chrome/browser/metrics/drive_metrics_provider_mac.mm
|
| +++ b/chrome/browser/metrics/drive_metrics_provider_mac.mm
|
| @@ -4,9 +4,71 @@
|
|
|
| #include "chrome/browser/metrics/drive_metrics_provider.h"
|
|
|
| +#include <CoreFoundation/CoreFoundation.h>
|
| +#include <DiskArbitration/DiskArbitration.h>
|
| +#include <Foundation/Foundation.h>
|
| +#include <IOKit/IOKitLib.h>
|
| +#include <IOKit/storage/IOStorageDeviceCharacteristics.h>
|
| +#include <stdlib.h>
|
| +#include <sys/stat.h>
|
| +
|
| +#include "base/files/file_path.h"
|
| +#include "base/mac/foundation_util.h"
|
| +#include "base/mac/mac_util.h"
|
| +#include "base/mac/scoped_cftyperef.h"
|
| +#include "base/mac/scoped_ioobject.h"
|
| +
|
| // static
|
| bool DriveMetricsProvider::HasSeekPenalty(const base::FilePath& path,
|
| bool* has_seek_penalty) {
|
| - // TODO(dbeam): implement.
|
| + struct stat path_stat;
|
| + if (stat(path.value().c_str(), &path_stat) < 0)
|
| + return false;
|
| +
|
| + const char* dev_name = devname(path_stat.st_dev, S_IFBLK);
|
| + if (!dev_name)
|
| + return false;
|
| +
|
| + std::string bsd_name("/dev/");
|
| + bsd_name.append(dev_name);
|
| +
|
| + base::ScopedCFTypeRef<DASessionRef> session(
|
| + DASessionCreate(kCFAllocatorDefault));
|
| + if (!session)
|
| + return false;
|
| +
|
| + base::ScopedCFTypeRef<DADiskRef> disk(DADiskCreateFromBSDName(
|
| + kCFAllocatorDefault, session, bsd_name.c_str()));
|
| + if (!disk)
|
| + return false;
|
| +
|
| + base::mac::ScopedIOObject<io_object_t> io_media(DADiskCopyIOMedia(disk));
|
| + base::ScopedCFTypeRef<CFDictionaryRef> characteristics(
|
| + static_cast<CFDictionaryRef>(IORegistryEntrySearchCFProperty(
|
| + io_media,
|
| + kIOServicePlane,
|
| + CFSTR(kIOPropertyDeviceCharacteristicsKey),
|
| + kCFAllocatorDefault,
|
| + kIORegistryIterateRecursively | kIORegistryIterateParents)));
|
| + if (!characteristics)
|
| + return false;
|
| +
|
| + CFStringRef type_ref = base::mac::GetValueFromDictionary<CFStringRef>(
|
| + characteristics, CFSTR(kIOPropertyMediumTypeKey));
|
| + if (!type_ref)
|
| + return false;
|
| +
|
| + NSString* type = base::mac::CFToNSCast(type_ref);
|
| + if ([type isEqualToString:@kIOPropertyMediumTypeRotationalKey]) {
|
| + *has_seek_penalty = true;
|
| + return true;
|
| + } else if ([type isEqualToString:@kIOPropertyMediumTypeSolidStateKey]) {
|
| + *has_seek_penalty = false;
|
| + return true;
|
| + }
|
| +
|
| + // TODO(dbeam): should I look for these Rotational/Solid State keys in
|
| + // |characteristics|? What if I find device characteristic but there's no
|
| + // type? Assume rotational?
|
| return false;
|
| }
|
|
|