Commit b56d074f authored by danielng's avatar danielng Committed by Commit Bot

crostini: Clean up UI for Crostini mic settings and enable flag by

default

Follow up from CL:2086359 to ensure that the Crostini mic sharing
dialog only shows when Crostini needs to be restarted. Tests were
added to check this and the flag regarding the mic sharing settings
is now enabled by default. Note that the mic is not shared by default.

Tests: Tested mannually and expanded the appropriate browser test
Bug: 1016193
Change-Id: I4b416feedddbe4e3b7f0c5fc638701f9f809ae66
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2123579
Commit-Queue: Daniel Ng <danielng@google.com>
Reviewed-by: default avatarJulian Watson <juwa@google.com>
Reviewed-by: default avatarKyle Horimoto <khorimoto@chromium.org>
Cr-Commit-Position: refs/heads/master@{#754807}
parent 04faa46e
...@@ -1266,9 +1266,12 @@ void CrostiniManager::StartTerminaVm(std::string name, ...@@ -1266,9 +1266,12 @@ void CrostiniManager::StartTerminaVm(std::string name,
request.set_owner_id(owner_id_); request.set_owner_id(owner_id_);
if (base::FeatureList::IsEnabled(chromeos::features::kCrostiniGpuSupport)) if (base::FeatureList::IsEnabled(chromeos::features::kCrostiniGpuSupport))
request.set_enable_gpu(true); request.set_enable_gpu(true);
if (IsMicSharingEnabled(profile_)) { bool is_mic_sharing_enabled = IsMicSharingEnabled(profile_);
if (is_mic_sharing_enabled) {
request.set_enable_audio_capture(true); request.set_enable_audio_capture(true);
} }
profile_->GetPrefs()->SetBoolean(
crostini::prefs::kCrostiniMicSharingAtLastLaunch, is_mic_sharing_enabled);
const int32_t cpus = base::SysInfo::NumberOfProcessors() - num_cores_disabled; const int32_t cpus = base::SysInfo::NumberOfProcessors() - num_cores_disabled;
DCHECK_LT(0, cpus); DCHECK_LT(0, cpus);
request.set_cpus(cpus); request.set_cpus(cpus);
......
...@@ -77,10 +77,15 @@ const char kCrostiniLastDiskSize[] = "crostini.last_disk_size"; ...@@ -77,10 +77,15 @@ const char kCrostiniLastDiskSize[] = "crostini.last_disk_size";
const char kCrostiniPortForwarding[] = "crostini.port_forwarding.ports"; const char kCrostiniPortForwarding[] = "crostini.port_forwarding.ports";
// A boolean preference indicating whether Crostini is able to access the mic. // A boolean preference indicating whether Crostini is able to access the mic.
const char kCrostiniMicSharing[] = "crostini.mic_sharing"; const char kCrostiniMicSharing[] = "crostini.mic_sharing";
// A boolean preference indicating whether Crostini was given access to the mic
// the last time it launched.
const char kCrostiniMicSharingAtLastLaunch[] =
"crostini.mic_sharing_at_last_launch";
void RegisterProfilePrefs(PrefRegistrySimple* registry) { void RegisterProfilePrefs(PrefRegistrySimple* registry) {
registry->RegisterBooleanPref(kCrostiniEnabled, false); registry->RegisterBooleanPref(kCrostiniEnabled, false);
registry->RegisterBooleanPref(kCrostiniMicSharing, true); registry->RegisterBooleanPref(kCrostiniMicSharing, false);
registry->RegisterBooleanPref(kCrostiniMicSharingAtLastLaunch, false);
registry->RegisterDictionaryPref(kCrostiniMimeTypes); registry->RegisterDictionaryPref(kCrostiniMimeTypes);
registry->RegisterListPref(kCrostiniPortForwarding); registry->RegisterListPref(kCrostiniPortForwarding);
registry->RegisterListPref(kCrostiniSharedUsbDevices); registry->RegisterListPref(kCrostiniSharedUsbDevices);
......
...@@ -33,6 +33,7 @@ extern const char kCrostiniLastLaunchTimeWindowStart[]; ...@@ -33,6 +33,7 @@ extern const char kCrostiniLastLaunchTimeWindowStart[];
extern const char kCrostiniLastDiskSize[]; extern const char kCrostiniLastDiskSize[];
extern const char kCrostiniPortForwarding[]; extern const char kCrostiniPortForwarding[];
extern const char kCrostiniMicSharing[]; extern const char kCrostiniMicSharing[];
extern const char kCrostiniMicSharingAtLastLaunch[];
void RegisterProfilePrefs(PrefRegistrySimple* registry); void RegisterProfilePrefs(PrefRegistrySimple* registry);
......
...@@ -457,6 +457,8 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() { ...@@ -457,6 +457,8 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
settings_api::PrefType::PREF_TYPE_BOOLEAN; settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[crostini::prefs::kCrostiniMicSharing] = (*s_whitelist)[crostini::prefs::kCrostiniMicSharing] =
settings_api::PrefType::PREF_TYPE_BOOLEAN; settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[crostini::prefs::kCrostiniMicSharingAtLastLaunch] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[crostini::prefs::kCrostiniSharedUsbDevices] = (*s_whitelist)[crostini::prefs::kCrostiniSharedUsbDevices] =
settings_api::PrefType::PREF_TYPE_LIST; settings_api::PrefType::PREF_TYPE_LIST;
(*s_whitelist)[crostini::prefs::kCrostiniContainers] = (*s_whitelist)[crostini::prefs::kCrostiniContainers] =
......
...@@ -94,6 +94,7 @@ js_library("crostini_subpage") { ...@@ -94,6 +94,7 @@ js_library("crostini_subpage") {
"..:os_route", "..:os_route",
"..:route_origin_behavior", "..:route_origin_behavior",
"../..:router", "../..:router",
"../../controls:settings_toggle_button",
"../../prefs:prefs_behavior", "../../prefs:prefs_behavior",
] ]
} }
...@@ -141,6 +141,15 @@ cr.define('settings', function() { ...@@ -141,6 +141,15 @@ cr.define('settings', function() {
* @return {!Promise<boolean>} Whether resizing succeeded(true) or failed. * @return {!Promise<boolean>} Whether resizing succeeded(true) or failed.
*/ */
resizeCrostiniDisk(vmName, newSizeBytes) {} resizeCrostiniDisk(vmName, newSizeBytes) {}
/**
* Checks if a proposed change to mic sharing requires Crostini to be
* restarted for it to take effect.
* @param {boolean} proposedValue Reflects what mic sharing is being set
* to.
* @return {!Promise<boolean>} Whether Crostini requires a restart or not.
*/
checkCrostiniMicSharingStatus(proposedValue) {}
} }
/** @implements {settings.CrostiniBrowserProxy} */ /** @implements {settings.CrostiniBrowserProxy} */
...@@ -242,6 +251,11 @@ cr.define('settings', function() { ...@@ -242,6 +251,11 @@ cr.define('settings', function() {
resizeCrostiniDisk(vmName, newSizeBytes) { resizeCrostiniDisk(vmName, newSizeBytes) {
return cr.sendWithPromise('resizeCrostiniDisk', vmName, newSizeBytes); return cr.sendWithPromise('resizeCrostiniDisk', vmName, newSizeBytes);
} }
/** @override */
checkCrostiniMicSharingStatus(proposedValue) {
return cr.sendWithPromise('checkCrostiniMicSharingStatus', proposedValue);
}
} }
// The singleton instance_ can be replaced with a test version of this wrapper // The singleton instance_ can be replaced with a test version of this wrapper
......
...@@ -254,13 +254,20 @@ Polymer({ ...@@ -254,13 +254,20 @@ Polymer({
}, },
/** /**
* Shows a dialog when adjusting mic settings. * If a change to the mic settings requires Crostini to be restarted, a
* TODO(danielng): We should only show the dialog if termina is running and * dialog is shown.
* the settings change to be different to the current state of termina.
* @private * @private
*/ */
onMicSharingChange_: function() { onMicSharingChange_: function() {
this.showCrostiniMicSharingDialog_ = true; const proposedValue = /** @type {!SettingsToggleButtonElement} */
(this.$$('#crostini-mic-sharing')).checked;
settings.CrostiniBrowserProxyImpl.getInstance()
.checkCrostiniMicSharingStatus(proposedValue)
.then(requiresRestart => {
if (requiresRestart) {
this.showCrostiniMicSharingDialog_ = true;
}
});
}, },
/** @private */ /** @private */
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "chrome/browser/chromeos/crostini/crostini_features.h" #include "chrome/browser/chromeos/crostini/crostini_features.h"
#include "chrome/browser/chromeos/crostini/crostini_installer.h" #include "chrome/browser/chromeos/crostini/crostini_installer.h"
#include "chrome/browser/chromeos/crostini/crostini_port_forwarder.h" #include "chrome/browser/chromeos/crostini/crostini_port_forwarder.h"
#include "chrome/browser/chromeos/crostini/crostini_pref_names.h"
#include "chrome/browser/chromeos/crostini/crostini_types.mojom.h" #include "chrome/browser/chromeos/crostini/crostini_types.mojom.h"
#include "chrome/browser/chromeos/crostini/crostini_util.h" #include "chrome/browser/chromeos/crostini/crostini_util.h"
#include "chrome/browser/chromeos/file_manager/path_util.h" #include "chrome/browser/chromeos/file_manager/path_util.h"
...@@ -136,6 +137,10 @@ void CrostiniHandler::RegisterMessages() { ...@@ -136,6 +137,10 @@ void CrostiniHandler::RegisterMessages() {
"resizeCrostiniDisk", "resizeCrostiniDisk",
base::BindRepeating(&CrostiniHandler::HandleResizeCrostiniDisk, base::BindRepeating(&CrostiniHandler::HandleResizeCrostiniDisk,
weak_ptr_factory_.GetWeakPtr())); weak_ptr_factory_.GetWeakPtr()));
web_ui()->RegisterMessageCallback(
"checkCrostiniMicSharingStatus",
base::BindRepeating(&CrostiniHandler::HandleCheckCrostiniMicSharingStatus,
weak_ptr_factory_.GetWeakPtr()));
} }
void CrostiniHandler::OnJavascriptAllowed() { void CrostiniHandler::OnJavascriptAllowed() {
...@@ -528,5 +533,19 @@ void CrostiniHandler::ResolveResizeCrostiniDiskCallback( ...@@ -528,5 +533,19 @@ void CrostiniHandler::ResolveResizeCrostiniDiskCallback(
base::Value(succeeded)); base::Value(succeeded));
} }
void CrostiniHandler::HandleCheckCrostiniMicSharingStatus(
const base::ListValue* args) {
CHECK_EQ(2U, args->GetList().size());
std::string callback_id = args->GetList()[0].GetString();
bool proposed_value = args->GetList()[1].GetBool();
bool requiresRestart =
crostini::IsCrostiniRunning(profile_) &&
profile_->GetPrefs()->GetBoolean(
crostini::prefs::kCrostiniMicSharingAtLastLaunch) != proposed_value;
ResolveJavascriptCallback(base::Value(std::move(callback_id)),
base::Value(requiresRestart));
}
} // namespace settings } // namespace settings
} // namespace chromeos } // namespace chromeos
...@@ -109,6 +109,8 @@ class CrostiniHandler : public ::settings::SettingsPageUIHandler, ...@@ -109,6 +109,8 @@ class CrostiniHandler : public ::settings::SettingsPageUIHandler,
void HandleResizeCrostiniDisk(const base::ListValue* args); void HandleResizeCrostiniDisk(const base::ListValue* args);
void ResolveResizeCrostiniDiskCallback(const std::string& callback_id, void ResolveResizeCrostiniDiskCallback(const std::string& callback_id,
bool succeeded); bool succeeded);
// Checks if a restart is required to update mic sharing settings.
void HandleCheckCrostiniMicSharingStatus(const base::ListValue* args);
Profile* profile_; Profile* profile_;
// weak_ptr_factory_ should always be last member. // weak_ptr_factory_ should always be last member.
......
...@@ -269,6 +269,8 @@ suite('CrostiniPageTests', function() { ...@@ -269,6 +269,8 @@ suite('CrostiniPageTests', function() {
}); });
test('ToggleCrostiniMicSharing', async function() { test('ToggleCrostiniMicSharing', async function() {
// Testing under the premise that Crostini is currently running and the
// mic is being shared with Crostini.
assertTrue(!!subpage.$$('#crostini-mic-sharing')); assertTrue(!!subpage.$$('#crostini-mic-sharing'));
assertFalse(!!subpage.$$('settings-crostini-mic-sharing-dialog')); assertFalse(!!subpage.$$('settings-crostini-mic-sharing-dialog'));
setCrostiniPrefs(true, {micSharing: true}); setCrostiniPrefs(true, {micSharing: true});
...@@ -279,14 +281,21 @@ suite('CrostiniPageTests', function() { ...@@ -279,14 +281,21 @@ suite('CrostiniPageTests', function() {
await flushAsync(); await flushAsync();
assertTrue(!!subpage.$$('settings-crostini-mic-sharing-dialog')); assertTrue(!!subpage.$$('settings-crostini-mic-sharing-dialog'));
const dialog = subpage.$$('settings-crostini-mic-sharing-dialog'); const dialog = subpage.$$('settings-crostini-mic-sharing-dialog');
const dialogClosedPromise = test_util.eventToPromise('close', dialog);
dialog.$$('cr-dialog cr-button').click(); dialog.$$('cr-dialog cr-button').click();
await flushAsync(); await Promise.all([dialogClosedPromise, flushAsync()]);
assertFalse(!!subpage.$$('settings-crostini-mic-sharing-dialog'));
assertFalse(subpage.$$('#crostini-mic-sharing').checked); assertFalse(subpage.$$('#crostini-mic-sharing').checked);
assertFalse(subpage.$$('#crostini-mic-sharing').pref.value); assertFalse(subpage.$$('#crostini-mic-sharing').pref.value);
subpage.$$('#crostini-mic-sharing').click(); subpage.$$('#crostini-mic-sharing').click();
assertTrue(subpage.$$('#crostini-mic-sharing').checked); assertTrue(subpage.$$('#crostini-mic-sharing').checked);
assertTrue(subpage.$$('#crostini-mic-sharing').pref.value); assertTrue(subpage.$$('#crostini-mic-sharing').pref.value);
await flushAsync();
// Dialog should only appear when a restart is required, as the setting
// was initiated as true, changing the setting back to true does not
// require a restart.
assertFalse(!!subpage.$$('settings-crostini-mic-sharing-dialog'));
}); });
test('Remove', async function() { test('Remove', async function() {
......
...@@ -6,20 +6,15 @@ ...@@ -6,20 +6,15 @@
class TestCrostiniBrowserProxy extends TestBrowserProxy { class TestCrostiniBrowserProxy extends TestBrowserProxy {
constructor() { constructor() {
super([ super([
'requestCrostiniInstallerView', 'requestCrostiniInstallerView', 'requestRemoveCrostini',
'requestRemoveCrostini', 'getCrostiniSharedPathsDisplayText', 'getCrostiniSharedUsbDevices',
'getCrostiniSharedPathsDisplayText', 'setCrostiniUsbDeviceShared', 'removeCrostiniSharedPath',
'getCrostiniSharedUsbDevices', 'exportCrostiniContainer', 'importCrostiniContainer',
'setCrostiniUsbDeviceShared',
'removeCrostiniSharedPath',
'exportCrostiniContainer',
'importCrostiniContainer',
'requestCrostiniContainerUpgradeView', 'requestCrostiniContainerUpgradeView',
'requestCrostiniUpgraderDialogStatus', 'requestCrostiniUpgraderDialogStatus',
'requestCrostiniContainerUpgradeAvailable', 'requestCrostiniContainerUpgradeAvailable', 'addCrostiniPortForward',
'addCrostiniPortForward', 'getCrostiniDiskInfo', 'resizeCrostiniDisk',
'getCrostiniDiskInfo', 'checkCrostiniMicSharingStatus'
'resizeCrostiniDisk',
]); ]);
this.sharedUsbDevices = []; this.sharedUsbDevices = [];
this.removeSharedPathResult = true; this.removeSharedPathResult = true;
...@@ -130,4 +125,10 @@ class TestCrostiniBrowserProxy extends TestBrowserProxy { ...@@ -130,4 +125,10 @@ class TestCrostiniBrowserProxy extends TestBrowserProxy {
this.methodCalled('resizeCrostiniDisk', vmName, newSizeBytes); this.methodCalled('resizeCrostiniDisk', vmName, newSizeBytes);
return this.getNewPromiseFor('resizeCrostiniDisk'); return this.getNewPromiseFor('resizeCrostiniDisk');
} }
/** @override */
checkCrostiniMicSharingStatus(proposedValue) {
this.methodCalled('checkCrostiniMicSharingStatus', proposedValue);
return Promise.resolve(!proposedValue);
}
} }
...@@ -87,7 +87,7 @@ const base::Feature kCrostiniUsername{"CrostiniUsername", ...@@ -87,7 +87,7 @@ const base::Feature kCrostiniUsername{"CrostiniUsername",
// Enables the option to share the mic with Crostini or not // Enables the option to share the mic with Crostini or not
const base::Feature kCrostiniShowMicSetting{"CrostiniShowMicSetting", const base::Feature kCrostiniShowMicSetting{"CrostiniShowMicSetting",
base::FEATURE_DISABLED_BY_DEFAULT}; base::FEATURE_ENABLED_BY_DEFAULT};
// Enables or disables Crostini GPU support. // Enables or disables Crostini GPU support.
const base::Feature kCrostiniGpuSupport{"CrostiniGpuSupport", const base::Feature kCrostiniGpuSupport{"CrostiniGpuSupport",
......
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