blob: e66c0e2098f43c87a4653d0baaa586766c7e4dce [file] [log] [blame]
// Copyright 2013 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/browser/extensions/api/music_manager_private/device_id.h"
#include <CoreFoundation/CoreFoundation.h>
#include <DiskArbitration/DASession.h>
#include <DiskArbitration/DADisk.h>
#include <sys/mount.h>
#include "base/bind.h"
#include "base/mac/foundation_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/strings/sys_string_conversions.h"
#include "content/public/browser/browser_thread.h"
namespace {
const char kRootDirectory[] = "/";
// Return the BSD name (e.g. '/dev/disk1') of the root directory by enumerating
// through the mounted volumes .
// Return "" if an error occured.
std::string FindBSDNameOfSystemDisk() {
struct statfs* mounted_volumes;
int num_volumes = getmntinfo(&mounted_volumes, 0);
if (num_volumes == 0) {
VLOG(1) << "Cannot enumerate list of mounted volumes.";
return std::string();
}
for (int i = 0; i < num_volumes; i++) {
struct statfs* vol = &mounted_volumes[i];
if (std::string(vol->f_mntonname) == kRootDirectory) {
return std::string(vol->f_mntfromname);
}
}
VLOG(1) << "Cannot find disk mounted as '" << kRootDirectory << "'.";
return std::string();
}
// Return the Volume UUID property of a BSD disk name (e.g. '/dev/disk1').
// Return "" if an error occured.
std::string GetVolumeUUIDFromBSDName(const std::string& bsd_name) {
const CFAllocatorRef allocator = NULL;
base::ScopedCFTypeRef<DASessionRef> session(DASessionCreate(allocator));
if (session.get() == NULL) {
VLOG(1) << "Error creating DA Session.";
return std::string();
}
base::ScopedCFTypeRef<DADiskRef> disk(
DADiskCreateFromBSDName(allocator, session, bsd_name.c_str()));
if (disk.get() == NULL) {
VLOG(1) << "Error creating DA disk from BSD disk name.";
return std::string();
}
base::ScopedCFTypeRef<CFDictionaryRef> disk_description(
DADiskCopyDescription(disk));
if (disk_description.get() == NULL) {
VLOG(1) << "Error getting disk description.";
return std::string();
}
CFUUIDRef volume_uuid = base::mac::GetValueFromDictionary<CFUUIDRef>(
disk_description,
kDADiskDescriptionVolumeUUIDKey);
if (volume_uuid == NULL) {
VLOG(1) << "Error getting volume UUID of disk.";
return std::string();
}
base::ScopedCFTypeRef<CFStringRef> volume_uuid_string(
CFUUIDCreateString(allocator, volume_uuid));
if (volume_uuid_string.get() == NULL) {
VLOG(1) << "Error creating string from CSStringRef.";
return std::string();
}
return base::SysCFStringRefToUTF8(volume_uuid_string.get());
}
// Return Volume UUID property of disk mounted as "/".
void GetVolumeUUID(const extensions::api::DeviceId::IdCallback& callback) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
std::string result;
std::string bsd_name = FindBSDNameOfSystemDisk();
if (!bsd_name.empty()) {
VLOG(4) << "BSD name of root directory: '" << bsd_name << "'";
result = GetVolumeUUIDFromBSDName(bsd_name);
}
content::BrowserThread::PostTask(
content::BrowserThread::UI,
FROM_HERE,
base::Bind(callback, result));
}
}
namespace extensions {
namespace api {
// MacOS: Return Volume UUID property of disk mounted as "/".
/* static */
void DeviceId::GetMachineId(const IdCallback& callback) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
content::BrowserThread::PostTask(
content::BrowserThread::FILE,
FROM_HERE,
base::Bind(GetVolumeUUID, callback));
}
} // namespace api
} // namespace extensions