Add shortcut to toggle camera access (behind flag)
This CL creates a new shortcut that toggles the setting "Camera access" in the "Privacy controls" section of ChromeOS Settings. When the setting is enabled or disabled, a toast message is displayed. Example of toast message: https://screenshot.googleplex.com/4FVYuo4rpArdez6 There is a special case where camera access may be force disabled, due to an admin remoting into a user's ChromeOS instance. In this case, the shortcut has no effect, and a toast message is shown indicating that the setting cannot be changed. Bug: b/383772675 Change-Id: I64fa7e8e0de2427e23f4bae368c64a9166c0ec1a Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6092031 Commit-Queue: Camden Bickel <cambickel@google.com> Reviewed-by: Jimmy Gong <jimmyxgong@chromium.org> Reviewed-by: Alex Gough <ajgo@chromium.org> Reviewed-by: David Padlipsky <dpad@google.com> Reviewed-by: Jiaming Cheng <jiamingc@chromium.org> Cr-Commit-Position: refs/heads/main@{#1401983}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
5cb7edb85a
commit
4dca0cd88d
ash
accelerators
accelerator_commands.ccaccelerator_commands.haccelerator_controller_impl.ccash_accelerator_configuration.cc
ash_strings.grdash_strings_grd
IDS_ASH_ACCELERATOR_DESCRIPTION_TOGGLE_CAMERA_ENABLED.png.sha1IDS_ASH_CAMERA_ACCESS_DISABLED.png.sha1IDS_ASH_CAMERA_NOW_ALLOWED.png.sha1IDS_ASH_CAMERA_NOW_DISALLOWED.png.sha1
constants
public
cpp
mojom
webui
shortcut_customization_ui
tools/metrics/histograms/metadata
@ -51,6 +51,8 @@
|
||||
#include "ash/system/notification_center/notification_center_tray.h"
|
||||
#include "ash/system/palette/palette_tray.h"
|
||||
#include "ash/system/power/power_button_controller.h"
|
||||
#include "ash/system/privacy_hub/camera_privacy_switch_controller.h"
|
||||
#include "ash/system/privacy_hub/privacy_hub_controller.h"
|
||||
#include "ash/system/status_area_widget.h"
|
||||
#include "ash/system/time/calendar_metrics.h"
|
||||
#include "ash/system/time/calendar_model.h"
|
||||
@ -146,6 +148,9 @@ constexpr char kAssistantErrorToastId[] = "assistant_error";
|
||||
// Toast ID for the notification center tray "No notifications" toast.
|
||||
constexpr char kNotificationCenterTrayNoNotificationsToastId[] =
|
||||
"notification_center_tray_toast_ids.no_notifications";
|
||||
// Toast IDs for the Toggle Camera Allowed shortcut.
|
||||
constexpr char kToggleCameraToastId[] = "toggle_camera_toast";
|
||||
constexpr char kCameraForceDisabledToastId[] = "camera_force_disabled_toast";
|
||||
|
||||
// These values are written to logs. New enum values can be added, but existing
|
||||
// enums must never be renumbered or deleted and reused.
|
||||
@ -1438,6 +1443,54 @@ void ToggleCalendar() {
|
||||
calendar_metrics::CalendarEventSource::kKeyboard);
|
||||
}
|
||||
|
||||
void ToggleCameraAllowed() {
|
||||
if (!features::IsToggleCameraShortcutEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* pref_service =
|
||||
Shell::Get()->session_controller()->GetActivePrefService();
|
||||
if (!pref_service) {
|
||||
return;
|
||||
}
|
||||
|
||||
PrivacyHubController* privacy_hub_controller =
|
||||
Shell::Get()->privacy_hub_controller();
|
||||
if (!privacy_hub_controller) {
|
||||
return;
|
||||
}
|
||||
|
||||
CameraPrivacySwitchController* camera_privacy_switch_controller =
|
||||
privacy_hub_controller->camera_controller();
|
||||
if (!camera_privacy_switch_controller) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Camera access may be force-disabled in cases where an admin is using Remote
|
||||
// Desktop to control a user's device. This shortcut should respect that
|
||||
// setting and should not enable the camera in such situations.
|
||||
if (camera_privacy_switch_controller->IsCameraAccessForceDisabled()) {
|
||||
ShowToast(kCameraForceDisabledToastId,
|
||||
ToastCatalogName::kCameraForceDisabled,
|
||||
l10n_util::GetStringUTF16(IDS_ASH_CAMERA_ACCESS_DISABLED));
|
||||
return;
|
||||
}
|
||||
|
||||
// Toggle the value of the pref.
|
||||
const bool wasCameraPreviouslyAllowed =
|
||||
pref_service->GetBoolean(prefs::kUserCameraAllowed);
|
||||
const bool isCameraNowAllowed = !wasCameraPreviouslyAllowed;
|
||||
pref_service->SetBoolean(prefs::kUserCameraAllowed, isCameraNowAllowed);
|
||||
|
||||
if (isCameraNowAllowed) {
|
||||
ShowToast(kToggleCameraToastId, ToastCatalogName::kCameraNowAllowed,
|
||||
l10n_util::GetStringUTF16(IDS_ASH_CAMERA_NOW_ALLOWED));
|
||||
} else {
|
||||
ShowToast(kToggleCameraToastId, ToastCatalogName::kCameraNowAllowed,
|
||||
l10n_util::GetStringUTF16(IDS_ASH_CAMERA_NOW_DISALLOWED));
|
||||
}
|
||||
}
|
||||
|
||||
void ToggleCapsLock() {
|
||||
ImeControllerImpl* ime_controller = Shell::Get()->ime_controller();
|
||||
ime_controller->SetCapsLockEnabled(!ime_controller->IsCapsLockEnabled());
|
||||
|
@ -321,6 +321,9 @@ ASH_EXPORT void ToggleCalendar();
|
||||
// Turns caps lock on and off.
|
||||
ASH_EXPORT void ToggleCapsLock();
|
||||
|
||||
// Enables or disables camera access in privacy settings.
|
||||
ASH_EXPORT void ToggleCameraAllowed();
|
||||
|
||||
// Toggles the clipboard history.
|
||||
ASH_EXPORT void ToggleClipboardHistory(bool is_plain_text_paste);
|
||||
|
||||
|
@ -970,6 +970,8 @@ bool AcceleratorControllerImpl::CanPerformAction(
|
||||
launcher_state_machine_.get());
|
||||
case AcceleratorAction::kToggleCalendar:
|
||||
return true;
|
||||
case AcceleratorAction::kToggleCameraAllowed:
|
||||
return features::IsToggleCameraShortcutEnabled();
|
||||
case AcceleratorAction::kToggleCapsLock:
|
||||
return CanHandleToggleCapsLock(
|
||||
accelerator, previous_accelerator,
|
||||
@ -1541,6 +1543,9 @@ void AcceleratorControllerImpl::PerformAction(
|
||||
base::TimeTicks());
|
||||
break;
|
||||
}
|
||||
case AcceleratorAction::kToggleCameraAllowed:
|
||||
accelerators::ToggleCameraAllowed();
|
||||
break;
|
||||
case AcceleratorAction::kToggleCalendar:
|
||||
accelerators::ToggleCalendar();
|
||||
break;
|
||||
|
@ -165,6 +165,11 @@ std::vector<ash::AcceleratorData> GetDefaultAccelerators() {
|
||||
AppendAcceleratorData(accelerators, ash::kGeminiAcceleratorData);
|
||||
}
|
||||
|
||||
if (ash::features::IsToggleCameraShortcutEnabled()) {
|
||||
AppendAcceleratorData(accelerators,
|
||||
ash::kToggleCameraAllowedAcceleratorData);
|
||||
}
|
||||
|
||||
return accelerators;
|
||||
}
|
||||
|
||||
|
@ -2834,6 +2834,15 @@ You can also use the keyboard shortcut. First, highlight text, then press <ph na
|
||||
<message name="IDS_ASH_DESKS_DESK_16_MINI_VIEW_TITLE" desc="The label of the sixteenth virtual desk thumbnail.">
|
||||
Desk 16
|
||||
</message>
|
||||
<message name="IDS_ASH_CAMERA_NOW_ALLOWED" desc="The toast message that appears when the shortcut to toggle camera access is invoked, and camera access is now enabled.">
|
||||
Apps can access camera
|
||||
</message>
|
||||
<message name="IDS_ASH_CAMERA_NOW_DISALLOWED" desc="The toast message that appears when the shortcut to toggle camera access is invoked, and camera access is now disabled.">
|
||||
Apps can't access camera
|
||||
</message>
|
||||
<message name="IDS_ASH_CAMERA_ACCESS_DISABLED" desc="The toast message that appears when the shortcut to toggle camera access is invoked, but camera access cannot be enabled because there is currently an admin remote desktop session active.">
|
||||
Can't turn on camera access remotely
|
||||
</message>
|
||||
<message name="IDS_ASH_DESKS_MAX_NUM_REACHED" desc="Message shown to users when they attempt to add a new virtual desk when the maximum number of desks has been reached.">
|
||||
Maximum number of desks reached.
|
||||
</message>
|
||||
@ -4251,6 +4260,9 @@ No devices connected.
|
||||
<message name="IDS_ASH_ACCELERATOR_DESCRIPTION_RESIZE_PIP_WINDOW" desc="Label for accelerator action - Resize the picture-in-picture window.">
|
||||
Switch between the maximum or current size of the picture-in-picture window
|
||||
</message>
|
||||
<message name="IDS_ASH_ACCELERATOR_DESCRIPTION_TOGGLE_CAMERA_ENABLED" desc="Label for accelerator action - Toggle whether the camera access setting is enabled.">
|
||||
Turn on/off camera access
|
||||
</message>
|
||||
<message name="IDS_ASH_ACCELERATOR_DESCRIPTION_FOCUS_PREVIOUS_PANE" desc="Label for accelerator action - Move focus to previous pane.">
|
||||
Move focus to previous pane
|
||||
</message>
|
||||
|
@ -0,0 +1 @@
|
||||
aedece62ff765a62d22ccb2d49fb357762d6a82d
|
@ -0,0 +1 @@
|
||||
2809c83c5a28363acaf2845ca58f7dc2b546e036
|
1
ash/ash_strings_grd/IDS_ASH_CAMERA_NOW_ALLOWED.png.sha1
Normal file
1
ash/ash_strings_grd/IDS_ASH_CAMERA_NOW_ALLOWED.png.sha1
Normal file
@ -0,0 +1 @@
|
||||
2af96f6c53b44238c80d5fc66e3a264d94976725
|
@ -0,0 +1 @@
|
||||
cf8f82a2fdd55359a73604f39bc4081fcdbffc4a
|
@ -330,7 +330,10 @@ enum class ToastCatalogName {
|
||||
kCoralSavedGroupLimitMax = 58,
|
||||
kScannerActionSuccess = 59,
|
||||
kScannerActionFailure = 60,
|
||||
kMaxValue = kScannerActionFailure
|
||||
kCameraNowAllowed = 61,
|
||||
kCameraNowDisallowed = 62,
|
||||
kCameraForceDisabled = 63,
|
||||
kMaxValue = kCameraForceDisabled
|
||||
};
|
||||
|
||||
} // namespace ash
|
||||
|
@ -173,6 +173,7 @@ namespace ash {
|
||||
ACCELERATOR_ACTION_ENTRY(ResizePipWindow) \
|
||||
ACCELERATOR_ACTION_ENTRY(ToggleGeminiApp) \
|
||||
ACCELERATOR_ACTION_ENTRY(ToggleDoNotDisturb) \
|
||||
ACCELERATOR_ACTION_ENTRY(ToggleCameraAllowed) \
|
||||
/* Debug actions are kept at an offset.*/ \
|
||||
/* This offset should be kept consistent with the enum*/ \
|
||||
/* `AcceleratorAction` in*/ \
|
||||
|
@ -18,12 +18,12 @@ namespace ash {
|
||||
namespace {
|
||||
|
||||
// The total number of accelerator actions.
|
||||
constexpr int kAcceleratorActionsTotalNum = 169;
|
||||
constexpr int kAcceleratorActionsTotalNum = 170;
|
||||
// The toal number of debug accelerators, these will not be used for hashing.
|
||||
constexpr int kDebugAcceleratorActionsNum = 28;
|
||||
// The hash of accelerator actions. Please update this when adding a new
|
||||
// accelerator action.
|
||||
constexpr char kAcceleratorActionsHash[] = "c959943640043de5e44136e3154e30d2";
|
||||
constexpr char kAcceleratorActionsHash[] = "cdcdcd8ea8502dc46c7564f52e56d696";
|
||||
|
||||
// Define the mapping between an AcceleratorAction and its string name.
|
||||
// Example:
|
||||
|
@ -456,6 +456,17 @@ ASH_PUBLIC_EXPORT inline constexpr size_t
|
||||
kToggleDoNotDisturbAcceleratorDataLength =
|
||||
std::size(kToggleDoNotDisturbAcceleratorData);
|
||||
|
||||
// TODO(385364574): Replace this fake temporary keycode with actual keycode.
|
||||
ASH_PUBLIC_EXPORT inline constexpr AcceleratorData
|
||||
kToggleCameraAllowedAcceleratorData[] = {
|
||||
{true, ui::VKEY_F23,
|
||||
ui::EF_COMMAND_DOWN | ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN,
|
||||
AcceleratorAction::kToggleCameraAllowed},
|
||||
};
|
||||
ASH_PUBLIC_EXPORT inline constexpr size_t
|
||||
kToggleCameraAllowedAcceleratorDataLength =
|
||||
std::size(kToggleCameraAllowedAcceleratorData);
|
||||
|
||||
// The public-facing interface for accelerator handling, which is Ash's duty to
|
||||
// implement.
|
||||
class ASH_PUBLIC_EXPORT AcceleratorController {
|
||||
|
@ -147,6 +147,7 @@ enum AcceleratorAction {
|
||||
kResizePipWindow,
|
||||
kToggleGeminiApp,
|
||||
kToggleDoNotDisturb,
|
||||
kToggleCameraAllowed,
|
||||
// The following are DEBUG actions with an offset. This is to keep the enum
|
||||
// in sync with `AcceleratorActions` in ash/public/cpp/accelerator_actions.h.
|
||||
kDebugClearUseKMeansPref = 9000,
|
||||
|
@ -297,6 +297,8 @@ EnumTraits<mojom_accelerator_action, ash::AcceleratorAction>::ToMojom(
|
||||
return mojom_accelerator_action::kToggleGeminiApp;
|
||||
case ash::kToggleDoNotDisturb:
|
||||
return mojom_accelerator_action::kToggleDoNotDisturb;
|
||||
case ash::AcceleratorAction::kToggleCameraAllowed:
|
||||
return mojom_accelerator_action::kToggleCameraAllowed;
|
||||
case ash::AcceleratorAction::kDebugClearUseKMeansPref:
|
||||
return mojom_accelerator_action::kDebugClearUseKMeansPref;
|
||||
case ash::AcceleratorAction::kDebugKeyboardBacklightToggle:
|
||||
@ -785,6 +787,9 @@ bool EnumTraits<mojom_accelerator_action, ash::AcceleratorAction>::FromMojom(
|
||||
case mojom_accelerator_action::kToggleDoNotDisturb:
|
||||
*out = ash::AcceleratorAction::kToggleDoNotDisturb;
|
||||
return true;
|
||||
case mojom_accelerator_action::kToggleCameraAllowed:
|
||||
*out = ash::AcceleratorAction::kToggleCameraAllowed;
|
||||
return true;
|
||||
case mojom_accelerator_action::kDebugClearUseKMeansPref:
|
||||
*out = ash::AcceleratorAction::kDebugClearUseKMeansPref;
|
||||
return true;
|
||||
|
@ -459,6 +459,8 @@ bool ShouldExcludeItem(const AcceleratorLayoutDetails& details) {
|
||||
return !features::IsAppLaunchShortcutEnabled();
|
||||
case kToggleSnapGroupWindowsMinimizeAndRestore:
|
||||
return true;
|
||||
case kToggleCameraAllowed:
|
||||
return !features::IsToggleCameraShortcutEnabled();
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -571,6 +571,14 @@ const AcceleratorLayoutMap& GetAcceleratorLayoutMap() {
|
||||
mojom::AcceleratorSubcategory::kGeneralControls, /*locked=*/false,
|
||||
mojom::AcceleratorLayoutStyle::kDefault,
|
||||
mojom::AcceleratorSource::kAsh)},
|
||||
{AcceleratorAction::kToggleCameraAllowed,
|
||||
AcceleratorLayoutDetails(
|
||||
AcceleratorAction::kToggleCameraAllowed,
|
||||
IDS_ASH_ACCELERATOR_DESCRIPTION_TOGGLE_CAMERA_ENABLED,
|
||||
mojom::AcceleratorCategory::kGeneral,
|
||||
mojom::AcceleratorSubcategory::kGeneralControls,
|
||||
/*locked=*/false, mojom::AcceleratorLayoutStyle::kDefault,
|
||||
mojom::AcceleratorSource::kAsh)},
|
||||
{AcceleratorAction::kOpenFileManager,
|
||||
AcceleratorLayoutDetails(
|
||||
AcceleratorAction::kOpenFileManager,
|
||||
|
@ -296,6 +296,7 @@ inline constexpr uint32_t kAcceleratorLayouts[] = {
|
||||
AcceleratorAction::kSwitchToPreviousUser,
|
||||
AcceleratorAction::kStartAssistant,
|
||||
AcceleratorAction::kToggleDoNotDisturb,
|
||||
AcceleratorAction::kToggleCameraAllowed,
|
||||
|
||||
// General > Apps
|
||||
AcceleratorAction::kOpenFileManager,
|
||||
|
@ -2393,6 +2393,9 @@ chromeos/ash/components/peripheral_notification/peripheral_notification_manager.
|
||||
<int value="58" label="Coral Saved Groups Limit Max"/>
|
||||
<int value="59" label="Scanner Action Success"/>
|
||||
<int value="60" label="Scanner Action Failure"/>
|
||||
<int value="61" label="Apps Can Access Camera"/>
|
||||
<int value="62" label="Apps Can't Access Camera"/>
|
||||
<int value="63" label="Can't Turn On Camera Access Remotely"/>
|
||||
</enum>
|
||||
|
||||
<enum name="TogglePickerAction">
|
||||
|
@ -152,6 +152,7 @@ chromium-metrics-reviews@google.com.
|
||||
<variant name="TilingWindowResizeUp"/>
|
||||
<variant name="ToggleAppList"/>
|
||||
<variant name="ToggleCalendar"/>
|
||||
<variant name="ToggleCameraAllowed"/>
|
||||
<variant name="ToggleCapsLock"/>
|
||||
<variant name="ToggleClipboardHistory"/>
|
||||
<variant name="ToggleDictation"/>
|
||||
|
@ -191,6 +191,7 @@ chromium-metrics-reviews@google.com.
|
||||
<int value="137" label="ResizePipWindow"/>
|
||||
<int value="138" label="ToggleGeminiApp"/>
|
||||
<int value="139" label="ToggleDoNotDisturb"/>
|
||||
<int value="140" label="ToggleCameraAllowed"/>
|
||||
<int value="9000" label="DebugClearUseKMeansPref"/>
|
||||
<int value="9001" label="DebugKeyboardBacklightToggle"/>
|
||||
<int value="9002" label="DebugMicrophoneMuteToggle"/>
|
||||
|
Reference in New Issue
Block a user