summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-02 01:25:41 +0000
committerjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-02 01:25:41 +0000
commit97df4b330f4a2b1a34adb1eb8e5f5e7f60d716ff (patch)
tree46cd48cb3b533fb88bb6e6975427e7741578cb5c /chrome
parent7a0f5a3abf37e21eb15f4fe4058e917426e2e105 (diff)
downloadchromium_src-97df4b330f4a2b1a34adb1eb8e5f5e7f60d716ff.zip
chromium_src-97df4b330f4a2b1a34adb1eb8e5f5e7f60d716ff.tar.gz
chromium_src-97df4b330f4a2b1a34adb1eb8e5f5e7f60d716ff.tar.bz2
Don't send tab switching/killing/creating keyboard accelerators to pages. This avoids tabs maliciously preventing closing using ctrl+f4/ctrl+w/alt+f4, and also hung/slow renderers from making tab cycling sluggish.
BUG=5496 TEST=added ui test Review URL: http://codereview.chromium.org/224023 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27814 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/browser.cc22
-rw-r--r--chrome/browser/browser.h1
-rw-r--r--chrome/browser/browser_focus_uitest.cc40
-rw-r--r--chrome/browser/browser_window.h5
-rw-r--r--chrome/browser/chromeos/main_menu.h3
-rw-r--r--chrome/browser/cocoa/browser_window_cocoa.h1
-rw-r--r--chrome/browser/cocoa/browser_window_cocoa.mm6
-rw-r--r--chrome/browser/extensions/extension_host.cc4
-rw-r--r--chrome/browser/extensions/extension_host.h1
-rw-r--r--chrome/browser/gtk/browser_window_gtk.cc51
-rw-r--r--chrome/browser/gtk/browser_window_gtk.h1
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc19
-rw-r--r--chrome/browser/renderer_host/render_view_host.h1
-rw-r--r--chrome/browser/renderer_host/render_view_host_delegate.h4
-rw-r--r--chrome/browser/renderer_host/render_widget_host.cc9
-rw-r--r--chrome/browser/renderer_host/render_widget_host.h6
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_gtk.cc6
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_gtk.h2
-rw-r--r--chrome/browser/tab_contents/interstitial_page.cc6
-rw-r--r--chrome/browser/tab_contents/tab_contents_delegate.h6
-rw-r--r--chrome/browser/tab_contents/tab_contents_view.cc6
-rw-r--r--chrome/browser/tab_contents/tab_contents_view.h6
-rw-r--r--chrome/browser/views/frame/browser_view.cc20
-rw-r--r--chrome/browser/views/frame/browser_view.h1
-rw-r--r--chrome/test/test_browser_window.h1
25 files changed, 198 insertions, 30 deletions
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc
index ae1b5538..13288c9 100644
--- a/chrome/browser/browser.cc
+++ b/chrome/browser/browser.cc
@@ -2108,6 +2108,28 @@ void Browser::ShowPageInfo(Profile* profile,
window()->ShowPageInfo(profile, url, ssl, show_history);
}
+bool Browser::IsReservedAccelerator(const NativeWebKeyboardEvent& event) {
+ // Other platforms don't send close-app keyboard shortcuts to apps first.
+#if defined(OS_WIN)
+ if ((event.modifiers & NativeWebKeyboardEvent::AltKey) &&
+ event.windowsKeyCode == VK_F4) {
+ return true;
+ }
+#endif
+
+ int command_id = window()->GetCommandId(event);
+ return command_id == IDC_CLOSE_TAB ||
+ command_id == IDC_CLOSE_POPUPS ||
+ command_id == IDC_CLOSE_WINDOW ||
+ command_id == IDC_NEW_INCOGNITO_WINDOW ||
+ command_id == IDC_NEW_TAB ||
+ command_id == IDC_NEW_WINDOW ||
+ command_id == IDC_RESTORE_TAB ||
+ command_id == IDC_SELECT_NEXT_TAB ||
+ command_id == IDC_SELECT_PREVIOUS_TAB ||
+ command_id == IDC_TASK_MANAGER;
+}
+
void Browser::ShowRepostFormWarningDialog(TabContents *tab_contents) {
window()->ShowRepostFormWarningDialog(tab_contents);
}
diff --git a/chrome/browser/browser.h b/chrome/browser/browser.h
index be4e1c2..b83eeea 100644
--- a/chrome/browser/browser.h
+++ b/chrome/browser/browser.h
@@ -539,6 +539,7 @@ class Browser : public TabStripModelDelegate,
const GURL& url,
const NavigationEntry::SSLStatus& ssl,
bool show_history);
+ virtual bool IsReservedAccelerator(const NativeWebKeyboardEvent& event);
virtual void ShowRepostFormWarningDialog(TabContents* tab_contents);
// Overridden from SelectFileDialog::Listener:
diff --git a/chrome/browser/browser_focus_uitest.cc b/chrome/browser/browser_focus_uitest.cc
index 89abf91..e5f014a 100644
--- a/chrome/browser/browser_focus_uitest.cc
+++ b/chrome/browser/browser_focus_uitest.cc
@@ -15,8 +15,13 @@
#include "chrome/browser/tab_contents/tab_contents_view.h"
#include "chrome/browser/view_ids.h"
#include "chrome/common/chrome_paths.h"
+#include "chrome/test/automation/browser_proxy.h"
+#include "chrome/test/automation/tab_proxy.h"
+#include "chrome/test/automation/window_proxy.h"
#include "chrome/test/in_process_browser_test.h"
+#include "chrome/test/ui/ui_test.h"
#include "chrome/test/ui_test_utils.h"
+#include "views/event.h"
#include "views/focus/focus_manager.h"
#include "views/view.h"
#include "views/window/window.h"
@@ -737,3 +742,38 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, FocusOnReloadCrashedTab) {
browser()->ShowDownloadsTab();
CheckViewHasFocus(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW);
}
+
+#if !defined(OS_MACOSX) // see BrowserWindowCocoa::GetCommandId
+// Tests that tab related keyboard accelerators are reserved by the app.
+
+class BrowserInteractiveTest : public UITest {
+};
+
+TEST_F(BrowserInteractiveTest, ReserveKeyboardAccelerators) {
+ const std::string kBadPage =
+ "<html><script>"
+ "document.onkeydown = function() {"
+ " event.preventDefault();"
+ " return false;"
+ "}"
+ "</script></html>";
+ scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
+ browser->AppendTab(GURL("data:text/html," + kBadPage));
+ int tab_count = 0;
+ ASSERT_TRUE(browser->GetTabCount(&tab_count));
+ ASSERT_EQ(tab_count, 2);
+
+ int active_tab = 0;
+ ASSERT_TRUE(browser->GetActiveTabIndex(&active_tab));
+ ASSERT_EQ(active_tab, 1);
+
+ scoped_refptr<WindowProxy> window(browser->GetWindow());
+ ASSERT_TRUE(window->SimulateOSKeyPress(
+ base::VKEY_TAB, views::Event::EF_CONTROL_DOWN));
+ ASSERT_TRUE(browser->WaitForTabToBecomeActive(0, action_max_timeout_ms()));
+
+ ASSERT_TRUE(window->SimulateOSKeyPress(
+ base::VKEY_F4, views::Event::EF_CONTROL_DOWN));
+ ASSERT_TRUE(browser->WaitForTabCountToBecome(1, action_max_timeout_ms()));
+}
+#endif
diff --git a/chrome/browser/browser_window.h b/chrome/browser/browser_window.h
index 5de0857..b26b447 100644
--- a/chrome/browser/browser_window.h
+++ b/chrome/browser/browser_window.h
@@ -21,6 +21,7 @@ class TabContents;
class TabContentsContainer;
class TemplateURL;
class ToolbarView;
+struct NativeWebKeyboardEvent;
namespace gfx {
class Rect;
@@ -255,6 +256,10 @@ class BrowserWindow {
// Shows the app menu (for accessibility).
virtual void ShowAppMenu() = 0;
+ // Returns the id of the keyboard accelerator associated with the given
+ // keyboard event if one exists, otherwise -1.
+ virtual int GetCommandId(const NativeWebKeyboardEvent& event) = 0;
+
// Construct a BrowserWindow implementation for the specified |browser|.
static BrowserWindow* CreateBrowserWindow(Browser* browser);
diff --git a/chrome/browser/chromeos/main_menu.h b/chrome/browser/chromeos/main_menu.h
index 85bf5689..e1f7a5f 100644
--- a/chrome/browser/chromeos/main_menu.h
+++ b/chrome/browser/chromeos/main_menu.h
@@ -132,6 +132,9 @@ class MainMenu : public RenderViewHostDelegate,
virtual void UpdateDragCursor(WebKit::WebDragOperation operation) {}
virtual void GotFocus() {}
virtual void TakeFocus(bool reverse) {}
+ virtual bool IsReservedAccelerator(const NativeWebKeyboardEvent& event) {
+ return false;
+ }
virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {}
virtual void HandleMouseEvent() {}
virtual void HandleMouseLeave() {}
diff --git a/chrome/browser/cocoa/browser_window_cocoa.h b/chrome/browser/cocoa/browser_window_cocoa.h
index 922e4f3..73e3bff 100644
--- a/chrome/browser/cocoa/browser_window_cocoa.h
+++ b/chrome/browser/cocoa/browser_window_cocoa.h
@@ -88,6 +88,7 @@ class BrowserWindowCocoa : public BrowserWindow,
bool show_history);
virtual void ShowPageMenu();
virtual void ShowAppMenu();
+ virtual int GetCommandId(const NativeWebKeyboardEvent& event);
// Overridden from NotificationObserver
virtual void Observe(NotificationType type,
diff --git a/chrome/browser/cocoa/browser_window_cocoa.mm b/chrome/browser/cocoa/browser_window_cocoa.mm
index a83e091..3afae7e 100644
--- a/chrome/browser/cocoa/browser_window_cocoa.mm
+++ b/chrome/browser/cocoa/browser_window_cocoa.mm
@@ -320,6 +320,12 @@ void BrowserWindowCocoa::ShowAppMenu() {
// No-op. Mac doesn't support showing the menus via alt keys.
}
+int BrowserWindowCocoa::GetCommandId(const NativeWebKeyboardEvent& event) {
+ // TODO(port): return the command id if this is a keyboard accelerator.
+ // CommandForKeyboardShortcut() doesn't have the full list.
+ return -1;
+}
+
void BrowserWindowCocoa::Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc
index 84852e2..0f3f6d8 100644
--- a/chrome/browser/extensions/extension_host.cc
+++ b/chrome/browser/extensions/extension_host.cc
@@ -415,6 +415,10 @@ void ExtensionHost::GotFocus() {
void ExtensionHost::TakeFocus(bool reverse) {
}
+bool ExtensionHost::IsReservedAccelerator(const NativeWebKeyboardEvent& event) {
+ return false;
+}
+
void ExtensionHost::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {
}
diff --git a/chrome/browser/extensions/extension_host.h b/chrome/browser/extensions/extension_host.h
index 7f3ad2cf..70690ef 100644
--- a/chrome/browser/extensions/extension_host.h
+++ b/chrome/browser/extensions/extension_host.h
@@ -128,6 +128,7 @@ class ExtensionHost : public RenderViewHostDelegate,
virtual void UpdateDragCursor(WebKit::WebDragOperation operation);
virtual void GotFocus();
virtual void TakeFocus(bool reverse);
+ virtual bool IsReservedAccelerator(const NativeWebKeyboardEvent& event);
virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event);
virtual void HandleMouseEvent();
virtual void HandleMouseLeave();
diff --git a/chrome/browser/gtk/browser_window_gtk.cc b/chrome/browser/gtk/browser_window_gtk.cc
index 1fff4f4..d9a43ca 100644
--- a/chrome/browser/gtk/browser_window_gtk.cc
+++ b/chrome/browser/gtk/browser_window_gtk.cc
@@ -198,6 +198,10 @@ const struct AcceleratorMapping {
{ GDK_Page_Up, IDC_MOVE_TAB_PREVIOUS,
GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
{ GDK_Page_Up, IDC_SELECT_PREVIOUS_TAB, GDK_CONTROL_MASK },
+ { GDK_t, IDC_NEW_TAB, GDK_CONTROL_MASK },
+ { GDK_n, IDC_NEW_WINDOW, GDK_CONTROL_MASK },
+ { GDK_n, IDC_NEW_INCOGNITO_WINDOW,
+ GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
{ GDK_w, IDC_CLOSE_TAB, GDK_CONTROL_MASK },
{ GDK_t, IDC_RESTORE_TAB,
GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
@@ -361,18 +365,15 @@ int GetCommandId(guint accel_key, GdkModifierType modifier) {
kAcceleratorMap[i].modifier_type == modifier)
return kAcceleratorMap[i].command_id;
}
- NOTREACHED();
- return 0;
+
+ return -1;
}
-// An event handler for key press events. We need to special case key
-// combinations that are not valid gtk accelerators. This function returns
-// TRUE if it can handle the key press.
-gboolean HandleCustomAccelerator(guint keyval, GdkModifierType modifier,
- Browser* browser) {
+int GetCustomCommandId(guint keyval, GdkModifierType modifier) {
// Filter modifier to only include accelerator modifiers.
modifier = static_cast<GdkModifierType>(
modifier & gtk_accelerator_get_default_mod_mask());
+
switch (keyval) {
// Gtk doesn't allow GDK_Tab or GDK_ISO_Left_Tab to be an accelerator (see
// gtk_accelerator_valid), so we need to handle these accelerators
@@ -384,18 +385,29 @@ gboolean HandleCustomAccelerator(guint keyval, GdkModifierType modifier,
case GDK_ISO_Left_Tab:
case GDK_KP_Tab:
if (GDK_CONTROL_MASK == modifier) {
- browser->ExecuteCommand(IDC_SELECT_NEXT_TAB);
- return TRUE;
+ return IDC_SELECT_NEXT_TAB;
} else if ((GDK_CONTROL_MASK | GDK_SHIFT_MASK) == modifier) {
- browser->ExecuteCommand(IDC_SELECT_PREVIOUS_TAB);
- return TRUE;
+ return IDC_SELECT_PREVIOUS_TAB;
}
break;
default:
break;
}
- return FALSE;
+ return -1;
+}
+
+// An event handler for key press events. We need to special case key
+// combinations that are not valid gtk accelerators. This function returns
+// TRUE if it can handle the key press.
+gboolean HandleCustomAccelerator(guint keyval, GdkModifierType modifier,
+ Browser* browser) {
+ int command = GetCustomCommandId(keyval, modifier);
+ if (command == -1)
+ return FALSE;
+
+ browser->ExecuteCommand(command);
+ return TRUE;
}
// Handle accelerators that we don't want the native widget to be able to
@@ -1153,6 +1165,18 @@ void BrowserWindowGtk::ShowPageMenu() {
void BrowserWindowGtk::ShowAppMenu() {
}
+int BrowserWindowGtk::GetCommandId(const NativeWebKeyboardEvent& event) {
+ if (!event.os_event)
+ return -1;
+
+ guint keyval = event.os_event->keyval;
+ GdkModifierType modifier = GdkModifierType(event.os_event->state);
+ int command = ::GetCommandId(keyval, modifier);
+ if (command == -1)
+ command = GetCustomCommandId(keyval, modifier);
+ return command;
+}
+
void BrowserWindowGtk::ConfirmBrowserCloseWithPendingDownloads() {
new DownloadInProgressDialogGtk(browser());
}
@@ -1881,7 +1905,8 @@ gboolean BrowserWindowGtk::OnGtkAccelerator(GtkAccelGroup* accel_group,
guint keyval,
GdkModifierType modifier,
BrowserWindowGtk* browser_window) {
- int command_id = GetCommandId(keyval, modifier);
+ int command_id = ::GetCommandId(keyval, modifier);
+ DCHECK(command_id != -1);
browser_window->ExecuteBrowserCommand(command_id);
return TRUE;
diff --git a/chrome/browser/gtk/browser_window_gtk.h b/chrome/browser/gtk/browser_window_gtk.h
index d109821..549a84a 100644
--- a/chrome/browser/gtk/browser_window_gtk.h
+++ b/chrome/browser/gtk/browser_window_gtk.h
@@ -121,6 +121,7 @@ class BrowserWindowGtk : public BrowserWindow,
bool show_history);
virtual void ShowPageMenu();
virtual void ShowAppMenu();
+ virtual int GetCommandId(const NativeWebKeyboardEvent& event);
// Overridden from NotificationObserver:
virtual void Observe(NotificationType type,
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index 2b66289..c0cb864 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -1425,19 +1425,18 @@ void RenderViewHost::OnUserMetricsRecordAction(const std::wstring& action) {
UserMetrics::RecordComputedAction(action.c_str(), process()->profile());
}
+bool RenderViewHost::ShouldSendToRenderer(const NativeWebKeyboardEvent& event) {
+ RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
+ if (!view)
+ return true;
+ return !view->IsReservedAccelerator(event);
+}
+
void RenderViewHost::UnhandledKeyboardEvent(
const NativeWebKeyboardEvent& event) {
RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
- if (view) {
- // TODO(brettw) why do we have to filter these types of events here. Can't
- // the renderer just send us the ones we care abount, or maybe the view
- // should be able to decide which ones it wants or not?
- if ((event.type == WebInputEvent::RawKeyDown) ||
- (event.type == WebInputEvent::KeyDown) ||
- (event.type == WebInputEvent::Char)) {
- view->HandleKeyboardEvent(event);
- }
- }
+ 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 328a566..72ee9eb 100644
--- a/chrome/browser/renderer_host/render_view_host.h
+++ b/chrome/browser/renderer_host/render_view_host.h
@@ -436,6 +436,7 @@ class RenderViewHost : public RenderWidgetHost,
protected:
// RenderWidgetHost protected overrides.
+ virtual bool ShouldSendToRenderer(const NativeWebKeyboardEvent& event);
virtual void UnhandledKeyboardEvent(const NativeWebKeyboardEvent& event);
virtual void OnUserGesture();
virtual void NotifyRendererUnresponsive();
diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h
index 9c121a1..d31d94c 100644
--- a/chrome/browser/renderer_host/render_view_host_delegate.h
+++ b/chrome/browser/renderer_host/render_view_host_delegate.h
@@ -125,6 +125,10 @@ 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 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).
diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc
index d9971ec..01ee015 100644
--- a/chrome/browser/renderer_host/render_widget_host.cc
+++ b/chrome/browser/renderer_host/render_widget_host.cc
@@ -400,6 +400,13 @@ void RenderWidgetHost::ForwardKeyboardEvent(
if (!process_->HasConnection())
return;
+ // Tab switching/closing accelerators aren't sent to the renderer to avoid a
+ // hung/malicious renderer from interfering.
+ if (!ShouldSendToRenderer(key_event)) {
+ UnhandledKeyboardEvent(key_event);
+ 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.
@@ -754,7 +761,7 @@ void RenderWidgetHost::OnMsgInputEventAck(const IPC::Message& message) {
if (!message.ReadBool(&iter, &processed))
process()->ReceivedBadMessage(message.type());
- KeyQueue::value_type front_item = key_queue_.front();
+ NativeWebKeyboardEvent front_item = key_queue_.front();
key_queue_.pop();
if (!processed) {
diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h
index a80d1fd..2438e16 100644
--- a/chrome/browser/renderer_host/render_widget_host.h
+++ b/chrome/browser/renderer_host/render_widget_host.h
@@ -357,6 +357,12 @@ 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 when we an InputEvent was not processed by the renderer. This is
// overridden by RenderView to send upwards to its delegate.
virtual void UnhandledKeyboardEvent(const NativeWebKeyboardEvent& event) {}
diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
index 0440820..d382aff 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
@@ -519,6 +519,9 @@ void RenderWidgetHostViewGtk::Destroy() {
// See http://www.crbug.com/11847 for details.
gtk_widget_destroy(view_.get());
+ // The RenderWidgetHost's destruction led here, so don't call it.
+ host_ = NULL;
+
MessageLoop::current()->DeleteSoon(FROM_HERE, this);
}
@@ -643,6 +646,9 @@ void RenderWidgetHostViewGtk::DestroyPluginContainer(
void RenderWidgetHostViewGtk::ForwardKeyboardEvent(
const NativeWebKeyboardEvent& event) {
+ if (!host_)
+ return;
+
EditCommands edit_commands;
if (key_bindings_handler_->Match(event, &edit_commands)) {
host_->ForwardEditCommandsForNextKeyEvent(edit_commands);
diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.h b/chrome/browser/renderer_host/render_widget_host_view_gtk.h
index 2f7e6b3..933629e 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_gtk.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.h
@@ -90,7 +90,7 @@ class RenderWidgetHostViewGtk : public RenderWidgetHostView {
void ShowCurrentCursor();
// The model object.
- RenderWidgetHost* const host_;
+ RenderWidgetHost* host_;
// The native UI widget.
OwnedWidgetGtk view_;
diff --git a/chrome/browser/tab_contents/interstitial_page.cc b/chrome/browser/tab_contents/interstitial_page.cc
index 4191d4d..935dc1c 100644
--- a/chrome/browser/tab_contents/interstitial_page.cc
+++ b/chrome/browser/tab_contents/interstitial_page.cc
@@ -93,6 +93,7 @@ class InterstitialPage::InterstitialPageRVHViewDelegate
virtual void UpdateDragCursor(WebDragOperation operation);
virtual void GotFocus();
virtual void TakeFocus(bool reverse);
+ virtual bool IsReservedAccelerator(const NativeWebKeyboardEvent& event);
virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event);
virtual void HandleMouseEvent();
virtual void HandleMouseLeave();
@@ -575,6 +576,11 @@ void InterstitialPage::InterstitialPageRVHViewDelegate::TakeFocus(
interstitial_page_->tab()->GetViewDelegate()->TakeFocus(reverse);
}
+bool InterstitialPage::InterstitialPageRVHViewDelegate::IsReservedAccelerator(
+ const NativeWebKeyboardEvent& event) {
+ return false;
+}
+
void InterstitialPage::InterstitialPageRVHViewDelegate::HandleKeyboardEvent(
const NativeWebKeyboardEvent& event) {
if (interstitial_page_->tab() && interstitial_page_->tab()->GetViewDelegate())
diff --git a/chrome/browser/tab_contents/tab_contents_delegate.h b/chrome/browser/tab_contents/tab_contents_delegate.h
index 156bb18..c61a4d7 100644
--- a/chrome/browser/tab_contents/tab_contents_delegate.h
+++ b/chrome/browser/tab_contents/tab_contents_delegate.h
@@ -214,6 +214,12 @@ class TabContentsDelegate {
bool show_history) {
}
+ // Returns whether the event is a reserved keyboard shortcut that should not
+ // be sent to the renderer.
+ virtual bool IsReservedAccelerator(const NativeWebKeyboardEvent& event) {
+ return false;
+ }
+
// Allows delegates to handle unhandled keyboard messages coming back from
// the renderer.
// Returns true if the keyboard message was handled.
diff --git a/chrome/browser/tab_contents/tab_contents_view.cc b/chrome/browser/tab_contents/tab_contents_view.cc
index 7a45e04..99a052a 100644
--- a/chrome/browser/tab_contents/tab_contents_view.cc
+++ b/chrome/browser/tab_contents/tab_contents_view.cc
@@ -56,6 +56,12 @@ void TabContentsView::ShowCreatedWidget(int route_id,
ShowCreatedWidgetInternal(widget_host_view, initial_pos);
}
+bool TabContentsView::IsReservedAccelerator(
+ const NativeWebKeyboardEvent& event) {
+ return tab_contents()->delegate() &&
+ tab_contents()->delegate()->IsReservedAccelerator(event);
+}
+
RenderWidgetHostView* TabContentsView::CreateNewWidgetInternal(
int route_id, bool activatable) {
return delegate_view_helper_.CreateNewWidget(route_id, activatable,
diff --git a/chrome/browser/tab_contents/tab_contents_view.h b/chrome/browser/tab_contents/tab_contents_view.h
index ca42276..978b086 100644
--- a/chrome/browser/tab_contents/tab_contents_view.h
+++ b/chrome/browser/tab_contents/tab_contents_view.h
@@ -20,11 +20,6 @@ class RenderViewHost;
class RenderWidgetHost;
class RenderWidgetHostView;
class TabContents;
-class WebKeyboardEvent;
-
-namespace base {
-class WaitableEvent;
-}
// The TabContentsView is an interface that is implemented by the platform-
// dependent web contents views. The TabContents uses this interface to talk to
@@ -181,6 +176,7 @@ class TabContentsView : public RenderViewHostDelegate::View {
bool user_gesture,
const GURL& creator_url);
virtual void ShowCreatedWidget(int route_id, const gfx::Rect& initial_pos);
+ virtual bool IsReservedAccelerator(const NativeWebKeyboardEvent& event);
// The TabContents whose contents we display.
TabContents* tab_contents_;
diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc
index 50fd3bd..a9fea14 100644
--- a/chrome/browser/views/frame/browser_view.cc
+++ b/chrome/browser/views/frame/browser_view.cc
@@ -12,6 +12,7 @@
#include "base/command_line.h"
#include "base/keyboard_codes.h"
#include "base/time.h"
+#include "base/win_util.h"
#include "build/build_config.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/app_modal_dialog_queue.h"
@@ -48,6 +49,7 @@
#include "chrome/browser/tab_contents/tab_contents_view.h"
#include "chrome/browser/window_sizer.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/common/native_web_keyboard_event.h"
#include "chrome/common/native_window_notification_source.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/pref_names.h"
@@ -1127,6 +1129,24 @@ void BrowserView::ShowAppMenu() {
toolbar_->app_menu()->Activate();
}
+int BrowserView::GetCommandId(const NativeWebKeyboardEvent& event) {
+ views::Accelerator accelerator(
+ win_util::WinToKeyboardCode(event.windowsKeyCode),
+ (event.modifiers & NativeWebKeyboardEvent::ShiftKey) ==
+ NativeWebKeyboardEvent::ShiftKey,
+ (event.modifiers & NativeWebKeyboardEvent::ControlKey) ==
+ NativeWebKeyboardEvent::ControlKey,
+ (event.modifiers & NativeWebKeyboardEvent::AltKey) ==
+ NativeWebKeyboardEvent::AltKey);
+
+ std::map<views::Accelerator, int>::const_iterator iter =
+ accelerator_table_.find(accelerator);
+ if (iter == accelerator_table_.end())
+ return -1;
+
+ return iter->second;
+}
+
///////////////////////////////////////////////////////////////////////////////
// BrowserView, BrowserWindowTesting implementation:
diff --git a/chrome/browser/views/frame/browser_view.h b/chrome/browser/views/frame/browser_view.h
index f910e29..f4f2c2e 100644
--- a/chrome/browser/views/frame/browser_view.h
+++ b/chrome/browser/views/frame/browser_view.h
@@ -261,6 +261,7 @@ class BrowserView : public BrowserWindow,
bool show_history);
virtual void ShowAppMenu();
virtual void ShowPageMenu();
+ virtual int GetCommandId(const NativeWebKeyboardEvent& event);
// Overridden from BrowserWindowTesting:
virtual BookmarkBarView* GetBookmarkBarView() const;
diff --git a/chrome/test/test_browser_window.h b/chrome/test/test_browser_window.h
index 636e951..0859089 100644
--- a/chrome/test/test_browser_window.h
+++ b/chrome/test/test_browser_window.h
@@ -53,6 +53,7 @@ class TestBrowserWindow : public BrowserWindow {
virtual void FocusToolbar() {}
virtual void ShowPageMenu() {}
virtual void ShowAppMenu() {}
+ virtual int GetCommandId(const NativeWebKeyboardEvent& event) { return -1; }
virtual bool IsBookmarkBarVisible() const { return false; }
virtual gfx::Rect GetRootWindowResizerRect() const { return gfx::Rect(); }
virtual void ConfirmAddSearchProvider(const TemplateURL* template_url,