This source file includes following definitions.
- MakeDeviceUniqueId
- GetDeviceInfo
- CheckMountedPathOnFileThread
- Init
- CheckExistingMountPoints
- OnDiskEvent
- OnDeviceEvent
- OnMountEvent
- OnFormatEvent
- SetMediaTransferProtocolManagerForTest
- GetStorageInfoForPath
- NotifyUnmountResult
- EjectDevice
- media_transfer_protocol_manager
- AddMountedPath
- CreateInternal
#include "components/storage_monitor/storage_monitor_chromeos.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/storage_monitor/media_storage_util.h"
#include "components/storage_monitor/media_transfer_protocol_device_observer_linux.h"
#include "components/storage_monitor/removable_device_constants.h"
#include "content/public/browser/browser_thread.h"
#include "device/media_transfer_protocol/media_transfer_protocol_manager.h"
using chromeos::disks::DiskMountManager;
namespace storage_monitor {
namespace {
std::string MakeDeviceUniqueId(const DiskMountManager::Disk& disk) {
std::string uuid = disk.fs_uuid();
if (!uuid.empty())
return kFSUniqueIdPrefix + uuid;
const std::string& vendor = disk.vendor_id();
const std::string& product = disk.product_id();
if (vendor.empty() && product.empty())
return std::string();
return kVendorModelSerialPrefix + vendor + ":" + product + ":";
}
bool GetDeviceInfo(const DiskMountManager::MountPointInfo& mount_info,
bool has_dcim,
StorageInfo* info) {
DCHECK(info);
std::string source_path = mount_info.source_path;
const DiskMountManager::Disk* disk =
DiskMountManager::GetInstance()->FindDiskBySourcePath(source_path);
if (!disk || disk->device_type() == chromeos::DEVICE_TYPE_UNKNOWN)
return false;
std::string unique_id = MakeDeviceUniqueId(*disk);
base::string16 device_label = base::UTF8ToUTF16(disk->device_label());
MediaStorageUtil::RecordDeviceInfoHistogram(true, unique_id, device_label);
if (unique_id.empty())
return false;
StorageInfo::Type type = has_dcim ?
StorageInfo::REMOVABLE_MASS_STORAGE_WITH_DCIM :
StorageInfo::REMOVABLE_MASS_STORAGE_NO_DCIM;
*info = StorageInfo(StorageInfo::MakeDeviceId(type, unique_id),
mount_info.mount_path,
device_label,
base::UTF8ToUTF16(disk->vendor_name()),
base::UTF8ToUTF16(disk->product_name()),
disk->total_size_in_bytes());
return true;
}
bool CheckMountedPathOnFileThread(
const DiskMountManager::MountPointInfo& mount_info) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
return MediaStorageUtil::HasDcim(base::FilePath(mount_info.mount_path));
}
}
using content::BrowserThread;
StorageMonitorCros::StorageMonitorCros()
: weak_ptr_factory_(this) {
}
StorageMonitorCros::~StorageMonitorCros() {
DiskMountManager* manager = DiskMountManager::GetInstance();
if (manager) {
manager->RemoveObserver(this);
}
}
void StorageMonitorCros::Init() {
DCHECK(DiskMountManager::GetInstance());
DiskMountManager::GetInstance()->AddObserver(this);
CheckExistingMountPoints();
if (!media_transfer_protocol_manager_) {
scoped_refptr<base::MessageLoopProxy> loop_proxy;
media_transfer_protocol_manager_.reset(
device::MediaTransferProtocolManager::Initialize(loop_proxy));
}
media_transfer_protocol_device_observer_.reset(
new MediaTransferProtocolDeviceObserverLinux(
receiver(), media_transfer_protocol_manager_.get()));
}
void StorageMonitorCros::CheckExistingMountPoints() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
const DiskMountManager::MountPointMap& mount_point_map =
DiskMountManager::GetInstance()->mount_points();
for (DiskMountManager::MountPointMap::const_iterator it =
mount_point_map.begin(); it != mount_point_map.end(); ++it) {
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::FILE, FROM_HERE,
base::Bind(&CheckMountedPathOnFileThread, it->second),
base::Bind(&StorageMonitorCros::AddMountedPath,
weak_ptr_factory_.GetWeakPtr(), it->second));
}
BrowserThread::PostTaskAndReply(
BrowserThread::FILE, FROM_HERE,
base::Bind(&base::DoNothing),
base::Bind(&StorageMonitorCros::MarkInitialized,
weak_ptr_factory_.GetWeakPtr()));
}
void StorageMonitorCros::OnDiskEvent(DiskMountManager::DiskEvent event,
const DiskMountManager::Disk* disk) {}
void StorageMonitorCros::OnDeviceEvent(DiskMountManager::DeviceEvent event,
const std::string& device_path) {}
void StorageMonitorCros::OnMountEvent(
DiskMountManager::MountEvent event,
chromeos::MountError error_code,
const DiskMountManager::MountPointInfo& mount_info) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (mount_info.mount_type != chromeos::MOUNT_TYPE_DEVICE)
return;
if (error_code != chromeos::MOUNT_ERROR_NONE)
return;
if (mount_info.mount_condition != chromeos::disks::MOUNT_CONDITION_NONE)
return;
switch (event) {
case DiskMountManager::MOUNTING: {
if (ContainsKey(mount_map_, mount_info.mount_path)) {
NOTREACHED();
return;
}
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::FILE, FROM_HERE,
base::Bind(&CheckMountedPathOnFileThread, mount_info),
base::Bind(&StorageMonitorCros::AddMountedPath,
weak_ptr_factory_.GetWeakPtr(), mount_info));
break;
}
case DiskMountManager::UNMOUNTING: {
MountMap::iterator it = mount_map_.find(mount_info.mount_path);
if (it == mount_map_.end())
return;
receiver()->ProcessDetach(it->second.device_id());
mount_map_.erase(it);
break;
}
}
}
void StorageMonitorCros::OnFormatEvent(DiskMountManager::FormatEvent event,
chromeos::FormatError error_code,
const std::string& device_path) {}
void StorageMonitorCros::SetMediaTransferProtocolManagerForTest(
device::MediaTransferProtocolManager* test_manager) {
DCHECK(!media_transfer_protocol_manager_);
media_transfer_protocol_manager_.reset(test_manager);
}
bool StorageMonitorCros::GetStorageInfoForPath(
const base::FilePath& path,
StorageInfo* device_info) const {
DCHECK(device_info);
if (media_transfer_protocol_device_observer_->GetStorageInfoForPath(
path, device_info)) {
return true;
}
if (!path.IsAbsolute())
return false;
base::FilePath current = path;
while (!ContainsKey(mount_map_, current.value()) &&
current != current.DirName()) {
current = current.DirName();
}
MountMap::const_iterator info_it = mount_map_.find(current.value());
if (info_it == mount_map_.end())
return false;
*device_info = info_it->second;
return true;
}
void NotifyUnmountResult(
base::Callback<void(StorageMonitor::EjectStatus)> callback,
chromeos::MountError error_code) {
if (error_code == chromeos::MOUNT_ERROR_NONE)
callback.Run(StorageMonitor::EJECT_OK);
else
callback.Run(StorageMonitor::EJECT_FAILURE);
}
void StorageMonitorCros::EjectDevice(
const std::string& device_id,
base::Callback<void(EjectStatus)> callback) {
StorageInfo::Type type;
if (!StorageInfo::CrackDeviceId(device_id, &type, NULL)) {
callback.Run(EJECT_FAILURE);
return;
}
if (type == StorageInfo::MTP_OR_PTP) {
media_transfer_protocol_device_observer_->EjectDevice(device_id, callback);
return;
}
std::string mount_path;
for (MountMap::const_iterator info_it = mount_map_.begin();
info_it != mount_map_.end(); ++info_it) {
if (info_it->second.device_id() == device_id)
mount_path = info_it->first;
}
if (mount_path.empty()) {
callback.Run(EJECT_NO_SUCH_DEVICE);
return;
}
DiskMountManager* manager = DiskMountManager::GetInstance();
if (!manager) {
callback.Run(EJECT_FAILURE);
return;
}
manager->UnmountPath(mount_path, chromeos::UNMOUNT_OPTIONS_NONE,
base::Bind(NotifyUnmountResult, callback));
}
device::MediaTransferProtocolManager*
StorageMonitorCros::media_transfer_protocol_manager() {
return media_transfer_protocol_manager_.get();
}
void StorageMonitorCros::AddMountedPath(
const DiskMountManager::MountPointInfo& mount_info,
bool has_dcim) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (ContainsKey(mount_map_, mount_info.mount_path)) {
return;
}
StorageInfo info;
if (!GetDeviceInfo(mount_info, has_dcim, &info))
return;
if (info.device_id().empty())
return;
mount_map_.insert(std::make_pair(mount_info.mount_path, info));
receiver()->ProcessAttach(info);
}
StorageMonitor* StorageMonitor::CreateInternal() {
return new StorageMonitorCros();
}
}