blob: bbe921500cdeec0b136e5a71a41b39f260dd6183 [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ash/crosapi/volume_manager_ash.h"
#include <utility>
#include <vector>
#include "base/memory/weak_ptr.h"
#include "chrome/browser/ash/file_manager/volume_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
namespace crosapi {
namespace {
bool IsVolumeAvailableToLacros(const file_manager::Volume& volume) {
// Use type (available only in ash-chrome) to decide whether a volume can be
// used by lacros-chrome. This is needed because virtual file system support
// for lacros is WIP.
// TODO(crbug.com/1296438): Adjust as needed re. VFS support progress, being
// mindful of version skew and its limits.
auto type = volume.type();
return type == file_manager::VOLUME_TYPE_DOWNLOADS_DIRECTORY ||
type == file_manager::VOLUME_TYPE_REMOVABLE_DISK_PARTITION ||
type == file_manager::VOLUME_TYPE_MOUNTED_ARCHIVE_FILE ||
type == file_manager::VOLUME_TYPE_SMB;
}
crosapi::mojom::VolumePtr ConvertVolumeToMojom(
const file_manager::Volume& src_volume) {
crosapi::mojom::VolumePtr dst_volume = crosapi::mojom::Volume::New();
dst_volume->volume_id = src_volume.volume_id();
dst_volume->volume_label = src_volume.volume_label();
dst_volume->writable = !src_volume.is_read_only();
// TODO(crbug.com/1296438): Deprecate once VFS works fully, being mindful of
// version skew and its limits.
dst_volume->is_available_to_lacros = IsVolumeAvailableToLacros(src_volume);
dst_volume->mount_path = src_volume.mount_path();
return dst_volume;
}
std::vector<crosapi::mojom::VolumePtr> ConvertVolumeListToMojom(
std::vector<base::WeakPtr<file_manager::Volume>> src_volume_list) {
std::vector<crosapi::mojom::VolumePtr> dst_volume_list;
for (const auto& src_volume : src_volume_list) {
if (src_volume.get())
dst_volume_list.emplace_back(ConvertVolumeToMojom(*src_volume));
}
return dst_volume_list;
}
// Returns volume list converted to crosapi form.
std::vector<crosapi::mojom::VolumePtr> ReadVolumeList() {
content::BrowserContext* browser_context =
ProfileManager::GetPrimaryUserProfile();
const std::vector<base::WeakPtr<file_manager::Volume>> volume_list =
file_manager::VolumeManager::Get(browser_context)->GetVolumeList();
return ConvertVolumeListToMojom(volume_list);
}
} // namespace
VolumeManagerAsh::VolumeManagerAsh() = default;
VolumeManagerAsh::~VolumeManagerAsh() = default;
void VolumeManagerAsh::BindReceiver(
mojo::PendingReceiver<mojom::VolumeManager> receiver) {
receivers_.Add(this, std::move(receiver));
}
void VolumeManagerAsh::AddVolumeListObserver(
mojo::PendingRemote<mojom::VolumeListObserver> observer) {
if (!is_observing_volume_manager_) {
Profile* profile = ProfileManager::GetPrimaryUserProfile();
auto* volume_manager = file_manager::VolumeManager::Get(profile);
volume_manager->AddObserver(this);
is_observing_volume_manager_ = true;
}
mojo::Remote<mojom::VolumeListObserver> remote(std::move(observer));
// Note: The observer is NOT provided with the initial value.
volume_list_observers_.Add(std::move(remote));
}
void VolumeManagerAsh::GetFullVolumeList(GetFullVolumeListCallback callback) {
std::move(callback).Run(ReadVolumeList());
}
void VolumeManagerAsh::GetVolumeMountInfo(const std::string& volume_id,
GetVolumeMountInfoCallback callback) {
content::BrowserContext* browser_context =
ProfileManager::GetPrimaryUserProfile();
base::WeakPtr<file_manager::Volume> src_volume =
file_manager::VolumeManager::Get(browser_context)
->FindVolumeById(volume_id);
std::move(callback).Run(src_volume.get() ? ConvertVolumeToMojom(*src_volume)
: nullptr);
}
void VolumeManagerAsh::OnVolumeMounted(ash::MountError error_code,
const file_manager::Volume& volume) {
DispatchVolumeList();
}
void VolumeManagerAsh::OnVolumeUnmounted(ash::MountError error_code,
const file_manager::Volume& volume) {
DispatchVolumeList();
}
void VolumeManagerAsh::OnShutdownStart(
file_manager::VolumeManager* volume_manager) {
// Using DCHECK since this function gets called only if observing.
DCHECK(is_observing_volume_manager_);
volume_manager->RemoveObserver(this);
is_observing_volume_manager_ = false;
}
void VolumeManagerAsh::DispatchVolumeList() {
if (volume_list_observers_.empty())
return;
std::vector<crosapi::mojom::VolumePtr> volume_list = ReadVolumeList();
for (auto& observer : volume_list_observers_) {
std::vector<crosapi::mojom::VolumePtr> volume_list_copy;
for (auto& volume : volume_list) {
volume_list_copy.emplace_back(volume->Clone());
}
observer->OnVolumeListChanged(std::move(volume_list_copy));
}
}
} // namespace crosapi