// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/storage_monitor/mtp_manager_client_chromeos.h"
#include <utility>
#include "base/containers/contains.h"
#include "base/functional/bind.h"
#include "base/strings/utf_string_conversions.h"
#include "components/storage_monitor/storage_info.h"
#include "components/storage_monitor/storage_info_utils.h"
namespace storage_monitor {
MtpManagerClientChromeOS::MtpManagerClientChromeOS(
StorageMonitor::Receiver* receiver,
device::mojom::MtpManager* mtp_manager)
: mtp_manager_(mtp_manager), notifications_(receiver) {
mtp_manager_->EnumerateStoragesAndSetClient(
receiver_.BindNewEndpointAndPassRemote(),
base::BindOnce(&MtpManagerClientChromeOS::OnReceivedStorages,
weak_ptr_factory_.GetWeakPtr()));
}
MtpManagerClientChromeOS::~MtpManagerClientChromeOS() {}
bool MtpManagerClientChromeOS::GetStorageInfoForPath(
const base::FilePath& path,
StorageInfo* storage_info) const {
DCHECK(storage_info);
if (!path.IsAbsolute())
return false;
std::vector<base::FilePath::StringType> path_components =
path.GetComponents();
if (path_components.size() < 2)
return false;
// First and second component of the path specifies the device location.
// E.g.: If |path| is "/usb:2,2:65537/DCIM/Folder_a", "/usb:2,2:65537" is the
// device location.
const auto info_it =
storage_map_.find(GetDeviceLocationFromStorageName(path_components[1]));
if (info_it == storage_map_.end())
return false;
*storage_info = info_it->second;
return true;
}
void MtpManagerClientChromeOS::EjectDevice(
const std::string& device_id,
base::OnceCallback<void(StorageMonitor::EjectStatus)> callback) {
std::string location;
if (!GetLocationForDeviceId(device_id, &location)) {
std::move(callback).Run(StorageMonitor::EJECT_NO_SUCH_DEVICE);
return;
}
// TODO(thestig): Change this to tell the MTP manager to eject the device.
StorageDetached(location);
std::move(callback).Run(StorageMonitor::EJECT_OK);
}
// device::mojom::MtpManagerClient override.
void MtpManagerClientChromeOS::StorageAttached(
device::mojom::MtpStorageInfoPtr mtp_storage_info) {
if (!mtp_storage_info)
return;
// Create StorageMonitor format StorageInfo and update the local map.
std::string device_id = GetDeviceIdFromStorageInfo(*mtp_storage_info);
std::u16string storage_label =
GetDeviceLabelFromStorageInfo(*mtp_storage_info);
std::string location =
GetDeviceLocationFromStorageName(mtp_storage_info->storage_name);
std::u16string vendor_name = base::UTF8ToUTF16(mtp_storage_info->vendor);
std::u16string product_name = base::UTF8ToUTF16(mtp_storage_info->product);
if (device_id.empty() || storage_label.empty())
return;
DCHECK(!base::Contains(storage_map_, location));
StorageInfo storage_info(device_id, location, storage_label, vendor_name,
product_name, 0);
storage_map_[location] = storage_info;
// Notify StorageMonitor observers about the event.
notifications_->ProcessAttach(storage_info);
}
// device::mojom::MtpManagerClient override.
void MtpManagerClientChromeOS::StorageDetached(
const std::string& storage_name) {
DCHECK(!storage_name.empty());
StorageLocationToInfoMap::iterator it =
storage_map_.find(GetDeviceLocationFromStorageName(storage_name));
if (it == storage_map_.end())
return;
// Notify StorageMonitor observers about the event.
notifications_->ProcessDetach(it->second.device_id());
storage_map_.erase(it);
}
void MtpManagerClientChromeOS::OnReceivedStorages(
std::vector<device::mojom::MtpStorageInfoPtr> storage_info_list) {
for (auto& storage_info : storage_info_list)
StorageAttached(std::move(storage_info));
}
bool MtpManagerClientChromeOS::GetLocationForDeviceId(
const std::string& device_id,
std::string* location) const {
for (const auto& it : storage_map_) {
if (it.second.device_id() == device_id) {
*location = it.first;
return true;
}
}
return false;
}
} // namespace storage_monitor