| // 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/file_manager/fusebox_daemon.h" |
| |
| #include "base/check.h" |
| #include "base/functional/bind.h" |
| #include "base/functional/callback_helpers.h" |
| #include "base/logging.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/no_destructor.h" |
| #include "base/system/sys_info.h" |
| #include "chrome/browser/ash/fusebox/fusebox_server.h" |
| |
| namespace file_manager { |
| |
| // static |
| scoped_refptr<FuseBoxDaemon> FuseBoxDaemon::GetInstance() { |
| static base::NoDestructor<base::WeakPtr<FuseBoxDaemon>> daemon; |
| |
| scoped_refptr<FuseBoxDaemon> p = daemon->get(); |
| if (!p) { |
| p = new FuseBoxDaemon(); |
| *daemon = p->weak_ptr_factory_.GetWeakPtr(); |
| } |
| |
| return p; |
| } |
| |
| FuseBoxDaemon::FuseBoxDaemon() { |
| cros_disks_mount_manager_ = CrosDisksMountManager::GetInstance(); |
| |
| if (!cros_disks_mount_manager_) { |
| return; // cros_disks_mount_manager_ can be null in unit_tests. |
| } |
| |
| constexpr auto type = ash::MountType::kNetworkStorage; |
| constexpr auto mode = ash::MountAccessMode::kReadWrite; |
| |
| cros_disks_mount_manager_->MountPath( |
| CrosDisksFuseBoxHelperURI(), |
| /*source_format*/ {}, |
| /*mount_label*/ {}, |
| /*options*/ {/* add fusebox --flags here */}, type, mode, |
| base::BindOnce(&FuseBoxDaemon::MountResponse, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| void FuseBoxDaemon::MountResponse(ash::MountError error, |
| const FuseBoxMountInfo& info) { |
| if (error == ash::MountError::kSuccess) { |
| mounted_ = true; |
| } else { |
| if (base::SysInfo::IsRunningOnChromeOS()) { |
| LOG(ERROR) << CrosDisksFuseBoxHelperURI() << " mount error " << error; |
| } |
| mounted_ = (error == ash::MountError::kPathAlreadyMounted); |
| } |
| |
| if (mounted_ && !pending_attach_storage_calls_.empty()) { |
| const auto queued = pending_attach_storage_calls_.size(); |
| VLOG(1) << "Calling " << queued << " queued AttachStorage calls"; |
| for (const auto& it : pending_attach_storage_calls_) { |
| const auto& [url, read_only] = it.second; |
| AttachStorage(it.first, url, read_only); |
| } |
| } |
| |
| pending_attach_storage_calls_.clear(); |
| } |
| |
| void FuseBoxDaemon::AttachStorage(const std::string& subdir, |
| const std::string& url, |
| bool read_only) { |
| if (!mounted_) { |
| VLOG(1) << "FuseBox is not mounted: queued AttachStorage call"; |
| pending_attach_storage_calls_.emplace(subdir, std::pair{url, read_only}); |
| return; |
| } |
| |
| if (auto* fusebox_server = fusebox::Server::GetInstance()) { |
| fusebox_server->RegisterFSURLPrefix(subdir, url, read_only); |
| } else { |
| VLOG(1) << "No FuseBox server available for AttachStorage"; |
| } |
| } |
| |
| void FuseBoxDaemon::DetachStorage(const std::string& subdir) { |
| if (!mounted_) { |
| VLOG(1) << "Fusebox is not mounted, removing queued AttachStorage call"; |
| pending_attach_storage_calls_.erase(subdir); |
| return; |
| } |
| |
| if (auto* fusebox_server = fusebox::Server::GetInstance()) { |
| fusebox_server->UnregisterFSURLPrefix(subdir); |
| } else { |
| VLOG(1) << "No FuseBox server available for DetachStorage"; |
| } |
| } |
| |
| FuseBoxDaemon::~FuseBoxDaemon() { |
| if (!cros_disks_mount_manager_) { |
| return; // cros_disks_mount_manager_ can be null in unit_tests. |
| } |
| |
| cros_disks_mount_manager_->UnmountPath(CrosDisksFuseBoxHelperURI(), |
| base::DoNothing()); |
| } |
| |
| } // namespace file_manager |