333 lines
14 KiB
Diff
333 lines
14 KiB
Diff
From: uazo <uazo@users.noreply.github.com>
|
|
Date: Tue, 14 Mar 2023 15:48:21 +0000
|
|
Subject: Keyboard protection flag
|
|
|
|
Hides user preference on the system keyboard by setting the standard
|
|
eng layout and removing the layout information from the javascript
|
|
keyboard events.
|
|
|
|
License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html
|
|
---
|
|
.../common/ProductionSupportedFlagList.java | 5 +
|
|
.../Keyboard-protection-flag.inc | 10 ++
|
|
.../renderer/core/events/keyboard_event.cc | 136 ++++++++++++++++++
|
|
.../renderer/core/events/keyboard_event.h | 2 +
|
|
ui/base/ui_base_features.cc | 8 ++
|
|
ui/base/ui_base_features.h | 2 +
|
|
.../dom/dom_keyboard_layout_map_win.cc | 13 ++
|
|
.../keycodes/keyboard_code_conversion.cc | 10 +-
|
|
ui/events/keycodes/keyboard_code_conversion.h | 2 +-
|
|
9 files changed, 185 insertions(+), 3 deletions(-)
|
|
create mode 100644 cromite_flags/chrome/browser/about_flags_cc/Keyboard-protection-flag.inc
|
|
|
|
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
|
|
--- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
|
|
+++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
|
|
@@ -993,6 +993,11 @@ public final class ProductionSupportedFlagList {
|
|
+ " also enable the same behaviour as this flag. Additionally, developer"
|
|
+ " preferences via the AndroidX API or manifest metadata supersedes this"
|
|
+ " flag."),
|
|
+ Flag.baseFeature(
|
|
+ "SystemKeyboardProtection",
|
|
+ "Hides user preference on the system keyboard by setting the standard "
|
|
+ + "eng layout and removing the layout information from the "
|
|
+ + "javascript keyboard events."),
|
|
Flag.baseFeature(
|
|
BlinkFeatures.ASYNC_SET_COOKIE,
|
|
"When enabled, the communication between renderer and network service is "
|
|
diff --git a/cromite_flags/chrome/browser/about_flags_cc/Keyboard-protection-flag.inc b/cromite_flags/chrome/browser/about_flags_cc/Keyboard-protection-flag.inc
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/cromite_flags/chrome/browser/about_flags_cc/Keyboard-protection-flag.inc
|
|
@@ -0,0 +1,10 @@
|
|
+#ifdef FLAG_SECTION
|
|
+
|
|
+ {"system-keyboard-protection",
|
|
+ "System keyboard protection",
|
|
+ "Hides user preference on the system keyboard by setting the standard "
|
|
+ "eng layout and removing the layout information from the "
|
|
+ "javascript keyboard events.", kOsAll,
|
|
+ FEATURE_VALUE_TYPE(features::kSystemKeyboardProtection)},
|
|
+
|
|
+#endif
|
|
diff --git a/third_party/blink/renderer/core/events/keyboard_event.cc b/third_party/blink/renderer/core/events/keyboard_event.cc
|
|
--- a/third_party/blink/renderer/core/events/keyboard_event.cc
|
|
+++ b/third_party/blink/renderer/core/events/keyboard_event.cc
|
|
@@ -36,6 +36,18 @@
|
|
#include "third_party/blink/renderer/platform/windows_keyboard_codes.h"
|
|
#include "ui/events/keycodes/dom/keycode_converter.h"
|
|
|
|
+#include "base/feature_list.h"
|
|
+#include "third_party/blink/renderer/core/dom/element.h"
|
|
+#include "third_party/blink/renderer/core/dom/events/event_dispatch_result.h"
|
|
+#include "third_party/blink/renderer/core/dom/events/event_dispatcher.h"
|
|
+#include "third_party/blink/renderer/core/editing/editing_utilities.h"
|
|
+#include "third_party/blink/renderer/core/html/forms/text_control_element.h"
|
|
+#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
|
|
+#include "ui/base/ui_base_features.h"
|
|
+#include "ui/events/event_constants.h"
|
|
+#include "ui/events/keycodes/dom/dom_codes_array.h"
|
|
+#include "ui/events/keycodes/keyboard_code_conversion.h"
|
|
+
|
|
namespace blink {
|
|
|
|
namespace {
|
|
@@ -132,6 +144,124 @@ KeyboardEvent::KeyboardEvent(const WebKeyboardEvent& key,
|
|
else
|
|
key_code_ = char_code_;
|
|
|
|
+ bool keyboard_protection = features::IsSystemKeyboardProtectionEnabled();
|
|
+ if (dom_window) {
|
|
+ if (auto* frame = dom_window->GetFrame()) {
|
|
+ String protocol =
|
|
+ frame->GetSecurityContext()->GetSecurityOrigin()->Protocol();
|
|
+ if (SchemeRegistry::IsWebUIScheme(protocol)) {
|
|
+ keyboard_protection = false;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if (keyboard_protection) {
|
|
+ // we need character for transformation
|
|
+ ui::DomKey ascii_key;
|
|
+ ui::DomKey original_dom_key =
|
|
+ static_cast<ui::DomKey>(key.dom_key);
|
|
+ // 1 <= char_code <= 26: exclude ctrl-a ... control-z
|
|
+ if (char_code_ > 26 && original_dom_key.IsCharacter())
|
|
+ ascii_key = ui::DomKey::FromCharacter(key.text[0]);
|
|
+ else
|
|
+ ascii_key = original_dom_key;
|
|
+
|
|
+ // if there is an element with focus, do not transform
|
|
+ // the characters into the English layout, since the
|
|
+ // recalculated character in the html innerText could
|
|
+ // be used to reconstruct the user's layout.
|
|
+ // if there is no focus, the event will contain the English
|
|
+ // layout information, since the real character will not be
|
|
+ // available for a textbox or content-editable element
|
|
+ // for comparision.
|
|
+ bool is_editable;
|
|
+ if (modifiers_ & WebInputEvent::kControlKey) {
|
|
+ // special case for ctrl keys
|
|
+ is_editable = false;
|
|
+ } else if (Document* document = dom_window->document()) {
|
|
+ if (Node* node = EventTargetNodeForDocument(document)) {
|
|
+ auto* text_control = ToTextControlOrNull(node);
|
|
+ auto* element = DynamicTo<Element>(node);
|
|
+ is_editable = IsEditable(*node) ||
|
|
+ (text_control && !text_control->IsDisabledOrReadOnly()) ||
|
|
+ (element &&
|
|
+ EqualIgnoringAsciiCase(
|
|
+ element->FastGetAttribute(html_names::kRoleAttr), "textbox"));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // get domcode of us layout keyboard
|
|
+ // we transform the character pressed by the user into
|
|
+ // the relevant domkey of the English keyboard
|
|
+ // so, for example:
|
|
+ // for ascii_key = "
|
|
+ // in italian keyboard --> shift + Digit2
|
|
+ // in us keybord --> shift + Quote
|
|
+ int shift_needed = 0;
|
|
+ ui::DomCode us_code = ui::UsLayoutDomKeyToDomCode(ascii_key, &shift_needed);
|
|
+ if (us_code == ui::DomCode::NONE && !is_editable) {
|
|
+ // the keyboard may have non latin characters
|
|
+ // we have to traslate the DomCode to us layout DomCode
|
|
+ // but do not recalculate if there is an element with
|
|
+ // focus (or is a contenteditable)
|
|
+ ui::KeyboardCode ignored;
|
|
+ int flags = ui::EF_NONE;
|
|
+ if (modifiers_ & WebInputEvent::kAltKey)
|
|
+ flags |= ui::EF_ALT_DOWN;
|
|
+ if (modifiers_ & WebInputEvent::kControlKey)
|
|
+ flags |= ui::EF_CONTROL_DOWN;
|
|
+ if (modifiers_& WebInputEvent::kMetaKey)
|
|
+ flags |= ui::EF_COMMAND_DOWN;
|
|
+ if (modifiers_ & WebInputEvent::kShiftKey ||
|
|
+ modifiers_ & WebInputEvent::kCapsLockOn)
|
|
+ flags |= ui::EF_SHIFT_DOWN;
|
|
+ if (modifiers_ & WebInputEvent::kNumLockOn)
|
|
+ flags |= ui::EF_NUM_LOCK_ON;
|
|
+ if (ui::DomCodeToUsLayoutDomKey(
|
|
+ static_cast<ui::DomCode>(key.dom_code), flags, &ascii_key, &ignored)) {
|
|
+ us_code = ui::UsLayoutDomKeyToDomCode(ascii_key, &shift_needed);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // adjust the shift modifier
|
|
+ if (shift_needed == 0)
|
|
+ modifiers_ &= ~WebInputEvent::kShiftKey;
|
|
+ else if (shift_needed == 1)
|
|
+ modifiers_ |= WebInputEvent::kShiftKey;
|
|
+
|
|
+ // convert keyboard code to us layout (platform code)
|
|
+ if (type() == event_type_names::kKeydown ||
|
|
+ type() == event_type_names::kKeyup) {
|
|
+ int windows_key_code = ui::DomCodeToUsLayoutNonLocatedKeyboardCode(us_code);
|
|
+ key_code_ = windows_key_code;
|
|
+ }
|
|
+
|
|
+ // regenerate key_ and code_ for us keyboard
|
|
+ // if the value is not recalculated, or a key is not found
|
|
+ // in the English layout, the value is empty
|
|
+ key_ = FromUtf8(ui::KeycodeConverter::DomKeyToKeyString(ascii_key));
|
|
+ code_ = FromUtf8(ui::KeycodeConverter::DomCodeToCodeString(us_code));
|
|
+
|
|
+ // suppress event if is ctrl/shift/alt... otherwise key_code of
|
|
+ // the next character can be stolen
|
|
+ // and do not send dead keys
|
|
+ // we cannot do otherwise because some characters are generated
|
|
+ // with the shift or without depending on the keyboard
|
|
+ if (ui::KeycodeConverter::IsDomKeyForModifier(original_dom_key) ||
|
|
+ original_dom_key.IsDeadKey()) {
|
|
+ suppress_event_ = true;
|
|
+ }
|
|
+
|
|
+ // do not leak status of numlock/capslock/scrolllock/etc
|
|
+ modifiers_ &= ~(WebInputEvent::kSymbolKey | WebInputEvent::kFnKey |
|
|
+ WebInputEvent::kAltGrKey | WebInputEvent::kMetaKey |
|
|
+ /*WebInputEvent::kAltKey |*/ WebInputEvent::kIsKeyPad |
|
|
+ WebInputEvent::kSymbolKey | WebInputEvent::kScrollLockOn |
|
|
+ WebInputEvent::kCapsLockOn | WebInputEvent::kNumLockOn);
|
|
+
|
|
+ // always clear location
|
|
+ location_ = KeyboardEvent::kDomKeyLocationStandard;
|
|
+ }
|
|
+
|
|
#if BUILDFLAG(IS_ANDROID)
|
|
// FIXME: Check to see if this applies to other OS.
|
|
// If the key event belongs to IME composition then propagate to JS.
|
|
@@ -205,6 +335,12 @@ unsigned KeyboardEvent::which() const {
|
|
return (unsigned)keyCode();
|
|
}
|
|
|
|
+DispatchEventResult KeyboardEvent::DispatchEvent(EventDispatcher& dispatcher) {
|
|
+ if (suppress_event_)
|
|
+ return DispatchEventResult::kNotCanceled;
|
|
+ return dispatcher.Dispatch();
|
|
+}
|
|
+
|
|
void KeyboardEvent::InitLocationModifiers(unsigned location) {
|
|
switch (location) {
|
|
case KeyboardEvent::kDomKeyLocationNumpad:
|
|
diff --git a/third_party/blink/renderer/core/events/keyboard_event.h b/third_party/blink/renderer/core/events/keyboard_event.h
|
|
--- a/third_party/blink/renderer/core/events/keyboard_event.h
|
|
+++ b/third_party/blink/renderer/core/events/keyboard_event.h
|
|
@@ -99,6 +99,7 @@ class CORE_EXPORT KeyboardEvent final : public UIEventWithKeyState {
|
|
unsigned which() const override;
|
|
bool isComposing() const { return is_composing_; }
|
|
|
|
+ DispatchEventResult DispatchEvent(EventDispatcher&) override;
|
|
|
|
void Trace(Visitor*) const override;
|
|
|
|
@@ -112,6 +113,7 @@ class CORE_EXPORT KeyboardEvent final : public UIEventWithKeyState {
|
|
bool is_composing_ = false;
|
|
unsigned char_code_ = 0;
|
|
unsigned key_code_ = 0;
|
|
+ bool suppress_event_ = false;
|
|
};
|
|
|
|
template <>
|
|
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc
|
|
--- a/ui/base/ui_base_features.cc
|
|
+++ b/ui/base/ui_base_features.cc
|
|
@@ -145,6 +145,14 @@ bool ShouldUseCursorEventHook() {
|
|
// Allows system keyboard event capture via the keyboard lock API.
|
|
BASE_FEATURE(kSystemKeyboardLock, base::FEATURE_ENABLED_BY_DEFAULT);
|
|
|
|
+CROMITE_FEATURE(kSystemKeyboardProtection,
|
|
+ "SystemKeyboardProtection",
|
|
+ base::FEATURE_ENABLED_BY_DEFAULT);
|
|
+
|
|
+bool IsSystemKeyboardProtectionEnabled() {
|
|
+ return base::FeatureList::IsEnabled(kSystemKeyboardProtection);
|
|
+}
|
|
+
|
|
// Enables GPU rasterization for all UI drawing (where not blocklisted).
|
|
BASE_FEATURE(kUiGpuRasterization, base::FEATURE_ENABLED_BY_DEFAULT);
|
|
|
|
diff --git a/ui/base/ui_base_features.h b/ui/base/ui_base_features.h
|
|
--- a/ui/base/ui_base_features.h
|
|
+++ b/ui/base/ui_base_features.h
|
|
@@ -29,6 +29,8 @@ COMPONENT_EXPORT(UI_BASE_FEATURES)
|
|
BASE_DECLARE_FEATURE(kSettingsShowsPerKeyboardSettings);
|
|
#endif // BUILDFLAG(IS_CHROMEOS)
|
|
COMPONENT_EXPORT(UI_BASE_FEATURES) BASE_DECLARE_FEATURE(kSystemKeyboardLock);
|
|
+COMPONENT_EXPORT(UI_BASE_FEATURES) BASE_DECLARE_FEATURE(kSystemKeyboardProtection);
|
|
+COMPONENT_EXPORT(UI_BASE_FEATURES) bool IsSystemKeyboardProtectionEnabled();
|
|
COMPONENT_EXPORT(UI_BASE_FEATURES)
|
|
BASE_DECLARE_FEATURE(kUiCompositorScrollWithLayers);
|
|
COMPONENT_EXPORT(UI_BASE_FEATURES)
|
|
diff --git a/ui/events/keycodes/dom/dom_keyboard_layout_map_win.cc b/ui/events/keycodes/dom/dom_keyboard_layout_map_win.cc
|
|
--- a/ui/events/keycodes/dom/dom_keyboard_layout_map_win.cc
|
|
+++ b/ui/events/keycodes/dom/dom_keyboard_layout_map_win.cc
|
|
@@ -13,6 +13,8 @@
|
|
#include "base/check_op.h"
|
|
#include "base/containers/flat_map.h"
|
|
#include "base/logging.h"
|
|
+#include "base/feature_list.h"
|
|
+#include "ui/base/ui_base_features.h"
|
|
#include "ui/events/keycodes/dom/dom_code.h"
|
|
#include "ui/events/keycodes/dom/dom_key.h"
|
|
#include "ui/events/keycodes/dom/dom_keyboard_layout_map_base.h"
|
|
@@ -73,6 +75,17 @@ uint32_t DomKeyboardLayoutMapWin::GetKeyboardLayoutCount() {
|
|
iter != keyboard_layout_handles_.end())
|
|
std::iter_swap(keyboard_layout_handles_.begin(), iter);
|
|
|
|
+ if (features::IsSystemKeyboardProtectionEnabled()) {
|
|
+ HKL actual_layout = GetKeyboardLayout(0);
|
|
+
|
|
+ // get handle for en-us keyboard layout
|
|
+ keyboard_layout_handles_.clear();
|
|
+ keyboard_layout_handles_.resize(1);
|
|
+ keyboard_layout_handles_[0] = LoadKeyboardLayoutA("00000409", KLF_ACTIVATE);
|
|
+
|
|
+ // reactivate user keyboard layout
|
|
+ ActivateKeyboardLayout(actual_layout, KLF_SETFORPROCESS);
|
|
+ }
|
|
return keyboard_layout_handles_.size();
|
|
}
|
|
|
|
diff --git a/ui/events/keycodes/keyboard_code_conversion.cc b/ui/events/keycodes/keyboard_code_conversion.cc
|
|
--- a/ui/events/keycodes/keyboard_code_conversion.cc
|
|
+++ b/ui/events/keycodes/keyboard_code_conversion.cc
|
|
@@ -297,16 +297,22 @@ int ModifierDomKeyToEventFlag(DomKey key) {
|
|
// DomKey::SYMBOL_LOCK
|
|
}
|
|
|
|
-DomCode UsLayoutDomKeyToDomCode(DomKey dom_key) {
|
|
+DomCode UsLayoutDomKeyToDomCode(DomKey dom_key, int *need_shift) {
|
|
if (dom_key.IsCharacter()) {
|
|
char16_t c = dom_key.ToCharacter();
|
|
for (const auto& it : kPrintableCodeMap) {
|
|
- if (it.character[0] == c || it.character[1] == c) {
|
|
+ if (it.character[0] == c) {
|
|
+ *need_shift = 0;
|
|
+ return it.dom_code;
|
|
+ }
|
|
+ if (it.character[1] == c) {
|
|
+ *need_shift = 1;
|
|
return it.dom_code;
|
|
}
|
|
}
|
|
}
|
|
|
|
+ *need_shift = -1;
|
|
for (const auto& it : kNonPrintableCodeMap) {
|
|
if (it.dom_key == dom_key)
|
|
return it.dom_code;
|
|
diff --git a/ui/events/keycodes/keyboard_code_conversion.h b/ui/events/keycodes/keyboard_code_conversion.h
|
|
--- a/ui/events/keycodes/keyboard_code_conversion.h
|
|
+++ b/ui/events/keycodes/keyboard_code_conversion.h
|
|
@@ -111,7 +111,7 @@ EVENTS_BASE_EXPORT int ModifierDomKeyToEventFlag(DomKey key);
|
|
|
|
// Returns the physical DOM code along with a corresponding non-located
|
|
// Windows-based key_code.
|
|
-EVENTS_BASE_EXPORT DomCode UsLayoutDomKeyToDomCode(DomKey dom_key);
|
|
+EVENTS_BASE_EXPORT DomCode UsLayoutDomKeyToDomCode(DomKey dom_key, int *need_shift);
|
|
|
|
} // namespace ui
|
|
|
|
--
|