Commit 45492c7c authored by David Munro's avatar David Munro Committed by Commit Bot

crostini: Let users choose their username when installing.

Bug: chromium:914515
Test: manual
Cq-Depend: chromium:2004185
Change-Id: Iee8645e016f716e48c80fcaeee04d2ec25ce8cd1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2010238
Commit-Queue: David Munro <davidmunro@google.com>
Reviewed-by: default avatarNicholas Verne <nverne@chromium.org>
Reviewed-by: default avatarTrent Apted <tapted@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Auto-Submit: David Munro <davidmunro@google.com>
Cr-Commit-Position: refs/heads/master@{#733883}
parent bf746311
......@@ -3591,6 +3591,9 @@
<message name="IDS_CROSTINI_INSTALLER_DISK_SIZE_MESSAGE" desc="Text shown in the Crostini installer dialog describing how and why to choose the initial size of the Crostini disk">
Disk space to reserve for Crostini (you can change this later).
</message>
<message name="IDS_CROSTINI_INSTALLER_USERNAME_MESSAGE" desc="Text shown in the Crostini installer dialog prompting the user to pick their username">
Select a username
</message>
<message name="IDS_CROSTINI_UNINSTALLER_TITLE" desc="Title of the Crostini uninstaller, a dialog for uninstalling Linux, the associated VM and Linux files.">
Delete Linux (Beta)
</message>
......
......@@ -292,25 +292,25 @@ class CrostiniManager::CrostiniRestarter
}
// Allow concierge to choose an appropriate disk image size.
int64_t disk_size_available = options_.disk_size.value_or(0);
int64_t disk_size_bytes = options_.disk_size_bytes.value_or(0);
// If we have an already existing disk, CreateDiskImage will just return its
// path so we can pass it to StartTerminaVm.
StartStage(mojom::InstallerState::kCreateDiskImage);
crostini_manager_->CreateDiskImage(
base::FilePath(vm_name_),
vm_tools::concierge::StorageLocation::STORAGE_CRYPTOHOME_ROOT,
disk_size_available,
disk_size_bytes,
base::BindOnce(&CrostiniRestarter::CreateDiskImageFinished, this,
disk_size_available));
disk_size_bytes));
}
void CreateDiskImageFinished(int64_t disk_size_available,
void CreateDiskImageFinished(int64_t disk_size_bytes,
bool success,
vm_tools::concierge::DiskImageStatus status,
const base::FilePath& result_path) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
for (auto& observer : observer_list_) {
observer.OnDiskImageCreated(success, status, disk_size_available);
observer.OnDiskImageCreated(success, status, disk_size_bytes);
}
if (ReturnEarlyIfAborted()) {
return;
......
......@@ -147,7 +147,7 @@ class CrostiniManager : public KeyedService,
virtual void OnConciergeStarted(bool success) {}
virtual void OnDiskImageCreated(bool success,
vm_tools::concierge::DiskImageStatus status,
int64_t disk_size_available) {}
int64_t disk_size_bytes) {}
virtual void OnVmStarted(bool success) {}
virtual void OnContainerDownloading(int32_t download_percent) {}
virtual void OnContainerCreated(CrostiniResult result) {}
......@@ -158,9 +158,9 @@ class CrostiniManager : public KeyedService,
};
struct RestartOptions {
// This normally will not have effect on existing container.
// These two options only affect new containers.
base::Optional<std::string> container_username;
base::Optional<int64_t> disk_size;
base::Optional<int64_t> disk_size_bytes;
RestartOptions();
~RestartOptions();
......
......@@ -83,16 +83,24 @@
</div>
<div id="configure-message" hidden="[[!isState_(state_, State.CONFIGURE)]]">
<div>$i18n{configureMessage}</div>
<div>$i18n{diskSizeMessage}</div>
<div class="outer">
<cr-slider id="diskSlider" pin="true"
value="[[defaultDiskSizeTick_]]"
area-describedby="configure-message"
ticks="[[diskSizeTicks_]]">
</cr-slider>
<div id="labels">
<div id="label-begin">[[minDisk_]]</div>
<div id="label-end">[[maxDisk_]]</div>
<div hidden="[[!showUsernameSelection_()]]">
<div>$i18n{usernameMessage}</div>
<cr-input label="Username" id="username" type="text"
value="{{username_}}">
</cr-input>
</div>
<div hidden="[[!showDiskResizing_()]]">
<div>$i18n{diskSizeMessage}</div>
<div class="outer">
<cr-slider id="diskSlider" pin="true"
value="[[defaultDiskSizeTick_]]"
area-describedby="configure-message"
ticks="[[diskSizeTicks_]]">
</cr-slider>
<div id="labels">
<div id="label-begin">[[minDisk_]]</div>
<div id="label-end">[[maxDisk_]]</div>
</div>
</div>
</div>
</div>
......
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
import 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
import 'chrome://resources/cr_elements/cr_slider/cr_slider.m.js';
import 'chrome://resources/cr_elements/shared_vars_css.m.js';
import 'chrome://resources/polymer/v3_0/paper-progress/paper-progress.js';
......@@ -94,6 +95,12 @@ Polymer({
chosenDiskSize_: {
type: Number,
},
username_: {
type: String,
notify: true,
value: loadTimeData.getString('defaultContainerUsername'),
},
},
/** @override */
......@@ -167,7 +174,7 @@ Polymer({
this.installerState_ = InstallerState.kStart;
this.installerProgress_ = 0;
this.state_ = State.INSTALLING;
BrowserProxy.getInstance().handler.install(diskSize);
BrowserProxy.getInstance().handler.install(diskSize, this.username_);
},
/** @private */
......@@ -242,7 +249,7 @@ Polymer({
* @private
*/
canInstall_(state) {
if (loadTimeData.getBoolean('diskResizingEnabled')) {
if (this.configurePageAccessible_()) {
return state === State.CONFIGURE || state === State.ERROR;
} else {
return state === State.PROMPT || state === State.ERROR;
......@@ -255,8 +262,7 @@ Polymer({
* @private
*/
showNextButton_(state) {
return loadTimeData.getBoolean('diskResizingEnabled') &&
state === State.PROMPT;
return this.configurePageAccessible_() && state === State.PROMPT;
},
/**
......@@ -273,10 +279,7 @@ Polymer({
* @private
*/
getInstallButtonLabel_(state) {
if (!loadTimeData.getBoolean('diskResizingEnabled') &&
state === State.PROMPT) {
// TODO(dmunro): Remove all the flag checks once we're rolled out and no
// longer need them.
if (!this.configurePageAccessible_() && state === State.PROMPT) {
return loadTimeData.getString('install');
}
switch (state) {
......@@ -393,4 +396,25 @@ Polymer({
return messageId ? loadTimeData.getString(messageId) : '';
},
/**
* @private
*/
configurePageAccessible_() {
return this.showDiskResizing_() || this.showUsernameSelection_();
},
/**
* @private
*/
showDiskResizing_() {
return loadTimeData.getBoolean('diskResizingEnabled');
},
/**
* @private
*/
showUsernameSelection_() {
return loadTimeData.getBoolean('crostiniCustomUsername');
},
});
......@@ -17,8 +17,9 @@ interface PageHandlerFactory {
// Lives in the browser process. A renderer use this to control Crostini
// installation.
interface PageHandler {
// Start installation, |disk_size| is in bytes.
Install(int64 disk_size);
// Start installation, |disk_size| is in bytes, username is the user's
// desired username for inside the container.
Install(int64 disk_size, string username);
// Cancel an on-going installation
Cancel();
// If a user cancels the installation without starting it at all, this should
......
......@@ -41,12 +41,14 @@ CrostiniInstallerPageHandler::CrostiniInstallerPageHandler(
CrostiniInstallerPageHandler::~CrostiniInstallerPageHandler() = default;
void CrostiniInstallerPageHandler::Install(int64_t disk_size) {
// TODO(crbug.com/1016195): Web page should allow input container username,
// and here we will pass that to Install().
void CrostiniInstallerPageHandler::Install(int64_t disk_size_bytes,
const std::string& username) {
crostini::CrostiniManager::RestartOptions options{};
if (base::FeatureList::IsEnabled(chromeos::features::kCrostiniDiskResizing)) {
options.disk_size = disk_size;
options.disk_size_bytes = disk_size_bytes;
}
if (base::FeatureList::IsEnabled(chromeos::features::kCrostiniUsername)) {
options.container_username = username;
}
installer_ui_delegate_->Install(
std::move(options),
......
......@@ -34,7 +34,7 @@ class CrostiniInstallerPageHandler
~CrostiniInstallerPageHandler() override;
// chromeos::crostini_installer::mojom::PageHandler:
void Install(int64_t disk_size) override;
void Install(int64_t disk_size_bytes, const std::string& username) override;
void Cancel() override;
void CancelBeforeStart() override;
void Close() override;
......
......@@ -72,6 +72,7 @@ void AddStringResources(content::WebUIDataSource* source) {
{"configureMessage", IDS_CROSTINI_INSTALLER_CONFIGURE_MESSAGE},
{"diskSizeMessage", IDS_CROSTINI_INSTALLER_DISK_SIZE_MESSAGE},
{"usernameMessage", IDS_CROSTINI_INSTALLER_USERNAME_MESSAGE},
};
AddLocalizedStringsBulk(source, kStrings);
......@@ -111,12 +112,18 @@ CrostiniInstallerUI::CrostiniInstallerUI(content::WebUI* web_ui)
: ui::MojoWebDialogUI{web_ui} {
content::WebUIDataSource* source =
content::WebUIDataSource::Create(chrome::kChromeUICrostiniInstallerHost);
auto* profile = Profile::FromWebUI(web_ui);
source->OverrideContentSecurityPolicyScriptSrc(
"script-src chrome://resources chrome://test 'self';");
AddStringResources(source);
source->AddBoolean(
"diskResizingEnabled",
base::FeatureList::IsEnabled(chromeos::features::kCrostiniDiskResizing));
source->AddBoolean(
"crostiniCustomUsername",
base::FeatureList::IsEnabled(chromeos::features::kCrostiniUsername));
source->AddString("defaultContainerUsername",
crostini::DefaultContainerUserNameForProfile(profile));
source->AddResourcePath("app.js", IDR_CROSTINI_INSTALLER_APP_JS);
source->AddResourcePath("browser_proxy.js",
......@@ -133,7 +140,7 @@ CrostiniInstallerUI::CrostiniInstallerUI(content::WebUI* web_ui)
source->UseStringsJs();
source->EnableReplaceI18nInJS();
content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source);
content::WebUIDataSource::Add(profile, source);
}
CrostiniInstallerUI::~CrostiniInstallerUI() = default;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment