Commit 3d4b330d authored by Marina Ciocea's avatar Marina Ciocea Committed by Commit Bot

Map user input monitor key press count in shared memory region.

Notes:
- Key press count is written to a share memory region and used by audio::InputStream implementation
(audio service side was already landed in https://crrev.com/c/1011605/31).
- AudioInputStreamBroker passes a readonly handle to the shmem over IPC to audio::InputStream.
- Lock in UserInputMonitor was removed because Enable/Disable can only be called from UI thread
in new audio service input stream implementation, or on audio thread in old implementation.
- UserInputMonitor::EnableKeyPressMonitoring() returning void will be removed after switching to
audio service input streams.

Design doc: https://docs.google.com/document/d/1GHL4uMlIFox2eAqsjUQVA8eJ7HYU3g2AoyAqyx3pxMA/edit?usp=sharing

Bug: 836226

Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel
Change-Id: I75b5b4cb0ed49ce17df84a03300bb9da52d86846
Reviewed-on: https://chromium-review.googlesource.com/1032733
Commit-Queue: Marina Ciocea <marinaciocea@chromium.org>
Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Reviewed-by: default avatarMax Morin <maxmorin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#557115}
parent b450ddb8
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <utility> #include <utility>
#include "base/command_line.h" #include "base/command_line.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "content/browser/browser_main_loop.h" #include "content/browser/browser_main_loop.h"
#include "content/browser/media/media_internals.h" #include "content/browser/media/media_internals.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
...@@ -16,6 +17,7 @@ ...@@ -16,6 +17,7 @@
#include "content/public/common/content_client.h" #include "content/public/common/content_client.h"
#include "media/audio/audio_logging.h" #include "media/audio/audio_logging.h"
#include "media/base/media_switches.h" #include "media/base/media_switches.h"
#include "media/base/user_input_monitor.h"
#include "mojo/public/cpp/system/platform_handle.h" #include "mojo/public/cpp/system/platform_handle.h"
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
...@@ -61,15 +63,19 @@ AudioInputStreamBroker::AudioInputStreamBroker( ...@@ -61,15 +63,19 @@ AudioInputStreamBroker::AudioInputStreamBroker(
params_.set_format(media::AudioParameters::AUDIO_FAKE); params_.set_format(media::AudioParameters::AUDIO_FAKE);
} }
BrowserMainLoop* browser_main_loop = BrowserMainLoop::GetInstance();
// May be null in unit tests.
if (!browser_main_loop)
return;
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
if (params_.channel_layout() == if (params_.channel_layout() ==
media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) { media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) {
BrowserMainLoop* browser_main_loop = BrowserMainLoop::GetInstance();
// May be null in unit tests.
if (browser_main_loop)
browser_main_loop->keyboard_mic_registration()->Register(); browser_main_loop->keyboard_mic_registration()->Register();
} }
#else
user_input_monitor_ = static_cast<media::UserInputMonitorBase*>(
browser_main_loop->user_input_monitor());
#endif #endif
} }
...@@ -85,6 +91,9 @@ AudioInputStreamBroker::~AudioInputStreamBroker() { ...@@ -85,6 +91,9 @@ AudioInputStreamBroker::~AudioInputStreamBroker() {
if (browser_main_loop) if (browser_main_loop)
browser_main_loop->keyboard_mic_registration()->Deregister(); browser_main_loop->keyboard_mic_registration()->Deregister();
} }
#else
// Check that DisableKeyPressMonitoring() was called.
DCHECK(!user_input_monitor_);
#endif #endif
auto* process_host = RenderProcessHost::FromID(render_process_id()); auto* process_host = RenderProcessHost::FromID(render_process_id());
...@@ -100,6 +109,12 @@ void AudioInputStreamBroker::CreateStream( ...@@ -100,6 +109,12 @@ void AudioInputStreamBroker::CreateStream(
DCHECK(!observer_binding_.is_bound()); DCHECK(!observer_binding_.is_bound());
DCHECK(!client_request_); DCHECK(!client_request_);
base::ReadOnlySharedMemoryRegion key_press_count_buffer;
if (user_input_monitor_) {
key_press_count_buffer =
user_input_monitor_->EnableKeyPressMonitoringWithMapping();
}
media::mojom::AudioInputStreamClientPtr client; media::mojom::AudioInputStreamClientPtr client;
client_request_ = mojo::MakeRequest(&client); client_request_ = mojo::MakeRequest(&client);
...@@ -126,7 +141,7 @@ void AudioInputStreamBroker::CreateStream( ...@@ -126,7 +141,7 @@ void AudioInputStreamBroker::CreateStream(
media::AudioLogFactory::AudioComponent::AUDIO_INPUT_CONTROLLER, media::AudioLogFactory::AudioComponent::AUDIO_INPUT_CONTROLLER,
log_component_id, render_process_id(), render_frame_id()), log_component_id, render_process_id(), render_frame_id()),
device_id_, params_, shared_memory_count_, enable_agc_, device_id_, params_, shared_memory_count_, enable_agc_,
mojo::ScopedSharedBufferHandle(), mojo::WrapReadOnlySharedMemoryRegion(std::move(key_press_count_buffer)),
base::BindOnce(&AudioInputStreamBroker::StreamCreated, base::BindOnce(&AudioInputStreamBroker::StreamCreated,
weak_ptr_factory_.GetWeakPtr(), std::move(stream))); weak_ptr_factory_.GetWeakPtr(), std::move(stream)));
} }
...@@ -155,6 +170,14 @@ void AudioInputStreamBroker::StreamCreated( ...@@ -155,6 +170,14 @@ void AudioInputStreamBroker::StreamCreated(
void AudioInputStreamBroker::Cleanup() { void AudioInputStreamBroker::Cleanup() {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (user_input_monitor_) {
user_input_monitor_->DisableKeyPressMonitoring();
// Set to nullptr to check that DisableKeyPressMonitoring() was called
// before destructor
user_input_monitor_ = nullptr;
}
std::move(deleter_).Run(this); std::move(deleter_).Run(this);
} }
......
...@@ -17,6 +17,10 @@ ...@@ -17,6 +17,10 @@
#include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/binding.h"
#include "services/audio/public/mojom/stream_factory.mojom.h" #include "services/audio/public/mojom/stream_factory.mojom.h"
namespace media {
class UserInputMonitorBase;
}
namespace content { namespace content {
// AudioInputStreamBroker is used to broker a connection between a client // AudioInputStreamBroker is used to broker a connection between a client
...@@ -53,6 +57,7 @@ class CONTENT_EXPORT AudioInputStreamBroker final ...@@ -53,6 +57,7 @@ class CONTENT_EXPORT AudioInputStreamBroker final
media::AudioParameters params_; media::AudioParameters params_;
const uint32_t shared_memory_count_; const uint32_t shared_memory_count_;
const bool enable_agc_; const bool enable_agc_;
media::UserInputMonitorBase* user_input_monitor_ = nullptr;
DeleterCallback deleter_; DeleterCallback deleter_;
......
...@@ -104,14 +104,14 @@ class MockEventHandler : public media::AudioInputDelegate::EventHandler { ...@@ -104,14 +104,14 @@ class MockEventHandler : public media::AudioInputDelegate::EventHandler {
MOCK_METHOD1(OnStreamError, void(int)); MOCK_METHOD1(OnStreamError, void(int));
}; };
class MockUserInputMonitor : public media::UserInputMonitorBase { class MockUserInputMonitor : public media::UserInputMonitor {
public: public:
MockUserInputMonitor() {} MockUserInputMonitor() {}
uint32_t GetKeyPressCount() const override { return 0; } uint32_t GetKeyPressCount() const override { return 0; }
MOCK_METHOD0(StartKeyboardMonitoring, void()); MOCK_METHOD0(EnableKeyPressMonitoring, void());
MOCK_METHOD0(StopKeyboardMonitoring, void()); MOCK_METHOD0(DisableKeyPressMonitoring, void());
}; };
class MockAudioInputStream : public media::AudioInputStream { class MockAudioInputStream : public media::AudioInputStream {
......
...@@ -82,14 +82,14 @@ class MockSyncWriter : public AudioInputController::SyncWriter { ...@@ -82,14 +82,14 @@ class MockSyncWriter : public AudioInputController::SyncWriter {
MOCK_METHOD0(Close, void()); MOCK_METHOD0(Close, void());
}; };
class MockUserInputMonitor : public UserInputMonitorBase { class MockUserInputMonitor : public UserInputMonitor {
public: public:
MockUserInputMonitor() = default; MockUserInputMonitor() = default;
uint32_t GetKeyPressCount() const override { return 0; } uint32_t GetKeyPressCount() const override { return 0; }
MOCK_METHOD0(StartKeyboardMonitoring, void()); MOCK_METHOD0(EnableKeyPressMonitoring, void());
MOCK_METHOD0(StopKeyboardMonitoring, void()); MOCK_METHOD0(DisableKeyPressMonitoring, void());
}; };
class MockAudioInputStream : public AudioInputStream { class MockAudioInputStream : public AudioInputStream {
...@@ -185,13 +185,13 @@ TEST_P(AudioInputControllerTest, CreateRecordAndClose) { ...@@ -185,13 +185,13 @@ TEST_P(AudioInputControllerTest, CreateRecordAndClose) {
.Times(AtLeast(10)) .Times(AtLeast(10))
.WillRepeatedly( .WillRepeatedly(
CheckCountAndPostQuitTask(&count, 10, message_loop_.task_runner())); CheckCountAndPostQuitTask(&count, 10, message_loop_.task_runner()));
EXPECT_CALL(user_input_monitor_, StartKeyboardMonitoring()); EXPECT_CALL(user_input_monitor_, EnableKeyPressMonitoring());
controller_->Record(); controller_->Record();
// Record and wait until ten Write() callbacks are received. // Record and wait until ten Write() callbacks are received.
base::RunLoop().Run(); base::RunLoop().Run();
EXPECT_CALL(user_input_monitor_, StopKeyboardMonitoring()); EXPECT_CALL(user_input_monitor_, DisableKeyPressMonitoring());
EXPECT_CALL(sync_writer_, Close()); EXPECT_CALL(sync_writer_, Close());
CloseAudioController(); CloseAudioController();
} }
...@@ -212,10 +212,10 @@ TEST_P(AudioInputControllerTest, CloseTwice) { ...@@ -212,10 +212,10 @@ TEST_P(AudioInputControllerTest, CloseTwice) {
CreateAudioController(); CreateAudioController();
ASSERT_TRUE(controller_.get()); ASSERT_TRUE(controller_.get());
EXPECT_CALL(user_input_monitor_, StartKeyboardMonitoring()); EXPECT_CALL(user_input_monitor_, EnableKeyPressMonitoring());
controller_->Record(); controller_->Record();
EXPECT_CALL(user_input_monitor_, StopKeyboardMonitoring()); EXPECT_CALL(user_input_monitor_, DisableKeyPressMonitoring());
EXPECT_CALL(sync_writer_, Close()); EXPECT_CALL(sync_writer_, Close());
CloseAudioController(); CloseAudioController();
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "media/base/user_input_monitor.h" #include "media/base/user_input_monitor.h"
#include <utility>
#include "base/atomicops.h" #include "base/atomicops.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
...@@ -11,26 +13,28 @@ ...@@ -11,26 +13,28 @@
namespace media { namespace media {
uint32_t ReadKeyPressMonitorCount( uint32_t ReadKeyPressMonitorCount(
const base::ReadOnlySharedMemoryMapping& shmem_mapping) { const base::ReadOnlySharedMemoryMapping& readonly_mapping) {
if (!shmem_mapping.IsValid()) if (!readonly_mapping.IsValid())
return 0; return 0;
// No ordering constraints between Load/Store operations, a temporary // No ordering constraints between Load/Store operations, a temporary
// inconsistent value is fine. // inconsistent value is fine.
return base::subtle::NoBarrier_Load( return base::subtle::NoBarrier_Load(
reinterpret_cast<const base::subtle::Atomic32*>(shmem_mapping.memory())); reinterpret_cast<const base::subtle::Atomic32*>(
readonly_mapping.memory()));
} }
void WriteKeyPressMonitorCount( void WriteKeyPressMonitorCount(
const base::WritableSharedMemoryMapping& shmem_mapping, const base::WritableSharedMemoryMapping& writable_mapping,
uint32_t count) { uint32_t count) {
if (!shmem_mapping.IsValid()) if (!writable_mapping.IsValid())
return; return;
// No ordering constraints between Load/Store operations, a temporary // No ordering constraints between Load/Store operations, a temporary
// inconsistent value is fine. // inconsistent value is fine.
base::subtle::NoBarrier_Store( base::subtle::NoBarrier_Store(
reinterpret_cast<base::subtle::Atomic32*>(shmem_mapping.memory()), count); reinterpret_cast<base::subtle::Atomic32*>(writable_mapping.memory()),
count);
} }
#ifdef DISABLE_USER_INPUT_MONITOR #ifdef DISABLE_USER_INPUT_MONITOR
...@@ -45,26 +49,48 @@ UserInputMonitor::UserInputMonitor() = default; ...@@ -45,26 +49,48 @@ UserInputMonitor::UserInputMonitor() = default;
UserInputMonitor::~UserInputMonitor() = default; UserInputMonitor::~UserInputMonitor() = default;
UserInputMonitorBase::UserInputMonitorBase() = default; UserInputMonitorBase::UserInputMonitorBase() {
DETACH_FROM_SEQUENCE(owning_sequence_);
}
UserInputMonitorBase::~UserInputMonitorBase() { UserInputMonitorBase::~UserInputMonitorBase() {
DCHECK_EQ(0u, references_); DCHECK_EQ(0u, references_);
} }
void UserInputMonitorBase::EnableKeyPressMonitoring() { void UserInputMonitorBase::EnableKeyPressMonitoring() {
base::AutoLock auto_lock(lock_); DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
++references_; if (++references_ == 1) {
if (references_ == 1) {
StartKeyboardMonitoring(); StartKeyboardMonitoring();
DVLOG(2) << "Started keyboard monitoring."; DVLOG(2) << "Started keyboard monitoring.";
} }
} }
base::ReadOnlySharedMemoryRegion
UserInputMonitorBase::EnableKeyPressMonitoringWithMapping() {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
if (++references_ == 1) {
base::MappedReadOnlyRegion shmem =
base::ReadOnlySharedMemoryRegion::Create(sizeof(uint32_t));
if (!shmem.region.IsValid() || !shmem.mapping.IsValid()) {
DVLOG(2) << "Error mapping key press count shmem.";
return base::ReadOnlySharedMemoryRegion();
}
key_press_count_region_ =
base::ReadOnlySharedMemoryRegion(std::move(shmem.region));
WriteKeyPressMonitorCount(shmem.mapping, 0u);
StartKeyboardMonitoring(std::move(shmem.mapping));
DVLOG(2) << "Started keyboard monitoring.";
}
return key_press_count_region_.Duplicate();
}
void UserInputMonitorBase::DisableKeyPressMonitoring() { void UserInputMonitorBase::DisableKeyPressMonitoring() {
base::AutoLock auto_lock(lock_); DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
DCHECK_NE(references_, 0u); DCHECK_NE(references_, 0u);
--references_; if (--references_ == 0) {
if (references_ == 0) { key_press_count_region_ = base::ReadOnlySharedMemoryRegion();
StopKeyboardMonitoring(); StopKeyboardMonitoring();
DVLOG(2) << "Stopped keyboard monitoring."; DVLOG(2) << "Stopped keyboard monitoring.";
} }
......
...@@ -58,27 +58,32 @@ class MEDIA_EXPORT UserInputMonitor { ...@@ -58,27 +58,32 @@ class MEDIA_EXPORT UserInputMonitor {
}; };
// Monitors and notifies about keyboard events. // Monitors and notifies about keyboard events.
// Thread safe.
class MEDIA_EXPORT UserInputMonitorBase : public UserInputMonitor { class MEDIA_EXPORT UserInputMonitorBase : public UserInputMonitor {
public: public:
UserInputMonitorBase(); UserInputMonitorBase();
~UserInputMonitorBase() override; ~UserInputMonitorBase() override;
// A caller must call EnableKeyPressMonitoring and // A caller must call EnableKeyPressMonitoring(WithMapping) and
// DisableKeyPressMonitoring in pair. // DisableKeyPressMonitoring in pair on the same sequence.
void EnableKeyPressMonitoring() override; void EnableKeyPressMonitoring() override;
void DisableKeyPressMonitoring() override; void DisableKeyPressMonitoring() override;
// Initializes a MappedReadOnlyRegion storing key press count. Returns a
// readonly region to the mapping and passes the writable mapping to platform
// specific implementation, to update key press count. If monitoring is
// already enabled, it only returns a handle to readonly region.
base::ReadOnlySharedMemoryRegion EnableKeyPressMonitoringWithMapping();
private: private:
virtual void StartKeyboardMonitoring() = 0; virtual void StartKeyboardMonitoring() = 0;
virtual void StartKeyboardMonitoring(
base::WritableSharedMemoryMapping mapping) = 0;
virtual void StopKeyboardMonitoring() = 0; virtual void StopKeyboardMonitoring() = 0;
// Aquired in EnableKeyPressMonitoring()/DisableKeyPressMonitoring(). Together
// with |references_| updated under lock, it is used to ensure operation
// ordering for start/stop keyboard monitoring, i.e. start is always followed
// by stop and start is only called when keyboard monitoring is stopped.
base::Lock lock_;
size_t references_ = 0; size_t references_ = 0;
base::ReadOnlySharedMemoryRegion key_press_count_region_;
SEQUENCE_CHECKER(owning_sequence_);
DISALLOW_COPY_AND_ASSIGN(UserInputMonitorBase); DISALLOW_COPY_AND_ASSIGN(UserInputMonitorBase);
}; };
......
...@@ -43,6 +43,7 @@ class UserInputMonitorLinuxCore ...@@ -43,6 +43,7 @@ class UserInputMonitorLinuxCore
uint32_t GetKeyPressCount() const; uint32_t GetKeyPressCount() const;
void StartMonitor(); void StartMonitor();
void StartMonitorWithMapping(base::WritableSharedMemoryMapping mapping);
void StopMonitor(); void StopMonitor();
private: private:
...@@ -54,6 +55,9 @@ class UserInputMonitorLinuxCore ...@@ -54,6 +55,9 @@ class UserInputMonitorLinuxCore
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
// Used for sharing key press count value.
std::unique_ptr<base::WritableSharedMemoryMapping> key_press_count_mapping_;
// //
// The following members should only be accessed on the IO thread. // The following members should only be accessed on the IO thread.
// //
...@@ -79,6 +83,8 @@ class UserInputMonitorLinux : public UserInputMonitorBase { ...@@ -79,6 +83,8 @@ class UserInputMonitorLinux : public UserInputMonitorBase {
private: private:
// Private UserInputMonitor overrides. // Private UserInputMonitor overrides.
void StartKeyboardMonitoring() override; void StartKeyboardMonitoring() override;
void StartKeyboardMonitoring(
base::WritableSharedMemoryMapping mapping) override;
void StopKeyboardMonitoring() override; void StopKeyboardMonitoring() override;
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
...@@ -192,6 +198,13 @@ void UserInputMonitorLinuxCore::StartMonitor() { ...@@ -192,6 +198,13 @@ void UserInputMonitorLinuxCore::StartMonitor() {
OnXEvent(); OnXEvent();
} }
void UserInputMonitorLinuxCore::StartMonitorWithMapping(
base::WritableSharedMemoryMapping mapping) {
StartMonitor();
key_press_count_mapping_ =
std::make_unique<base::WritableSharedMemoryMapping>(std::move(mapping));
}
void UserInputMonitorLinuxCore::StopMonitor() { void UserInputMonitorLinuxCore::StopMonitor() {
DCHECK(io_task_runner_->BelongsToCurrentThread()); DCHECK(io_task_runner_->BelongsToCurrentThread());
...@@ -219,6 +232,8 @@ void UserInputMonitorLinuxCore::StopMonitor() { ...@@ -219,6 +232,8 @@ void UserInputMonitorLinuxCore::StopMonitor() {
x_control_display_ = NULL; x_control_display_ = NULL;
} }
key_press_count_mapping_.reset();
// Stop observing message loop destruction if no event is being monitored. // Stop observing message loop destruction if no event is being monitored.
base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this); base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
} }
...@@ -243,6 +258,10 @@ void UserInputMonitorLinuxCore::ProcessXEvent(xEvent* event) { ...@@ -243,6 +258,10 @@ void UserInputMonitorLinuxCore::ProcessXEvent(xEvent* event) {
XkbKeycodeToKeysym(x_control_display_, event->u.u.detail, 0, 0); XkbKeycodeToKeysym(x_control_display_, event->u.u.detail, 0, 0);
ui::KeyboardCode key_code = ui::KeyboardCodeFromXKeysym(key_sym); ui::KeyboardCode key_code = ui::KeyboardCodeFromXKeysym(key_sym);
counter_.OnKeyboardEvent(type, key_code); counter_.OnKeyboardEvent(type, key_code);
// Update count value in shared memory.
if (key_press_count_mapping_)
WriteKeyPressMonitorCount(*key_press_count_mapping_, GetKeyPressCount());
} }
// static // static
...@@ -279,6 +298,14 @@ void UserInputMonitorLinux::StartKeyboardMonitoring() { ...@@ -279,6 +298,14 @@ void UserInputMonitorLinux::StartKeyboardMonitoring() {
core_->AsWeakPtr())); core_->AsWeakPtr()));
} }
void UserInputMonitorLinux::StartKeyboardMonitoring(
base::WritableSharedMemoryMapping mapping) {
io_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&UserInputMonitorLinuxCore::StartMonitorWithMapping,
core_->AsWeakPtr(), std::move(mapping)));
}
void UserInputMonitorLinux::StopKeyboardMonitoring() { void UserInputMonitorLinux::StopKeyboardMonitoring() {
io_task_runner_->PostTask( io_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&UserInputMonitorLinuxCore::StopMonitor, FROM_HERE, base::BindOnce(&UserInputMonitorLinuxCore::StopMonitor,
......
...@@ -9,10 +9,16 @@ ...@@ -9,10 +9,16 @@
#include <memory> #include <memory>
#include "base/macros.h" #include "base/macros.h"
#include "base/timer/timer.h"
namespace media { namespace media {
namespace { namespace {
// Update key press count in shared memory twice as frequent as
// AudioInputController::AudioCallback::OnData() callback for WebRTC.
constexpr base::TimeDelta kUpdateKeyPressCountIntervalMs =
base::TimeDelta::FromMilliseconds(5);
class UserInputMonitorMac : public UserInputMonitorBase { class UserInputMonitorMac : public UserInputMonitorBase {
public: public:
UserInputMonitorMac(); UserInputMonitorMac();
...@@ -22,8 +28,18 @@ class UserInputMonitorMac : public UserInputMonitorBase { ...@@ -22,8 +28,18 @@ class UserInputMonitorMac : public UserInputMonitorBase {
private: private:
void StartKeyboardMonitoring() override; void StartKeyboardMonitoring() override;
void StartKeyboardMonitoring(
base::WritableSharedMemoryMapping mapping) override;
void StopKeyboardMonitoring() override; void StopKeyboardMonitoring() override;
void UpdateKeyPressCountShmem();
// Used for sharing key press count value.
std::unique_ptr<base::WritableSharedMemoryMapping> key_press_count_mapping_;
// Timer for updating key press count in |key_press_count_mapping_|.
base::RepeatingTimer key_press_count_timer_;
DISALLOW_COPY_AND_ASSIGN(UserInputMonitorMac); DISALLOW_COPY_AND_ASSIGN(UserInputMonitorMac);
}; };
...@@ -40,7 +56,26 @@ uint32_t UserInputMonitorMac::GetKeyPressCount() const { ...@@ -40,7 +56,26 @@ uint32_t UserInputMonitorMac::GetKeyPressCount() const {
void UserInputMonitorMac::StartKeyboardMonitoring() {} void UserInputMonitorMac::StartKeyboardMonitoring() {}
void UserInputMonitorMac::StopKeyboardMonitoring() {} void UserInputMonitorMac::StartKeyboardMonitoring(
base::WritableSharedMemoryMapping mapping) {
key_press_count_mapping_ =
std::make_unique<base::WritableSharedMemoryMapping>(std::move(mapping));
key_press_count_timer_.Start(FROM_HERE, kUpdateKeyPressCountIntervalMs, this,
&UserInputMonitorMac::UpdateKeyPressCountShmem);
}
void UserInputMonitorMac::StopKeyboardMonitoring() {
if (!key_press_count_mapping_)
return;
key_press_count_timer_.AbandonAndStop();
key_press_count_mapping_.reset();
}
void UserInputMonitorMac::UpdateKeyPressCountShmem() {
DCHECK(key_press_count_mapping_);
WriteKeyPressMonitorCount(*key_press_count_mapping_, GetKeyPressCount());
}
} // namespace } // namespace
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#if defined(OS_LINUX) #if defined(OS_LINUX)
...@@ -38,7 +39,35 @@ TEST(UserInputMonitorTest, CreatePlatformSpecific) { ...@@ -38,7 +39,35 @@ TEST(UserInputMonitorTest, CreatePlatformSpecific) {
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
} }
TEST(UserInputMonitorTest, KeyPressMonitorReadWriteCount) { TEST(UserInputMonitorTest, CreatePlatformSpecificWithMapping) {
#if defined(OS_LINUX)
base::MessageLoopForIO message_loop;
base::FileDescriptorWatcher file_descriptor_watcher(&message_loop);
#else
base::MessageLoopForUI message_loop;
#endif // defined(OS_LINUX)
std::unique_ptr<UserInputMonitor> monitor = UserInputMonitor::Create(
message_loop.task_runner(), message_loop.task_runner());
if (!monitor)
return;
base::ReadOnlySharedMemoryMapping readonly_mapping =
static_cast<UserInputMonitorBase*>(monitor.get())
->EnableKeyPressMonitoringWithMapping()
.Map();
EXPECT_EQ(0u, ReadKeyPressMonitorCount(readonly_mapping));
monitor->DisableKeyPressMonitoring();
monitor.reset();
base::RunLoop().RunUntilIdle();
// Check that read only region remains valid after disable.
EXPECT_EQ(0u, ReadKeyPressMonitorCount(readonly_mapping));
}
TEST(UserInputMonitorTest, ReadWriteKeyPressMonitorCount) {
std::unique_ptr<base::MappedReadOnlyRegion> shmem = std::unique_ptr<base::MappedReadOnlyRegion> shmem =
std::make_unique<base::MappedReadOnlyRegion>( std::make_unique<base::MappedReadOnlyRegion>(
base::ReadOnlySharedMemoryRegion::Create(sizeof(uint32_t))); base::ReadOnlySharedMemoryRegion::Create(sizeof(uint32_t)));
......
...@@ -57,6 +57,7 @@ class UserInputMonitorWinCore ...@@ -57,6 +57,7 @@ class UserInputMonitorWinCore
uint32_t GetKeyPressCount() const; uint32_t GetKeyPressCount() const;
void StartMonitor(); void StartMonitor();
void StartMonitorWithMapping(base::WritableSharedMemoryMapping mapping);
void StopMonitor(); void StopMonitor();
private: private:
...@@ -71,6 +72,9 @@ class UserInputMonitorWinCore ...@@ -71,6 +72,9 @@ class UserInputMonitorWinCore
// Task runner on which |window_| is created. // Task runner on which |window_| is created.
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
// Used for sharing key press count value.
std::unique_ptr<base::WritableSharedMemoryMapping> key_press_count_mapping_;
// These members are only accessed on the UI thread. // These members are only accessed on the UI thread.
std::unique_ptr<base::win::MessageWindow> window_; std::unique_ptr<base::win::MessageWindow> window_;
KeyboardEventCounter counter_; KeyboardEventCounter counter_;
...@@ -90,6 +94,8 @@ class UserInputMonitorWin : public UserInputMonitorBase { ...@@ -90,6 +94,8 @@ class UserInputMonitorWin : public UserInputMonitorBase {
private: private:
// Private UserInputMonitor overrides. // Private UserInputMonitor overrides.
void StartKeyboardMonitoring() override; void StartKeyboardMonitoring() override;
void StartKeyboardMonitoring(
base::WritableSharedMemoryMapping mapping) override;
void StopKeyboardMonitoring() override; void StopKeyboardMonitoring() override;
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
...@@ -143,6 +149,13 @@ void UserInputMonitorWinCore::StartMonitor() { ...@@ -143,6 +149,13 @@ void UserInputMonitorWinCore::StartMonitor() {
base::MessageLoopCurrent::Get()->AddDestructionObserver(this); base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
} }
void UserInputMonitorWinCore::StartMonitorWithMapping(
base::WritableSharedMemoryMapping mapping) {
StartMonitor();
key_press_count_mapping_ =
std::make_unique<base::WritableSharedMemoryMapping>(std::move(mapping));
}
void UserInputMonitorWinCore::StopMonitor() { void UserInputMonitorWinCore::StopMonitor() {
DCHECK(ui_task_runner_->BelongsToCurrentThread()); DCHECK(ui_task_runner_->BelongsToCurrentThread());
...@@ -159,6 +172,8 @@ void UserInputMonitorWinCore::StopMonitor() { ...@@ -159,6 +172,8 @@ void UserInputMonitorWinCore::StopMonitor() {
window_ = nullptr; window_ = nullptr;
key_press_count_mapping_.reset();
// Stop observing message loop destruction if no event is being monitored. // Stop observing message loop destruction if no event is being monitored.
base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this); base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
} }
...@@ -196,6 +211,10 @@ LRESULT UserInputMonitorWinCore::OnInput(HRAWINPUT input_handle) { ...@@ -196,6 +211,10 @@ LRESULT UserInputMonitorWinCore::OnInput(HRAWINPUT input_handle) {
ui::KeyboardCode key_code = ui::KeyboardCode key_code =
ui::KeyboardCodeForWindowsKeyCode(input->data.keyboard.VKey); ui::KeyboardCodeForWindowsKeyCode(input->data.keyboard.VKey);
counter_.OnKeyboardEvent(event, key_code); counter_.OnKeyboardEvent(event, key_code);
// Update count value in shared memory.
if (key_press_count_mapping_)
WriteKeyPressMonitorCount(*key_press_count_mapping_, GetKeyPressCount());
} }
return DefRawInputProc(&input, 1, sizeof(RAWINPUTHEADER)); return DefRawInputProc(&input, 1, sizeof(RAWINPUTHEADER));
...@@ -241,6 +260,14 @@ void UserInputMonitorWin::StartKeyboardMonitoring() { ...@@ -241,6 +260,14 @@ void UserInputMonitorWin::StartKeyboardMonitoring() {
core_->AsWeakPtr())); core_->AsWeakPtr()));
} }
void UserInputMonitorWin::StartKeyboardMonitoring(
base::WritableSharedMemoryMapping mapping) {
ui_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&UserInputMonitorWinCore::StartMonitorWithMapping,
core_->AsWeakPtr(), std::move(mapping)));
}
void UserInputMonitorWin::StopKeyboardMonitoring() { void UserInputMonitorWin::StopKeyboardMonitoring() {
ui_task_runner_->PostTask( ui_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&UserInputMonitorWinCore::StopMonitor, FROM_HERE, base::BindOnce(&UserInputMonitorWinCore::StopMonitor,
......
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