summaryrefslogtreecommitdiffstats
path: root/chrome/browser/renderer_host
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/renderer_host')
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc15
-rw-r--r--chrome/browser/renderer_host/render_view_host.h5
-rw-r--r--chrome/browser/renderer_host/render_view_host_delegate.h13
-rw-r--r--chrome/browser/renderer_host/render_widget_host.cc218
-rw-r--r--chrome/browser/renderer_host/render_widget_host.h55
-rw-r--r--chrome/browser/renderer_host/render_widget_host_unittest.cc249
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.h6
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.mm10
8 files changed, 102 insertions, 469 deletions
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index a473519..e214972 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -1477,20 +1477,17 @@ void RenderViewHost::OnUserMetricsRecordAction(const std::string& action) {
UserMetrics::RecordComputedAction(action.c_str(), process()->profile());
}
-bool RenderViewHost::ShouldSendToRenderer(const NativeWebKeyboardEvent& event) {
+bool RenderViewHost::PreHandleKeyboardEvent(
+ const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) {
RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
- if (!view)
- return true;
- return !view->IsReservedAccelerator(event);
+ return view && view->PreHandleKeyboardEvent(event, is_keyboard_shortcut);
}
-bool RenderViewHost::UnhandledKeyboardEvent(
+void RenderViewHost::UnhandledKeyboardEvent(
const NativeWebKeyboardEvent& event) {
RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
- if (view) {
- return view->HandleKeyboardEvent(event);
- }
- return false;
+ if (view)
+ view->HandleKeyboardEvent(event);
}
void RenderViewHost::OnUserGesture() {
diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h
index 99ee05f..0d923ca 100644
--- a/chrome/browser/renderer_host/render_view_host.h
+++ b/chrome/browser/renderer_host/render_view_host.h
@@ -443,8 +443,9 @@ class RenderViewHost : public RenderWidgetHost,
protected:
// RenderWidgetHost protected overrides.
- virtual bool ShouldSendToRenderer(const NativeWebKeyboardEvent& event);
- virtual bool UnhandledKeyboardEvent(const NativeWebKeyboardEvent& event);
+ virtual bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
+ bool* is_keyboard_shortcut);
+ virtual void UnhandledKeyboardEvent(const NativeWebKeyboardEvent& event);
virtual void OnUserGesture();
virtual void NotifyRendererUnresponsive();
virtual void NotifyRendererResponsive();
diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h
index a3d75c6..972a75b 100644
--- a/chrome/browser/renderer_host/render_view_host_delegate.h
+++ b/chrome/browser/renderer_host/render_view_host_delegate.h
@@ -126,15 +126,18 @@ class RenderViewHostDelegate {
// true, it means the focus was retrieved by doing a Shift-Tab.
virtual void TakeFocus(bool reverse) = 0;
- // Returns whether the event is a reserved keyboard shortcut that should not
- // be sent to the renderer.
- virtual bool IsReservedAccelerator(const NativeWebKeyboardEvent& event) = 0;
+ // Callback to give the browser a chance to handle the specified keyboard
+ // event before sending it to the renderer.
+ // Returns true if the |event| was handled. Otherwise, if the |event| would
+ // be handled in HandleKeyboardEvent() method as a normal keyboard shortcut,
+ // |*is_keyboard_shortcut| should be set to true.
+ virtual bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
+ bool* is_keyboard_shortcut) = 0;
// Callback to inform the browser that the renderer did not process the
// specified events. This gives an opportunity to the browser to process the
// event (used for keyboard shortcuts).
- // Returns true if the event was handled.
- virtual bool HandleKeyboardEvent(const NativeWebKeyboardEvent& event) = 0;
+ virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event) = 0;
// Notifications about mouse events in this view. This is useful for
// implementing global 'on hover' features external to the view.
diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc
index 1ba09234..c40bbf8 100644
--- a/chrome/browser/renderer_host/render_widget_host.cc
+++ b/chrome/browser/renderer_host/render_widget_host.cc
@@ -51,9 +51,6 @@ static const int kPaintMsgTimeoutMS = 40;
// How long to wait before we consider a renderer hung.
static const int kHungRendererDelayMs = 20000;
-// How long a PaintRect_ACK message can be postponed at most, in milliseconds.
-static const int kPaintACKMsgMaxPostponedDurationMS = 1000;
-
///////////////////////////////////////////////////////////////////////////////
// RenderWidgetHost
@@ -76,10 +73,7 @@ RenderWidgetHost::RenderWidgetHost(RenderProcessHost* process,
text_direction_updated_(false),
text_direction_(WebKit::WebTextDirectionLeftToRight),
text_direction_canceled_(false),
- pending_key_events_(0),
- suppress_next_char_events_(false),
- paint_ack_postponed_(false),
- death_flag_(NULL) {
+ suppress_next_char_events_(false) {
if (routing_id_ == MSG_ROUTING_NONE)
routing_id_ = process_->GetNextRoutingID();
@@ -90,10 +84,6 @@ RenderWidgetHost::RenderWidgetHost(RenderProcessHost* process,
}
RenderWidgetHost::~RenderWidgetHost() {
- // Force the method that destroys this object to exit immediately.
- if (death_flag_)
- *death_flag_ = true;
-
// Clear our current or cached backing store if either remains.
BackingStoreManager::RemoveBackingStore(this);
@@ -375,7 +365,7 @@ void RenderWidgetHost::ForwardMouseEvent(const WebMouseEvent& mouse_event) {
OnUserGesture();
}
- ForwardInputEvent(mouse_event, sizeof(WebMouseEvent));
+ ForwardInputEvent(mouse_event, sizeof(WebMouseEvent), false);
}
void RenderWidgetHost::ForwardWheelEvent(
@@ -383,7 +373,7 @@ void RenderWidgetHost::ForwardWheelEvent(
if (process_->ignore_input_events())
return;
- ForwardInputEvent(wheel_event, sizeof(WebMouseWheelEvent));
+ ForwardInputEvent(wheel_event, sizeof(WebMouseWheelEvent), false);
}
void RenderWidgetHost::ForwardKeyboardEvent(
@@ -400,104 +390,52 @@ void RenderWidgetHost::ForwardKeyboardEvent(
// Double check the type to make sure caller hasn't sent us nonsense that
// will mess up our key queue.
if (WebInputEvent::isKeyboardEventType(key_event.type)) {
- // Don't add this key to the queue if we have no way to send the message...
- if (!process_->HasConnection())
- return;
-
- // To help understand following logic, please refer to the comments
- // explaining |pending_key_events_| and |suppress_next_char_events_|
- // members. And the comments in OnMsgInputEventAck() method, which contains
- // the bottom half of the logic.
- //
- // There are to different situations for us to handle key events:
- // 1. After sending a key event to the renderer, we receive its ACK message
- // from the renderer before sending the next key event.
- // In this case, there is always no more than 1 key event in |key_queue_|,
- // and we send the key event one by one in this method, except that a
- // sequence of Char events may be suppressed directly if the preceding
- // RawKeyDown event was handled as an accelerator key in the browser.
- //
- // 2. We get the next key event before receving the previous one's ACK
- // message from the renderer.
- // In this case, when we get a key event, the previous key event is still in
- // |keq_queue_| waiting for being handled in OnMsgInputEventAck() method.
- // Then we need handle following cases differently:
- // 1) If we get a Char event, then the previous key event in |key_queue_|
- // waiting for ACK must be a RawKeyDown event. Then we need keep this Char
- // event in |key_queue_| rather than sending it immediately, because we
- // can't determine if we should send it to the renderer or just suppress
- // it, until we receive the preceding RawKeyDown event's ACK message.
- // We increase the count of |pending_key_events_| to help remember this
- // Char event is not sent to the renderer yet.
- // 2) If there is already one or more key event pending in |key_queue_|
- // (|pending_key_events_| > 0), we can not send a new key event
- // immediately no matter what type it is. Otherwise the key events will be
- // in wrong order. In this case we just keep them in |key_queue_| and
- // increase |pending_key_events_| to remember them.
- //
- // Then all pending key events in |key_queue_| will be handled properly in
- // OnMsgInputEventAck() method. Please refer to that method for details.
-
- // Tab switching/closing accelerators aren't sent to the renderer to avoid a
- // hung/malicious renderer from interfering.
- if (!ShouldSendToRenderer(key_event)) {
- if (key_event.type == WebKeyboardEvent::RawKeyDown)
- suppress_next_char_events_ = true;
- UnhandledKeyboardEvent(key_event);
- // We might be deleted now.
- return;
- }
-
- bool is_char = (key_event.type == WebKeyboardEvent::Char);
-
- // Handle the first situation mentioned above.
if (suppress_next_char_events_) {
// If preceding RawKeyDown event was handled by the browser, then we need
// suppress all Char events generated by it. Please note that, one
// RawKeyDown event may generate multiple Char events, so we can't reset
// |suppress_next_char_events_| until we get a KeyUp or a RawKeyDown.
- if (is_char)
+ if (key_event.type == WebKeyboardEvent::Char)
return;
// We get a KeyUp or a RawKeyDown event.
suppress_next_char_events_ = false;
}
+ // We need to set |suppress_next_char_events_| to true if
+ // PreHandleKeyboardEvent() returns true, but |this| may already be
+ // destroyed at that time. So set |suppress_next_char_events_| true here,
+ // then revert it afterwards when necessary.
+ if (key_event.type == WebKeyboardEvent::RawKeyDown)
+ suppress_next_char_events_ = true;
+
+ bool is_keyboard_shortcut = false;
+ // Tab switching/closing accelerators aren't sent to the renderer to avoid a
+ // hung/malicious renderer from interfering.
+ if (PreHandleKeyboardEvent(key_event, &is_keyboard_shortcut))
+ return;
+
+ if (key_event.type == WebKeyboardEvent::RawKeyDown)
+ suppress_next_char_events_ = false;
+
+ // Don't add this key to the queue if we have no way to send the message...
+ if (!process_->HasConnection())
+ return;
+
// 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_back(key_event);
HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size());
- // Handle the second situation mentioned above.
- size_t key_queue_size = key_queue_.size();
- if ((is_char && key_queue_size > 1) || pending_key_events_) {
- // The event is not send to the renderer, increase |pending_key_events_|
- // to remember it.
- ++pending_key_events_;
-
- // Some sanity checks.
- // At least one key event in the front of |key_queue_| has been sent to
- // the renderer, otherwise we won't be able to get any ACK back from the
- // renderer.
- DCHECK(key_queue_size > pending_key_events_);
- // Char events must be preceded by RawKeyDown events.
- // TODO(suzhe): verify it on all platforms.
- DCHECK(key_queue_[key_queue_size - pending_key_events_ - 1].type ==
- WebKeyboardEvent::RawKeyDown);
- // The first pending key event must be a Char event. Other key events must
- // already be sent to the renderer at this point.
- DCHECK(key_queue_[key_queue_size - pending_key_events_].type ==
- WebKeyboardEvent::Char);
- } else {
- // Fall into the first situation, so we can send the event immediately.
- // Only forward the non-native portions of our event.
- ForwardInputEvent(key_event, sizeof(WebKeyboardEvent));
- }
+ // Only forward the non-native portions of our event.
+ ForwardInputEvent(key_event, sizeof(WebKeyboardEvent),
+ is_keyboard_shortcut);
}
}
void RenderWidgetHost::ForwardInputEvent(const WebInputEvent& input_event,
- int event_size) {
+ int event_size,
+ bool is_keyboard_shortcut) {
if (!process_->HasConnection())
return;
@@ -506,6 +444,9 @@ void RenderWidgetHost::ForwardInputEvent(const WebInputEvent& input_event,
IPC::Message* message = new ViewMsg_HandleInputEvent(routing_id_);
message->WriteData(
reinterpret_cast<const char*>(&input_event), event_size);
+ // |is_keyboard_shortcut| only makes sense for RawKeyDown events.
+ if (input_event.type == WebInputEvent::RawKeyDown)
+ message->WriteBool(is_keyboard_shortcut);
input_event_start_time_ = TimeTicks::Now();
Send(message);
@@ -539,13 +480,11 @@ void RenderWidgetHost::RendererExited() {
// Must reset these to ensure that keyboard events work with a new renderer.
key_queue_.clear();
- pending_key_events_ = 0;
suppress_next_char_events_ = false;
// Reset some fields in preparation for recovering from a crash.
resize_ack_pending_ = false;
repaint_ack_pending_ = false;
- paint_ack_postponed_ = false;
in_flight_size_.SetSize(0, 0);
current_size_.SetSize(0, 0);
@@ -681,10 +620,6 @@ void RenderWidgetHost::OnMsgRequestMove(const gfx::Rect& pos) {
void RenderWidgetHost::OnMsgPaintRect(
const ViewHostMsg_PaintRect_Params& params) {
- // We shouldn't receive PaintRect message when the last PaintRect_ACK has not
- // been sent to the renderer yet.
- DCHECK(!paint_ack_postponed_);
-
TimeTicks paint_start = TimeTicks::Now();
// Update our knowledge of the RenderWidget's size.
@@ -732,16 +667,7 @@ void RenderWidgetHost::OnMsgPaintRect(
// This must be done AFTER we're done painting with the bitmap supplied by the
// renderer. This ACK is a signal to the renderer that the backing store can
// be re-used, so the bitmap may be invalid after this call.
- //
- // Postpone the ACK message until all pending key events have been sent to the
- // renderer, so that the renderer can process the updates caused by the key
- // events in batch.
- if (pending_key_events_ > 0) {
- paint_ack_postponed_ = true;
- paint_ack_postponed_time_ = TimeTicks::Now();
- } else {
- Send(new ViewMsg_PaintRect_ACK(routing_id_));
- }
+ Send(new ViewMsg_PaintRect_ACK(routing_id_));
// We don't need to update the view if the view is hidden. We must do this
// early return after the ACK is sent, however, or the renderer will not send
@@ -1009,92 +935,20 @@ void RenderWidgetHost::ProcessKeyboardEventAck(int type, bool processed) {
<< "the renderer. (" << key_queue_.front().type << " vs. "
<< type << "). Ignoring event.";
- // Something must be wrong. |key_queue_| must be cleared here to make sure
- // the feedback loop for sending upcoming keyboard events can be resumed
- // correctly.
+ // Something must be wrong. Clear the |key_queue_| and
+ // |suppress_next_char_events_| so that we can resume from the error.
key_queue_.clear();
- pending_key_events_ = 0;
suppress_next_char_events_ = false;
} else {
- // Track if |this| is destroyed or not.
- bool is_dead = false;
- death_flag_ = &is_dead;
-
NativeWebKeyboardEvent front_item = key_queue_.front();
key_queue_.pop_front();
- bool processed_by_browser = false;
if (!processed) {
- processed_by_browser = UnhandledKeyboardEvent(front_item);
+ UnhandledKeyboardEvent(front_item);
// WARNING: This RenderWidgetHost can be deallocated at this point
// (i.e. in the case of Ctrl+W, where the call to
// UnhandledKeyboardEvent destroys this RenderWidgetHost).
}
-
- // This RenderWidgetHost was already deallocated, we can't do anything
- // from now on, including resetting |death_flag_|. So just return.
- if (is_dead)
- return;
-
- // Reset |death_flag_| to NULL, otherwise it'll point to an invalid memory
- // address after returning from this method.
- death_flag_ = NULL;
-
- // Suppress the following Char events if the RawKeyDown event was handled
- // by the browser rather than the renderer.
- if (front_item.type == WebKeyboardEvent::RawKeyDown)
- suppress_next_char_events_ = processed_by_browser;
-
- // If more than one key events in |key_queue_| were already sent to the
- // renderer but haven't got ACK messages yet, we must wait for ACK
- // messages of these key events before sending more key events to the
- // renderer.
- if (pending_key_events_ && key_queue_.size() == pending_key_events_) {
- size_t i = 0;
- if (suppress_next_char_events_) {
- // Suppress the sequence of pending Char events if preceding
- // RawKeyDown event was handled by the browser.
- while (pending_key_events_ &&
- key_queue_[0].type == WebKeyboardEvent::Char) {
- --pending_key_events_;
- key_queue_.pop_front();
- }
- } else {
- // Otherwise, send these pending Char events to the renderer.
- // Note: we can't remove them from |key_queue_|, as we still need to
- // wait for their ACK messages from the renderer.
- while (pending_key_events_ &&
- key_queue_[i].type == WebKeyboardEvent::Char) {
- --pending_key_events_;
- ForwardInputEvent(key_queue_[i++], sizeof(WebKeyboardEvent));
- }
- }
-
- // Reset |suppress_next_char_events_| if there is still one or more
- // pending KeyUp or RawKeyDown events in the queue.
- // We can't reset it if there is no pending event anymore, because we
- // don't know if the following event is a Char event or not.
- if (pending_key_events_)
- suppress_next_char_events_ = false;
-
- // We can safely send following pending KeyUp and RawKeyDown events to
- // the renderer, until we meet another Char event.
- while (pending_key_events_ &&
- key_queue_[i].type != WebKeyboardEvent::Char) {
- --pending_key_events_;
- ForwardInputEvent(key_queue_[i++], sizeof(WebKeyboardEvent));
- }
- }
- }
-
- // Send the pending PaintRect_ACK message after sending all pending key
- // events or after a certain duration, so that the renderer can process
- // the updates caused by the key events in batch.
- if (paint_ack_postponed_ && (pending_key_events_ == 0 ||
- (TimeTicks::Now() - paint_ack_postponed_time_).InMilliseconds() >
- kPaintACKMsgMaxPostponedDurationMS)) {
- paint_ack_postponed_ = false;
- Send(new ViewMsg_PaintRect_ACK(routing_id_));
}
}
diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h
index 4104c6d..dc425b0 100644
--- a/chrome/browser/renderer_host/render_widget_host.h
+++ b/chrome/browser/renderer_host/render_widget_host.h
@@ -345,8 +345,8 @@ class RenderWidgetHost : public IPC::Channel::Listener,
protected:
// Internal implementation of the public Forward*Event() methods.
- void ForwardInputEvent(
- const WebKit::WebInputEvent& input_event, int event_size);
+ void ForwardInputEvent(const WebKit::WebInputEvent& input_event,
+ int event_size, bool is_keyboard_shortcut);
// Called when we receive a notification indicating that the renderer
// process has gone. This will reset our state so that our state will be
@@ -357,18 +357,20 @@ class RenderWidgetHost : public IPC::Channel::Listener,
// This is used for various IPC messages, including plugins.
gfx::NativeViewId GetNativeViewId();
- // Called when an InputEvent is received to check if the event should be sent
- // to the renderer or not.
- virtual bool ShouldSendToRenderer(const NativeWebKeyboardEvent& event) {
- return true;
+ // Called to handled a keyboard event before sending it to the renderer.
+ // This is overridden by RenderView to send upwards to its delegate.
+ // Returns true if the event was handled, and then the keyboard event will
+ // not be sent to the renderer anymore. Otherwise, if the |event| would
+ // be handled in HandleKeyboardEvent() method as a normal keyboard shortcut,
+ // |*is_keyboard_shortcut| should be set to true.
+ virtual bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
+ bool* is_keyboard_shortcut) {
+ return false;
}
- // Called when we an InputEvent was not processed by the renderer. This is
+ // Called when a keyboard event was not processed by the renderer. This is
// overridden by RenderView to send upwards to its delegate.
- // Returns true if the event was handled by its delegate.
- virtual bool UnhandledKeyboardEvent(const NativeWebKeyboardEvent& event) {
- return false;
- }
+ virtual void UnhandledKeyboardEvent(const NativeWebKeyboardEvent& event) {}
// Notification that the user has made some kind of input that could
// perform an action. The render view host overrides this to forward the
@@ -541,7 +543,6 @@ class RenderWidgetHost : public IPC::Channel::Listener,
// 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.
- // See the description of |pending_key_events_| below for more details.
KeyQueue key_queue_;
// Set when we update the text direction of the selected input element.
@@ -553,19 +554,6 @@ class RenderWidgetHost : public IPC::Channel::Listener,
// NotifyTextDirection().
bool text_direction_canceled_;
- // How many key events in |key_queue_| are not sent to the renderer yet,
- // counted from the back of |key_queue_|.
- // In order to suppress a Char event when necessary (see the description of
- // |suppress_next_char_events_| below), we can't just send it to the
- // renderer as soon as we get it. Instead, we need wait for the result of
- // preceding RawKeyDown event back from the renderer, and then decide how to
- // process the pending Char events according to the result.
- // So if we get one or more Char events before receiving the result of
- // preceding RawKeyDown event, we need keep them in |key_queue_|. And in
- // order to keep the order the key events, all following key events must be
- // pending until the pending Char events got processed.
- size_t pending_key_events_;
-
// Indicates if the next sequence of Char events should be suppressed or not.
// System may translate a RawKeyDown event into zero or more Char events,
// usually we send them to the renderer directly in sequence. However, If a
@@ -581,23 +569,6 @@ class RenderWidgetHost : public IPC::Channel::Listener,
// changed.
bool suppress_next_char_events_;
- // True if the PaintRect_ACK message for the last PaintRect message is still
- // not sent yet. This is used for optimizing the painting overhead when there
- // are many pending key events in the queue.
- bool paint_ack_postponed_;
-
- // The time when a PaintRect_ACK message is postponed, so that we can send the
- // message after a certain duration.
- base::TimeTicks paint_ack_postponed_time_;
-
- // During the call to some methods, eg. OnMsgInputEventAck, this
- // RenderWidgetHost object may be destroyed before executing some code that
- // still want to access this object. To avoid this situation, |death_flag_|
- // shall be pointed to a local variable in the method, and then |*death_flag_|
- // will be set to true when destroying this RenderWidgetHost object, then the
- // method shall exit immediately when |*death_flag_| becomes true.
- bool* death_flag_;
-
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHost);
};
diff --git a/chrome/browser/renderer_host/render_widget_host_unittest.cc b/chrome/browser/renderer_host/render_widget_host_unittest.cc
index 027ab8b..e3f4517 100644
--- a/chrome/browser/renderer_host/render_widget_host_unittest.cc
+++ b/chrome/browser/renderer_host/render_widget_host_unittest.cc
@@ -124,8 +124,10 @@ class MockRenderWidgetHost : public RenderWidgetHost {
public:
MockRenderWidgetHost(RenderProcessHost* process, int routing_id)
: RenderWidgetHost(process, routing_id),
+ prehandle_keyboard_event_(false),
+ prehandle_keyboard_event_called_(false),
+ prehandle_keyboard_event_type_(WebInputEvent::Undefined),
unhandled_keyboard_event_called_(false),
- handle_unhandled_keyboard_event_(false),
unhandled_keyboard_event_type_(WebInputEvent::Undefined) {
}
@@ -139,20 +141,37 @@ class MockRenderWidgetHost : public RenderWidgetHost {
return unhandled_keyboard_event_type_;
}
- void set_handle_unhandled_keyboard_event(bool handle) {
- handle_unhandled_keyboard_event_ = handle;
+ bool prehandle_keyboard_event_called() const {
+ return prehandle_keyboard_event_called_;
+ }
+
+ WebInputEvent::Type prehandle_keyboard_event_type() const {
+ return prehandle_keyboard_event_type_;
+ }
+
+ void set_prehandle_keyboard_event(bool handle) {
+ prehandle_keyboard_event_ = handle;
}
protected:
- virtual bool UnhandledKeyboardEvent(const NativeWebKeyboardEvent& event) {
+ virtual bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
+ bool* is_keyboard_shortcut) {
+ prehandle_keyboard_event_type_ = event.type;
+ prehandle_keyboard_event_called_ = true;
+ return prehandle_keyboard_event_;
+ }
+
+ virtual void UnhandledKeyboardEvent(const NativeWebKeyboardEvent& event) {
unhandled_keyboard_event_type_ = event.type;
unhandled_keyboard_event_called_ = true;
- return handle_unhandled_keyboard_event_;
}
private:
+ bool prehandle_keyboard_event_;
+ bool prehandle_keyboard_event_called_;
+ WebInputEvent::Type prehandle_keyboard_event_type_;
+
bool unhandled_keyboard_event_called_;
- bool handle_unhandled_keyboard_event_;
WebInputEvent::Type unhandled_keyboard_event_type_;
};
@@ -496,67 +515,23 @@ TEST_F(RenderWidgetHostTest, IgnoreKeyEventsHandledByRenderer) {
EXPECT_FALSE(host_->unhandled_keyboard_event_called());
}
-TEST_F(RenderWidgetHostTest, DontSuppressNextCharEventsNoPending) {
- // Simulate a keyboard event.
- SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
-
- // 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.
- SendInputEventACK(WebInputEvent::RawKeyDown, false);
-
- EXPECT_TRUE(host_->unhandled_keyboard_event_called());
- EXPECT_EQ(WebInputEvent::RawKeyDown, host_->unhandled_keyboard_event_type());
-
- // Forward the Char event.
- SimulateKeyboardEvent(WebInputEvent::Char);
-
- // 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.
- SendInputEventACK(WebInputEvent::Char, false);
-
- EXPECT_TRUE(host_->unhandled_keyboard_event_called());
- EXPECT_EQ(WebInputEvent::Char, host_->unhandled_keyboard_event_type());
-
- // Forward the KeyUp event.
- SimulateKeyboardEvent(WebInputEvent::KeyUp);
-
- // Make sure we sent the input event to the renderer.
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_HandleInputEvent::ID));
+TEST_F(RenderWidgetHostTest, PreHandleRawKeyDownEvent) {
+ // Simluate the situation that the browser handled the key down event during
+ // pre-handle phrase.
+ host_->set_prehandle_keyboard_event(true);
process_->sink().ClearMessages();
- // Send the simulated response from the renderer back.
- SendInputEventACK(WebInputEvent::KeyUp, false);
-
- EXPECT_TRUE(host_->unhandled_keyboard_event_called());
- EXPECT_EQ(WebInputEvent::KeyUp, host_->unhandled_keyboard_event_type());
-}
-
-TEST_F(RenderWidgetHostTest, SuppressNextCharEventsNoPending) {
// Simulate a keyboard event.
SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
- // Make sure we sent the input event to the renderer.
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
+ EXPECT_TRUE(host_->prehandle_keyboard_event_called());
+ EXPECT_EQ(WebInputEvent::RawKeyDown, host_->prehandle_keyboard_event_type());
- // Simluate the situation that the browser handled the key down event.
- host_->set_handle_unhandled_keyboard_event(true);
-
- // Send the simulated response from the renderer back.
- SendInputEventACK(WebInputEvent::RawKeyDown, false);
+ // Make sure the RawKeyDown event is not sent to the renderer.
+ EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_TRUE(host_->unhandled_keyboard_event_called());
- EXPECT_EQ(WebInputEvent::RawKeyDown, host_->unhandled_keyboard_event_type());
+ // The browser won't pre-handle a Char event.
+ host_->set_prehandle_keyboard_event(false);
// Forward the Char event.
SimulateKeyboardEvent(WebInputEvent::Char);
@@ -564,114 +539,10 @@ TEST_F(RenderWidgetHostTest, SuppressNextCharEventsNoPending) {
// Make sure the Char event is suppressed.
EXPECT_EQ(0U, process_->sink().message_count());
- // Forward another Char event.
- SimulateKeyboardEvent(WebInputEvent::Char);
-
- // Make sure the Char event is suppressed.
- EXPECT_EQ(0U, process_->sink().message_count());
-
// Forward the KeyUp event.
SimulateKeyboardEvent(WebInputEvent::KeyUp);
- // Make sure we sent the input event to the renderer.
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
-
- // The browser does not handle KeyUp events.
- host_->set_handle_unhandled_keyboard_event(false);
-
- // Send the simulated response from the renderer back.
- SendInputEventACK(WebInputEvent::KeyUp, false);
-
- EXPECT_TRUE(host_->unhandled_keyboard_event_called());
- EXPECT_EQ(WebInputEvent::KeyUp, host_->unhandled_keyboard_event_type());
-}
-
-TEST_F(RenderWidgetHostTest, DontSuppressNextCharEventsPending) {
- SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
-
- // Make sure we sent the input event to the renderer.
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
-
- // Forward the Char event before receiving the ACK of previous KeyDown event.
- SimulateKeyboardEvent(WebInputEvent::Char);
-
- // Make sure the Char event is pending.
- EXPECT_EQ(0U, process_->sink().message_count());
-
- // Forward the KeyUp event before receiving the ACK of previous KeyDown event.
- SimulateKeyboardEvent(WebInputEvent::KeyUp);
-
- // Make sure the KeyUp event is pending.
- EXPECT_EQ(0U, process_->sink().message_count());
-
- // Send the simulated response of the KeyDown event from the renderer back.
- SendInputEventACK(WebInputEvent::RawKeyDown, false);
-
- EXPECT_TRUE(host_->unhandled_keyboard_event_called());
- EXPECT_EQ(WebInputEvent::RawKeyDown, host_->unhandled_keyboard_event_type());
-
- // Make sure both pending Char and KeyUp were sent to the renderer.
- EXPECT_EQ(2U, process_->sink().message_count());
- EXPECT_EQ(ViewMsg_HandleInputEvent::ID,
- process_->sink().GetMessageAt(0)->type());
- EXPECT_EQ(ViewMsg_HandleInputEvent::ID,
- process_->sink().GetMessageAt(1)->type());
- process_->sink().ClearMessages();
-
- // Send the simulated response from the renderer back.
- SendInputEventACK(WebInputEvent::Char, false);
-
- EXPECT_TRUE(host_->unhandled_keyboard_event_called());
- EXPECT_EQ(WebInputEvent::Char, host_->unhandled_keyboard_event_type());
-
- // Send the simulated response from the renderer back.
- SendInputEventACK(WebInputEvent::KeyUp, false);
-
- EXPECT_TRUE(host_->unhandled_keyboard_event_called());
- EXPECT_EQ(WebInputEvent::KeyUp, host_->unhandled_keyboard_event_type());
-}
-
-TEST_F(RenderWidgetHostTest, SuppressNextCharEventsPending) {
- SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
-
- // Make sure we sent the KeyDown event to the renderer.
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
-
- // Forward the Char event before receiving the ACK of previous KeyDown event.
- SimulateKeyboardEvent(WebInputEvent::Char);
-
- // Make sure the Char event is pending.
- EXPECT_EQ(0U, process_->sink().message_count());
-
- // Forward another Char event before receiving the ACK of previous KeyDown
- // event.
- SimulateKeyboardEvent(WebInputEvent::Char);
-
- // Make sure the Char event is pending.
- EXPECT_EQ(0U, process_->sink().message_count());
-
- // Forward the KeyUp event before receiving the ACK of previous KeyDown event.
- SimulateKeyboardEvent(WebInputEvent::KeyUp);
-
- // Make sure the KeyUp event is pending.
- EXPECT_EQ(0U, process_->sink().message_count());
-
- // Simluate the situation that the browser handled the key down event.
- host_->set_handle_unhandled_keyboard_event(true);
-
- // Send the simulated response of the KeyDown event from the renderer back.
- SendInputEventACK(WebInputEvent::RawKeyDown, false);
-
- EXPECT_TRUE(host_->unhandled_keyboard_event_called());
- EXPECT_EQ(WebInputEvent::RawKeyDown, host_->unhandled_keyboard_event_type());
-
- // Make sure only pending KeyUp was sent to the renderer.
+ // Make sure only KeyUp was sent to the renderer.
EXPECT_EQ(1U, process_->sink().message_count());
EXPECT_EQ(ViewMsg_HandleInputEvent::ID,
process_->sink().GetMessageAt(0)->type());
@@ -683,51 +554,3 @@ TEST_F(RenderWidgetHostTest, SuppressNextCharEventsPending) {
EXPECT_TRUE(host_->unhandled_keyboard_event_called());
EXPECT_EQ(WebInputEvent::KeyUp, host_->unhandled_keyboard_event_type());
}
-
-TEST_F(RenderWidgetHostTest, ManyKeyEventsPending) {
- process_->sink().ClearMessages();
-
- for (int i = 0; i < 10; ++i) {
- // Forward a KeyDown event.
- SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
-
- // Forward a Char event before receiving the ACK of previous KeyDown event.
- SimulateKeyboardEvent(WebInputEvent::Char);
-
- // Forward a KeyUp event before receiving the ACK of previous KeyDown event.
- SimulateKeyboardEvent(WebInputEvent::KeyUp);
- }
-
- // Make sure only the first KeyDown event was sent to the renderer. All others
- // are pending.
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
-
- for (int i = 0; i < 10; ++i) {
- // Send the simulated response of the KeyDown event from the renderer back.
- SendInputEventACK(WebInputEvent::RawKeyDown, false);
- EXPECT_TRUE(host_->unhandled_keyboard_event_called());
- EXPECT_EQ(WebInputEvent::RawKeyDown,
- host_->unhandled_keyboard_event_type());
-
- // Make sure the following pending Char, KeyUp and KeyDown event were sent
- // to the renderer.
- if (i < 9)
- EXPECT_EQ(3U, process_->sink().message_count());
- else
- EXPECT_EQ(2U, process_->sink().message_count());
- process_->sink().ClearMessages();
-
- // Send the simulated response of the Char event from the renderer back.
- SendInputEventACK(WebInputEvent::Char, false);
- EXPECT_TRUE(host_->unhandled_keyboard_event_called());
- EXPECT_EQ(WebInputEvent::Char, host_->unhandled_keyboard_event_type());
-
- // Send the simulated response of the KeyUp event from the renderer back.
- SendInputEventACK(WebInputEvent::KeyUp, false);
- EXPECT_TRUE(host_->unhandled_keyboard_event_called());
- EXPECT_EQ(WebInputEvent::KeyUp, host_->unhandled_keyboard_event_type());
- }
-}
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.h b/chrome/browser/renderer_host/render_widget_host_view_mac.h
index 0e65cef..c661578 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.h
@@ -43,18 +43,12 @@ class RWHVMEditCommandHelper;
NSTrackingRectTag lastToolTipTag_;
scoped_nsobject<NSString> toolTip_;
- BOOL ignoreKeyEvents_;
scoped_nsobject<NSEvent> lastKeyPressedEvent_;
}
- (void)setCanBeKeyView:(BOOL)can;
- (void)setCloseOnDeactivate:(BOOL)b;
- (void)setToolTipAtMousePoint:(NSString *)string;
-
-// When a keyboard event comes back from the renderer, we redispatch it. This
-// makes sure we ignore it if we should receive it during redispatch, instead
-// of sending it to the renderer again.
-- (void)setIgnoreKeyEvents:(BOOL)ignorekeyEvents;
@end
///////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
index 8317479..17f4a66 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
@@ -589,14 +589,7 @@ void RenderWidgetHostViewMac::SetBackground(const SkBitmap& background) {
renderWidgetHostView_->render_widget_host_->ForwardMouseEvent(event);
}
-- (void)setIgnoreKeyEvents:(BOOL)ignorekeyEvents {
- ignoreKeyEvents_ = ignorekeyEvents;
-}
-
- (BOOL)performKeyEquivalent:(NSEvent*)theEvent {
- if (ignoreKeyEvents_)
- return NO;
-
// |performKeyEquivalent:| is sent to all views of a window, not only down the
// responder chain (cf. "Handling Key Equivalents" in
// http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/EventOverview/HandlingKeyEvents/HandlingKeyEvents.html
@@ -642,9 +635,6 @@ void RenderWidgetHostViewMac::SetBackground(const SkBitmap& background) {
}
- (void)keyEvent:(NSEvent *)theEvent wasKeyEquivalent:(BOOL)equiv {
- if (ignoreKeyEvents_)
- return;
-
DCHECK([theEvent type] != NSKeyDown ||
!equiv == !([theEvent modifierFlags] & NSCommandKeyMask));