diff options
Diffstat (limited to 'chrome/browser/renderer_host')
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)); |