summaryrefslogtreecommitdiffstats
path: root/chrome_frame
diff options
context:
space:
mode:
authorananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-17 08:21:35 +0000
committerananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-17 08:21:35 +0000
commita15d4a42a5b5e1fc2390c45188c4d8fa3c381a3f (patch)
treeb051c7d0daf57be61d3f226437d0775df84cb21f /chrome_frame
parent2e59325fed2416cd23d0b418cd46e302148aa584 (diff)
downloadchromium_src-a15d4a42a5b5e1fc2390c45188c4d8fa3c381a3f.zip
chromium_src-a15d4a42a5b5e1fc2390c45188c4d8fa3c381a3f.tar.gz
chromium_src-a15d4a42a5b5e1fc2390c45188c4d8fa3c381a3f.tar.bz2
We need to support the following accelerators in the ChromeFrame Active document, to ensure that the following
accelerators navigate backwards and forwards in IE history. 1. VK_BACK and Alt + VK_LEFT to navigate back. 2. Shift + VK_BACK and Alt + VK_RIGHT to navigate forward. This CL adds support for this. We load the accelerator table in our Active document and when we receive an accelerator from Chrome, we first call the Windows API TranslateAccelerator to translate any accelerators and then continue with the default handling. Added handlers for navigating back and forward. Test=covered by unit test. Fixes bug http://code.google.com/p/chromium/issues/detail?id=35629 Bug=35629 Review URL: http://codereview.chromium.org/600117 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@39208 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame')
-rw-r--r--chrome_frame/chrome_active_document.cc39
-rw-r--r--chrome_frame/chrome_active_document.h8
-rw-r--r--chrome_frame/resources/chrome_frame_resources.grd4
-rw-r--r--chrome_frame/resources/structured_resources.rc8
-rw-r--r--chrome_frame/test/chrome_frame_test_utils.cc10
-rw-r--r--chrome_frame/test/chrome_frame_test_utils.h7
-rw-r--r--chrome_frame/test/data/fulltab_back_page.html16
-rw-r--r--chrome_frame/test/data/fulltab_forward_page.html16
-rw-r--r--chrome_frame/test/simulate_input.cc21
-rw-r--r--chrome_frame/test/simulate_input.h4
-rw-r--r--chrome_frame/test/test_mock_with_web_server.cc120
11 files changed, 245 insertions, 8 deletions
diff --git a/chrome_frame/chrome_active_document.cc b/chrome_frame/chrome_active_document.cc
index e212b9c..886c9df 100644
--- a/chrome_frame/chrome_active_document.cc
+++ b/chrome_frame/chrome_active_document.cc
@@ -52,7 +52,8 @@ bool g_first_launch_by_process_ = true;
ChromeActiveDocument::ChromeActiveDocument()
: first_navigation_(true),
- is_automation_client_reused_(false) {
+ is_automation_client_reused_(false),
+ accelerator_table_(NULL) {
url_fetcher_.set_frame_busting(false);
memset(&navigation_info_, 0, sizeof(navigation_info_));
}
@@ -95,6 +96,11 @@ HRESULT ChromeActiveDocument::FinalConstruct() {
enabled_commands_map_[OLECMDID_PASTE] = true;
enabled_commands_map_[OLECMDID_SELECTALL] = true;
enabled_commands_map_[OLECMDID_SAVEAS] = true;
+
+ accelerator_table_ =
+ LoadAccelerators(GetModuleHandle(L"npchrome_frame.dll"),
+ MAKEINTRESOURCE(IDR_CHROME_FRAME_IE_FULL_TAB));
+ DCHECK(accelerator_table_ != NULL);
return S_OK;
}
@@ -487,6 +493,10 @@ bool IsFindAccelerator(const MSG& msg) {
void ChromeActiveDocument::OnAcceleratorPressed(int tab_handle,
const MSG& accel_message) {
+ if (::TranslateAccelerator(m_hWnd, accelerator_table_,
+ const_cast<MSG*>(&accel_message)))
+ return;
+
bool handled_accel = false;
if (in_place_frame_ != NULL) {
handled_accel = (S_OK == in_place_frame_->TranslateAcceleratorW(
@@ -978,3 +988,30 @@ HRESULT ChromeActiveDocument::GetBrowserServiceAndTravelLog(
return hr;
}
+
+LRESULT ChromeActiveDocument::OnForward(WORD notify_code, WORD id,
+ HWND control_window,
+ BOOL& bHandled) {
+ ScopedComPtr<IWebBrowser2> web_browser2;
+ DoQueryService(SID_SWebBrowserApp, m_spClientSite, web_browser2.Receive());
+ DCHECK(web_browser2);
+
+ if (web_browser2) {
+ web_browser2->GoForward();
+ }
+ return 0;
+}
+
+LRESULT ChromeActiveDocument::OnBack(WORD notify_code, WORD id,
+ HWND control_window,
+ BOOL& bHandled) {
+ ScopedComPtr<IWebBrowser2> web_browser2;
+ DoQueryService(SID_SWebBrowserApp, m_spClientSite, web_browser2.Receive());
+ DCHECK(web_browser2);
+
+ if (web_browser2) {
+ web_browser2->GoBack();
+ }
+ return 0;
+}
+
diff --git a/chrome_frame/chrome_active_document.h b/chrome_frame/chrome_active_document.h
index aeec2d82..e7a4397 100644
--- a/chrome_frame/chrome_active_document.h
+++ b/chrome_frame/chrome_active_document.h
@@ -146,6 +146,8 @@ BEGIN_COM_MAP(ChromeActiveDocument)
END_COM_MAP()
BEGIN_MSG_MAP(ChromeActiveDocument)
+ COMMAND_ID_HANDLER(IDC_FORWARD, OnForward)
+ COMMAND_ID_HANDLER(IDC_BACK, OnBack)
CHAIN_MSG_MAP(Base)
END_MSG_MAP()
@@ -299,6 +301,10 @@ END_EXEC_COMMAND_MAP()
// Get the travel log from the client site
HRESULT GetBrowserServiceAndTravelLog(IBrowserService** browser_service,
ITravelLog** travel_log);
+ LRESULT OnForward(WORD notify_code, WORD id, HWND control_window,
+ BOOL& bHandled);
+ LRESULT OnBack(WORD notify_code, WORD id, HWND control_window,
+ BOOL& bHandled);
protected:
typedef std::map<int, bool> EnabledCommandsMap;
@@ -324,6 +330,8 @@ END_EXEC_COMMAND_MAP()
ScopedComPtr<IInternetSecurityManager> security_manager_;
+ HACCEL accelerator_table_;
+
public:
ScopedComPtr<IOleInPlaceFrame> in_place_frame_;
OLEINPLACEFRAMEINFO frame_info_;
diff --git a/chrome_frame/resources/chrome_frame_resources.grd b/chrome_frame/resources/chrome_frame_resources.grd
index ebb9e11..ea9f98f 100644
--- a/chrome_frame/resources/chrome_frame_resources.grd
+++ b/chrome_frame/resources/chrome_frame_resources.grd
@@ -40,6 +40,10 @@ for localizable strings
<structure name="IDD_FIND_DIALOG" file="structured_resources.rc" type="dialog" >
</structure>
</structures>
+ <structures first_id="50005">
+ <structure name="IDR_CHROME_FRAME_IE_FULL_TAB" file="structured_resources.rc" type="accelerators" >
+ </structure>
+ </structures>
<includes>
<include name="IDR_BHO" file="../bho.rgs" type="REGISTRY" />
<include name="IDR_CHROMETAB" file="../chrome_tab.rgs" type="REGISTRY" />
diff --git a/chrome_frame/resources/structured_resources.rc b/chrome_frame/resources/structured_resources.rc
index 22e0337..d2dbed3 100644
--- a/chrome_frame/resources/structured_resources.rc
+++ b/chrome_frame/resources/structured_resources.rc
@@ -22,3 +22,11 @@ BEGIN
CONTROL "&Up",IDC_DIRECTION_UP,"Button",BS_AUTORADIOBUTTON,155,34,38,10
LTEXT "Fi&nd what:",IDC_STATIC,6,7,35,8
END
+
+IDR_CHROME_FRAME_IE_FULL_TAB ACCELERATORS
+BEGIN
+ VK_LEFT, IDC_BACK, VIRTKEY, ALT
+ VK_BACK, IDC_BACK, VIRTKEY
+ VK_BACK, IDC_FORWARD, VIRTKEY, SHIFT
+ VK_RIGHT, IDC_FORWARD, VIRTKEY, ALT
+END
diff --git a/chrome_frame/test/chrome_frame_test_utils.cc b/chrome_frame/test/chrome_frame_test_utils.cc
index dc1f116..04e1597 100644
--- a/chrome_frame/test/chrome_frame_test_utils.cc
+++ b/chrome_frame/test/chrome_frame_test_utils.cc
@@ -749,4 +749,14 @@ void WebBrowserEventSink::Exec(const GUID* cmd_group_guid, DWORD command_id,
command_id, cmd_exec_opt, in_args, out_args));
}
+void WebBrowserEventSink::NavigateBackward() {
+ SendMouseClick(10, 10, simulate_input::LEFT);
+ simulate_input::SendMnemonic(VK_BACK, false, false, false, false, false);
+}
+
+void WebBrowserEventSink::NavigateForward() {
+ SendMouseClick(10, 10, simulate_input::LEFT);
+ simulate_input::SendMnemonic(VK_BACK, true, false, false, false, false);
+}
+
} // namespace chrome_frame_test
diff --git a/chrome_frame/test/chrome_frame_test_utils.h b/chrome_frame/test/chrome_frame_test_utils.h
index 91d8438..6799913 100644
--- a/chrome_frame/test/chrome_frame_test_utils.h
+++ b/chrome_frame/test/chrome_frame_test_utils.h
@@ -171,6 +171,13 @@ class WebBrowserEventSink
void Exec(const GUID* cmd_group_guid, DWORD command_id,
DWORD cmd_exec_opt, VARIANT* in_args, VARIANT* out_args);
+ // Navigates to the next item in history by sending the Shift+Back key
+ // combination
+ void NavigateForward();
+
+ // Navigates to the next item in history by sending the Backstroke key.
+ void NavigateBackward();
+
BEGIN_COM_MAP(WebBrowserEventSink)
END_COM_MAP()
diff --git a/chrome_frame/test/data/fulltab_back_page.html b/chrome_frame/test/data/fulltab_back_page.html
new file mode 100644
index 0000000..fe0ab97
--- /dev/null
+++ b/chrome_frame/test/data/fulltab_back_page.html
@@ -0,0 +1,16 @@
+<html>
+ <head>
+ <meta http-equiv="x-ua-compatible" content="chrome=1" />
+ <title>ChromeFrame fulltab Esc keystroke back page</title>
+ <script language=javascript>
+ function onLoad() {
+ // Onload handling goes here.
+ }
+ </script>
+ </head>
+
+ <body onload="onLoad();">
+ ChromeFrame full tab mode Esc keystroke back page.
+ Verifies whether the Esc keystroke navigates backwards in ChromeFrame.
+ </body>
+</html>
diff --git a/chrome_frame/test/data/fulltab_forward_page.html b/chrome_frame/test/data/fulltab_forward_page.html
new file mode 100644
index 0000000..2f8e2e2
--- /dev/null
+++ b/chrome_frame/test/data/fulltab_forward_page.html
@@ -0,0 +1,16 @@
+<html>
+ <head>
+ <meta http-equiv="x-ua-compatible" content="chrome=1" />
+ <title>ChromeFrame fulltab Shift-Esc keystroke forward page</title>
+ <script language=javascript>
+ function onLoad() {
+ // onload handling goes here.
+ }
+ </script>
+ </head>
+
+ <body onload="onLoad();">
+ ChromeFrame full tab mode Shift-Esc keystroke forward page.
+ Verifies whether the Shift-Esc keystroke navigates forward in ChromeFrame.
+ </body>
+</html>
diff --git a/chrome_frame/test/simulate_input.cc b/chrome_frame/test/simulate_input.cc
index 82002a9..082b58b 100644
--- a/chrome_frame/test/simulate_input.cc
+++ b/chrome_frame/test/simulate_input.cc
@@ -121,7 +121,7 @@ void SendChar(wchar_t c, bool control, bool alt) {
// Sends a keystroke to the currently active application with optional
// modifiers set.
-bool SendMnemonic(WORD mnemonic_char, bool shift_pressed, bool control_pressed,
+void SendMnemonic(WORD mnemonic_char, bool shift_pressed, bool control_pressed,
bool alt_pressed, bool extended, bool unicode) {
INPUT keys[4] = {0}; // Keyboard events
int key_count = 0; // Number of generated events
@@ -129,41 +129,52 @@ bool SendMnemonic(WORD mnemonic_char, bool shift_pressed, bool control_pressed,
if (shift_pressed) {
keys[key_count].type = INPUT_KEYBOARD;
keys[key_count].ki.wVk = VK_SHIFT;
+ keys[key_count].ki.wScan = MapVirtualKey(VK_SHIFT, 0);
key_count++;
}
if (control_pressed) {
keys[key_count].type = INPUT_KEYBOARD;
keys[key_count].ki.wVk = VK_CONTROL;
+ keys[key_count].ki.wScan = MapVirtualKey(VK_CONTROL, 0);
key_count++;
}
if (alt_pressed) {
keys[key_count].type = INPUT_KEYBOARD;
keys[key_count].ki.wVk = VK_MENU;
+ keys[key_count].ki.wScan = MapVirtualKey(VK_MENU, 0);
key_count++;
}
keys[key_count].type = INPUT_KEYBOARD;
keys[key_count].ki.wVk = mnemonic_char;
+ keys[key_count].ki.wScan = MapVirtualKey(mnemonic_char, 0);
+
if (extended)
keys[key_count].ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
if (unicode)
keys[key_count].ki.dwFlags |= KEYEVENTF_UNICODE;
key_count++;
+ bool should_sleep = key_count > 1;
+
// Send key downs
for (int i = 0; i < key_count; i++) {
SendInput(1, &keys[ i ], sizeof(keys[0]));
keys[i].ki.dwFlags |= KEYEVENTF_KEYUP;
+ if (should_sleep) {
+ Sleep(100);
+ }
}
// Now send key ups in reverse order
for (int i = key_count; i; i--) {
SendInput(1, &keys[ i - 1 ], sizeof(keys[0]));
+ if (should_sleep) {
+ Sleep(100);
+ }
}
-
- return true;
}
void SetKeyboardFocusToWindow(HWND window) {
@@ -215,8 +226,8 @@ void SendMouseClick(HWND window, int x, int y, MouseButton button) {
::SendInput(1, &input_info, sizeof(INPUT));
}
-bool SendExtendedKey(WORD key, bool shift, bool control, bool alt) {
- return SendMnemonic(key, shift, control, alt, true, false);
+void SendExtendedKey(WORD key, bool shift, bool control, bool alt) {
+ SendMnemonic(key, shift, control, alt, true, false);
}
} // namespace simulate_input
diff --git a/chrome_frame/test/simulate_input.h b/chrome_frame/test/simulate_input.h
index 562362a..972269c 100644
--- a/chrome_frame/test/simulate_input.h
+++ b/chrome_frame/test/simulate_input.h
@@ -27,7 +27,7 @@ void SetKeyboardFocusToWindow(HWND window);
// Sends a keystroke to the currently active application with optional
// modifiers set.
-bool SendMnemonic(WORD mnemonic_char, bool shift_pressed, bool control_pressed,
+void SendMnemonic(WORD mnemonic_char, bool shift_pressed, bool control_pressed,
bool alt_pressed, bool extended, bool unicode);
// Sends a mouse click to the window passed in.
@@ -40,7 +40,7 @@ void SendChar(wchar_t c, bool control, bool alt);
// Sends extended keystroke to the currently active application with optional
// modifiers set.
-bool SendExtendedKey(WORD key, bool shift, bool control, bool alt);
+void SendExtendedKey(WORD key, bool shift, bool control, bool alt);
// Iterates through all the characters in the string and simulates
// keyboard input. The input goes to the currently active application.
diff --git a/chrome_frame/test/test_mock_with_web_server.cc b/chrome_frame/test/test_mock_with_web_server.cc
index c2c56e8..70495e9 100644
--- a/chrome_frame/test/test_mock_with_web_server.cc
+++ b/chrome_frame/test/test_mock_with_web_server.cc
@@ -7,6 +7,7 @@
#include "chrome/common/url_constants.h"
#include "chrome_frame/utils.h"
+#include "chrome_frame/test/simulate_input.h"
#include "chrome_frame/test/test_with_web_server.h"
#define GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING
@@ -1216,3 +1217,122 @@ TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_ContextMenuViewSource) {
loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
}
+const wchar_t kKeyboardTestForwardUrl[] =
+ L"http://localhost:1337/files/fulltab_forward_page.html";
+
+const wchar_t kKeyboardTestBackUrl[] =
+ L"http://localhost:1337/files/fulltab_back_page.html";
+
+TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_KeyboardBackForwardTest) {
+ chrome_frame_test::TimedMsgLoop loop;
+ CComObjectStackEx<MockWebBrowserEventSink> mock;
+ CComObjectStackEx<MockWebBrowserEventSink> view_source_mock;
+ ::testing::InSequence sequence; // Everything in sequence
+
+ // This test performs the following steps.
+ // 1. Launches IE and navigates to
+ // http://localhost:1337/files/fulltab_back_page.html
+ // 2. It then navigates to
+ // http://localhost:1337/files/fulltab_back_page.html
+ // 3. Sends the VK_BACK keystroke to IE, which should navigate back to
+ // http://localhost:1337/files/fulltab_back_page.html
+ // 4. Sends the Shift + VK_BACK keystroke to IE which should navigate
+ // forward to http://localhost:1337/files/fulltab_forward_page.html
+
+ EXPECT_CALL(mock,
+ OnBeforeNavigate2(_, testing::Field(&VARIANT::bstrVal,
+ testing::StrCaseEq(kKeyboardTestBackUrl)),
+ _, _, _, _, _))
+ .WillOnce(testing::Return(S_OK));
+ EXPECT_CALL(mock, OnNavigateComplete2(_, _))
+ .WillOnce(testing::Return());
+ EXPECT_CALL(mock,
+ OnBeforeNavigate2(_, testing::Field(&VARIANT::bstrVal,
+ testing::StrCaseEq(kKeyboardTestBackUrl)),
+ _, _, _, _, _))
+ .Times(testing::AnyNumber()).WillRepeatedly(testing::Return(S_OK));
+ EXPECT_CALL(mock, OnNavigateComplete2(_, _))
+ .Times(testing::AnyNumber()).WillRepeatedly(testing::Return());
+
+ VARIANT empty = ScopedVariant::kEmptyVariant;
+
+ EXPECT_CALL(mock, OnLoad(testing::StrEq(kKeyboardTestBackUrl)))
+ .WillOnce(testing::IgnoreResult(testing::InvokeWithoutArgs(
+ CreateFunctor(
+ &mock, &chrome_frame_test::WebBrowserEventSink::Navigate,
+ std::wstring(kKeyboardTestForwardUrl)))));
+
+ EXPECT_CALL(mock,
+ OnBeforeNavigate2(_, testing::Field(&VARIANT::bstrVal,
+ testing::StrCaseEq(kKeyboardTestForwardUrl)),
+ _, _, _, _, _))
+ .WillOnce(testing::Return(S_OK));
+ EXPECT_CALL(mock, OnNavigateComplete2(_, _))
+ .WillOnce(testing::Return());
+ EXPECT_CALL(mock,
+ OnBeforeNavigate2(_, testing::Field(&VARIANT::bstrVal,
+ testing::StrCaseEq(kKeyboardTestForwardUrl)),
+ _, _, _, _, _))
+ .Times(testing::AnyNumber()).WillRepeatedly(testing::Return(S_OK));
+ EXPECT_CALL(mock, OnNavigateComplete2(_, _))
+ .Times(testing::AnyNumber()).WillRepeatedly(testing::Return());
+
+ EXPECT_CALL(mock, OnLoad(testing::StrEq(kKeyboardTestForwardUrl)))
+ .WillOnce(testing::InvokeWithoutArgs(CreateFunctor(&loop,
+ &chrome_frame_test::TimedMsgLoop::PostDelayedTask, FROM_HERE,
+ NewRunnableMethod(
+ &mock,
+ &MockWebBrowserEventSink::NavigateBackward), 500)));
+
+ EXPECT_CALL(mock,
+ OnBeforeNavigate2(_, testing::Field(&VARIANT::bstrVal,
+ testing::StrCaseEq(kKeyboardTestBackUrl)),
+ _, _, _, _, _))
+ .WillOnce(testing::Return(S_OK));
+ EXPECT_CALL(mock, OnNavigateComplete2(_, _))
+ .WillOnce(testing::Return());
+ EXPECT_CALL(mock,
+ OnBeforeNavigate2(_, testing::Field(&VARIANT::bstrVal,
+ testing::StrCaseEq(kKeyboardTestBackUrl)),
+ _, _, _, _, _))
+ .Times(testing::AnyNumber()).WillRepeatedly(testing::Return(S_OK));
+ EXPECT_CALL(mock, OnNavigateComplete2(_, _))
+ .Times(testing::AnyNumber()).WillRepeatedly(testing::Return());
+
+ EXPECT_CALL(mock, OnLoad(testing::StrEq(kKeyboardTestBackUrl)))
+ .WillOnce(testing::InvokeWithoutArgs(CreateFunctor(&loop,
+ &chrome_frame_test::TimedMsgLoop::PostDelayedTask, FROM_HERE,
+ NewRunnableMethod(
+ &mock,
+ &MockWebBrowserEventSink::NavigateForward), 500)));
+
+ EXPECT_CALL(mock,
+ OnBeforeNavigate2(_, testing::Field(&VARIANT::bstrVal,
+ testing::StrCaseEq(kKeyboardTestForwardUrl)),
+ _, _, _, _, _))
+ .WillOnce(testing::Return(S_OK));
+ EXPECT_CALL(mock, OnNavigateComplete2(_, _))
+ .WillOnce(testing::Return());
+ EXPECT_CALL(mock,
+ OnBeforeNavigate2(_, testing::Field(&VARIANT::bstrVal,
+ testing::StrCaseEq(kKeyboardTestForwardUrl)),
+ _, _, _, _, _))
+ .Times(testing::AnyNumber()).WillRepeatedly(testing::Return(S_OK));
+ EXPECT_CALL(mock, OnNavigateComplete2(_, _))
+ .Times(testing::AnyNumber()).WillRepeatedly(testing::Return());
+
+ EXPECT_CALL(mock, OnLoad(testing::StrEq(kKeyboardTestForwardUrl)))
+ .Times(1)
+ .WillOnce(QUIT_LOOP_SOON(loop, 2));
+
+ HRESULT hr = mock.LaunchIEAndNavigate(kKeyboardTestBackUrl);
+ ASSERT_HRESULT_SUCCEEDED(hr);
+ if (hr == S_FALSE)
+ return;
+
+ ASSERT_TRUE(mock.web_browser2() != NULL);
+ loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
+ mock.Uninitialize();
+ chrome_frame_test::CloseAllIEWindows();
+}
+