1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/api/music_manager_private/device_id.h"
7 #include <CoreFoundation/CoreFoundation.h>
8 #include <DiskArbitration/DASession.h>
9 #include <DiskArbitration/DADisk.h>
10 #include <sys/mount.h>
12 #include "base/bind.h"
13 #include "base/mac/foundation_util.h"
14 #include "base/mac/scoped_cftyperef.h"
15 #include "base/strings/sys_string_conversions.h"
16 #include "content/public/browser/browser_thread.h"
20 const char kRootDirectory[] = "/";
22 // Return the BSD name (e.g. '/dev/disk1') of the root directory by enumerating
23 // through the mounted volumes .
24 // Return "" if an error occured.
25 std::string FindBSDNameOfSystemDisk() {
26 struct statfs* mounted_volumes;
27 int num_volumes = getmntinfo(&mounted_volumes, 0);
28 if (num_volumes == 0) {
29 VLOG(1) << "Cannot enumerate list of mounted volumes.";
33 for (int i = 0; i < num_volumes; i++) {
34 struct statfs* vol = &mounted_volumes[i];
35 if (std::string(vol->f_mntonname) == kRootDirectory) {
36 return std::string(vol->f_mntfromname);
40 VLOG(1) << "Cannot find disk mounted as '" << kRootDirectory << "'.";
44 // Return the Volume UUID property of a BSD disk name (e.g. '/dev/disk1').
45 // Return "" if an error occured.
46 std::string GetVolumeUUIDFromBSDName(const std::string& bsd_name) {
47 const CFAllocatorRef allocator = NULL;
49 base::ScopedCFTypeRef<DASessionRef> session(DASessionCreate(allocator));
50 if (session.get() == NULL) {
51 VLOG(1) << "Error creating DA Session.";
55 base::ScopedCFTypeRef<DADiskRef> disk(
56 DADiskCreateFromBSDName(allocator, session, bsd_name.c_str()));
57 if (disk.get() == NULL) {
58 VLOG(1) << "Error creating DA disk from BSD disk name.";
62 base::ScopedCFTypeRef<CFDictionaryRef> disk_description(
63 DADiskCopyDescription(disk));
64 if (disk_description.get() == NULL) {
65 VLOG(1) << "Error getting disk description.";
69 CFUUIDRef volume_uuid = base::mac::GetValueFromDictionary<CFUUIDRef>(
71 kDADiskDescriptionVolumeUUIDKey);
72 if (volume_uuid == NULL) {
73 VLOG(1) << "Error getting volume UUID of disk.";
77 base::ScopedCFTypeRef<CFStringRef> volume_uuid_string(
78 CFUUIDCreateString(allocator, volume_uuid));
79 if (volume_uuid_string.get() == NULL) {
80 VLOG(1) << "Error creating string from CSStringRef.";
84 return base::SysCFStringRefToUTF8(volume_uuid_string.get());
87 // Return Volume UUID property of disk mounted as "/".
88 void GetVolumeUUID(const extensions::api::DeviceId::IdCallback& callback) {
89 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
92 std::string bsd_name = FindBSDNameOfSystemDisk();
93 if (!bsd_name.empty()) {
94 VLOG(4) << "BSD name of root directory: '" << bsd_name << "'";
95 result = GetVolumeUUIDFromBSDName(bsd_name);
97 content::BrowserThread::PostTask(
98 content::BrowserThread::UI,
100 base::Bind(callback, result));
105 namespace extensions {
108 // MacOS: Return Volume UUID property of disk mounted as "/".
110 void DeviceId::GetMachineId(const IdCallback& callback) {
111 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
113 content::BrowserThread::PostTask(
114 content::BrowserThread::FILE,
116 base::Bind(GetVolumeUUID, callback));
120 } // namespace extensions