blob: d0abab9201ebfcf97121b038ea910dc4d8d61cf5 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/extensions/file_manager/private_api_mount.h"
#include <memory>
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/feature_list.h"
#include "base/files/file_util.h"
#include "base/format_macros.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string_util.h"
#include "base/task/post_task.h"
#include "chrome/browser/ash/drive/file_system_util.h"
#include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h"
#include "chrome/browser/chromeos/file_manager/file_tasks_notifier.h"
#include "chrome/browser/chromeos/file_manager/fileapi_util.h"
#include "chrome/browser/chromeos/file_manager/volume_manager.h"
#include "chrome/browser/chromeos/smb_client/smb_service.h"
#include "chrome/browser/chromeos/smb_client/smb_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/api/file_manager_private.h"
#include "chromeos/disks/disk_mount_manager.h"
#include "components/drive/event_logger.h"
#include "content/public/browser/browser_thread.h"
#include "google_apis/drive/task_util.h"
#include "storage/browser/file_system/file_system_url.h"
#include "ui/shell_dialogs/selected_file_info.h"
namespace extensions {
using chromeos::disks::DiskMountManager;
using content::BrowserThread;
namespace file_manager_private = extensions::api::file_manager_private;
FileManagerPrivateAddMountFunction::FileManagerPrivateAddMountFunction() =
default;
ExtensionFunction::ResponseAction FileManagerPrivateAddMountFunction::Run() {
using file_manager_private::AddMount::Params;
const std::unique_ptr<Params> params = Params::Create(*args_);
EXTENSION_FUNCTION_VALIDATE(params);
Profile* const profile = Profile::FromBrowserContext(browser_context());
drive::EventLogger* logger = file_manager::util::GetLogger(profile);
if (logger) {
logger->Log(logging::LOG_INFO, "%s[%d] called. (source: '%s')", name(),
request_id(),
params->source.empty() ? "(none)" : params->source.c_str());
}
set_log_on_completion(true);
const base::FilePath path = file_manager::util::GetLocalPathFromURL(
render_frame_host(), profile, GURL(params->source));
if (path.empty())
return RespondNow(Error("Invalid path"));
if (auto* notifier =
file_manager::file_tasks::FileTasksNotifier::GetForProfile(profile)) {
const scoped_refptr<storage::FileSystemContext> file_system_context =
file_manager::util::GetFileSystemContextForRenderFrameHost(
profile, render_frame_host());
std::vector<storage::FileSystemURL> urls;
const storage::FileSystemURL url =
file_system_context->CrackURL(GURL(params->source));
urls.push_back(url);
notifier->NotifyFileTasks(urls);
}
DCHECK_CURRENTLY_ON(BrowserThread::UI);
std::vector<std::string> options;
if (params->password)
options.push_back("password=" + *params->password);
// MountPath() takes a std::string.
DiskMountManager* disk_mount_manager = DiskMountManager::GetInstance();
disk_mount_manager->MountPath(
path.AsUTF8Unsafe(), base::ToLowerASCII(path.Extension()),
path.BaseName().AsUTF8Unsafe(), options, chromeos::MOUNT_TYPE_ARCHIVE,
chromeos::MOUNT_ACCESS_MODE_READ_WRITE);
// Pass back the actual source path of the mount point.
return RespondNow(OneArgument(base::Value(path.AsUTF8Unsafe())));
}
ExtensionFunction::ResponseAction FileManagerPrivateRemoveMountFunction::Run() {
using file_manager_private::RemoveMount::Params;
const std::unique_ptr<Params> params(Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
Profile* const profile = Profile::FromBrowserContext(browser_context());
drive::EventLogger* logger = file_manager::util::GetLogger(profile);
if (logger) {
logger->Log(logging::LOG_INFO, "%s[%d] called. (volume_id: '%s')", name(),
request_id(), params->volume_id.c_str());
}
set_log_on_completion(true);
using file_manager::Volume;
using file_manager::VolumeManager;
VolumeManager* const volume_manager = VolumeManager::Get(profile);
DCHECK(volume_manager);
base::WeakPtr<Volume> volume =
volume_manager->FindVolumeById(params->volume_id);
if (!volume.get())
return RespondNow(Error("Volume not available"));
// TODO(tbarzic): Send response when callback is received, it would make more
// sense than remembering issued unmount requests in file manager and showing
// errors for them when MountCompleted event is received.
switch (volume->type()) {
case file_manager::VOLUME_TYPE_REMOVABLE_DISK_PARTITION:
case file_manager::VOLUME_TYPE_MOUNTED_ARCHIVE_FILE: {
DiskMountManager::GetInstance()->UnmountPath(
volume->mount_path().value(),
DiskMountManager::UnmountPathCallback());
break;
}
case file_manager::VOLUME_TYPE_PROVIDED: {
chromeos::file_system_provider::Service* service =
chromeos::file_system_provider::Service::Get(browser_context());
DCHECK(service);
// TODO(mtomasz): Pass a more detailed error than just a bool.
if (!service->RequestUnmount(volume->provider_id(),
volume->file_system_id())) {
return RespondNow(Error("Unmount failed"));
}
break;
}
case file_manager::VOLUME_TYPE_CROSTINI:
file_manager::VolumeManager::Get(profile)->RemoveSshfsCrostiniVolume(
volume->mount_path(), base::DoNothing());
break;
case file_manager::VOLUME_TYPE_SMB:
chromeos::smb_client::SmbServiceFactory::Get(profile)->UnmountSmbFs(
volume->mount_path());
break;
default:
// Requested unmounting a device which is not unmountable.
return RespondNow(Error("Invalid volume type"));
}
return RespondNow(NoArguments());
}
ExtensionFunction::ResponseAction
FileManagerPrivateGetVolumeMetadataListFunction::Run() {
if (args_->GetSize())
return RespondNow(Error("Invalid arguments"));
Profile* const profile = Profile::FromBrowserContext(browser_context());
const std::vector<base::WeakPtr<file_manager::Volume>>& volume_list =
file_manager::VolumeManager::Get(profile)->GetVolumeList();
std::string log_string;
std::vector<file_manager_private::VolumeMetadata> result;
for (const auto& volume : volume_list) {
file_manager_private::VolumeMetadata volume_metadata;
file_manager::util::VolumeToVolumeMetadata(profile, *volume,
&volume_metadata);
result.push_back(std::move(volume_metadata));
if (!log_string.empty())
log_string += ", ";
log_string += volume->mount_path().AsUTF8Unsafe();
}
drive::EventLogger* logger = file_manager::util::GetLogger(profile);
if (logger) {
logger->Log(logging::LOG_INFO,
"%s[%d] succeeded. (results: '[%s]', %" PRIuS " mount points)",
name(), request_id(), log_string.c_str(), result.size());
}
return RespondNow(ArgumentList(
file_manager_private::GetVolumeMetadataList::Results::Create(result)));
}
} // namespace extensions