blob: 7559e034ef91f34cb3cf1906caf76e50920df087 [file] [log] [blame]
// Copyright 2018 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/ui/webui/settings/chromeos/crostini_handler.h"
#include <string>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "chrome/browser/chromeos/crostini/crostini_export_import.h"
#include "chrome/browser/chromeos/crostini/crostini_manager.h"
#include "chrome/browser/chromeos/crostini/crostini_share_path.h"
#include "chrome/browser/chromeos/crostini/crostini_util.h"
#include "chrome/browser/chromeos/file_manager/path_util.h"
#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/browser_thread.h"
namespace chromeos {
namespace settings {
CrostiniHandler::CrostiniHandler(Profile* profile)
: profile_(profile), weak_ptr_factory_(this) {}
CrostiniHandler::~CrostiniHandler() {
DisallowJavascript();
}
void CrostiniHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback(
"requestCrostiniInstallerView",
base::BindRepeating(&CrostiniHandler::HandleRequestCrostiniInstallerView,
weak_ptr_factory_.GetWeakPtr()));
web_ui()->RegisterMessageCallback(
"requestRemoveCrostini",
base::BindRepeating(&CrostiniHandler::HandleRequestRemoveCrostini,
weak_ptr_factory_.GetWeakPtr()));
web_ui()->RegisterMessageCallback(
"getCrostiniSharedPathsDisplayText",
base::BindRepeating(
&CrostiniHandler::HandleGetCrostiniSharedPathsDisplayText,
weak_ptr_factory_.GetWeakPtr()));
web_ui()->RegisterMessageCallback(
"removeCrostiniSharedPath",
base::BindRepeating(&CrostiniHandler::HandleRemoveCrostiniSharedPath,
weak_ptr_factory_.GetWeakPtr()));
web_ui()->RegisterMessageCallback(
"getCrostiniSharedUsbDevices",
base::BindRepeating(&CrostiniHandler::HandleGetCrostiniSharedUsbDevices,
weak_ptr_factory_.GetWeakPtr()));
web_ui()->RegisterMessageCallback(
"setCrostiniUsbDeviceShared",
base::BindRepeating(&CrostiniHandler::HandleSetCrostiniUsbDeviceShared,
weak_ptr_factory_.GetWeakPtr()));
web_ui()->RegisterMessageCallback(
"exportCrostiniContainer",
base::BindRepeating(&CrostiniHandler::HandleExportCrostiniContainer,
weak_ptr_factory_.GetWeakPtr()));
web_ui()->RegisterMessageCallback(
"importCrostiniContainer",
base::BindRepeating(&CrostiniHandler::HandleImportCrostiniContainer,
weak_ptr_factory_.GetWeakPtr()));
web_ui()->RegisterMessageCallback(
"requestCrostiniInstallerStatus",
base::BindRepeating(
&CrostiniHandler::HandleCrostiniInstallerStatusRequest,
weak_ptr_factory_.GetWeakPtr()));
}
void CrostiniHandler::OnJavascriptAllowed() {
crostini::CrostiniManager::GetForProfile(profile_)
->AddInstallerViewStatusObserver(this);
if (chromeos::CrosUsbDetector::Get()) {
chromeos::CrosUsbDetector::Get()->AddSharedUsbDeviceObserver(this);
}
}
void CrostiniHandler::OnJavascriptDisallowed() {
if (crostini::CrostiniManager::GetForProfile(profile_)
->HasInstallerViewStatusObserver(this)) {
crostini::CrostiniManager::GetForProfile(profile_)
->RemoveInstallerViewStatusObserver(this);
}
if (chromeos::CrosUsbDetector::Get()) {
chromeos::CrosUsbDetector::Get()->RemoveSharedUsbDeviceObserver(this);
}
}
void CrostiniHandler::HandleRequestCrostiniInstallerView(
const base::ListValue* args) {
AllowJavascript();
ShowCrostiniInstallerView(Profile::FromWebUI(web_ui()),
crostini::CrostiniUISurface::kSettings);
}
void CrostiniHandler::HandleRequestRemoveCrostini(const base::ListValue* args) {
AllowJavascript();
ShowCrostiniUninstallerView(Profile::FromWebUI(web_ui()),
crostini::CrostiniUISurface::kSettings);
}
void CrostiniHandler::HandleGetCrostiniSharedPathsDisplayText(
const base::ListValue* args) {
AllowJavascript();
CHECK_EQ(2U, args->GetSize());
std::string callback_id;
const base::ListValue* paths;
CHECK(args->GetString(0, &callback_id));
CHECK(args->GetList(1, &paths));
base::ListValue texts;
for (auto it = paths->begin(); it != paths->end(); ++it) {
texts.AppendString(file_manager::util::GetPathDisplayTextForSettings(
profile_, it->GetString()));
}
ResolveJavascriptCallback(base::Value(callback_id), texts);
}
void CrostiniHandler::HandleRemoveCrostiniSharedPath(
const base::ListValue* args) {
CHECK_EQ(2U, args->GetSize());
std::string vm_name;
CHECK(args->GetString(0, &vm_name));
std::string path;
CHECK(args->GetString(1, &path));
crostini::CrostiniSharePath::GetForProfile(profile_)->UnsharePath(
vm_name, base::FilePath(path),
/*unpersist=*/true,
base::BindOnce(
[](const std::string& path, bool result, std::string failure_reason) {
if (!result) {
LOG(ERROR) << "Error unsharing " << path << ": "
<< failure_reason;
}
},
path));
}
namespace {
base::ListValue UsbDevicesToListValue(
const std::vector<SharedUsbDeviceInfo> shared_usbs) {
base::ListValue usb_devices_list;
for (auto device : shared_usbs) {
base::Value device_info(base::Value::Type::DICTIONARY);
device_info.SetKey("guid", base::Value(device.guid));
device_info.SetKey("label", base::Value(device.label));
device_info.SetKey("shared", base::Value(device.shared));
usb_devices_list.GetList().push_back(std::move(device_info));
}
return usb_devices_list;
}
} // namespace
void CrostiniHandler::HandleGetCrostiniSharedUsbDevices(
const base::ListValue* args) {
AllowJavascript();
CHECK_EQ(1U, args->GetSize());
std::string callback_id = args->GetList()[0].GetString();
chromeos::CrosUsbDetector* detector = chromeos::CrosUsbDetector::Get();
if (!detector) {
ResolveJavascriptCallback(base::Value(callback_id), base::ListValue());
return;
}
ResolveJavascriptCallback(
base::Value(callback_id),
UsbDevicesToListValue(detector->GetSharedUsbDevices()));
}
void CrostiniHandler::HandleSetCrostiniUsbDeviceShared(
const base::ListValue* args) {
CHECK_EQ(2U, args->GetSize());
const auto& args_list = args->GetList();
std::string guid = args_list[0].GetString();
bool shared = args_list[1].GetBool();
chromeos::CrosUsbDetector* detector = chromeos::CrosUsbDetector::Get();
if (!detector)
return;
if (shared) {
detector->AttachUsbDeviceToVm(crostini::kCrostiniDefaultVmName, guid,
base::DoNothing());
return;
}
detector->DetachUsbDeviceFromVm(crostini::kCrostiniDefaultVmName, guid,
base::DoNothing());
}
void CrostiniHandler::OnSharedUsbDevicesChanged(
const std::vector<SharedUsbDeviceInfo> shared_usbs) {
FireWebUIListener("crostini-shared-usb-devices-changed",
UsbDevicesToListValue(shared_usbs));
}
void CrostiniHandler::HandleExportCrostiniContainer(
const base::ListValue* args) {
CHECK_EQ(0U, args->GetSize());
crostini::CrostiniExportImport::GetForProfile(profile_)->ExportContainer(
web_ui()->GetWebContents());
}
void CrostiniHandler::HandleImportCrostiniContainer(
const base::ListValue* args) {
CHECK_EQ(0U, args->GetSize());
crostini::CrostiniExportImport::GetForProfile(profile_)->ImportContainer(
web_ui()->GetWebContents());
}
void CrostiniHandler::HandleCrostiniInstallerStatusRequest(
const base::ListValue* args) {
AllowJavascript();
CHECK_EQ(0U, args->GetSize());
bool status = crostini::CrostiniManager::GetForProfile(profile_)
->GetInstallerViewStatus();
OnCrostiniInstallerViewStatusChanged(status);
}
void CrostiniHandler::OnCrostiniInstallerViewStatusChanged(bool status) {
// It's technically possible for this to be called before Javascript is
// enabled, in which case we must not call FireWebUIListener
if (IsJavascriptAllowed()) {
// Other side listens with cr.addWebUIListener
FireWebUIListener("crostini-installer-status-changed", base::Value(status));
}
}
} // namespace settings
} // namespace chromeos