blob: 01d9b419137a19e276dae68a6399a8d3a7a71290 [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/file_manager/fusebox_mounter.h"
#include <cerrno>
#include <utility>
#include "ash/constants/ash_features.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/check.h"
#include "base/logging.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string_util.h"
#include "base/task/thread_pool.h"
#include "chrome/browser/ash/fusebox/fusebox_server.h"
#include "chromeos/ash/components/dbus/cros_disks/cros_disks_client.h"
#include "chromeos/ash/components/disks/disk_mount_manager.h"
namespace file_manager {
namespace {
// The first "fusebox" is the URI scheme that is matched by cros-disks'
// "fusebox_helper.cc". The second "fusebox" is the "foo" in "/media/fuse/foo".
const char kFuseBoxMounterURI[] = "fusebox://fusebox";
} // namespace
FuseBoxMounter::FuseBoxMounter() = default;
FuseBoxMounter::~FuseBoxMounter() = default;
void FuseBoxMounter::AttachStorage(const std::string& subdir,
const std::string& url,
bool read_only) {
if (!mounted_) {
VLOG(1) << "Fusebox isn't mounted, queueing AttachStorage call";
pending_attach_storage_calls_.emplace(subdir,
std::make_pair(url, read_only));
return;
}
fusebox::Server* fusebox_server = fusebox::Server::GetInstance();
if (fusebox_server) {
fusebox_server->RegisterFSURLPrefix(subdir, url, read_only);
} else {
VLOG(1) << "No fusebox server available on AttachStorage";
}
}
void FuseBoxMounter::DetachStorage(const std::string& subdir) {
if (!mounted_) {
VLOG(1) << "Fusebox isn't mounted, removing queued AttachStorage call";
pending_attach_storage_calls_.erase(subdir);
return;
}
fusebox::Server* fusebox_server = fusebox::Server::GetInstance();
if (fusebox_server) {
fusebox_server->UnregisterFSURLPrefix(subdir);
} else {
VLOG(1) << "No fusebox server available on DetachStorage";
}
}
void FuseBoxMounter::Mount(FuseBoxDiskMountManager* disk_mount_manager) {
DCHECK(disk_mount_manager);
constexpr auto type = ash::MountType::kNetworkStorage;
constexpr auto mode = ash::MountAccessMode::kReadWrite;
disk_mount_manager->MountPath(kFuseBoxMounterURI, /*source_format*/ {},
/*mount_label*/ {},
/*options*/ {}, type, mode,
base::BindOnce(&FuseBoxMounter::MountResponse,
weak_ptr_factory_.GetWeakPtr()));
}
void FuseBoxMounter::Unmount(FuseBoxDiskMountManager* disk_mount_manager) {
DCHECK(disk_mount_manager);
if (!mounted_) {
VLOG(1) << "FuseBoxMounter::Unmount ignored: not mounted";
return;
}
disk_mount_manager->UnmountPath(
kFuseBoxMounterURI, base::BindOnce(&FuseBoxMounter::UnmountResponse,
weak_ptr_factory_.GetWeakPtr()));
}
void FuseBoxMounter::MountResponse(ash::MountError error,
const FuseBoxMountInfo& info) {
if (error != ash::MountError::kSuccess) {
LOG(ERROR) << kFuseBoxMounterURI << " mount error " << error;
} else {
mounted_ = true;
if (!pending_attach_storage_calls_.empty()) {
VLOG(1) << "Calling " << pending_attach_storage_calls_.size()
<< " 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 FuseBoxMounter::UnmountResponse(ash::MountError error) {
if (error != ash::MountError::kSuccess) {
LOG(ERROR) << kFuseBoxMounterURI << " unmount error " << error;
} else {
mounted_ = false;
}
pending_attach_storage_calls_.clear();
}
} // namespace file_manager