Commit e2824413 authored by erg@google.com's avatar erg@google.com

Don't send WebInputEvents from the renderer to the browser.

The browser process now keeps a queue of the last keyboard
events that it sent to the renderer in a queue and pops them
on ACK. If a key is unhandled, we use the copy in the browser
process; we don't even send the key back in the ACK anymore.
Review URL: http://codereview.chromium.org/27244

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10563 0039d316-1c4b-4281-b951-d872f2087c98
parent afb34a67
...@@ -1200,7 +1200,7 @@ void RenderViewHost::OnUserMetricsRecordAction(const std::wstring& action) { ...@@ -1200,7 +1200,7 @@ void RenderViewHost::OnUserMetricsRecordAction(const std::wstring& action) {
UserMetrics::RecordComputedAction(action.c_str(), process()->profile()); UserMetrics::RecordComputedAction(action.c_str(), process()->profile());
} }
void RenderViewHost::UnhandledInputEvent(const WebInputEvent& event) { void RenderViewHost::UnhandledKeyboardEvent(const WebKeyboardEvent& event) {
RenderViewHostDelegate::View* view = delegate_->GetViewDelegate(); RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
if (view) { if (view) {
// TODO(brettw) why do we have to filter these types of events here. Can't // TODO(brettw) why do we have to filter these types of events here. Can't
...@@ -1208,8 +1208,7 @@ void RenderViewHost::UnhandledInputEvent(const WebInputEvent& event) { ...@@ -1208,8 +1208,7 @@ void RenderViewHost::UnhandledInputEvent(const WebInputEvent& event) {
// should be able to decide which ones it wants or not? // should be able to decide which ones it wants or not?
if ((event.type == WebInputEvent::KEY_DOWN) || if ((event.type == WebInputEvent::KEY_DOWN) ||
(event.type == WebInputEvent::CHAR)) { (event.type == WebInputEvent::CHAR)) {
view->HandleKeyboardEvent( view->HandleKeyboardEvent(event);
static_cast<const WebKeyboardEvent&>(event));
} }
} }
} }
......
...@@ -423,7 +423,7 @@ class RenderViewHost : public RenderWidgetHost { ...@@ -423,7 +423,7 @@ class RenderViewHost : public RenderWidgetHost {
protected: protected:
// RenderWidgetHost protected overrides. // RenderWidgetHost protected overrides.
virtual void UnhandledInputEvent(const WebInputEvent& event); virtual void UnhandledKeyboardEvent(const WebKeyboardEvent& event);
virtual void OnEnterOrSpace(); virtual void OnEnterOrSpace();
virtual void NotifyRendererUnresponsive(); virtual void NotifyRendererUnresponsive();
virtual void NotifyRendererResponsive(); virtual void NotifyRendererResponsive();
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "chrome/browser/renderer_host/render_widget_host.h" #include "chrome/browser/renderer_host/render_widget_host.h"
#include "base/gfx/native_widget_types.h" #include "base/gfx/native_widget_types.h"
#include "base/histogram.h"
#include "base/message_loop.h" #include "base/message_loop.h"
#include "base/keyboard_codes.h" #include "base/keyboard_codes.h"
#include "chrome/browser/renderer_host/backing_store.h" #include "chrome/browser/renderer_host/backing_store.h"
...@@ -305,6 +306,14 @@ void RenderWidgetHost::ForwardInputEvent(const WebInputEvent& input_event, ...@@ -305,6 +306,14 @@ void RenderWidgetHost::ForwardInputEvent(const WebInputEvent& input_event,
if (!process_->channel()) if (!process_->channel())
return; return;
if (WebInputEvent::IsKeyboardEventType(input_event.type)) {
// Put all WebKeyboardEvent objects in a queue since we can't trust the
// renderer and we need to give something to the UnhandledInputEvent
// handler.
key_queue_.push(static_cast<const WebKeyboardEvent&>(input_event));
HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size());
}
IPC::Message* message = new ViewMsg_HandleInputEvent(routing_id_); IPC::Message* message = new ViewMsg_HandleInputEvent(routing_id_);
message->WriteData( message->WriteData(
reinterpret_cast<const char*>(&input_event), event_size); reinterpret_cast<const char*>(&input_event), event_size);
...@@ -554,12 +563,24 @@ void RenderWidgetHost::OnMsgInputEventAck(const IPC::Message& message) { ...@@ -554,12 +563,24 @@ void RenderWidgetHost::OnMsgInputEventAck(const IPC::Message& message) {
} }
} }
const char* data = NULL; if (WebInputEvent::IsKeyboardEventType(type)) {
int length = 0; if (key_queue_.size() == 0) {
if (message.ReadData(&iter, &data, &length)) { LOG(ERROR) << "Got a KeyEvent back from the renderer but we "
const WebInputEvent* input_event = << "don't seem to have sent it to the renderer!";
reinterpret_cast<const WebInputEvent*>(data); } else if (key_queue_.front().type != type) {
UnhandledInputEvent(*input_event); LOG(ERROR) << "We seem to have a different key type sent from "
<< "the renderer. Ignoring event.";
} else {
bool processed = false;
r = message.ReadBool(&iter, &processed);
DCHECK(r);
if (!processed) {
UnhandledKeyboardEvent(key_queue_.front());
}
key_queue_.pop();
}
} }
} }
......
...@@ -5,12 +5,14 @@ ...@@ -5,12 +5,14 @@
#ifndef CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_H_ #ifndef CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_H_
#define CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_H_ #define CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_H_
#include <queue>
#include <vector> #include <vector>
#include "base/gfx/size.h" #include "base/gfx/size.h"
#include "base/timer.h" #include "base/timer.h"
#include "chrome/common/ipc_channel.h" #include "chrome/common/ipc_channel.h"
#include "testing/gtest/include/gtest/gtest_prod.h" #include "testing/gtest/include/gtest/gtest_prod.h"
#include "webkit/glue/webinputevent.h"
namespace gfx { namespace gfx {
class Rect; class Rect;
...@@ -221,7 +223,7 @@ class RenderWidgetHost : public IPC::Channel::Listener { ...@@ -221,7 +223,7 @@ class RenderWidgetHost : public IPC::Channel::Listener {
// Called when we an InputEvent was not processed by the renderer. This is // Called when we an InputEvent was not processed by the renderer. This is
// overridden by RenderView to send upwards to its delegate. // overridden by RenderView to send upwards to its delegate.
virtual void UnhandledInputEvent(const WebInputEvent& event) {} virtual void UnhandledKeyboardEvent(const WebKeyboardEvent& event) {}
// Notification that the user pressed the enter key or the spacebar. The // Notification that the user pressed the enter key or the spacebar. The
// render view host overrides this to forward the information to its delegate // render view host overrides this to forward the information to its delegate
...@@ -350,6 +352,11 @@ class RenderWidgetHost : public IPC::Channel::Listener { ...@@ -350,6 +352,11 @@ class RenderWidgetHost : public IPC::Channel::Listener {
// operation to finish. // operation to finish.
base::TimeTicks repaint_start_time_; base::TimeTicks repaint_start_time_;
// A queue of keyboard events. We can't trust data from the renderer so we
// stuff key events into a queue and pop them out on ACK, feeding our copy
// back to whatever unhandled handler instead of the returned version.
std::queue<WebKeyboardEvent> key_queue_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHost); DISALLOW_COPY_AND_ASSIGN(RenderWidgetHost);
}; };
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "base/basictypes.h" #include "base/basictypes.h"
#include "base/keyboard_codes.h"
#include "base/scoped_ptr.h" #include "base/scoped_ptr.h"
#include "base/shared_memory.h" #include "base/shared_memory.h"
#include "build/build_config.h" #include "build/build_config.h"
...@@ -119,6 +120,30 @@ class TestView : public TestRenderWidgetHostView { ...@@ -119,6 +120,30 @@ class TestView : public TestRenderWidgetHostView {
DISALLOW_COPY_AND_ASSIGN(TestView); DISALLOW_COPY_AND_ASSIGN(TestView);
}; };
// MockRenderWidgetHostTest ----------------------------------------------------
class MockRenderWidgetHost : public RenderWidgetHost {
public:
MockRenderWidgetHost(RenderProcessHost* process, int routing_id)
: RenderWidgetHost(process, routing_id),
unhandled_keyboard_event_called_(false) {
}
// Tests that make sure we ignore keyboard event acknowledgments to events we
// didn't send work by making sure we didn't call UnhandledKeyboardEvent().
bool unhandled_keyboard_event_called() const {
return unhandled_keyboard_event_called_;
}
protected:
virtual void UnhandledKeyboardEvent(const WebKeyboardEvent& event) {
unhandled_keyboard_event_called_ = true;
}
private:
bool unhandled_keyboard_event_called_;
};
// RenderWidgetHostTest -------------------------------------------------------- // RenderWidgetHostTest --------------------------------------------------------
class RenderWidgetHostTest : public testing::Test { class RenderWidgetHostTest : public testing::Test {
...@@ -133,7 +158,7 @@ class RenderWidgetHostTest : public testing::Test { ...@@ -133,7 +158,7 @@ class RenderWidgetHostTest : public testing::Test {
void SetUp() { void SetUp() {
profile_.reset(new TestingProfile()); profile_.reset(new TestingProfile());
process_ = new RenderWidgetHostProcess(profile_.get()); process_ = new RenderWidgetHostProcess(profile_.get());
host_.reset(new RenderWidgetHost(process_, 1)); host_.reset(new MockRenderWidgetHost(process_, 1));
view_.reset(new TestView); view_.reset(new TestView);
host_->set_view(view_.get()); host_->set_view(view_.get());
} }
...@@ -151,7 +176,7 @@ class RenderWidgetHostTest : public testing::Test { ...@@ -151,7 +176,7 @@ class RenderWidgetHostTest : public testing::Test {
scoped_ptr<TestingProfile> profile_; scoped_ptr<TestingProfile> profile_;
RenderWidgetHostProcess* process_; // Deleted automatically by the widget. RenderWidgetHostProcess* process_; // Deleted automatically by the widget.
scoped_ptr<RenderWidgetHost> host_; scoped_ptr<MockRenderWidgetHost> host_;
scoped_ptr<TestView> view_; scoped_ptr<TestView> view_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostTest); DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostTest);
...@@ -304,3 +329,38 @@ TEST_F(RenderWidgetHostTest, HiddenPaint) { ...@@ -304,3 +329,38 @@ TEST_F(RenderWidgetHostTest, HiddenPaint) {
ViewMsg_WasRestored::Read(restored, &needs_repaint); ViewMsg_WasRestored::Read(restored, &needs_repaint);
EXPECT_TRUE(needs_repaint); EXPECT_TRUE(needs_repaint);
} }
TEST_F(RenderWidgetHostTest, HandleKeyEventsWeSent) {
WebKeyboardEvent key_event;
key_event.type = WebInputEvent::KEY_DOWN;
key_event.modifiers = WebInputEvent::CTRL_KEY;
key_event.key_code = base::VKEY_L; // non-null made up value.
host_->ForwardKeyboardEvent(key_event);
// Make sure we sent the input event to the renderer.
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
ViewMsg_HandleInputEvent::ID));
process_->sink().ClearMessages();
// Send the simulated response from the renderer back.
scoped_ptr<IPC::Message> response(
new ViewHostMsg_HandleInputEvent_ACK(0));
response->WriteInt(key_event.type);
response->WriteBool(false);
host_->OnMessageReceived(*response);
EXPECT_TRUE(host_->unhandled_keyboard_event_called());
}
TEST_F(RenderWidgetHostTest, IgnoreKeyEventsWeDidntSend) {
// Send a simulated, unrequested key response. We should ignore this.
scoped_ptr<IPC::Message> response(
new ViewHostMsg_HandleInputEvent_ACK(0));
response->WriteInt(WebInputEvent::KEY_DOWN);
response->WriteBool(false);
host_->OnMessageReceived(*response);
EXPECT_FALSE(host_->unhandled_keyboard_event_called());
}
...@@ -267,10 +267,8 @@ void RenderWidget::OnHandleInputEvent(const IPC::Message& message) { ...@@ -267,10 +267,8 @@ void RenderWidget::OnHandleInputEvent(const IPC::Message& message) {
IPC::Message* response = new ViewHostMsg_HandleInputEvent_ACK(routing_id_); IPC::Message* response = new ViewHostMsg_HandleInputEvent_ACK(routing_id_);
response->WriteInt(input_event->type); response->WriteInt(input_event->type);
if (!processed) { response->WriteBool(processed);
// If the event was not processed we send it back.
response->WriteData(data, data_length);
}
Send(response); Send(response);
} }
......
...@@ -69,6 +69,11 @@ class WebInputEvent { ...@@ -69,6 +69,11 @@ class WebInputEvent {
Type type; Type type;
int modifiers; int modifiers;
// Returns true if the WebInputEvent |type| is a keyboard event.
static bool IsKeyboardEventType(int type) {
return type == KEY_DOWN || type == KEY_UP || type == CHAR;
}
}; };
// WebMouseEvent -------------------------------------------------------------- // WebMouseEvent --------------------------------------------------------------
......
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