15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/storage_monitor/media_storage_util.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/storage_monitor/removable_device_constants.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/storage_monitor/storage_monitor.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace storage_monitor {
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MediaDeviceNotification.DeviceInfo histogram values.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum DeviceInfoHistogramBuckets {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MASS_STORAGE_DEVICE_NAME_AND_UUID_AVAILABLE,
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MASS_STORAGE_DEVICE_UUID_MISSING,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MASS_STORAGE_DEVICE_NAME_MISSING,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MASS_STORAGE_DEVICE_NAME_AND_UUID_MISSING,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MTP_STORAGE_DEVICE_NAME_AND_UUID_AVAILABLE,
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MTP_STORAGE_DEVICE_UUID_MISSING,
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MTP_STORAGE_DEVICE_NAME_MISSING,
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MTP_STORAGE_DEVICE_NAME_AND_UUID_MISSING,
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEVICE_INFO_BUCKET_BOUNDARY
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(OS_WIN)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kRootPath[] = "/";
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef std::vector<StorageInfo> StorageInfoList;
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath::StringType FindRemovableStorageLocationById(
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& device_id) {
467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  StorageInfoList devices =
477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      StorageMonitor::GetInstance()->GetAllAvailableStorages();
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (StorageInfoList::const_iterator it = devices.begin();
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != devices.end(); ++it) {
507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (it->device_id() == device_id
517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        && StorageInfo::IsRemovableDevice(device_id))
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return it->location();
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base::FilePath::StringType();
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FilterAttachedDevicesOnFileThread(MediaStorageUtil::DeviceIdSet* devices) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MediaStorageUtil::DeviceIdSet missing_devices;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (MediaStorageUtil::DeviceIdSet::const_iterator it = devices->begin();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != devices->end();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    StorageInfo::Type type;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string unique_id;
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!StorageInfo::CrackDeviceId(*it, &type, &unique_id)) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      missing_devices.insert(*it);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (type == StorageInfo::FIXED_MASS_STORAGE ||
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        type == StorageInfo::ITUNES ||
734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        type == StorageInfo::IPHOTO ||
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        type == StorageInfo::PICASA) {
757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      if (!base::PathExists(base::FilePath::FromUTF8Unsafe(unique_id)))
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        missing_devices.insert(*it);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (!MediaStorageUtil::IsRemovableStorageAttached(*it))
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      missing_devices.insert(*it);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (MediaStorageUtil::DeviceIdSet::const_iterator it =
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           missing_devices.begin();
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != missing_devices.end();
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    devices->erase(*it);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool MediaStorageUtil::HasDcim(const base::FilePath& mount_point) {
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath::StringType dcim_dir(kDCIMDirectoryName);
997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!base::DirectoryExists(mount_point.Append(dcim_dir))) {
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Check for lowercase 'dcim' as well.
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath dcim_path_lower(
1026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        mount_point.Append(base::StringToLowerASCII(dcim_dir)));
1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (!base::DirectoryExists(dcim_path_lower))
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool MediaStorageUtil::CanCreateFileSystem(const std::string& device_id,
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           const base::FilePath& path) {
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  StorageInfo::Type type;
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!StorageInfo::CrackDeviceId(device_id, &type, NULL))
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (type == StorageInfo::MAC_IMAGE_CAPTURE)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
119effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return !path.empty() && path.IsAbsolute() && !path.ReferencesParent();
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStorageUtil::FilterAttachedDevices(DeviceIdSet* devices,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const base::Closure& done) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FilterAttachedDevicesOnFileThread(devices);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    done.Run();
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTaskAndReply(BrowserThread::FILE,
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  FROM_HERE,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  base::Bind(&FilterAttachedDevicesOnFileThread,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             devices),
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  done);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(kmadhusu) Write unit tests for GetDeviceInfoFromPath().
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool MediaStorageUtil::GetDeviceInfoFromPath(const base::FilePath& path,
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             StorageInfo* device_info,
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             base::FilePath* relative_path) {
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(device_info);
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(relative_path);
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!path.IsAbsolute())
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StorageInfo info;
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StorageMonitor* monitor = StorageMonitor::GetInstance();
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool found_device = monitor->GetStorageInfoForPath(path, &info);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (found_device && StorageInfo::IsRemovableDevice(info.device_id())) {
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath sub_folder_path;
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::FilePath device_path(info.location());
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (path != device_path) {
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool success = device_path.AppendRelativePath(path, &sub_folder_path);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(success);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    *device_info = info;
16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    *relative_path = sub_folder_path;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On Posix systems, there's one root so any absolute path could be valid.
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // TODO(gbillock): Delete this stanza? Posix systems should have the root
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // volume information. If not, we should move the below into the
16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // right GetStorageInfoForPath implementations.
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_POSIX)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!found_device)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Handle non-removable devices. Note: this is just overwriting
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // good values from StorageMonitor.
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(gbillock): Make sure return values from that class are definitive,
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // and don't do this here.
17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  info.set_device_id(
17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      StorageInfo::MakeDeviceId(StorageInfo::FIXED_MASS_STORAGE,
17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                path.AsUTF8Unsafe()));
18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  *device_info = info;
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  *relative_path = base::FilePath();
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath MediaStorageUtil::FindDevicePathById(
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& device_id) {
18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  StorageInfo::Type type;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string unique_id;
19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!StorageInfo::CrackDeviceId(device_id, &type, &unique_id))
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::FilePath();
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (type == StorageInfo::FIXED_MASS_STORAGE ||
19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      type == StorageInfo::ITUNES ||
1954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      type == StorageInfo::IPHOTO ||
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      type == StorageInfo::PICASA) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For this type, the unique_id is the path.
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::FilePath::FromUTF8Unsafe(unique_id);
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // For ImageCapture, the synthetic filesystem will be rooted at a fake
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // top-level directory which is the device_id.
20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (type == StorageInfo::MAC_IMAGE_CAPTURE) {
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(OS_WIN)
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::FilePath(kRootPath + device_id);
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(type == StorageInfo::MTP_OR_PTP ||
21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         type == StorageInfo::REMOVABLE_MASS_STORAGE_WITH_DCIM ||
21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         type == StorageInfo::REMOVABLE_MASS_STORAGE_NO_DCIM);
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base::FilePath(FindRemovableStorageLocationById(device_id));
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaStorageUtil::RecordDeviceInfoHistogram(
217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    bool mass_storage,
218a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const std::string& device_uuid,
219a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& device_label) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int event_number = 0;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!mass_storage)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event_number = 4;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
224b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (device_label.empty())
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event_number += 2;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (device_uuid.empty())
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event_number += 1;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum DeviceInfoHistogramBuckets event =
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<enum DeviceInfoHistogramBuckets>(event_number);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (event >= DEVICE_INFO_BUCKET_BOUNDARY) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("MediaDeviceNotifications.DeviceInfo", event,
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            DEVICE_INFO_BUCKET_BOUNDARY);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool MediaStorageUtil::IsRemovableStorageAttached(const std::string& id) {
240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StorageInfoList devices =
241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      StorageMonitor::GetInstance()->GetAllAvailableStorages();
242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (StorageInfoList::const_iterator it = devices.begin();
243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       it != devices.end(); ++it) {
244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (StorageInfo::IsRemovableDevice(id) && it->device_id() == id)
245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return true;
246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return false;
248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace storage_monitor
251