Commit 190f4ac2 authored by Joe Downing's avatar Joe Downing Committed by Commit Bot

[KeyboardLock] MacOS RWHV integration

This change includes the integration of the MacOS KeyboardHook impl in
the RenderWidgetHostViewMac and RenderWidgetHostViewCocoa classes.

RWHVMac handles the lock/unlock calls from RenderWidgetHostImpl and
forwards them to RWHVCocoa which handles the events and input routing.

The RenderWidgetHostViewMac and RenderWidgetHostViewCocoa integration
follows the same pattern I used for RenderWidgetHostViewAura and
RenderWidgetHostViewEventHandler. The main difference between this impl
and the Aura impl is that there is a bridge class between RWHVMac and
RWHVCocoa (RenderWidgetHostViewNsBridgeView).

BUG=680809

Change-Id: I524c98c059ae4883bf597704c326b5a0055f1212
Reviewed-on: https://chromium-review.googlesource.com/989618Reviewed-by: default avatarccameron <ccameron@chromium.org>
Reviewed-by: default avatarNick Carter <nick@chromium.org>
Commit-Queue: Joe Downing <joedow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#551491}
parent 425e15e2
......@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/keyboard_lock_browsertest.h"
#include <vector>
#include "base/macros.h"
......@@ -29,7 +31,7 @@ namespace content {
namespace {
// TODO(joedow): Enable tests on additional platforms as they are implemented.
#if defined(OS_WIN)
#if defined(OS_WIN) || defined(OS_MACOSX)
#define MAYBE_RUN(test_name) test_name
#else
#define MAYBE_RUN(test_name) DISABLED_##test_name
......@@ -69,9 +71,10 @@ constexpr char kKeyboardLockMethodCallWithSomeInvalidKeys[] =
constexpr char kKeyboardUnlockMethodCall[] = "navigator.keyboard.unlock()";
#if defined(USE_AURA)
bool g_window_has_focus = false;
#if defined(USE_AURA)
class TestRenderWidgetHostView : public RenderWidgetHostViewAura {
public:
TestRenderWidgetHostView(RenderWidgetHost* host, bool is_guest_view_hack)
......@@ -88,13 +91,6 @@ class TestRenderWidgetHostView : public RenderWidgetHostViewAura {
}
};
void InstallCreateHooksForKeyboardLockBrowserTests() {
WebContentsViewAura::InstallCreateHookForTests(
[](RenderWidgetHost* host,
bool is_guest_view_hack) -> RenderWidgetHostViewAura* {
return new TestRenderWidgetHostView(host, is_guest_view_hack);
});
}
#endif // USE_AURA
class FakeKeyboardLockWebContentsDelegate : public WebContentsDelegate {
......@@ -154,6 +150,22 @@ void FakeKeyboardLockWebContentsDelegate::CancelKeyboardLockRequest(
} // namespace
#if defined(USE_AURA)
void SetWindowFocusForKeyboardLockBrowserTests(bool is_focused) {
g_window_has_focus = is_focused;
}
void InstallCreateHooksForKeyboardLockBrowserTests() {
WebContentsViewAura::InstallCreateHookForTests(
[](RenderWidgetHost* host,
bool is_guest_view_hack) -> RenderWidgetHostViewAura* {
return new TestRenderWidgetHostView(host, is_guest_view_hack);
});
}
#endif // USE_AURA
class KeyboardLockBrowserTest : public ContentBrowserTest {
public:
KeyboardLockBrowserTest();
......@@ -206,10 +218,8 @@ KeyboardLockBrowserTest::~KeyboardLockBrowserTest() = default;
void KeyboardLockBrowserTest::SetUp() {
// Assume we have focus to start with.
g_window_has_focus = true;
#if defined(USE_AURA)
SetWindowFocusForKeyboardLockBrowserTests(true);
InstallCreateHooksForKeyboardLockBrowserTests();
#endif
SetUpFeatureList();
ContentBrowserTest::SetUp();
}
......@@ -299,7 +309,7 @@ void KeyboardLockBrowserTest::ExitFullscreen(const base::Location& from_here) {
}
void KeyboardLockBrowserTest::FocusContent(const base::Location& from_here) {
g_window_has_focus = true;
SetWindowFocusForKeyboardLockBrowserTests(true);
RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
web_contents()->GetRenderWidgetHostView()->GetRenderWidgetHost());
host->GotFocus();
......@@ -312,7 +322,7 @@ void KeyboardLockBrowserTest::FocusContent(const base::Location& from_here) {
}
void KeyboardLockBrowserTest::BlurContent(const base::Location& from_here) {
g_window_has_focus = false;
SetWindowFocusForKeyboardLockBrowserTests(false);
RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
web_contents()->GetRenderWidgetHostView()->GetRenderWidgetHost());
host->SetActive(false);
......
// 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.
#ifndef CONTENT_BROWSER_KEYBOARD_LOCK_BROWSERTEST_H_
#define CONTENT_BROWSER_KEYBOARD_LOCK_BROWSERTEST_H_
namespace content {
void SetWindowFocusForKeyboardLockBrowserTests(bool is_focused);
void InstallCreateHooksForKeyboardLockBrowserTests();
} // namespace content
#endif // CONTENT_BROWSER_KEYBOARD_LOCK_BROWSERTEST_H_
// 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 "content/browser/keyboard_lock_browsertest.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_mac.h"
#include "content/browser/web_contents/web_contents_view_mac.h"
namespace content {
namespace {
bool g_window_has_focus = false;
class TestRenderWidgetHostView : public RenderWidgetHostViewMac {
public:
TestRenderWidgetHostView(RenderWidgetHost* host, bool is_guest_view_hack)
: RenderWidgetHostViewMac(host, is_guest_view_hack) {}
~TestRenderWidgetHostView() override {}
bool HasFocus() const override { return g_window_has_focus; }
};
}
void SetWindowFocusForKeyboardLockBrowserTests(bool is_focused) {
g_window_has_focus = is_focused;
}
void InstallCreateHooksForKeyboardLockBrowserTests() {
WebContentsViewMac::InstallCreateHookForTests(
[](RenderWidgetHost* host,
bool is_guest_view_hack) -> RenderWidgetHostViewMac* {
return new TestRenderWidgetHostView(host, is_guest_view_hack);
});
}
} // namespace content
\ No newline at end of file
......@@ -9,7 +9,9 @@
#include <memory>
#include "base/containers/flat_set.h"
#include "base/macros.h"
#include "base/optional.h"
#include "base/strings/string16.h"
#include "content/common/mac/attributed_string_coder.h"
#include "third_party/blink/public/web/web_popup_type.h"
......@@ -92,6 +94,12 @@ class RenderWidgetHostNSViewBridge {
const mac::AttributedStringCoder::EncodedString& encoded_string,
gfx::Point baseline_point) = 0;
// Start intercepting keyboard events.
virtual void LockKeyboard(base::Optional<base::flat_set<int>> keys) = 0;
// Stop intercepting keyboard events.
virtual void UnlockKeyboard() = 0;
private:
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostNSViewBridge);
};
......
......@@ -53,6 +53,8 @@ class RenderWidgetHostViewNSViewBridgeLocal
void ShowDictionaryOverlay(
const mac::AttributedStringCoder::EncodedString& encoded_string,
gfx::Point baseline_point) override;
void LockKeyboard(base::Optional<base::flat_set<int>> keys) override;
void UnlockKeyboard() override;
private:
bool IsPopup() const {
......@@ -269,6 +271,15 @@ void RenderWidgetHostViewNSViewBridgeLocal::ShowDictionaryOverlay(
atPoint:flipped_baseline_point];
}
void RenderWidgetHostViewNSViewBridgeLocal::LockKeyboard(
base::Optional<base::flat_set<int>> keys) {
[cocoa_view_ lockKeyboard:std::move(keys)];
}
void RenderWidgetHostViewNSViewBridgeLocal::UnlockKeyboard() {
[cocoa_view_ unlockKeyboard];
}
} // namespace
// static
......
......@@ -10,7 +10,9 @@
#include <set>
#include <vector>
#include "base/containers/flat_set.h"
#include "base/mac/scoped_nsobject.h"
#include "base/optional.h"
#include "content/browser/renderer_host/input/mouse_wheel_rails_filter_mac.h"
#include "content/common/edit_command.h"
#import "ui/base/cocoa/command_dispatcher.h"
......@@ -215,6 +217,11 @@ struct DidOverscrollParams;
- (base::string16)selectedText;
// Set the current TextInputManager::CompositionRangeInfo from the renderer.
- (void)setCompositionRange:(gfx::Range)range;
// KeyboardLock methods.
- (void)lockKeyboard:(base::Optional<base::flat_set<int>>)keysToLock;
- (void)unlockKeyboard;
// Methods previously marked as private.
- (id)initWithClient:(content::RenderWidgetHostNSViewClient*)client;
- (void)setResponderDelegate:
......
......@@ -10,6 +10,7 @@
#include "base/debug/crash_logging.h"
#include "base/mac/bind_objc_block.h"
#include "base/mac/mac_util.h"
#include "base/stl_util.h"
#include "base/strings/sys_string_conversions.h"
#import "content/browser/accessibility/browser_accessibility_cocoa.h"
#import "content/browser/accessibility/browser_accessibility_mac.h"
......@@ -25,6 +26,8 @@
#include "ui/base/cocoa/cocoa_base_utils.h"
#include "ui/display/screen.h"
#include "ui/events/event_utils.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/gfx/mac/coordinate_conversion.h"
using content::BrowserAccessibility;
......@@ -187,7 +190,10 @@ void ExtractUnderlines(NSAttributedString* string,
// RenderWidgetHostViewCocoa ---------------------------------------------------
// Private methods:
@interface RenderWidgetHostViewCocoa ()
@interface RenderWidgetHostViewCocoa () {
bool keyboardLockActive_;
base::Optional<base::flat_set<int>> lockedKeys_;
}
- (void)processedWheelEvent:(const blink::WebMouseWheelEvent&)event
consumed:(BOOL)consumed;
- (void)keyEvent:(NSEvent*)theEvent wasKeyEquivalent:(BOOL)equiv;
......@@ -198,6 +204,7 @@ void ExtractUnderlines(NSAttributedString* string,
- (void)sendViewBoundsInWindowToClient;
- (void)sendWindowFrameInScreenToClient;
- (bool)clientIsDisconnected;
- (bool)isKeyLocked:(int)keyCode;
@end
@implementation RenderWidgetHostViewCocoa
......@@ -214,6 +221,7 @@ void ExtractUnderlines(NSAttributedString* string,
client_ = client;
canBeKeyView_ = YES;
isStylusEnteringProximity_ = false;
keyboardLockActive_ = false;
}
return self;
}
......@@ -535,6 +543,26 @@ void ExtractUnderlines(NSAttributedString* string,
}
}
- (void)lockKeyboard:(base::Optional<base::flat_set<int>>)keysToLock {
// TODO(joedow): Integrate System-level keyboard hook into this method.
lockedKeys_ = std::move(keysToLock);
keyboardLockActive_ = true;
}
- (void)unlockKeyboard {
keyboardLockActive_ = false;
lockedKeys_.reset();
}
- (bool)isKeyLocked:(int)keyCode {
// Note: We do not want to treat the ESC key as locked as that key is used
// to exit fullscreen and we don't want to prevent them from exiting.
const int escNativeKeyCode =
ui::KeycodeConverter::DomCodeToNativeKeycode(ui::DomCode::ESCAPE);
return keyboardLockActive_ && keyCode != escNativeKeyCode &&
(!lockedKeys_ || base::ContainsKey(lockedKeys_.value(), keyCode));
}
- (BOOL)performKeyEquivalent:(NSEvent*)theEvent {
// |performKeyEquivalent:| is sent to all views of a window, not only down the
// responder chain (cf. "Handling Key Equivalents" in
......@@ -637,6 +665,11 @@ void ExtractUnderlines(NSAttributedString* string,
latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
// If KeyboardLock has been requested for this keyCode, then mark the event
// so it skips the pre-handler and is delivered straight to the website.
if ([self isKeyLocked:keyCode])
event.skip_in_browser = true;
// Do not forward key up events unless preceded by a matching key down,
// otherwise we might get an event from releasing the return key in the
// omnibox (https://crbug.com/338736) or from closing another window
......
......@@ -157,6 +157,9 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
bool LockMouse() override;
void UnlockMouse() override;
bool LockKeyboard(base::Optional<base::flat_set<int>> keys) override;
void UnlockKeyboard() override;
bool IsKeyboardLocked() override;
void GestureEventAck(const blink::WebGestureEvent& event,
InputEventAckState ack_result) override;
......@@ -532,6 +535,9 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
bool pinch_has_reached_zoom_threshold_ = false;
float pinch_unused_amount_ = 1.f;
// Tracks whether keyboard lock is active.
bool is_keyboard_locked_ = false;
// Factory used to safely scope delayed calls to ShutdownHost().
base::WeakPtrFactory<RenderWidgetHostViewMac> weak_factory_;
......
......@@ -951,6 +951,25 @@ void RenderWidgetHostViewMac::UnlockMouse() {
host()->LostMouseLock();
}
bool RenderWidgetHostViewMac::LockKeyboard(
base::Optional<base::flat_set<int>> keys) {
is_keyboard_locked_ = true;
ns_view_bridge_->LockKeyboard(std::move(keys));
return true;
}
void RenderWidgetHostViewMac::UnlockKeyboard() {
if (!is_keyboard_locked_)
return;
is_keyboard_locked_ = false;
ns_view_bridge_->UnlockKeyboard();
}
bool RenderWidgetHostViewMac::IsKeyboardLocked() {
return is_keyboard_locked_;
}
void RenderWidgetHostViewMac::GestureEventAck(const WebGestureEvent& event,
InputEventAckState ack_result) {
bool consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
......
......@@ -747,6 +747,8 @@ test("content_browsertests") {
"../browser/indexed_db/mock_browsertest_indexed_db_class_factory.h",
"../browser/isolated_origin_browsertest.cc",
"../browser/keyboard_lock_browsertest.cc",
"../browser/keyboard_lock_browsertest.h",
"../browser/keyboard_lock_browsertest_mac.mm",
"../browser/loader/cors_file_origin_browsertest.cc",
"../browser/loader/cross_site_document_blocking_browsertest.cc",
"../browser/loader/prefetch_browsertest.cc",
......
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