| // 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" |
| |
| 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(Profile* profile) { |
| const std::vector<base::WeakPtr<file_manager::Volume>> volume_list = |
| file_manager::VolumeManager::Get(profile)->GetVolumeList(); |
| return ConvertVolumeListToMojom(volume_list); |
| } |
| |
| } // namespace |
| |
| VolumeManagerAsh::VolumeManagerAsh() = default; |
| |
| VolumeManagerAsh::~VolumeManagerAsh() = default; |
| |
| void VolumeManagerAsh::SetProfile(Profile* profile) { |
| CHECK(profile); |
| if (profile_ == profile) { |
| VLOG(1) << "VolumeManagerAsh service is already initialized. Skip init."; |
| return; |
| } |
| |
| profile_ = profile; |
| profile_observation_.Observe(profile_); |
| } |
| |
| void VolumeManagerAsh::BindReceiver( |
| mojo::PendingReceiver<mojom::VolumeManager> receiver) { |
| // profile_ should be set beforehand. |
| CHECK(profile_); |
| receivers_.Add(this, std::move(receiver)); |
| } |
| |
| void VolumeManagerAsh::AddVolumeListObserver( |
| mojo::PendingRemote<mojom::VolumeListObserver> observer) { |
| if (!is_observing_volume_manager_ && profile_) { |
| 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) { |
| if (profile_) { |
| std::move(callback).Run(ReadVolumeList(profile_)); |
| } |
| } |
| |
| void VolumeManagerAsh::GetVolumeMountInfo(const std::string& volume_id, |
| GetVolumeMountInfoCallback callback) { |
| if (profile_) { |
| base::WeakPtr<file_manager::Volume> src_volume = |
| file_manager::VolumeManager::Get(profile_)->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::OnProfileWillBeDestroyed(Profile* profile) { |
| CHECK_EQ(profile_, profile); |
| profile_ = nullptr; |
| profile_observation_.Reset(); |
| } |
| |
| void VolumeManagerAsh::DispatchVolumeList() { |
| if (volume_list_observers_.empty() || !profile_) { |
| return; |
| } |
| std::vector<crosapi::mojom::VolumePtr> volume_list = ReadVolumeList(profile_); |
| 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 |