summaryrefslogtreecommitdiffstats
path: root/chrome_frame/test
diff options
context:
space:
mode:
authorkkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-12 22:07:03 +0000
committerkkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-12 22:07:03 +0000
commit6448b3abcfa035eaf65b7c0c15bb728513f228fe (patch)
tree3d8ee0bf2f528e93616a1d7721bc721ef6726189 /chrome_frame/test
parentbb2eb35a70fcbc47be253bf50c8648c65271a19e (diff)
downloadchromium_src-6448b3abcfa035eaf65b7c0c15bb728513f228fe.zip
chromium_src-6448b3abcfa035eaf65b7c0c15bb728513f228fe.tar.gz
chromium_src-6448b3abcfa035eaf65b7c0c15bb728513f228fe.tar.bz2
[chrome_frame] Refactor/merge IE no interference tests with other mock event sink tests. Have the test mock contain, not inherit the IE event sink. Use the new test server to verify the right requests are being sent.
BUG=none TEST=none Review URL: http://codereview.chromium.org/2822016 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@52137 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame/test')
-rw-r--r--chrome_frame/test/chrome_frame_test_utils.cc53
-rw-r--r--chrome_frame/test/chrome_frame_test_utils.h26
-rw-r--r--chrome_frame/test/data/anchor.html15
-rw-r--r--chrome_frame/test/data/javascript_redirect.html (renamed from chrome_frame/test/data/no_interference/javascript_redirect.html)2
-rw-r--r--chrome_frame/test/data/link.html5
-rw-r--r--chrome_frame/test/data/no_interference/empty.html0
-rw-r--r--chrome_frame/test/data/no_interference/link.html5
-rw-r--r--chrome_frame/test/data/no_interference/window_open.html13
-rw-r--r--chrome_frame/test/data/simple.html6
-rw-r--r--chrome_frame/test/data/window_open.html24
-rw-r--r--chrome_frame/test/ie_event_sink.cc545
-rw-r--r--chrome_frame/test/ie_event_sink.h230
-rw-r--r--chrome_frame/test/mock_ie_event_sink_actions.h172
-rw-r--r--chrome_frame/test/mock_ie_event_sink_test.cc172
-rw-r--r--chrome_frame/test/mock_ie_event_sink_test.h230
-rw-r--r--chrome_frame/test/navigation_test.cc635
-rw-r--r--chrome_frame/test/no_interference_test.cc269
-rw-r--r--chrome_frame/test/simulate_input.cc16
-rw-r--r--chrome_frame/test/simulate_input.h5
-rw-r--r--chrome_frame/test/test_mock_with_web_server.cc1635
-rw-r--r--chrome_frame/test/test_mock_with_web_server.h139
-rw-r--r--chrome_frame/test/test_server.cc38
-rw-r--r--chrome_frame/test/test_server.h21
-rw-r--r--chrome_frame/test/test_with_web_server.cc83
-rw-r--r--chrome_frame/test/test_with_web_server.h119
-rw-r--r--chrome_frame/test/ui_test.cc541
26 files changed, 2868 insertions, 2131 deletions
diff --git a/chrome_frame/test/chrome_frame_test_utils.cc b/chrome_frame/test/chrome_frame_test_utils.cc
index e50d665..6b03bf4 100644
--- a/chrome_frame/test/chrome_frame_test_utils.cc
+++ b/chrome_frame/test/chrome_frame_test_utils.cc
@@ -356,7 +356,8 @@ HRESULT LaunchIEAsComServer(IWebBrowser2** web_browser) {
// This causes the IWebBrowser2 interface which is returned to be useless,
// i.e it does not receive any events, etc. Our workaround for this is
// to impersonate a low integrity token and then launch IE.
- if (win_util::GetWinVersion() == win_util::WINVERSION_VISTA) {
+ if (win_util::GetWinVersion() == win_util::WINVERSION_VISTA &&
+ GetInstalledIEVersion() == IE_7) {
// Create medium integrity browser that will launch IE broker.
ScopedComPtr<IWebBrowser2> medium_integrity_browser;
hr = medium_integrity_browser.CreateInstance(CLSID_InternetExplorer, NULL,
@@ -893,6 +894,56 @@ FilePath GetProfilePathForIE() {
return profile_path;
}
+FilePath GetTestDataFolder() {
+ FilePath test_dir;
+ PathService::Get(base::DIR_SOURCE_ROOT, &test_dir);
+ test_dir = test_dir.Append(FILE_PATH_LITERAL("chrome_frame"))
+ .Append(FILE_PATH_LITERAL("test"))
+ .Append(FILE_PATH_LITERAL("data"));
+ return test_dir;
+}
+
+std::wstring GetPathFromUrl(const std::wstring& url) {
+ string16 url16 = WideToUTF16(url);
+ GURL gurl = GURL(url16);
+ if (gurl.has_query()) {
+ GURL::Replacements replacements;
+ replacements.ClearQuery();
+ gurl = gurl.ReplaceComponents(replacements);
+ }
+ return UTF8ToWide(gurl.PathForRequest());
+}
+
+std::wstring GetPathAndQueryFromUrl(const std::wstring& url) {
+ string16 url16 = WideToUTF16(url);
+ GURL gurl = GURL(url16);
+ return UTF8ToWide(gurl.PathForRequest());
+}
+
+bool AddCFMetaTag(std::string* html_data) {
+ if (!html_data) {
+ NOTREACHED();
+ return false;
+ }
+ size_t head = html_data->find("<head>");
+ if (head == std::string::npos) {
+ // Add missing head section.
+ size_t html = html_data->find("<html>");
+ EXPECT_NE(std::string::npos, html) << "Meta tag will not be injected "
+ << "because the html tag could not be found";
+ if (html != std::string::npos) {
+ html_data->insert(html + strlen("<html>"), "<head></head>");
+ head = html_data->find("<head>");
+ }
+ }
+ if (head != std::string::npos) {
+ html_data->insert(
+ head + strlen("<head>"),
+ "<meta http-equiv=\"x-ua-compatible\" content=\"chrome=1\" />");
+ }
+ return head != std::string::npos;
+}
+
void DelaySendExtendedKeysEnter(TimedMsgLoop* loop, int delay, char c,
int repeat, simulate_input::Modifier mod) {
const unsigned int kInterval = 25;
diff --git a/chrome_frame/test/chrome_frame_test_utils.h b/chrome_frame/test/chrome_frame_test_utils.h
index fb553dd..13177fc 100644
--- a/chrome_frame/test/chrome_frame_test_utils.h
+++ b/chrome_frame/test/chrome_frame_test_utils.h
@@ -345,6 +345,18 @@ std::wstring GetExeVersion(const std::wstring& exe_path);
// Returns the version of Internet Explorer on the machine.
IEVersion GetInstalledIEVersion();
+// Returns the folder for CF test data.
+FilePath GetTestDataFolder();
+
+// Returns the path portion of the url.
+std::wstring GetPathFromUrl(const std::wstring& url);
+
+// Returns the path and query portion of the url.
+std::wstring GetPathAndQueryFromUrl(const std::wstring& url);
+
+// Adds the CF meta tag to the html page. Returns true if successful.
+bool AddCFMetaTag(std::string* html_data);
+
// Posts a delayed task to send an extended keystroke |repeat| times with an
// optional modifier via SendInput. Following this, the enter key is sent.
void DelaySendExtendedKeysEnter(TimedMsgLoop* loop, int delay, char c,
@@ -369,20 +381,6 @@ class CloseIeAtEndOfScope {
}
};
-// Specialization of CComObjectStackEx that performs object cleanup via
-// calling Base::Uninitialize() before we get to CComObjectStackEx' destructor.
-// The CComObjectStackEx destructor expects the reference count to be 0
-// or it will throw an assert. To work around that and to avoid having to
-// explicitly call Uninitialize() at the end of every test, we override the
-// destructor here to perform the cleanup.
-template <class Base>
-class ComStackObjectWithUninitialize : public CComObjectStackEx<Base> {
- public:
- virtual ~ComStackObjectWithUninitialize() {
- Base::Uninitialize();
- }
-};
-
// Starts the Chrome crash service which enables us to gather crash dumps
// during test runs.
base::ProcessHandle StartCrashService();
diff --git a/chrome_frame/test/data/anchor.html b/chrome_frame/test/data/anchor.html
index 7fde037..fa0bfa3 100644
--- a/chrome_frame/test/data/anchor.html
+++ b/chrome_frame/test/data/anchor.html
@@ -1,9 +1,8 @@
-<HTML>
- <HEAD>
- <meta http-equiv="X-UA-Compatible" content="chrome=1" />
- <TITLE> Chrome Frame Test </TITLE>
- </HEAD>
- <BODY>
+<html>
+ <head>
+ <title> Chrome Frame Test </title>
+ </head>
+ <body>
Chrome frame in full tab mode
Jump to different named sections here
@@ -47,5 +46,5 @@
<br /><br /><br /><br /><br /><br /><br /><br /><br /><br />
<br /><br /><br /><br /><br /><br /><br /><br /><br /><br />
<a name="a4"> A4 </a>
- </BODY>
-</HTML>
+ </body>
+</html> \ No newline at end of file
diff --git a/chrome_frame/test/data/no_interference/javascript_redirect.html b/chrome_frame/test/data/javascript_redirect.html
index 5e29ab1..7712686 100644
--- a/chrome_frame/test/data/no_interference/javascript_redirect.html
+++ b/chrome_frame/test/data/javascript_redirect.html
@@ -4,7 +4,7 @@
window.onload = function() {
var url = "" + window.location;
window.location = url.substring(0, url.lastIndexOf("/") + 1) +
- "empty.html";
+ "simple.html";
}
</script>
</head>
diff --git a/chrome_frame/test/data/link.html b/chrome_frame/test/data/link.html
new file mode 100644
index 0000000..a2c3513
--- /dev/null
+++ b/chrome_frame/test/data/link.html
@@ -0,0 +1,5 @@
+<html>
+ <body>
+ <a href="simple.html">Simple page</a>
+ </body>
+</html> \ No newline at end of file
diff --git a/chrome_frame/test/data/no_interference/empty.html b/chrome_frame/test/data/no_interference/empty.html
deleted file mode 100644
index e69de29..0000000
--- a/chrome_frame/test/data/no_interference/empty.html
+++ /dev/null
diff --git a/chrome_frame/test/data/no_interference/link.html b/chrome_frame/test/data/no_interference/link.html
deleted file mode 100644
index d84da5b..0000000
--- a/chrome_frame/test/data/no_interference/link.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
- <body>
- <a href="empty.html">Empty page</a>
- </body>
-</html> \ No newline at end of file
diff --git a/chrome_frame/test/data/no_interference/window_open.html b/chrome_frame/test/data/no_interference/window_open.html
deleted file mode 100644
index a8b1c37..0000000
--- a/chrome_frame/test/data/no_interference/window_open.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<html>
- <head>
- <script type="text/javascript">
- function popup() {
- window.open("empty.html", "test");
- }
- </script>
- </head>
-
- <body ondblclick="popup();">
- Calling window.open...
- </body>
-</html> \ No newline at end of file
diff --git a/chrome_frame/test/data/simple.html b/chrome_frame/test/data/simple.html
new file mode 100644
index 0000000..5e5ed37
--- /dev/null
+++ b/chrome_frame/test/data/simple.html
@@ -0,0 +1,6 @@
+<html>
+ <head>
+ <title>simple web page</title>
+ </head>
+ <body>simple web page</body>
+</html> \ No newline at end of file
diff --git a/chrome_frame/test/data/window_open.html b/chrome_frame/test/data/window_open.html
new file mode 100644
index 0000000..eb8599f
--- /dev/null
+++ b/chrome_frame/test/data/window_open.html
@@ -0,0 +1,24 @@
+<html>
+ <head>
+ <script type="text/javascript">
+ var new_window;
+
+ function OnDblClick() {
+ // Open popup to the url from the given query string.
+ var url = window.location.search.substring(1);
+ new_window = window.open(url, "_blank",
+ "left=10, top=10, height=250, width=250");
+ }
+
+ function OnKeyPress() {
+ var char_code = String.fromCharCode(event.keyCode);
+ if (char_code == 'C') {
+ new_window.close();
+ }
+ }
+ </script>
+ </head>
+ <body onkeypress="OnKeyPress();" ondblclick="OnDblClick();">
+ ChromeFrame full tab mode window open popup test
+ </body>
+</html>
diff --git a/chrome_frame/test/ie_event_sink.cc b/chrome_frame/test/ie_event_sink.cc
new file mode 100644
index 0000000..2f7d32c
--- /dev/null
+++ b/chrome_frame/test/ie_event_sink.cc
@@ -0,0 +1,545 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome_frame/test/ie_event_sink.h"
+
+#include "base/scoped_bstr_win.h"
+#include "base/scoped_handle.h"
+#include "base/utf_string_conversions.h"
+#include "base/win_util.h"
+#include "chrome_frame/test/chrome_frame_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chrome_frame_test {
+
+const int kDefaultWaitForIEToTerminateMs = 10 * 1000;
+
+_ATL_FUNC_INFO IEEventSink::kNavigateErrorInfo = {
+ CC_STDCALL, VT_EMPTY, 5, {
+ VT_DISPATCH,
+ VT_VARIANT | VT_BYREF,
+ VT_VARIANT | VT_BYREF,
+ VT_VARIANT | VT_BYREF,
+ VT_BOOL | VT_BYREF,
+ }
+};
+
+_ATL_FUNC_INFO IEEventSink::kNavigateComplete2Info = {
+ CC_STDCALL, VT_EMPTY, 2, {
+ VT_DISPATCH,
+ VT_VARIANT | VT_BYREF
+ }
+};
+
+_ATL_FUNC_INFO IEEventSink::kBeforeNavigate2Info = {
+ CC_STDCALL, VT_EMPTY, 7, {
+ VT_DISPATCH,
+ VT_VARIANT | VT_BYREF,
+ VT_VARIANT | VT_BYREF,
+ VT_VARIANT | VT_BYREF,
+ VT_VARIANT | VT_BYREF,
+ VT_VARIANT | VT_BYREF,
+ VT_BOOL | VT_BYREF
+ }
+};
+
+_ATL_FUNC_INFO IEEventSink::kNewWindow2Info = {
+ CC_STDCALL, VT_EMPTY, 2, {
+ VT_DISPATCH | VT_BYREF,
+ VT_BOOL | VT_BYREF,
+ }
+};
+
+_ATL_FUNC_INFO IEEventSink::kNewWindow3Info = {
+ CC_STDCALL, VT_EMPTY, 5, {
+ VT_DISPATCH | VT_BYREF,
+ VT_BOOL | VT_BYREF,
+ VT_UINT,
+ VT_BSTR,
+ VT_BSTR
+ }
+};
+
+_ATL_FUNC_INFO IEEventSink::kVoidMethodInfo = {
+ CC_STDCALL, VT_EMPTY, 0, {NULL}};
+
+_ATL_FUNC_INFO IEEventSink::kDocumentCompleteInfo = {
+ CC_STDCALL, VT_EMPTY, 2, {
+ VT_DISPATCH,
+ VT_VARIANT | VT_BYREF
+ }
+};
+
+_ATL_FUNC_INFO IEEventSink::kFileDownloadInfo = {
+ CC_STDCALL, VT_EMPTY, 2, {
+ VT_BOOL,
+ VT_BOOL | VT_BYREF
+ }
+};
+
+IEEventSink::IEEventSink()
+ : ALLOW_THIS_IN_INITIALIZER_LIST(
+ onmessage_(this, &IEEventSink::OnMessage)),
+ ALLOW_THIS_IN_INITIALIZER_LIST(
+ onloaderror_(this, &IEEventSink::OnLoadError)),
+ ALLOW_THIS_IN_INITIALIZER_LIST(
+ onload_(this, &IEEventSink::OnLoad)),
+ listener_(NULL),
+ ie_process_id_(0),
+ did_receive_on_quit_(false) {
+}
+
+IEEventSink::~IEEventSink() {
+ Uninitialize();
+}
+
+// IEEventSink member defines
+void IEEventSink::Attach(IDispatch* browser_disp) {
+ EXPECT_TRUE(NULL != browser_disp);
+ if (browser_disp) {
+ EXPECT_HRESULT_SUCCEEDED(web_browser2_.QueryFrom(browser_disp));
+ EXPECT_TRUE(S_OK == DispEventAdvise(web_browser2_,
+ &DIID_DWebBrowserEvents2));
+ FindIEProcessId();
+ }
+}
+
+void IEEventSink::Uninitialize() {
+ DisconnectFromChromeFrame();
+ if (web_browser2_.get()) {
+ if (m_dwEventCookie != 0xFEFEFEFE) {
+ DispEventUnadvise(web_browser2_);
+ CoDisconnectObject(this, 0);
+ }
+
+ if (!did_receive_on_quit_) {
+ // Log the browser window url for debugging purposes.
+ ScopedBstr browser_url;
+ web_browser2_->get_LocationURL(browser_url.Receive());
+ std::wstring browser_url_wstring;
+ browser_url_wstring.assign(browser_url, browser_url.Length());
+ std::string browser_url_string = WideToUTF8(browser_url_wstring);
+ EXPECT_TRUE(did_receive_on_quit_) << "OnQuit was not received for "
+ << "browser with url "
+ << browser_url_string;
+
+ web_browser2_->Quit();
+ }
+
+ ScopedHandle process;
+ process.Set(OpenProcess(SYNCHRONIZE, FALSE, ie_process_id_));
+ DLOG_IF(WARNING, !process.IsValid())
+ << StringPrintf("OpenProcess failed: %i", ::GetLastError());
+
+ web_browser2_.Release();
+
+ // IE may not have closed yet. Wait here for the process to finish.
+ // This is necessary at least on some browser/platform configurations.
+ if (process) {
+ DWORD max_wait = kDefaultWaitForIEToTerminateMs;
+ while (true) {
+ base::Time start = base::Time::Now();
+ HANDLE wait_for = process;
+ DWORD wait = MsgWaitForMultipleObjects(1, &wait_for, FALSE, max_wait,
+ QS_ALLINPUT);
+ if (wait == WAIT_OBJECT_0 + 1) {
+ MSG msg;
+ while (PeekMessage(&msg, NULL, 0, 0, TRUE) > 0) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ } else if (wait == WAIT_OBJECT_0) {
+ break;
+ } else {
+ DCHECK(wait == WAIT_TIMEOUT);
+ DLOG(ERROR) << "Wait for IE timed out";
+ break;
+ }
+ base::TimeDelta elapsed = base::Time::Now() - start;
+ ULARGE_INTEGER ms;
+ ms.QuadPart = elapsed.InMilliseconds();
+ DCHECK_EQ(ms.HighPart, 0U);
+ if (ms.LowPart > max_wait) {
+ DLOG(ERROR) << "Wait for IE timed out (2)";
+ break;
+ } else {
+ max_wait -= ms.LowPart;
+ }
+ }
+ }
+ }
+}
+
+bool IEEventSink::IsCFRendering() {
+ DCHECK(web_browser2_);
+
+ HWND renderer_window;
+ if (web_browser2_) {
+ ScopedComPtr<IDispatch> doc;
+ web_browser2_->get_Document(doc.Receive());
+ if (doc) {
+ ScopedComPtr<IOleWindow> ole_window;
+ ole_window.QueryFrom(doc);
+ if (ole_window) {
+ ole_window->GetWindow(&renderer_window);
+ if (IsWindow(renderer_window)) {
+ wchar_t class_name[MAX_PATH] = {0};
+ GetClassName(renderer_window, class_name, arraysize(class_name));
+ return _wcsicmp(class_name, L"Internet Explorer_Server") != 0;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+void IEEventSink::SetFocusToRenderer() {
+ simulate_input::SetKeyboardFocusToWindow(GetRendererWindow());
+}
+
+void IEEventSink::SendKeys(const wchar_t* input_string) {
+ SetFocusToRenderer();
+ simulate_input::SendStringW(input_string);
+}
+
+void IEEventSink::SendMouseClick(int x, int y,
+ simulate_input::MouseButton button) {
+ simulate_input::SendMouseClick(GetRendererWindow(), x, y, button);
+}
+
+void IEEventSink::ExpectRendererWindowHasFocus() {
+ HWND renderer_window = GetRendererWindow();
+ EXPECT_TRUE(IsWindow(renderer_window));
+
+ if (IsCFRendering()) {
+ for (HWND first_child = renderer_window;
+ IsWindow(first_child); first_child = GetWindow(first_child, GW_CHILD)) {
+ renderer_window = first_child;
+ }
+
+ wchar_t class_name[MAX_PATH] = {0};
+ GetClassName(renderer_window, class_name, arraysize(class_name));
+ EXPECT_EQ(0, _wcsicmp(class_name, L"Chrome_RenderWidgetHostHWND"));
+ }
+
+ DWORD renderer_thread = 0;
+ DWORD renderer_process = 0;
+ renderer_thread = GetWindowThreadProcessId(renderer_window,
+ &renderer_process);
+
+ ASSERT_TRUE(AttachThreadInput(GetCurrentThreadId(), renderer_thread, TRUE));
+ HWND focus_window = GetFocus();
+ EXPECT_TRUE(focus_window == renderer_window);
+ EXPECT_TRUE(AttachThreadInput(GetCurrentThreadId(), renderer_thread, FALSE));
+}
+
+void IEEventSink::ExpectAddressBarUrl(
+ const std::wstring& expected_url) {
+ DCHECK(web_browser2_);
+ if (web_browser2_) {
+ ScopedBstr address_bar_url;
+ EXPECT_EQ(S_OK, web_browser2_->get_LocationURL(address_bar_url.Receive()));
+ EXPECT_EQ(expected_url, std::wstring(address_bar_url));
+ }
+}
+
+void IEEventSink::Exec(const GUID* cmd_group_guid, DWORD command_id,
+ DWORD cmd_exec_opt, VARIANT* in_args,
+ VARIANT* out_args) {
+ ScopedComPtr<IOleCommandTarget> shell_browser_cmd_target;
+ DoQueryService(SID_STopLevelBrowser, web_browser2_,
+ shell_browser_cmd_target.Receive());
+ ASSERT_TRUE(NULL != shell_browser_cmd_target);
+ EXPECT_HRESULT_SUCCEEDED(shell_browser_cmd_target->Exec(cmd_group_guid,
+ command_id, cmd_exec_opt, in_args, out_args));
+}
+
+HWND IEEventSink::GetRendererWindow() {
+ HWND renderer_window = NULL;
+ if (IsCFRendering()) {
+ DCHECK(chrome_frame_);
+ ScopedComPtr<IOleWindow> ole_window;
+ ole_window.QueryFrom(chrome_frame_);
+ EXPECT_TRUE(ole_window.get());
+
+ if (ole_window) {
+ HWND activex_window = NULL;
+ ole_window->GetWindow(&activex_window);
+ EXPECT_TRUE(IsWindow(activex_window));
+
+ // chrome tab window is the first (and the only) child of activex
+ HWND chrome_tab_window = GetWindow(activex_window, GW_CHILD);
+ EXPECT_TRUE(IsWindow(chrome_tab_window));
+ renderer_window = GetWindow(chrome_tab_window, GW_CHILD);
+ }
+ } else {
+ DCHECK(web_browser2_);
+ ScopedComPtr<IDispatch> doc;
+ HRESULT hr = web_browser2_->get_Document(doc.Receive());
+ EXPECT_HRESULT_SUCCEEDED(hr);
+ EXPECT_TRUE(doc);
+ if (doc) {
+ ScopedComPtr<IOleWindow> ole_window;
+ ole_window.QueryFrom(doc);
+ EXPECT_TRUE(ole_window);
+ if (ole_window) {
+ ole_window->GetWindow(&renderer_window);
+ }
+ }
+ }
+
+ EXPECT_TRUE(IsWindow(renderer_window));
+ return renderer_window;
+}
+
+HRESULT IEEventSink::LaunchIEAndNavigate(
+ const std::wstring& navigate_url, IEEventListener* listener) {
+ listener_ = listener;
+ HRESULT hr = LaunchIEAsComServer(web_browser2_.Receive());
+ EXPECT_EQ(S_OK, hr);
+ if (hr == S_OK) {
+ FindIEProcessId();
+ web_browser2_->put_Visible(VARIANT_TRUE);
+ hr = DispEventAdvise(web_browser2_, &DIID_DWebBrowserEvents2);
+ EXPECT_TRUE(hr == S_OK);
+ hr = Navigate(navigate_url);
+ }
+
+ DLOG_IF(WARNING, FAILED(hr)) << "Failed to launch IE. Error:" << hr;
+ return hr;
+}
+
+HRESULT IEEventSink::Navigate(const std::wstring& navigate_url) {
+ VARIANT empty = ScopedVariant::kEmptyVariant;
+ ScopedVariant url;
+ url.Set(navigate_url.c_str());
+
+ HRESULT hr = S_OK;
+ hr = web_browser2_->Navigate2(url.AsInput(), &empty, &empty, &empty, &empty);
+ EXPECT_TRUE(hr == S_OK);
+ return hr;
+}
+
+HRESULT IEEventSink::CloseWebBrowser() {
+ if (!web_browser2_)
+ return E_FAIL;
+
+ DisconnectFromChromeFrame();
+ EXPECT_HRESULT_SUCCEEDED(web_browser2_->Quit());
+ return S_OK;
+}
+
+void IEEventSink::Refresh() {
+ ScopedVariant refresh_level(REFRESH_NORMAL);
+ web_browser2_->Refresh2(refresh_level.AsInput());
+}
+
+void IEEventSink::ConnectToChromeFrame() {
+ DCHECK(web_browser2_);
+ if (chrome_frame_.get())
+ return;
+ ScopedComPtr<IShellBrowser> shell_browser;
+ DoQueryService(SID_STopLevelBrowser, web_browser2_,
+ shell_browser.Receive());
+
+ if (shell_browser) {
+ ScopedComPtr<IShellView> shell_view;
+ shell_browser->QueryActiveShellView(shell_view.Receive());
+ if (shell_view) {
+ shell_view->GetItemObject(SVGIO_BACKGROUND, __uuidof(IChromeFrame),
+ reinterpret_cast<void**>(chrome_frame_.Receive()));
+ }
+
+ if (chrome_frame_) {
+ ScopedVariant onmessage(onmessage_.ToDispatch());
+ ScopedVariant onloaderror(onloaderror_.ToDispatch());
+ ScopedVariant onload(onload_.ToDispatch());
+ EXPECT_HRESULT_SUCCEEDED(chrome_frame_->put_onmessage(onmessage));
+ EXPECT_HRESULT_SUCCEEDED(chrome_frame_->put_onloaderror(onloaderror));
+ EXPECT_HRESULT_SUCCEEDED(chrome_frame_->put_onload(onload));
+ }
+ }
+}
+
+void IEEventSink::DisconnectFromChromeFrame() {
+ if (chrome_frame_) {
+ // Use a local ref counted copy of the IChromeFrame interface as the
+ // outgoing calls could cause the interface to be deleted due to a message
+ // pump running in the context of the outgoing call.
+ ScopedComPtr<IChromeFrame> chrome_frame(chrome_frame_);
+ chrome_frame_.Release();
+ ScopedVariant dummy(static_cast<IDispatch*>(NULL));
+ chrome_frame->put_onmessage(dummy);
+ chrome_frame->put_onload(dummy);
+ chrome_frame->put_onloaderror(dummy);
+ }
+}
+
+void IEEventSink::FindIEProcessId() {
+ HWND hwnd = NULL;
+ web_browser2_->get_HWND(reinterpret_cast<SHANDLE_PTR*>(&hwnd));
+ EXPECT_TRUE(::IsWindow(hwnd));
+ if (::IsWindow(hwnd))
+ ::GetWindowThreadProcessId(hwnd, &ie_process_id_);
+}
+
+// Event callbacks
+STDMETHODIMP_(void) IEEventSink::OnDownloadBegin() {
+ if (listener_)
+ listener_->OnDownloadBegin();
+}
+
+STDMETHODIMP_(void) IEEventSink::OnNewWindow2(IDispatch** disp,
+ VARIANT_BOOL* s) {
+ if (listener_)
+ listener_->OnNewWindow2(disp, s);
+}
+
+STDMETHODIMP_(void) IEEventSink::OnNavigateError(IDispatch* dispatch,
+ VARIANT* url, VARIANT* frame_name, VARIANT* status_code, VARIANT* cancel) {
+ DLOG(INFO) << __FUNCTION__;
+ if (listener_)
+ listener_->OnNavigateError(dispatch, url, frame_name, status_code, cancel);
+}
+
+STDMETHODIMP IEEventSink::OnBeforeNavigate2(
+ IDispatch* dispatch, VARIANT* url, VARIANT* flags,
+ VARIANT* target_frame_name, VARIANT* post_data, VARIANT* headers,
+ VARIANT_BOOL* cancel) {
+ DLOG(INFO) << __FUNCTION__
+ << StringPrintf("%ls - 0x%08X", url->bstrVal, this);
+ // Reset any existing reference to chrome frame since this is a new
+ // navigation.
+ DisconnectFromChromeFrame();
+ if (listener_)
+ listener_->OnBeforeNavigate2(dispatch, url, flags, target_frame_name,
+ post_data, headers, cancel);
+ return S_OK;
+}
+
+STDMETHODIMP_(void) IEEventSink::OnNavigateComplete2(
+ IDispatch* dispatch, VARIANT* url) {
+ DLOG(INFO) << __FUNCTION__;
+ ConnectToChromeFrame();
+ if (listener_)
+ listener_->OnNavigateComplete2(dispatch, url);
+}
+
+STDMETHODIMP_(void) IEEventSink::OnDocumentComplete(
+ IDispatch* dispatch, VARIANT* url) {
+ DLOG(INFO) << __FUNCTION__;
+ EXPECT_TRUE(url);
+ if (!url)
+ return;
+ if (listener_)
+ listener_->OnDocumentComplete(dispatch, url);
+}
+
+STDMETHODIMP_(void) IEEventSink::OnFileDownload(
+ VARIANT_BOOL active_doc, VARIANT_BOOL* cancel) {
+ DLOG(INFO) << __FUNCTION__ << StringPrintf(" 0x%08X ad=%i", this,
+ active_doc);
+ if (listener_)
+ listener_->OnFileDownload(active_doc, cancel);
+ // Always cancel file downloads in tests.
+ *cancel = VARIANT_TRUE;
+}
+
+STDMETHODIMP_(void) IEEventSink::OnNewWindow3(
+ IDispatch** dispatch, VARIANT_BOOL* cancel, DWORD flags, BSTR url_context,
+ BSTR url) {
+ DLOG(INFO) << __FUNCTION__;
+ EXPECT_TRUE(dispatch);
+ if (!dispatch)
+ return;
+
+ if (listener_)
+ listener_->OnNewWindow3(dispatch, cancel, flags, url_context, url);
+
+ // Note that |dispatch| is an [in/out] argument. IE is asking listeners if
+ // they want to use a IWebBrowser2 of their choice for the new window.
+ // Since we need to listen on events on the new browser, we create one
+ // if needed.
+ if (!*dispatch) {
+ ScopedComPtr<IDispatch> new_browser;
+ HRESULT hr = new_browser.CreateInstance(CLSID_InternetExplorer, NULL,
+ CLSCTX_LOCAL_SERVER);
+ DCHECK(SUCCEEDED(hr) && new_browser);
+ *dispatch = new_browser.Detach();
+ }
+
+ if (*dispatch)
+ listener_->OnNewBrowserWindow(*dispatch, url);
+}
+
+STDMETHODIMP_(void) IEEventSink::OnQuit() {
+ DLOG(INFO) << __FUNCTION__;
+
+ did_receive_on_quit_ = true;
+
+ DispEventUnadvise(web_browser2_);
+ CoDisconnectObject(this, 0);
+
+ if (listener_)
+ listener_->OnQuit();
+}
+
+HRESULT IEEventSink::OnLoad(const VARIANT* param) {
+ DLOG(INFO) << __FUNCTION__ << " " << param->bstrVal;
+ ScopedVariant stack_object(*param);
+ if (chrome_frame_) {
+ if (listener_)
+ listener_->OnLoad(param->bstrVal);
+ } else {
+ DLOG(WARNING) << "Invalid chrome frame pointer";
+ }
+ return S_OK;
+}
+
+HRESULT IEEventSink::OnLoadError(const VARIANT* param) {
+ DLOG(INFO) << __FUNCTION__ << " " << param->bstrVal;
+ if (chrome_frame_) {
+ if (listener_)
+ listener_->OnLoadError(param->bstrVal);
+ } else {
+ DLOG(WARNING) << "Invalid chrome frame pointer";
+ }
+ return S_OK;
+}
+
+HRESULT IEEventSink::OnMessage(const VARIANT* param) {
+ DLOG(INFO) << __FUNCTION__ << " " << param;
+ if (!chrome_frame_.get()) {
+ DLOG(WARNING) << "Invalid chrome frame pointer";
+ return S_OK;
+ }
+
+ ScopedVariant data, origin, source;
+ if (param && (V_VT(param) == VT_DISPATCH)) {
+ wchar_t* properties[] = { L"data", L"origin", L"source" };
+ const int prop_count = arraysize(properties);
+ DISPID ids[prop_count] = {0};
+
+ HRESULT hr = param->pdispVal->GetIDsOfNames(IID_NULL, properties,
+ prop_count, LOCALE_SYSTEM_DEFAULT, ids);
+ if (SUCCEEDED(hr)) {
+ DISPPARAMS params = { 0 };
+ EXPECT_HRESULT_SUCCEEDED(param->pdispVal->Invoke(ids[0], IID_NULL,
+ LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &params,
+ data.Receive(), NULL, NULL));
+ EXPECT_HRESULT_SUCCEEDED(param->pdispVal->Invoke(ids[1], IID_NULL,
+ LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &params,
+ origin.Receive(), NULL, NULL));
+ EXPECT_HRESULT_SUCCEEDED(param->pdispVal->Invoke(ids[2], IID_NULL,
+ LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &params,
+ source.Receive(), NULL, NULL));
+ }
+ }
+
+ if (listener_)
+ listener_->OnMessage(V_BSTR(&data), V_BSTR(&origin), V_BSTR(&source));
+ return S_OK;
+}
+
+} // namespace chrome_frame_test \ No newline at end of file
diff --git a/chrome_frame/test/ie_event_sink.h b/chrome_frame/test/ie_event_sink.h
new file mode 100644
index 0000000..6694575
--- /dev/null
+++ b/chrome_frame/test/ie_event_sink.h
@@ -0,0 +1,230 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_FRAME_TEST_IE_EVENT_SINK_H_
+#define CHROME_FRAME_TEST_IE_EVENT_SINK_H_
+
+#include <atlbase.h>
+#include <atlwin.h>
+#include <exdispid.h>
+#include <string>
+
+#include "base/lock.h"
+#include "base/scoped_comptr_win.h"
+
+#include "chrome_frame/test_utils.h"
+#include "chrome_frame/test/simulate_input.h"
+
+// Include without path to make GYP build see it.
+#include "chrome_tab.h" // NOLINT
+
+namespace chrome_frame_test {
+
+// Listener for all events from the IEEventSink, defined below. This includes
+// IE and CF events. Unfortunately some of these events are unreliable or have
+// strange behavior across different platforms/browsers. See notes besides
+// each method.
+class IEEventListener {
+ public:
+ virtual ~IEEventListener() {}
+
+ // IE callbacks
+ virtual void OnNavigateError(IDispatch* dispatch, VARIANT* url,
+ VARIANT* frame_name, VARIANT* status_code,
+ VARIANT* cancel) {}
+ // This does not occur in IE 6 in CF when navigating between fragments
+ // on the same page, although it does occur with back/forward across such.
+ virtual void OnBeforeNavigate2(IDispatch* dispatch, VARIANT* url,
+ VARIANT* flags, VARIANT* target_frame_name,
+ VARIANT* post_data, VARIANT* headers,
+ VARIANT_BOOL* cancel) {}
+ virtual void OnDownloadBegin() {}
+ virtual void OnNavigateComplete2(IDispatch* dispatch, VARIANT* url) {}
+ virtual void OnNewWindow2(IDispatch** dispatch, VARIANT_BOOL* cancel) {}
+ virtual void OnNewWindow3(IDispatch** dispatch, VARIANT_BOOL* cancel,
+ DWORD flags, BSTR url_context, BSTR url) {}
+ // This occurs twice on IE >= 7 after window.open calls.
+ virtual void OnDocumentComplete(IDispatch* dispatch, VARIANT* url_variant) {}
+ virtual void OnFileDownload(VARIANT_BOOL active_doc, VARIANT_BOOL* cancel) {}
+ virtual void OnQuit() {}
+
+ // CF callbacks
+ virtual void OnLoad(const wchar_t* url) {}
+ virtual void OnLoadError(const wchar_t* url) {}
+ virtual void OnMessage(const wchar_t* message, const wchar_t* origin,
+ const wchar_t* source) {}
+ virtual void OnNewBrowserWindow(IDispatch* new_window, const wchar_t* url) {}
+};
+
+// This class sets up event sinks to the IWebBrowser interface. It forwards
+// all events to its listener.
+// TODO(kkania): Delete WebBrowserEventSink and use this class instead for
+// the reliability tests.
+class IEEventSink
+ : public CComObjectRootEx<CComSingleThreadModel>,
+ public IDispEventSimpleImpl<0, IEEventSink,
+ &DIID_DWebBrowserEvents2>,
+ public IUnknown {
+ public:
+ // Needed to support PostTask.
+ static bool ImplementsThreadSafeReferenceCounting() {
+ return true;
+ }
+
+ typedef IDispEventSimpleImpl<0, IEEventSink,
+ &DIID_DWebBrowserEvents2> DispEventsImpl;
+ IEEventSink();
+ ~IEEventSink();
+
+ // Listen to events from this |browser_disp|, which should be queryable for
+ // IWebBrowser2.
+ void Attach(IDispatch* browser_disp);
+
+ // Stop listening to the associated web browser and possibly wait for it to
+ // close, if this browser has its own process.
+ void Uninitialize();
+
+ // Closes the web browser in such a way that the OnQuit notification will
+ // be fired when the window closes (async).
+ HRESULT CloseWebBrowser();
+
+ // Set input focus to chrome frame window.
+ void SetFocusToRenderer();
+
+ // Send keyboard input to the renderer window hosted in chrome using
+ // SendInput API.
+ void SendKeys(const wchar_t* input_string);
+
+ // Send mouse click to the renderer window hosted in chrome using
+ // SendInput API.
+ void SendMouseClick(int x, int y, simulate_input::MouseButton button);
+
+ // Get the HWND for the browser's renderer window.
+ HWND GetRendererWindow();
+
+ // Launch IE, use the given listener, and navigate to the given url.
+ HRESULT LaunchIEAndNavigate(const std::wstring& navigate_url,
+ IEEventListener* listener);
+
+ // Navigate to the given url.
+ HRESULT Navigate(const std::wstring& navigate_url);
+
+ // Returns whether CF is rendering the current page.
+ bool IsCFRendering();
+
+ // Expect the renderer window to have focus.
+ void ExpectRendererWindowHasFocus();
+
+ // Expect the address bar to have |url|.
+ void ExpectAddressBarUrl(const std::wstring& url);
+
+ // These methods are just simple wrappers of the IWebBrowser2 methods.
+ // They are needed because you cannot post tasks to IWebBrowser2.
+ void GoBack() {
+ web_browser2_->GoBack();
+ }
+
+ void GoForward() {
+ web_browser2_->GoForward();
+ }
+
+ void Refresh();
+
+ void Exec(const GUID* cmd_group_guid, DWORD command_id,
+ DWORD cmd_exec_opt, VARIANT* in_args, VARIANT* out_args);
+
+ // Set the listener for this sink, which can be NULL.
+ void set_listener(IEEventListener* listener) { listener_ = listener; }
+
+ IWebBrowser2* web_browser2() { return web_browser2_.get(); }
+
+ // Used only for debugging/logging purposes.
+ bool reference_count() { return m_dwRef; }
+
+ private:
+ void ConnectToChromeFrame();
+ void DisconnectFromChromeFrame();
+ void FindIEProcessId();
+
+ // IE callbacks.
+BEGIN_COM_MAP(IEEventSink)
+ COM_INTERFACE_ENTRY(IUnknown)
+END_COM_MAP()
+
+BEGIN_SINK_MAP(IEEventSink)
+ SINK_ENTRY_INFO(0, DIID_DWebBrowserEvents2, DISPID_BEFORENAVIGATE2,
+ OnBeforeNavigate2, &kBeforeNavigate2Info)
+ SINK_ENTRY_INFO(0, DIID_DWebBrowserEvents2, DISPID_DOWNLOADBEGIN,
+ OnDownloadBegin, &kVoidMethodInfo)
+ SINK_ENTRY_INFO(0, DIID_DWebBrowserEvents2, DISPID_NAVIGATECOMPLETE2,
+ OnNavigateComplete2, &kNavigateComplete2Info)
+ SINK_ENTRY_INFO(0, DIID_DWebBrowserEvents2, DISPID_NAVIGATEERROR,
+ OnNavigateError, &kNavigateErrorInfo)
+ SINK_ENTRY_INFO(0, DIID_DWebBrowserEvents2, DISPID_NEWWINDOW2,
+ OnNewWindow2, &kNewWindow2Info)
+ SINK_ENTRY_INFO(0, DIID_DWebBrowserEvents2, DISPID_NEWWINDOW3,
+ OnNewWindow3, &kNewWindow3Info)
+ SINK_ENTRY_INFO(0, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE,
+ OnDocumentComplete, &kDocumentCompleteInfo)
+ SINK_ENTRY_INFO(0, DIID_DWebBrowserEvents2, DISPID_FILEDOWNLOAD,
+ OnFileDownload, &kFileDownloadInfo)
+ SINK_ENTRY_INFO(0, DIID_DWebBrowserEvents2, DISPID_ONQUIT,
+ OnQuit, &kVoidMethodInfo)
+END_SINK_MAP()
+
+ STDMETHOD_(void, OnNavigateError)(IDispatch* dispatch, VARIANT* url,
+ VARIANT* frame_name, VARIANT* status_code,
+ VARIANT* cancel);
+ STDMETHOD(OnBeforeNavigate2)(IDispatch* dispatch, VARIANT* url,
+ VARIANT* flags, VARIANT* target_frame_name,
+ VARIANT* post_data, VARIANT* headers,
+ VARIANT_BOOL* cancel);
+ STDMETHOD_(void, OnDownloadBegin)();
+ STDMETHOD_(void, OnNavigateComplete2)(IDispatch* dispatch, VARIANT* url);
+ STDMETHOD_(void, OnNewWindow2)(IDispatch** dispatch, VARIANT_BOOL* cancel);
+ STDMETHOD_(void, OnNewWindow3)(IDispatch** dispatch, VARIANT_BOOL* cancel,
+ DWORD flags, BSTR url_context, BSTR url);
+ STDMETHOD_(void, OnDocumentComplete)(IDispatch* dispatch,
+ VARIANT* url_variant);
+ STDMETHOD_(void, OnFileDownload)(VARIANT_BOOL active_doc,
+ VARIANT_BOOL* cancel);
+ STDMETHOD_(void, OnQuit)();
+
+#ifdef _DEBUG
+ STDMETHOD(Invoke)(DISPID dispid, REFIID riid,
+ LCID lcid, WORD flags, DISPPARAMS* params, VARIANT* result,
+ EXCEPINFO* except_info, UINT* arg_error) {
+ DLOG(INFO) << __FUNCTION__ << L" disp id :" << dispid;
+ return DispEventsImpl::Invoke(dispid, riid, lcid, flags, params, result,
+ except_info, arg_error);
+ }
+#endif // _DEBUG
+
+ // IChromeFrame callbacks
+ HRESULT OnLoad(const VARIANT* param);
+ HRESULT OnLoadError(const VARIANT* param);
+ HRESULT OnMessage(const VARIANT* param);
+
+ ScopedComPtr<IWebBrowser2> web_browser2_;
+ ScopedComPtr<IChromeFrame> chrome_frame_;
+ DispCallback<IEEventSink> onmessage_;
+ DispCallback<IEEventSink> onloaderror_;
+ DispCallback<IEEventSink> onload_;
+ IEEventListener* listener_;
+ base::ProcessId ie_process_id_;
+ bool did_receive_on_quit_;
+
+ static _ATL_FUNC_INFO kBeforeNavigate2Info;
+ static _ATL_FUNC_INFO kNavigateComplete2Info;
+ static _ATL_FUNC_INFO kNavigateErrorInfo;
+ static _ATL_FUNC_INFO kNewWindow2Info;
+ static _ATL_FUNC_INFO kNewWindow3Info;
+ static _ATL_FUNC_INFO kVoidMethodInfo;
+ static _ATL_FUNC_INFO kDocumentCompleteInfo;
+ static _ATL_FUNC_INFO kFileDownloadInfo;
+};
+
+} // namespace chrome_frame_test
+
+#endif // CHROME_FRAME_TEST_IE_EVENT_SINK_H_ \ No newline at end of file
diff --git a/chrome_frame/test/mock_ie_event_sink_actions.h b/chrome_frame/test/mock_ie_event_sink_actions.h
new file mode 100644
index 0000000..ff7d84d
--- /dev/null
+++ b/chrome_frame/test/mock_ie_event_sink_actions.h
@@ -0,0 +1,172 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_FRAME_TEST_MOCK_IE_EVENT_SINK_ACTIONS_H_
+#define CHROME_FRAME_TEST_MOCK_IE_EVENT_SINK_ACTIONS_H_
+
+#include "chrome_frame/test/simulate_input.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace chrome_frame_test {
+
+MATCHER_P(UrlPathEq, url, "equals the path and query portion of the url") {
+ return arg == chrome_frame_test::GetPathAndQueryFromUrl(url);
+}
+
+ACTION_P3(DelayCloseBrowserMock, loop, delay, mock) {
+ loop->PostDelayedTask(FROM_HERE, NewRunnableMethod(mock->event_sink(),
+ &IEEventSink::CloseWebBrowser), delay);
+}
+
+ACTION_P(SetFocusToRenderer, mock) {
+ simulate_input::SetKeyboardFocusToWindow(
+ mock->event_sink()->GetRendererWindow());
+}
+
+ACTION_P2(Navigate, mock, navigate_url) {
+ mock->event_sink()->Navigate(navigate_url);
+}
+
+ACTION_P2(WatchWindow, mock, window_class) {
+ mock->WatchWindow(window_class);
+}
+
+ACTION_P(StopWindowWatching, mock) {
+ mock->StopWatching();
+}
+
+ACTION_P(ExpectRendererHasFocus, mock) {
+ mock->event_sink()->ExpectRendererWindowHasFocus();
+}
+
+ACTION_P8(DelayExecCommand, mock, loop, delay, cmd_group_guid, cmd_id,
+ cmd_exec_opt, in_args, out_args) {
+ loop->PostDelayedTask(FROM_HERE, NewRunnableMethod(mock->event_sink(),
+ &IEEventSink::Exec, cmd_group_guid, cmd_id, cmd_exec_opt, in_args,
+ out_args), delay);
+}
+
+ACTION_P3(DelayRefresh, mock, loop, delay) {
+ loop->PostDelayedTask(FROM_HERE, NewRunnableMethod(mock->event_sink(),
+ &IEEventSink::Refresh), delay);
+}
+
+ACTION_P6(DelaySendMouseClick, mock, loop, delay, x, y, button) {
+ loop->PostDelayedTask(FROM_HERE, NewRunnableMethod(mock->event_sink(),
+ &IEEventSink::SendMouseClick, x, y, button), delay);
+}
+
+ACTION_P5(DelaySendDoubleClick, mock, loop, delay, x, y) {
+ loop->PostDelayedTask(FROM_HERE, NewRunnableMethod(mock->event_sink(),
+ &IEEventSink::SendMouseClick, x, y, simulate_input::LEFT), delay);
+ loop->PostDelayedTask(FROM_HERE, NewRunnableMethod(mock->event_sink(),
+ &IEEventSink::SendMouseClick, x, y, simulate_input::LEFT), delay + 100);
+}
+
+ACTION_P4(DelaySendChar, loop, delay, c, mod) {
+ loop->PostDelayedTask(FROM_HERE, NewRunnableFunction(
+ simulate_input::SendCharA, c, mod), delay);
+}
+
+ACTION_P3(DelaySendString, loop, delay, str) {
+ loop->PostDelayedTask(FROM_HERE, NewRunnableFunction(
+ simulate_input::SendStringW, str), delay);
+}
+
+ACTION_P5(SendExtendedKeysEnter, loop, delay, c, repeat, mod) {
+ chrome_frame_test::DelaySendExtendedKeysEnter(loop, delay, c, repeat, mod);
+}
+
+ACTION(DoCloseWindow) {
+ ::PostMessage(arg0, WM_SYSCOMMAND, SC_CLOSE, 0);
+}
+
+ACTION_P3(DelayGoBack, mock, loop, delay) {
+ loop->PostDelayedTask(FROM_HERE, NewRunnableMethod(mock->event_sink(),
+ &IEEventSink::GoBack), delay);
+}
+
+ACTION_P3(DelayGoForward, mock, loop, delay) {
+ loop->PostDelayedTask(FROM_HERE, NewRunnableMethod(mock->event_sink(),
+ &IEEventSink::GoForward), delay);
+}
+
+ACTION_P(CloseBrowserMock, mock) {
+ mock->event_sink()->CloseWebBrowser();
+}
+
+ACTION_P(VerifyAddressBarUrl, mock) {
+ mock->event_sink()->ExpectAddressBarUrl(std::wstring(arg1));
+}
+
+ACTION_P4(DelaySendScanCode, loop, delay, c, mod) {
+ loop->PostDelayedTask(FROM_HERE, NewRunnableFunction(
+ simulate_input::SendScanCode, c, mod), delay);
+}
+
+// This function selects the address bar via the Alt+d shortcut. This is done
+// via a delayed task which executes after the delay which is passed in.
+// The subsequent operations like typing in the actual url and then hitting
+// enter to force the browser to navigate to it each execute as delayed tasks
+// timed at the delay passed in. The recommended value for delay is 2000 ms
+// to account for the time taken for the accelerator keys to be reflected back
+// from Chrome.
+ACTION_P3(TypeUrlInAddressBar, loop, url, delay) {
+ loop->PostDelayedTask(FROM_HERE, NewRunnableFunction(
+ simulate_input::SendCharA, 'd', simulate_input::ALT),
+ delay);
+
+ const unsigned int kInterval = 500;
+ int next_delay = delay + kInterval;
+
+ loop->PostDelayedTask(FROM_HERE, NewRunnableFunction(
+ simulate_input::SendStringW, url), next_delay);
+
+ next_delay = next_delay + kInterval;
+
+ loop->PostDelayedTask(FROM_HERE, NewRunnableFunction(
+ simulate_input::SendCharA, VK_RETURN, simulate_input::NONE),
+ next_delay);
+}
+
+ACTION_P5(ValidateWindowSize, mock, left, top, width, height) {
+ int actual_left = 0;
+ int actual_top = 0;
+ int actual_width = 0;
+ int actual_height = 0;
+
+ IWebBrowser2* web_browser2 = mock->event_sink()->web_browser2();
+ web_browser2->get_Left(reinterpret_cast<long*>(&actual_left));
+ web_browser2->get_Top(reinterpret_cast<long*>(&actual_top));
+ web_browser2->get_Width(reinterpret_cast<long*>(&actual_width));
+ web_browser2->get_Height(reinterpret_cast<long*>(&actual_height));
+
+ EXPECT_EQ(actual_left, left);
+ EXPECT_EQ(actual_top, top);
+
+ EXPECT_LE(actual_width, width + 20);
+ EXPECT_GT(actual_width, width - 20);
+ EXPECT_LE(actual_height, height + 100);
+ EXPECT_GT(actual_height, height - 100);
+}
+
+ACTION_P(VerifyAddressBarUrlWithGcf, mock) {
+ std::wstring expected_url = L"gcf:";
+ expected_url += arg1;
+ mock->event_sink()->ExpectAddressBarUrl(expected_url);
+}
+
+ACTION_P2(OpenContextMenu, loop, delay) {
+ loop->PostDelayedTask(FROM_HERE, NewRunnableFunction(
+ simulate_input::SendScanCode, VK_F10, simulate_input::SHIFT), delay);
+}
+
+ACTION_P3(SelectItem, loop, delay, index) {
+ chrome_frame_test::DelaySendExtendedKeysEnter(loop, delay, VK_DOWN, index + 1,
+ simulate_input::NONE);
+}
+
+} // namespace chrome_frame_test
+
+#endif // CHROME_FRAME_TEST_MOCK_IE_EVENT_SINK_ACTIONS_H_ \ No newline at end of file
diff --git a/chrome_frame/test/mock_ie_event_sink_test.cc b/chrome_frame/test/mock_ie_event_sink_test.cc
new file mode 100644
index 0000000..66d4799
--- /dev/null
+++ b/chrome_frame/test/mock_ie_event_sink_test.cc
@@ -0,0 +1,172 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome_frame/test/mock_ie_event_sink_test.h"
+
+#include <sstream>
+
+#include "base/utf_string_conversions.h"
+#include "chrome_frame/test/mock_ie_event_sink_actions.h"
+
+// Needed for CreateFunctor.
+#define GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING
+#include "testing/gmock_mutant.h"
+
+using testing::_;
+using testing::Cardinality;
+using testing::Exactly;
+using testing::ExpectationSet;
+using testing::InSequence;
+using testing::StrCaseEq;
+
+namespace chrome_frame_test {
+
+// MockIEEventSink methods
+ExpectationSet MockIEEventSink::ExpectNavigationCardinality(
+ const std::wstring& url, Cardinality before_cardinality,
+ Cardinality complete_cardinality) {
+ ExpectationSet navigation;
+ if (url.empty()) {
+ navigation += EXPECT_CALL(*this, OnBeforeNavigate2(_, _, _, _, _, _, _))
+ .Times(before_cardinality).RetiresOnSaturation();
+ } else {
+ navigation += EXPECT_CALL(*this, OnBeforeNavigate2(_,
+ testing::Field(&VARIANT::bstrVal,
+ StrCaseEq(url)), _, _, _, _, _))
+ .Times(before_cardinality).RetiresOnSaturation();
+ }
+
+ // Hack: OnFileDownload may occur zero or once (for reasons not understood)
+ // before each OnNavigateComplete2 which causes problems for tests expecting
+ // things in sequence. To redress this, expectations which allow multiple
+ // calls are split into expect statements expecting exactly one call or at
+ // most one call.
+ // TODO(kkania): Consider avoiding this problem by creating a mock without
+ // the OnFileDownload call or by removing the dependency of some tests on
+ // InSequence.
+ DLOG_IF(WARNING, complete_cardinality.ConservativeUpperBound() > 1000)
+ << "Cardinality upper bound may be too great to be split up into single "
+ << "expect statements. If you do not require this navigation to be in "
+ << "sequence, do not call this method.";
+ int call_count = 0;
+ InSequence expect_in_sequence_for_scope;
+ while (!complete_cardinality.IsSaturatedByCallCount(call_count)) {
+ navigation += EXPECT_CALL(*this, OnFileDownload(_, _))
+ .Times(testing::AtMost(1))
+ .RetiresOnSaturation();
+
+ Cardinality split_complete_cardinality = testing::Exactly(1);
+ if (complete_cardinality.IsSatisfiedByCallCount(call_count))
+ split_complete_cardinality = testing::AtMost(1);
+
+ if (url.empty()) {
+ navigation += EXPECT_CALL(*this, OnNavigateComplete2(_, _))
+ .Times(split_complete_cardinality)
+ .RetiresOnSaturation();
+ } else {
+ navigation += EXPECT_CALL(*this, OnNavigateComplete2(_,
+ testing::Field(&VARIANT::bstrVal,
+ StrCaseEq(url))))
+ .Times(split_complete_cardinality)
+ .RetiresOnSaturation();
+ }
+ call_count++;
+ }
+ return navigation;
+}
+
+void MockIEEventSink::ExpectNavigation(bool is_cf, const std::wstring& url) {
+ InSequence expect_in_sequence_for_scope;
+ if (is_cf) {
+ ExpectNavigationCardinality(url, Exactly(1), testing::Between(1, 2));
+ } else {
+ ExpectNavigationCardinality(url, Exactly(1), Exactly(1));
+ }
+}
+
+void MockIEEventSink::ExpectInPageNavigation(bool is_cf,
+ const std::wstring& url) {
+ InSequence expect_in_sequence_for_scope;
+ if (is_cf && GetInstalledIEVersion() == IE_6) {
+ // OnBeforeNavigation events are not sent for navigation between different
+ // anchors in a CF page in IE6.
+ ExpectNavigationCardinality(url, testing::AtMost(1),
+ testing::Between(1, 2));
+ } else {
+ ExpectNavigation(is_cf, url);
+ }
+}
+
+void MockIEEventSink::ExpectJavascriptWindowOpenNavigation(
+ bool parent_cf, bool new_window_cf, const std::wstring& url) {
+ DCHECK(!(parent_cf && !new_window_cf)) << "Cannot expect popup to be loaded"
+ " in Internet Explorer if parent window is loaded in Chrome Frame.";
+
+ if (parent_cf) {
+ InSequence expect_in_sequence_for_scope;
+ ExpectNavigation(IN_CF, L"");
+ ExpectNavigationCardinality(L"", testing::AtMost(1),
+ testing::Between(1, 2));
+ } else {
+ if (new_window_cf) {
+ ExpectNavigationCardinality(url, testing::AtMost(1), testing::AtMost(1));
+ // Sometimes an extra load occurs here for some reason.
+ EXPECT_CALL(*this, OnLoad(IN_IE, StrCaseEq(url)))
+ .Times(testing::AtMost(1));
+ ExpectNavigationCardinality(url, testing::AtMost(1),
+ testing::Between(1, 2));
+ } else {
+ ExpectNavigation(IN_IE, url);
+ }
+ }
+}
+
+void MockIEEventSink::ExpectNewWindow(MockIEEventSink* new_window_mock) {
+ DCHECK(new_window_mock);
+
+ EXPECT_CALL(*this, OnNewWindow3(_, _, _, _, _));
+ EXPECT_CALL(*this, OnNewBrowserWindow(_, _))
+ .WillOnce(testing::WithArgs<0>(testing::Invoke(testing::CreateFunctor(
+ new_window_mock, &MockIEEventSink::Attach))));
+}
+
+void MockIEEventSink::ExpectAnyNavigations() {
+ EXPECT_CALL(*this, OnBeforeNavigate2(_, _, _, _, _, _, _))
+ .Times(testing::AnyNumber());
+ EXPECT_CALL(*this, OnFileDownload(VARIANT_TRUE, _))
+ .Times(testing::AnyNumber());
+ EXPECT_CALL(*this, OnNavigateComplete2(_, _))
+ .Times(testing::AnyNumber());
+}
+
+// MockIEEventSinkTest methods
+MockIEEventSinkTest::MockIEEventSinkTest() : server_mock_(1337, L"127.0.0.1",
+ GetTestDataFolder()) {
+ EXPECT_CALL(server_mock_, Get(_, StrCaseEq(L"/favicon.ico"), _))
+ .WillRepeatedly(SendFast("HTTP/1.1 404 Not Found", ""));
+}
+
+void MockIEEventSinkTest::LaunchIEAndNavigate(const std::wstring& url) {
+ LaunchIENavigateAndLoop(url, kChromeFrameLongNavigationTimeoutInSeconds);
+}
+
+void MockIEEventSinkTest::LaunchIENavigateAndLoop(const std::wstring& url,
+ int timeout) {
+ EXPECT_CALL(ie_mock_, OnQuit())
+ .WillOnce(QUIT_LOOP(loop_));
+ HRESULT hr = ie_mock_.event_sink()->LaunchIEAndNavigate(url, &ie_mock_);
+ ASSERT_HRESULT_SUCCEEDED(hr);
+ if (hr == S_FALSE)
+ return;
+
+ ASSERT_TRUE(ie_mock_.event_sink()->web_browser2() != NULL);
+ loop_.RunFor(timeout);
+}
+
+std::wstring MockIEEventSinkTest::GetTestUrl(
+ const std::wstring& relative_path) {
+ return server_mock_.Resolve(relative_path.c_str());
+}
+
+} // namespace chrome_frame_test \ No newline at end of file
diff --git a/chrome_frame/test/mock_ie_event_sink_test.h b/chrome_frame/test/mock_ie_event_sink_test.h
new file mode 100644
index 0000000..f2a63fd
--- /dev/null
+++ b/chrome_frame/test/mock_ie_event_sink_test.h
@@ -0,0 +1,230 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_FRAME_TEST_MOCK_IE_EVENT_SINK_TEST_H_
+#define CHROME_FRAME_TEST_MOCK_IE_EVENT_SINK_TEST_H_
+
+#include <atlbase.h>
+#include <atlcom.h>
+#include <string>
+
+#include "chrome_frame/test/chrome_frame_test_utils.h"
+#include "chrome_frame/test/ie_event_sink.h"
+#include "chrome_frame/test/test_server.h"
+#include "chrome_frame/test/test_with_web_server.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chrome_frame_test {
+
+// Convenience enum for specifying whether a load occurred in IE or CF.
+enum LoadedInRenderer {
+ IN_IE = 0,
+ IN_CF
+};
+
+// This mocks an IEEventListener, providing methods for expecting certain
+// sequences of events.
+class MockIEEventSink : public IEEventListener {
+ public:
+ MockIEEventSink() {
+ CComObject<IEEventSink>::CreateInstance(&event_sink_);
+ event_sink_->AddRef();
+ }
+
+ ~MockIEEventSink() {
+ Detach();
+ int reference_count = event_sink_->reference_count();
+ DLOG_IF(ERROR, reference_count != 1)
+ << "Event sink is still referenced externally: ref count = "
+ << reference_count;
+ event_sink_->Release();
+ }
+
+ // Override IEEventListener methods.
+ MOCK_METHOD7(OnBeforeNavigate2, void (IDispatch* dispatch, // NOLINT
+ VARIANT* url,
+ VARIANT* flags,
+ VARIANT* target_frame_name,
+ VARIANT* post_data,
+ VARIANT* headers,
+ VARIANT_BOOL* cancel));
+ MOCK_METHOD2(OnNavigateComplete2, void (IDispatch* dispatch, // NOLINT
+ VARIANT* url));
+ MOCK_METHOD5(OnNewWindow3, void (IDispatch** dispatch, // NOLINT
+ VARIANT_BOOL* cancel,
+ DWORD flags,
+ BSTR url_context,
+ BSTR url));
+ MOCK_METHOD2(OnNewWindow2, void (IDispatch** dispatch, // NOLINT
+ VARIANT_BOOL* cancel));
+ MOCK_METHOD5(OnNavigateError, void (IDispatch* dispatch, // NOLINT
+ VARIANT* url,
+ VARIANT* frame_name,
+ VARIANT* status_code,
+ VARIANT* cancel));
+ MOCK_METHOD2(OnFileDownload, void (VARIANT_BOOL active_doc, // NOLINT
+ VARIANT_BOOL* cancel));
+ MOCK_METHOD0(OnQuit, void ()); // NOLINT
+ MOCK_METHOD1(OnLoadError, void (const wchar_t* url)); // NOLINT
+ MOCK_METHOD3(OnMessage, void (const wchar_t* message, // NOLINT
+ const wchar_t* origin,
+ const wchar_t* source));
+ MOCK_METHOD2(OnNewBrowserWindow, void (IDispatch* dispatch, // NOLINT
+ const wchar_t* url));
+
+ // Convenience OnLoad method which is called once when a page is loaded with
+ // |is_cf| set to whether the renderer is CF or not.
+ MOCK_METHOD2(OnLoad, void (bool is_cf, const wchar_t* url)); // NOLINT
+
+ // Attach |dispatch| to the event sink and begin listening to the source's
+ // events.
+ void Attach(IDispatch* dispatch) {
+ event_sink_->set_listener(this);
+ event_sink_->Attach(dispatch);
+ }
+
+ void Detach() {
+ event_sink_->set_listener(NULL);
+ event_sink_->Uninitialize();
+ }
+
+ // Expect a normal navigation to |url| to occur in CF or IE.
+ void ExpectNavigation(bool is_cf, const std::wstring& url);
+
+ // Same as above, but used when the new navigation is to a diffrent fragment
+ // in the same page.
+ void ExpectInPageNavigation(bool is_cf, const std::wstring& url);
+
+ // Expect a navigation in a new window created by a window.open call to |url|.
+ // |parent_cf| signifies whether the parent frame was loaded in CF, while
+ // |new_window_cf| signifies whether to expect the new page to be loaded in
+ // CF.
+ void ExpectJavascriptWindowOpenNavigation(bool parent_cf, bool new_window_cf,
+ const std::wstring& url);
+
+ // Expect a new window to open. The new event sink will be attached to
+ // |new_window_mock|.
+ void ExpectNewWindow(MockIEEventSink* new_window_mock);
+
+ // Expects any and all navigations.
+ void ExpectAnyNavigations();
+
+ IEEventSink* event_sink() { return event_sink_; }
+
+ private:
+ // Override IE's OnDocumentComplete to call our OnLoad, iff it is IE actually
+ // rendering the page.
+ virtual void OnDocumentComplete(IDispatch* dispatch, VARIANT* url) {
+ if (!event_sink_->IsCFRendering())
+ OnLoad(IN_IE, V_BSTR(url));
+ }
+
+ // Override CF's OnLoad to call our OnLoad.
+ virtual void OnLoad(const wchar_t* url) {
+ OnLoad(IN_CF, url);
+ }
+
+ // Helper method for expecting navigations. |before_cardinality| specifies
+ // the cardinality for the BeforeNavigate expectation and
+ // |complete_cardinality| specifies the cardinality for the NavigateComplete
+ // expectation. Returns the set of expectations added.
+ // Note: Prefer making a new Expect... method before making this public.
+ testing::ExpectationSet ExpectNavigationCardinality(const std::wstring& url,
+ testing::Cardinality before_cardinality,
+ testing::Cardinality complete_cardinality);
+
+ // It may be necessary to create this on the heap. Otherwise, if the
+ // reference count is greater than zero, a debug assert will be triggered
+ // in the destructor. This happens at least when IE crashes. In that case,
+ // DispEventUnadvise and CoDisconnectObject are not sufficient to decrement
+ // the reference count.
+ // TODO(kkania): Investigate if the above is true.
+ CComObject<IEEventSink>* event_sink_;
+};
+
+// Mocks a window observer so that tests can detect new windows.
+class MockWindowObserver : public WindowObserver {
+ public:
+ // Override WindowObserver methods.
+ MOCK_METHOD2(OnWindowDetected, void (HWND hwnd, // NOLINT
+ const std::string& caption));
+
+ // Watch for all windows of the given class type.
+ void WatchWindow(const wchar_t* window_class) {
+ DCHECK(window_class);
+ window_watcher_.AddObserver(this, WideToUTF8(window_class));
+ }
+
+ private:
+ WindowWatchdog window_watcher_;
+};
+
+// This test fixture provides common methods needed for testing CF
+// integration with IE. gMock is used to verify that IE is reporting correct
+// navigational events and MockWebServer is used to verify that the correct
+// requests are going out.
+class MockIEEventSinkTest {
+ public:
+ MockIEEventSinkTest();
+
+ ~MockIEEventSinkTest() {
+ // Detach manually here so that it occurs before |last_resort_close_ie_|
+ // is destroyed.
+ ie_mock_.Detach();
+ }
+
+ // Launches IE as a COM server and sets |ie_mock_| as the event sink, then
+ // navigates to the given url. Then the timed message loop is run until
+ // |ie_mock_| receives OnQuit or the timeout is exceeded.
+ void LaunchIEAndNavigate(const std::wstring& url);
+
+ // Same as above but allows the timeout to be specified.
+ void LaunchIENavigateAndLoop(const std::wstring& url, int timeout);
+
+ // Returns the url for the test file given. |relative_path| should be
+ // relative to the test data directory.
+ std::wstring GetTestUrl(const std::wstring& relative_path);
+
+ // Returns the absolute FilePath for the test file given. |relative_path|
+ // should be relative to the test data directory.
+ FilePath GetTestFilePath(const std::wstring& relative_path);
+
+ // Returns the url for an html page just containing some text. Iff |use_cf|
+ // is true, the chrome_frame meta tag will be included too.
+ std::wstring GetSimplePageUrl() {
+ return GetTestUrl(L"simple.html");
+ }
+
+ // Returns the url for an html page just containing one link to the simple
+ // page mentioned above.
+ std::wstring GetLinkPageUrl() {
+ return GetTestUrl(L"link.html");
+ }
+
+ // Returns the url for an html page containing several anchors pointing
+ // to different parts of the page. |index| specifies what fragment to
+ // append to the url. If zero, no fragment is appended. The highest fragment
+ // is #a4.
+ std::wstring GetAnchorPageUrl(int index) {
+ DCHECK_LT(index, 5);
+ std::wstring base_name = L"anchor.html";
+ if (index > 0)
+ base_name += std::wstring(L"#a") + IntToWString(index);
+ return GetTestUrl(base_name);
+ }
+
+ protected:
+ CloseIeAtEndOfScope last_resort_close_ie_;
+ chrome_frame_test::TimedMsgLoop loop_;
+ testing::StrictMock<MockIEEventSink> ie_mock_;
+ testing::StrictMock<MockWebServer> server_mock_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockIEEventSinkTest);
+};
+
+} // namespace chrome_frame_test
+
+#endif // CHROME_FRAME_TEST_MOCK_IE_EVENT_SINK_TEST_H_ \ No newline at end of file
diff --git a/chrome_frame/test/navigation_test.cc b/chrome_frame/test/navigation_test.cc
new file mode 100644
index 0000000..6258350
--- /dev/null
+++ b/chrome_frame/test/navigation_test.cc
@@ -0,0 +1,635 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/scoped_comptr_win.h"
+#include "base/win_util.h"
+#include "chrome_frame/test/chrome_frame_test_utils.h"
+#include "chrome_frame/test/mock_ie_event_sink_actions.h"
+#include "chrome_frame/test/mock_ie_event_sink_test.h"
+
+// Needed for CreateFunctor.
+#define GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING
+#include "testing/gmock_mutant.h"
+
+using testing::_;
+using testing::InSequence;
+using testing::StrEq;
+
+namespace chrome_frame_test {
+
+const wchar_t tab_enter_keys[] = { VK_TAB, VK_RETURN, 0 };
+
+// Test fixture for navigation-related tests. Each test is run thrice: IE, CF
+// with meta tag invocation, and CF with http header invocation. This is
+// accomplished by using gTest's parameterized test.
+class FullTabNavigationTest
+ : public MockIEEventSinkTest, public testing::TestWithParam<CFInvocation> {
+ public:
+ FullTabNavigationTest() {}
+};
+
+// Instantiate each test case. Instead of doing in one statement, it is split
+// into three so gTest prints nicer names.
+INSTANTIATE_TEST_CASE_P(IE, FullTabNavigationTest, testing::Values(
+ CFInvocation(CFInvocation::NONE)));
+INSTANTIATE_TEST_CASE_P(MetaTag, FullTabNavigationTest, testing::Values(
+ CFInvocation(CFInvocation::META_TAG)));
+INSTANTIATE_TEST_CASE_P(HttpHeader, FullTabNavigationTest, testing::Values(
+ CFInvocation(CFInvocation::HTTP_HEADER)));
+
+// This tests navigation to a typed URL.
+TEST_P(FullTabNavigationTest, FLAKY_TypeUrl) {
+ ie_mock_.ExpectNavigation(IN_IE, GetSimplePageUrl());
+ server_mock_.ExpectAndServeRequest(CFInvocation::None(), GetSimplePageUrl());
+ EXPECT_CALL(ie_mock_, OnLoad(IN_IE, StrEq(GetSimplePageUrl())))
+ .WillOnce(testing::DoAll(
+ SetFocusToRenderer(&ie_mock_),
+ TypeUrlInAddressBar(&loop_, GetAnchorPageUrl(0), 2000)));
+
+ bool in_cf = GetParam().invokes_cf();
+ ie_mock_.ExpectNavigation(in_cf, GetAnchorPageUrl(0));
+ server_mock_.ExpectAndServeRequest(GetParam(), GetAnchorPageUrl(0));
+ EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(GetAnchorPageUrl(0))))
+ .WillOnce(CloseBrowserMock(&ie_mock_));
+
+ LaunchIEAndNavigate(GetSimplePageUrl());
+}
+
+// This tests navigation to a typed URL containing an fragment.
+TEST_P(FullTabNavigationTest, FLAKY_TypeAnchorUrl) {
+ if (IsIBrowserServicePatchEnabled()) {
+ LOG(ERROR) << "Not running test. IBrowserServicePatch is in place.";
+ return;
+ }
+
+ ie_mock_.ExpectNavigation(IN_IE, GetSimplePageUrl());
+ server_mock_.ExpectAndServeRequest(CFInvocation::None(), GetSimplePageUrl());
+ EXPECT_CALL(ie_mock_, OnLoad(IN_IE, StrEq(GetSimplePageUrl())))
+ .WillOnce(testing::DoAll(
+ SetFocusToRenderer(&ie_mock_),
+ TypeUrlInAddressBar(&loop_, GetAnchorPageUrl(1), 2000)));
+
+ bool in_cf = GetParam().invokes_cf();
+ ie_mock_.ExpectNavigation(in_cf, GetAnchorPageUrl(1));
+ server_mock_.ExpectAndServeRequest(GetParam(), GetAnchorPageUrl(1));
+ EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(GetAnchorPageUrl(1))))
+ .WillOnce(CloseBrowserMock(&ie_mock_));
+
+ LaunchIEAndNavigate(GetSimplePageUrl());
+}
+
+// Tests refreshing when a cached copy is available.
+TEST_P(FullTabNavigationTest, FLAKY_RefreshWithCachedCopy) {
+ if (GetInstalledIEVersion() == IE_7) {
+ LOG(ERROR) << "Test disabled for this configuration.";
+ return;
+ }
+ bool in_cf = GetParam().invokes_cf();
+ ie_mock_.ExpectAnyNavigations();
+ InSequence expect_in_scope_for_sequence;
+
+ testing::Cardinality initial_req_cardinality = testing::Exactly(1);
+ // TODO(kkania): Remove this allowance for double request on meta tag when no
+ // longer necessary.
+ if (GetParam().type() == CFInvocation::META_TAG)
+ initial_req_cardinality = testing::Between(1, 2);
+ EXPECT_CALL(server_mock_, Get(_, UrlPathEq(GetSimplePageUrl()), _))
+ .Times(initial_req_cardinality)
+ .WillRepeatedly(SendAllowCacheResponse(&server_mock_, GetParam()));
+ EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(GetSimplePageUrl())))
+ .WillOnce(testing::DoAll(
+ SetFocusToRenderer(&ie_mock_),
+ DelayRefresh(&ie_mock_, &loop_, 0)));
+
+ if (in_cf) {
+ // For some reason IE7 requests the resource again.
+ if (GetInstalledIEVersion() == IE_7) {
+ server_mock_.ExpectAndServeRequest(GetParam(), GetSimplePageUrl());
+ }
+ EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(GetSimplePageUrl())))
+ .WillOnce(testing::DoAll(
+ SetFocusToRenderer(&ie_mock_),
+ CloseBrowserMock(&ie_mock_)));
+ } else {
+ // For some reason IE still requests the resource again, but does not
+ // trigger another load.
+ EXPECT_CALL(server_mock_, Get(_, UrlPathEq(GetSimplePageUrl()), _))
+ .WillOnce(CloseBrowserMock(&ie_mock_));
+ }
+
+ LaunchIEAndNavigate(GetSimplePageUrl());
+}
+
+// Test that multiple back and forward requests work.
+TEST_P(FullTabNavigationTest, FLAKY_MultipleBackForward) {
+ std::wstring page1 = GetSimplePageUrl();
+ std::wstring page2 = GetLinkPageUrl();
+ std::wstring page3 = GetAnchorPageUrl(0);
+ bool in_cf = GetParam().invokes_cf();
+ server_mock_.ExpectAndServeAnyRequests(GetParam());
+ InSequence expect_in_sequence_for_scope;
+
+ // Navigate to url 2 after the previous navigation is complete.
+ ie_mock_.ExpectNavigation(in_cf, page1);
+ EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(page1)))
+ .WillOnce(testing::DoAll(
+ VerifyAddressBarUrl(&ie_mock_),
+ Navigate(&ie_mock_, page2)));
+
+ // Navigate to url 3 after the previous navigation is complete.
+ ie_mock_.ExpectNavigation(in_cf, page2);
+ EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(page2)))
+ .WillOnce(testing::DoAll(
+ VerifyAddressBarUrl(&ie_mock_),
+ Navigate(&ie_mock_, page3)));
+
+ // We have reached url 3 and have two back entries for url 1 & 2.
+ // Go back to url 2 now.
+ ie_mock_.ExpectNavigation(in_cf, page3);
+ EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(page3)))
+ .WillOnce(testing::DoAll(
+ VerifyAddressBarUrl(&ie_mock_),
+ DelayGoBack(&ie_mock_, &loop_, 0)));
+
+ // We have reached url 2 and have 1 back & 1 forward entries for url 1 & 3.
+ // Go back to url 1 now.
+ ie_mock_.ExpectNavigation(in_cf, page2);
+ EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(page2)))
+ .WillOnce(testing::DoAll(
+ VerifyAddressBarUrl(&ie_mock_),
+ DelayGoBack(&ie_mock_, &loop_, 0)));
+
+ // We have reached url 1 and have 0 back & 2 forward entries for url 2 & 3.
+ // Go forward to url 2 now.
+ ie_mock_.ExpectNavigation(in_cf, page1);
+ EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(page1)))
+ .WillOnce(testing::DoAll(
+ VerifyAddressBarUrl(&ie_mock_),
+ DelayGoForward(&ie_mock_, &loop_, 0)));
+
+ // We have reached url 2 and have 1 back & 1 forward entries for url 1 & 3.
+ // Go forward to url 3 now.
+ ie_mock_.ExpectNavigation(in_cf, page2);
+ EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(page2)))
+ .WillOnce(testing::DoAll(
+ VerifyAddressBarUrl(&ie_mock_),
+ DelayGoForward(&ie_mock_, &loop_, 0)));
+
+ // We have reached url 2 and have 1 back & 1 forward entries for url 1 & 3.
+ ie_mock_.ExpectNavigation(in_cf, page3);
+ EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(page3)))
+ .WillOnce(testing::DoAll(
+ VerifyAddressBarUrl(&ie_mock_),
+ CloseBrowserMock(&ie_mock_)));
+
+ LaunchIEAndNavigate(page1);
+}
+
+// Test multiple back and forward operations among urls with anchors.
+// Marking this test FLAKY as it fails at times on the buildbot.
+// http://code.google.com/p/chromium/issues/detail?id=26549
+TEST_P(FullTabNavigationTest, FLAKY_BackForwardAnchor) {
+ bool in_cf = GetParam().invokes_cf();
+ if (!in_cf) {
+ LOG(ERROR) << "Test not yet implemented.";
+ return;
+ }
+ server_mock_.ExpectAndServeAnyRequests(GetParam());
+ InSequence expect_in_sequence_for_scope;
+
+ // Navigate to anchor 1:
+ // - First set focus to chrome renderer window
+ // Call WebBrowserEventSink::SetFocusToRenderer only once
+ // in the beginning. Calling it again will change focus from the
+ // current location to an element near the simulated mouse click.
+ // - Then send keyboard input of TAB + ENTER to cause navigation.
+ // It's better to send input as PostDelayedTask since the Activex
+ // message loop_ on the other side might be blocked when we get
+ // called in Onload.
+ // Back/Forward state at this point:
+ // Back: 0
+ // Forward: 0
+ ie_mock_.ExpectNavigation(in_cf, GetAnchorPageUrl(0));
+ EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(GetAnchorPageUrl(0))))
+ .WillOnce(testing::DoAll(
+ SetFocusToRenderer(&ie_mock_),
+ DelaySendString(&loop_, 500, tab_enter_keys)));
+
+ // Navigate to anchor 2 after the previous navigation is complete
+ // Back/Forward state at this point:
+ // Back: 1 (kAnchorUrl)
+ // Forward: 0
+ ie_mock_.ExpectInPageNavigation(in_cf, GetAnchorPageUrl(1));
+ EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(GetAnchorPageUrl(1))))
+ .WillOnce(testing::DoAll(
+ VerifyAddressBarUrl(&ie_mock_),
+ DelaySendString(&loop_, 500, tab_enter_keys)));
+
+ // Navigate to anchor 3 after the previous navigation is complete
+ // Back/Forward state at this point:
+ // Back: 2 (kAnchorUrl, kAnchor1Url)
+ // Forward: 0
+ ie_mock_.ExpectInPageNavigation(in_cf, GetAnchorPageUrl(2));
+ EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(GetAnchorPageUrl(2))))
+ .WillOnce(testing::DoAll(
+ VerifyAddressBarUrl(&ie_mock_),
+ DelaySendString(&loop_, 500, tab_enter_keys)));
+
+ // We will reach anchor 3 once the navigation is complete,
+ // then go back to anchor 2
+ // Back/Forward state at this point:
+ // Back: 3 (kAnchorUrl, kAnchor1Url, kAnchor2Url)
+ // Forward: 0
+ ie_mock_.ExpectInPageNavigation(in_cf, GetAnchorPageUrl(3));
+ EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(GetAnchorPageUrl(3))))
+ .WillOnce(testing::DoAll(
+ VerifyAddressBarUrl(&ie_mock_),
+ DelayGoBack(&ie_mock_, &loop_, 0)));
+
+ // We will reach anchor 2 once the navigation is complete,
+ // then go back to anchor 1
+ // Back/Forward state at this point:
+ // Back: 3 (kAnchorUrl, kAnchor1Url, kAnchor2Url)
+ // Forward: 1 (kAnchor3Url)
+ ie_mock_.ExpectNavigation(in_cf, GetAnchorPageUrl(2));
+ EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(GetAnchorPageUrl(2))))
+ .WillOnce(testing::DoAll(
+ VerifyAddressBarUrl(&ie_mock_),
+ DelayGoBack(&ie_mock_, &loop_, 0)));
+
+ // We will reach anchor 1 once the navigation is complete,
+ // now go forward to anchor 2
+ // Back/Forward state at this point:
+ // Back: 2 (kAnchorUrl, kAnchor1Url)
+ // Forward: 2 (kAnchor2Url, kAnchor3Url)
+ ie_mock_.ExpectNavigation(in_cf, GetAnchorPageUrl(1));
+ EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(GetAnchorPageUrl(1))))
+ .WillOnce(testing::DoAll(
+ VerifyAddressBarUrl(&ie_mock_),
+ DelayGoForward(&ie_mock_, &loop_, 0)));
+
+ // We have reached anchor 2, go forward to anchor 3 again
+ // Back/Forward state at this point:
+ // Back: 3 (kAnchorUrl, kAnchor1Url, kAnchor2Url)
+ // Forward: 1 (kAnchor3Url)
+ ie_mock_.ExpectNavigation(in_cf, GetAnchorPageUrl(2));
+ EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(GetAnchorPageUrl(2))))
+ .WillOnce(testing::DoAll(
+ VerifyAddressBarUrl(&ie_mock_),
+ DelayGoForward(&ie_mock_, &loop_, 0)));
+
+ // We have gone a few steps back and forward, this should be enough for now.
+ ie_mock_.ExpectNavigation(in_cf, GetAnchorPageUrl(3));
+ EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(GetAnchorPageUrl(3))))
+ .WillOnce(CloseBrowserMock(&ie_mock_));
+
+ LaunchIEAndNavigate(GetAnchorPageUrl(0));
+}
+
+// Test that a user cannot navigate to a restricted site and that the security
+// dialog appears.
+TEST_P(FullTabNavigationTest, FLAKY_RestrictedSite) {
+ if (!GetParam().invokes_cf() || GetInstalledIEVersion() == IE_8) {
+ // Test has been disabled on IE8 bot because it hangs at times.
+ // http://crbug.com/47596
+ LOG(ERROR) << "Test disabled for this configuration.";
+ return;
+ }
+ if (IsIBrowserServicePatchEnabled()) {
+ LOG(ERROR) << "Not running test. IBrowserServicePatch is in place.";
+ return;
+ }
+ MockWindowObserver win_observer_mock;
+ ScopedComPtr<IInternetSecurityManager> security_manager;
+ HRESULT hr = security_manager.CreateInstance(CLSID_InternetSecurityManager);
+ ASSERT_HRESULT_SUCCEEDED(hr);
+ // Add the server to restricted sites zone.
+ hr = security_manager->SetZoneMapping(URLZONE_UNTRUSTED,
+ GetTestUrl(L"").c_str(), SZM_CREATE);
+
+ EXPECT_CALL(ie_mock_, OnFileDownload(_, _))
+ .Times(testing::AnyNumber());
+ server_mock_.ExpectAndServeAnyRequests(GetParam());
+
+ ProtocolPatchMethod patch_method = GetPatchMethod();
+
+ const wchar_t* kDialogClass = L"#32770";
+ const char* kAlertDlgCaption = "Security Alert";
+
+ EXPECT_CALL(ie_mock_, OnBeforeNavigate2(_,
+ testing::Field(&VARIANT::bstrVal,
+ testing::StrCaseEq(GetSimplePageUrl())), _, _, _, _, _))
+ .Times(1)
+ .WillOnce(WatchWindow(&win_observer_mock, kDialogClass));
+
+ if (patch_method == PATCH_METHOD_INET_PROTOCOL) {
+ EXPECT_CALL(ie_mock_, OnBeforeNavigate2(_,
+ testing::Field(&VARIANT::bstrVal,
+ testing::HasSubstr(L"res://")), _, _, _, _, _))
+ .Times(testing::AtMost(1));
+ }
+
+ EXPECT_CALL(ie_mock_, OnNavigateComplete2(_,
+ testing::Field(&VARIANT::bstrVal, StrEq(GetSimplePageUrl()))))
+ .Times(testing::AtMost(1));
+
+ EXPECT_CALL(win_observer_mock, OnWindowDetected(_, StrEq(kAlertDlgCaption)))
+ .Times(1)
+ .WillOnce(testing::DoAll(
+ DoCloseWindow(),
+ CloseBrowserMock(&ie_mock_)));
+
+ LaunchIEAndNavigate(GetSimplePageUrl());
+
+ ASSERT_HRESULT_SUCCEEDED(security_manager->SetZoneMapping(URLZONE_UNTRUSTED,
+ GetTestUrl(L"").c_str(), SZM_DELETE));
+}
+
+// This test checks if window.open calls with target blank issued for a
+// different domain make it back to IE instead of completing the navigation
+// within Chrome. We validate this by initiating a navigation to a non existent
+// url which ensures we would get an error during navigation.
+// Marking this disabled as it leaves behind Chrome processes, at least on
+// IE 6 XP (http://crbug.com/48732).
+TEST_P(FullTabNavigationTest, DISABLED_JavascriptWindowOpenDifferentDomain) {
+ if (!GetParam().invokes_cf() || GetInstalledIEVersion() == IE_7) {
+ LOG(ERROR) << "Test disabled for this configuration.";
+ return;
+ }
+ std::wstring parent_url =
+ GetTestUrl(L"window_open.html?http://www.nonexistent.com");
+ MockIEEventSink new_window_mock;
+ ie_mock_.ExpectAnyNavigations();
+ new_window_mock.ExpectAnyNavigations();
+ server_mock_.ExpectAndServeAnyRequests(GetParam());
+
+ EXPECT_CALL(ie_mock_, OnLoad(GetParam().invokes_cf(), StrEq(parent_url)))
+ .WillOnce(DelaySendDoubleClick(&ie_mock_, &loop_, 0, 10, 10));
+
+ ie_mock_.ExpectNewWindow(&new_window_mock);
+
+ EXPECT_CALL(new_window_mock, OnNavigateError(_, _, _, _, _))
+ .Times(1)
+ .WillOnce(CloseBrowserMock(&new_window_mock));
+
+ EXPECT_CALL(new_window_mock, OnLoad(_, _))
+ .Times(testing::AtMost(1));
+
+ EXPECT_CALL(new_window_mock, OnQuit())
+ .Times(1)
+ .WillOnce(CloseBrowserMock(&ie_mock_));
+
+ // OnNavigateError can take a long time to fire.
+ LaunchIENavigateAndLoop(parent_url,
+ kChromeFrameLongNavigationTimeoutInSeconds * 4);
+ ASSERT_TRUE(new_window_mock.event_sink()->web_browser2() != NULL);
+}
+
+// Tests that a page that calls window.open can then close the popup.
+// Marking this test as FLAKY initially as it relies on getting focus and user
+// input which don't work correctly at times.
+// http://code.google.com/p/chromium/issues/detail?id=26549
+TEST_P(FullTabNavigationTest, FLAKY_JavascriptWindowOpenCanClose) {
+ std::wstring parent_url =
+ GetTestUrl(L"window_open.html?simple.html");
+ MockIEEventSink new_window_mock;
+ ie_mock_.ExpectAnyNavigations();
+ new_window_mock.ExpectAnyNavigations();
+ server_mock_.ExpectAndServeAnyRequests(GetParam());
+
+ // Sending 'A' to the renderer should cause window.open then window.close.
+ EXPECT_CALL(ie_mock_, OnLoad(GetParam().invokes_cf(), StrEq(parent_url)))
+ .WillOnce(DelaySendDoubleClick(&ie_mock_, &loop_, 0, 10, 10));
+
+ ie_mock_.ExpectNewWindow(&new_window_mock);
+
+ EXPECT_CALL(new_window_mock, OnLoad(_, StrEq(GetSimplePageUrl())))
+ .Times(testing::AtMost(2))
+ .WillOnce(testing::DoAll(
+ SetFocusToRenderer(&ie_mock_),
+ DelaySendChar(&loop_, 500, 'C', simulate_input::NONE)))
+ .WillOnce(testing::Return()); // just to stop a gmock warning
+
+ EXPECT_CALL(new_window_mock, OnQuit())
+ .WillOnce(CloseBrowserMock(&ie_mock_));
+
+ LaunchIEAndNavigate(parent_url);
+}
+
+// Parameter for tests using the NavigationTransitionTest fixture. Includes two
+// pages, each with their own possible CF invocation.
+struct NavigationTransitionTestParameter {
+ NavigationTransitionTestParameter(CFInvocation::Type type1,
+ CFInvocation::Type type2) {
+ page1_ = CFInvocation(type1);
+ page2_ = CFInvocation(type2);
+ }
+ CFInvocation page1_;
+ CFInvocation page2_;
+};
+
+// Parameterized test fixture for tests which test navigation transitions
+// between two pages.
+class NavigationTransitionTest
+ : public MockIEEventSinkTest,
+ public testing::TestWithParam<NavigationTransitionTestParameter> {
+ public:
+ NavigationTransitionTest() {}
+
+ virtual void SetUp() {
+ page1_ = GetParam().page1_;
+ page2_ = GetParam().page2_;
+ }
+
+ protected:
+ CFInvocation page1_;
+ CFInvocation page2_;
+};
+
+// This instantiates each parameterized test with some of the different CF
+// invocation methods.
+// TODO(kkania): Do not allow these tests to be cache the pages. This is used
+// currently because otherwise the meta tags can cause double requests. Change
+// ExpectAndServeRequestAllowCache to ExpectAndServeRequest when allowed.
+INSTANTIATE_TEST_CASE_P(
+ IEToIE,
+ NavigationTransitionTest,
+ testing::Values(NavigationTransitionTestParameter(
+ CFInvocation::NONE, CFInvocation::NONE)));
+INSTANTIATE_TEST_CASE_P(
+ IEToMetaTag,
+ NavigationTransitionTest,
+ testing::Values(NavigationTransitionTestParameter(
+ CFInvocation::NONE, CFInvocation::META_TAG)));
+INSTANTIATE_TEST_CASE_P(
+ IEToHttpHeader,
+ NavigationTransitionTest,
+ testing::Values(NavigationTransitionTestParameter(
+ CFInvocation::NONE, CFInvocation::HTTP_HEADER)));
+INSTANTIATE_TEST_CASE_P(
+ CFToCF,
+ NavigationTransitionTest,
+ testing::Values(NavigationTransitionTestParameter(
+ CFInvocation::META_TAG, CFInvocation::META_TAG)));
+INSTANTIATE_TEST_CASE_P(
+ CFToIE,
+ NavigationTransitionTest,
+ testing::Values(NavigationTransitionTestParameter(
+ CFInvocation::META_TAG, CFInvocation::NONE)));
+
+// Test window.open calls.
+// Marking this test as FLAKY initially as it relies on getting focus and user
+// input which don't work correctly at times.
+// http://code.google.com/p/chromium/issues/detail?id=26549
+TEST_P(NavigationTransitionTest, FLAKY_JavascriptWindowOpen) {
+ std::wstring parent_url = GetTestUrl(L"window_open.html?simple.html");
+ std::wstring new_window_url = GetSimplePageUrl();
+ testing::StrictMock<MockIEEventSink> new_window_mock;
+
+ ie_mock_.ExpectNavigation(page1_.invokes_cf(), parent_url);
+ server_mock_.ExpectAndServeRequestAllowCache(page1_, parent_url);
+ EXPECT_CALL(ie_mock_, OnLoad(page1_.invokes_cf(), StrEq(parent_url)))
+ .WillOnce(DelaySendDoubleClick(&ie_mock_, &loop_, 0, 10, 10));
+
+ // If the parent window is in CF, the child will load in CF regardless of
+ // whether the child page invokes CF.
+ bool expect_cf = page1_.invokes_cf() || page2_.invokes_cf();
+ ie_mock_.ExpectNewWindow(&new_window_mock);
+ new_window_mock.ExpectJavascriptWindowOpenNavigation(page1_.invokes_cf(),
+ expect_cf,
+ new_window_url);
+ EXPECT_CALL(server_mock_, Get(_, UrlPathEq(new_window_url), _))
+ .Times(testing::AtMost(1))
+ .WillOnce(SendAllowCacheResponse(&server_mock_, page2_));
+ EXPECT_CALL(new_window_mock, OnLoad(expect_cf, StrEq(new_window_url)))
+ .WillOnce(testing::DoAll(
+ ValidateWindowSize(&new_window_mock, 10, 10, 250, 250),
+ CloseBrowserMock(&new_window_mock)));
+
+ EXPECT_CALL(new_window_mock, OnQuit())
+ .WillOnce(CloseBrowserMock(&ie_mock_));
+
+ LaunchIENavigateAndLoop(parent_url,
+ kChromeFrameLongNavigationTimeoutInSeconds * 2);
+}
+
+// Test redirection with window.location in Javascript.
+// Disabled because crashes IE occasionally: http://crbug.com/48849.
+TEST_P(NavigationTransitionTest, DISABLED_JavascriptRedirection) {
+ std::wstring redirect_url = GetTestUrl(L"javascript_redirect.html");
+
+ ie_mock_.ExpectNavigation(page1_.invokes_cf(), redirect_url);
+ server_mock_.ExpectAndServeRequestAllowCache(page1_, redirect_url);
+ EXPECT_CALL(ie_mock_, OnLoad(page1_.invokes_cf(), StrEq(redirect_url)))
+ .WillOnce(VerifyAddressBarUrl(&ie_mock_));
+
+ ie_mock_.ExpectNavigation(page2_.invokes_cf(), GetSimplePageUrl());
+ server_mock_.ExpectAndServeRequestAllowCache(page2_, GetSimplePageUrl());
+ EXPECT_CALL(ie_mock_, OnLoad(page2_.invokes_cf(), StrEq(GetSimplePageUrl())))
+ .WillOnce(testing::DoAll(
+ VerifyAddressBarUrl(&ie_mock_),
+ CloseBrowserMock(&ie_mock_)));
+
+ LaunchIEAndNavigate(redirect_url);
+}
+
+// Test following a link by TAB + ENTER.
+TEST_P(NavigationTransitionTest, FLAKY_FollowLink) {
+ if (page1_.invokes_cf() && page2_.invokes_cf() &&
+ GetInstalledIEVersion() > IE_6) {
+ // For some reason IE 7 and 8 send two BeforeNavigate events for the second
+ // page for this case.
+ LOG(ERROR) << "Test disabled for this configuration.";
+ return;
+ }
+ ie_mock_.ExpectNavigation(page1_.invokes_cf(), GetLinkPageUrl());
+ server_mock_.ExpectAndServeRequestAllowCache(page1_, GetLinkPageUrl());
+ EXPECT_CALL(ie_mock_, OnLoad(page1_.invokes_cf(), StrEq(GetLinkPageUrl())))
+ .WillOnce(testing::DoAll(
+ SetFocusToRenderer(&ie_mock_),
+ DelaySendChar(&loop_, 500, VK_TAB, simulate_input::NONE),
+ DelaySendChar(&loop_, 1000, VK_RETURN, simulate_input::NONE)));
+
+ ie_mock_.ExpectNavigation(page2_.invokes_cf(), GetSimplePageUrl());
+ server_mock_.ExpectAndServeRequestAllowCache(page2_, GetSimplePageUrl());
+ EXPECT_CALL(ie_mock_, OnLoad(page2_.invokes_cf(), StrEq(GetSimplePageUrl())))
+ .WillOnce(testing::DoAll(
+ VerifyAddressBarUrl(&ie_mock_),
+ CloseBrowserMock(&ie_mock_)));
+
+ LaunchIEAndNavigate(GetLinkPageUrl());
+}
+
+// Basic navigation test fixture which uses the MockIEEventSink. These tests
+// are not parameterized.
+class NavigationTest : public MockIEEventSinkTest, public testing::Test {
+ public:
+ NavigationTest() {}
+};
+
+// gMock matcher which tests if a url is blank.
+MATCHER(BlankUrl, "is \"\" or NULL") {
+ return arg == NULL || wcslen(arg) == 0;
+}
+
+// Test navigation to a disallowed url.
+TEST_F(NavigationTest, DisallowedUrl) {
+ // If a navigation fails then IE issues a navigation to an interstitial
+ // page. Catch this to track navigation errors as the NavigateError
+ // notification does not seem to fire reliably.
+ const wchar_t disallowed_url[] = L"gcf:file:///C:/";
+
+ EXPECT_CALL(ie_mock_, OnBeforeNavigate2(_, testing::Field(&VARIANT::bstrVal,
+ StrEq(disallowed_url)),
+ _, _, _, _, _));
+ EXPECT_CALL(ie_mock_, OnLoad(IN_IE, BlankUrl()))
+ .Times(testing::AtMost(1));
+ EXPECT_CALL(ie_mock_, OnBeforeNavigate2(_, testing::Field(&VARIANT::bstrVal,
+ testing::StartsWith(L"res:")),
+ _, _, _, _, _));
+ EXPECT_CALL(ie_mock_, OnFileDownload(VARIANT_TRUE, _))
+ .Times(testing::AnyNumber())
+ .WillRepeatedly(testing::Return());
+ EXPECT_CALL(ie_mock_, OnNavigateComplete2(_, testing::Field(&VARIANT::bstrVal,
+ StrEq(disallowed_url))));
+ // Although we expect a load event for this, we should never receive a
+ // corresponding GET request.
+ EXPECT_CALL(ie_mock_, OnLoad(IN_IE, StrEq(disallowed_url)))
+ .WillOnce(CloseBrowserMock(&ie_mock_));
+
+ LaunchIEAndNavigate(disallowed_url);
+}
+
+// NOTE: This test is currently disabled as we haven't finished implementing
+// support for this yet. The test (as written) works fine for IE. CF might
+// have a different set of requirements once we fully support this and hence
+// the test might need some refining before being enabled.
+TEST_F(NavigationTest, DISABLED_DownloadInNewWindow) {
+ MockIEEventSink new_window_mock;
+ std::wstring kDownloadFromNewWin =
+ GetTestUrl(L"full_tab_download_from_new_window.html");
+
+ ie_mock_.ExpectNavigation(IN_CF, kDownloadFromNewWin);
+
+ EXPECT_CALL(ie_mock_, OnNewWindow3(_, _, _, _, _));
+
+ EXPECT_CALL(ie_mock_, OnNewBrowserWindow(_, _))
+ .WillOnce(testing::WithArgs<0>(testing::Invoke(testing::CreateFunctor(
+ &new_window_mock, &MockIEEventSink::Attach))));
+ EXPECT_CALL(new_window_mock, OnBeforeNavigate2(_, _, _, _, _, _, _));
+
+ EXPECT_CALL(new_window_mock, OnFileDownload(VARIANT_FALSE, _))
+ .Times(2)
+ .WillRepeatedly(CloseBrowserMock(&new_window_mock));
+
+ EXPECT_CALL(new_window_mock, OnNavigateComplete2(_, _));
+
+ EXPECT_CALL(new_window_mock, OnQuit()).WillOnce(CloseBrowserMock(&ie_mock_));
+
+ LaunchIEAndNavigate(kDownloadFromNewWin);
+}
+
+} // namespace chrome_frame_test \ No newline at end of file
diff --git a/chrome_frame/test/no_interference_test.cc b/chrome_frame/test/no_interference_test.cc
deleted file mode 100644
index 7b0ed39..0000000
--- a/chrome_frame/test/no_interference_test.cc
+++ /dev/null
@@ -1,269 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome_frame/test/test_mock_with_web_server.h"
-
-#include "base/scoped_variant_win.h"
-#include "base/utf_string_conversions.h"
-#include "chrome_frame/test/simulate_input.h"
-#include "chrome_frame/test/test_with_web_server.h"
-
-using chrome_frame_test::CloseIeAtEndOfScope;
-using chrome_frame_test::ComStackObjectWithUninitialize;
-using chrome_frame_test::kChromeFrameLongNavigationTimeoutInSeconds;
-using testing::_;
-
-namespace {
-
-// The same as MockWebBrowserEventSink, except OnDocumentComplete is added.
-// This class can be merged with its base class, but it would require some
-// modification to most of the test cases.
-class MockWebBrowserEventSink
- : public chrome_frame_test::MockWebBrowserEventSink {
- public:
- // This method is called for each OnDocumentComplete event in which the
- // document is rendered by IE and not CF.
- MOCK_METHOD1(OnIELoad, void (const wchar_t* url)); // NOLINT
-
- // The OnDocumentComplete event is received for every document load,
- // regardless of whether IE or CF is hosting. This method will call
- // OnIELoad iff the document was loaded in an IE renderer.
- STDMETHOD_(void, OnDocumentComplete)(IDispatch* dispatch,
- VARIANT* url_variant) {
- ScopedVariant url;
- if (url_variant)
- url.Reset(*url_variant);
- // To determine if the document is loaded in IE or CF, check if
- // IHTMLDocument2 can be retrieved. If so, call OnIELoad.
- ScopedComPtr<IWebBrowser2> web_browser2;
- web_browser2.QueryFrom(dispatch);
- EXPECT_TRUE(web_browser2);
- if (web_browser2) {
- ScopedComPtr<IDispatch> doc_dispatch;
- HRESULT hr = web_browser2->get_Document(doc_dispatch.Receive());
- EXPECT_HRESULT_SUCCEEDED(hr);
- EXPECT_TRUE(doc_dispatch);
- if (doc_dispatch) {
- ScopedComPtr<IHTMLDocument2> doc;
- doc.QueryFrom(doc_dispatch);
- if (doc) {
- OnIELoad(V_BSTR(&url));
- }
- }
- }
- }
-};
-
-// Fixture for tests which ensure that Chrome Frame does not interfere with
-// normal IE operation.
-// TODO(kkania): Move this fixture to test_mock_with_web_server.h and change
-// those tests to use this too.
-class NoInterferenceTest : public ChromeFrameTestWithWebServer {
- protected:
- // Launches IE and navigates to |url|, then waits until receiving a quit
- // message or the timeout is exceeded.
- void LaunchIEAndNavigate(const std::wstring& url) {
- EXPECT_CALL(mock_, OnQuit())
- .Times(testing::AtMost(1))
- .WillOnce(QUIT_LOOP(loop_));
- HRESULT hr = mock_.LaunchIEAndNavigate(url);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock_.web_browser2() != NULL);
- loop_.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
- mock_.Uninitialize();
- }
-
- const std::wstring GetTestUrl(const wchar_t* relative_path) {
- std::wstring path = std::wstring(L"files/no_interference/") +
- relative_path;
- return UTF8ToWide(server_.Resolve(path.c_str()).spec());
- }
-
- const std::wstring empty_page_url() {
- return GetTestUrl(L"empty.html");
- }
-
- // Returns the url for a page with a single link, which points to the
- // empty page.
- const std::wstring link_page_url() {
- return GetTestUrl(L"link.html");
- }
-
- CloseIeAtEndOfScope last_resort_close_ie;
- chrome_frame_test::TimedMsgLoop loop_;
- CComObjectStackEx<testing::StrictMock<MockWebBrowserEventSink> > mock_;
-};
-
-ACTION_P(ExpectIERendererWindowHasFocus, mock) {
- mock->ExpectIERendererWindowHasFocus();
-}
-
-ACTION_P6(DelaySendMouseClickToIE, mock, loop, delay, x, y, button) {
- loop->PostDelayedTask(FROM_HERE, NewRunnableMethod(mock,
- &MockWebBrowserEventSink::SendMouseClickToIE, x, y, button), delay);
-}
-
-ACTION_P2(OpenContextMenu, loop, delay) {
- loop->PostDelayedTask(FROM_HERE, NewRunnableFunction(
- simulate_input::SendScanCode, VK_F10, simulate_input::SHIFT), delay);
-}
-
-ACTION_P3(SelectItem, loop, delay, index) {
- chrome_frame_test::DelaySendExtendedKeysEnter(loop, delay, VK_DOWN, index + 1,
- simulate_input::NONE);
-}
-
-// A new IE renderer window should have focus.
-TEST_F(NoInterferenceTest, FLAKY_SimpleFocus) {
- mock_.ExpectNavigationInIE(empty_page_url());
- EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(empty_page_url())))
- .WillOnce(testing::DoAll(
- ExpectIERendererWindowHasFocus(&mock_),
- VerifyAddressBarUrl(&mock_),
- CloseBrowserMock(&mock_)));
-
- LaunchIEAndNavigate(empty_page_url());
-}
-
-// Javascript window.open should open a new window with an IE renderer.
-TEST_F(NoInterferenceTest, FLAKY_JavascriptWindowOpen) {
- const std::wstring kWindowOpenUrl = GetTestUrl(L"window_open.html");
- ComStackObjectWithUninitialize<
- testing::StrictMock<MockWebBrowserEventSink> > new_window_mock;
-
- mock_.ExpectNavigationInIE(kWindowOpenUrl);
- EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(kWindowOpenUrl)))
- .WillOnce(testing::DoAll(
- DelaySendMouseClickToIE(&mock_, &loop_, 0, 100, 100,
- simulate_input::LEFT),
- DelaySendMouseClickToIE(&mock_, &loop_, 0, 100, 100,
- simulate_input::LEFT)));
-
- EXPECT_CALL(mock_, OnNewWindow3(_, _, _, _, _));
-
- EXPECT_CALL(mock_, OnNewBrowserWindow(_, _))
- .WillOnce(testing::WithArgs<0>(testing::Invoke(CreateFunctor(
- &new_window_mock, &MockWebBrowserEventSink::Attach))));
-
- EXPECT_CALL(new_window_mock, OnBeforeNavigate2(_,
- testing::Field(&VARIANT::bstrVal,
- testing::StrCaseEq(empty_page_url())),
- _, _, _, _, _));
-
- EXPECT_CALL(new_window_mock, OnFileDownload(VARIANT_TRUE, _))
- .Times(testing::AnyNumber());
-
- EXPECT_CALL(new_window_mock, OnNavigateComplete2(_,
- testing::Field(&VARIANT::bstrVal,
- testing::StrCaseEq(empty_page_url()))))
- .WillOnce(testing::DoAll(
- testing::InvokeWithoutArgs(CreateFunctor(&new_window_mock,
- &chrome_frame_test::MockWebBrowserEventSink::ExpectAddressBarUrl,
- empty_page_url())),
- DelayCloseBrowserMock(&loop_, 2000, &new_window_mock)));
-
- // The DocumentComplete at times fires twice for new windows. Hack to account
- // for that.
- EXPECT_CALL(new_window_mock,
- OnIELoad(testing::StrCaseEq(empty_page_url())))
- .Times(testing::AtMost(2));
-
- EXPECT_CALL(new_window_mock, OnQuit())
- .WillOnce(DelayCloseBrowserMock(&loop_, 2000, &mock_));
-
- LaunchIEAndNavigate(kWindowOpenUrl);
-}
-
-// Redirecting with window.location in Javascript should work.
-TEST_F(NoInterferenceTest, JavascriptRedirect) {
- const std::wstring kRedirectUrl = GetTestUrl(L"javascript_redirect.html");
- mock_.ExpectNavigationInIE(kRedirectUrl);
- EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(kRedirectUrl)))
- .WillOnce(VerifyAddressBarUrl(&mock_));
-
- mock_.ExpectNavigationInIE(empty_page_url());
- EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(empty_page_url())))
- .WillOnce(testing::DoAll(
- VerifyAddressBarUrl(&mock_),
- CloseBrowserMock(&mock_)));
-
- LaunchIEAndNavigate(kRedirectUrl);
-}
-
-TEST_F(NoInterferenceTest, FLAKY_FollowLink) {
- mock_.ExpectNavigationInIE(link_page_url());
- EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(link_page_url())))
- .WillOnce(testing::DoAll(
- DelaySendMouseClickToIE(&mock_, &loop_, 0, 1, 1,
- simulate_input::LEFT),
- DelaySendScanCode(&loop_, 500, VK_TAB, simulate_input::NONE),
- DelaySendScanCode(&loop_, 1000, VK_RETURN, simulate_input::NONE)));
-
- mock_.ExpectNavigationInIE(empty_page_url());
- EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(empty_page_url())))
- .WillOnce(testing::DoAll(
- VerifyAddressBarUrl(&mock_),
- CloseBrowserMock(&mock_)));
-
- LaunchIEAndNavigate(link_page_url());
-}
-
-TEST_F(NoInterferenceTest, FLAKY_SelectContextMenuOpen) {
- mock_.ExpectNavigationInIE(link_page_url());
- // Focus the renderer window by clicking and then tab once to highlight the
- // link.
- EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(link_page_url())))
- .WillOnce(testing::DoAll(
- DelaySendMouseClickToIE(&mock_, &loop_, 0, 1, 1,
- simulate_input::LEFT),
- DelaySendScanCode(&loop_, 500, VK_TAB, simulate_input::NONE),
- OpenContextMenu(&loop_, 1000),
- SelectItem(&loop_, 1500, 0)));
-
- mock_.ExpectNavigationInIE(empty_page_url());
- EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(empty_page_url())))
- .WillOnce(testing::DoAll(
- VerifyAddressBarUrl(&mock_),
- CloseBrowserMock(&mock_)));
-
- LaunchIEAndNavigate(link_page_url());
-}
-
-TEST_F(NoInterferenceTest, FLAKY_SelectContextMenuOpenInNewWindow) {
- ComStackObjectWithUninitialize<
- testing::StrictMock<MockWebBrowserEventSink> > new_window_mock;
- int open_new_window_index = 2;
- if (chrome_frame_test::GetInstalledIEVersion() == IE_6)
- open_new_window_index = 1;
-
- // Focus the renderer window by clicking and then tab once to highlight the
- // link.
- mock_.ExpectNavigationInIE(link_page_url());
- EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(link_page_url())))
- .WillOnce(testing::DoAll(
- DelaySendMouseClickToIE(&mock_, &loop_, 0, 1, 1,
- simulate_input::LEFT),
- DelaySendScanCode(&loop_, 500, VK_TAB, simulate_input::NONE),
- OpenContextMenu(&loop_, 1000),
- SelectItem(&loop_, 1500, open_new_window_index)));
-
- mock_.ExpectNewWindowWithIE(empty_page_url(), &new_window_mock);
- // The DocumentComplete at times fires twice for new windows. Hack to account
- // for that.
- // TODO(kkania): Verifying the address bar is flaky with this, at least
- // on XP ie6. Fix.
- EXPECT_CALL(new_window_mock,
- OnIELoad(testing::StrCaseEq(empty_page_url())))
- .Times(testing::AtMost(2))
- .WillOnce(DelayCloseBrowserMock(&loop_, 2000, &new_window_mock));
-
- EXPECT_CALL(new_window_mock, OnQuit()).WillOnce(CloseBrowserMock(&mock_));
-
- LaunchIEAndNavigate(link_page_url());
-}
-
-} // namespace
diff --git a/chrome_frame/test/simulate_input.cc b/chrome_frame/test/simulate_input.cc
index 68d8edc..583bc56 100644
--- a/chrome_frame/test/simulate_input.cc
+++ b/chrome_frame/test/simulate_input.cc
@@ -244,21 +244,17 @@ void SendExtendedKey(WORD key, Modifier modifiers) {
SendMnemonic(key, modifiers, true, false);
}
-void SendStringW(const wchar_t* s) {
- while (*s) {
- wchar_t ch = *s;
- SendCharW(ch, NONE);
+void SendStringW(const std::wstring& s) {
+ for (size_t i = 0; i < s.length(); i++) {
+ SendCharW(s[i], NONE);
Sleep(10);
- s++;
}
}
-void SendStringA(const char* s) {
- while (*s) {
- char ch = *s;
- SendCharA(ch, NONE);
+void SendStringA(const std::string& s) {
+ for (size_t i = 0; i < s.length(); i++) {
+ SendCharA(s[i], NONE);
Sleep(10);
- s++;
}
}
diff --git a/chrome_frame/test/simulate_input.h b/chrome_frame/test/simulate_input.h
index fab22a8..112848b 100644
--- a/chrome_frame/test/simulate_input.h
+++ b/chrome_frame/test/simulate_input.h
@@ -6,6 +6,7 @@
#define CHROME_FRAME_TEST_SIMULATE_INPUT_H_
#include <windows.h>
+#include <string>
#include "base/basictypes.h"
#include "base/process_util.h"
@@ -55,8 +56,8 @@ void SendExtendedKey(WORD key, Modifier modifiers);
// Iterates through all the characters in the string and simulates
// keyboard input. The input goes to the currently active application.
-void SendStringW(const wchar_t* s);
-void SendStringA(const char* s);
+void SendStringW(const std::wstring& s);
+void SendStringA(const std::string& s);
} // end namespace simulate_input
diff --git a/chrome_frame/test/test_mock_with_web_server.cc b/chrome_frame/test/test_mock_with_web_server.cc
deleted file mode 100644
index fbadb54..0000000
--- a/chrome_frame/test/test_mock_with_web_server.cc
+++ /dev/null
@@ -1,1635 +0,0 @@
-// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-#include "chrome_frame/test/test_mock_with_web_server.h"
-
-#include <mshtmcid.h>
-
-#include "base/scoped_bstr_win.h"
-#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
-#include "testing/gmock_mutant.h"
-
-using testing::_;
-using testing::CreateFunctor;
-using chrome_frame_test::CloseIeAtEndOfScope;
-using chrome_frame_test::ComStackObjectWithUninitialize;
-using chrome_frame_test::kChromeFrameLongNavigationTimeoutInSeconds;
-using chrome_frame_test::MockWebBrowserEventSink;
-
-const wchar_t kChromeFrameFileUrl[] = L"gcf:file:///C:/";
-const wchar_t enter_key[] = { VK_RETURN, 0 };
-const wchar_t escape_key[] = { VK_ESCAPE, 0 };
-const wchar_t tab_enter_keys[] = { VK_TAB, VK_RETURN, 0 };
-
-namespace chrome_frame_test {
-
-ExpectationSet MockWebBrowserEventSink::ExpectNavigationCardinality(
- const std::wstring& url, testing::Cardinality cardinality) {
- // Expect a single navigation sequence. If URL is specified,
- // match the URL.
- // The navigation sequence is a set of OnBeforeNavigate2, OnFileDownload
- // and OnNavigationComplete2 events. For certain navigations, internal
- // vs external (and maybe between different IE versions) these events
- // events occur with different frequencies. Hence, the variable
- // cardinality.
- ExpectationSet navigation;
- if (url.empty()) {
- navigation += EXPECT_CALL(*this, OnBeforeNavigate2(_, _, _, _, _, _, _))
- .Times(cardinality);
- } else {
- navigation += EXPECT_CALL(*this, OnBeforeNavigate2(_,
- testing::Field(&VARIANT::bstrVal,
- testing::StrCaseEq(url)), _, _, _, _, _))
- .Times(cardinality);
- }
- navigation += EXPECT_CALL(*this, OnFileDownload(VARIANT_TRUE, _))
- .Times(cardinality);
-
- if (url.empty()) {
- navigation += EXPECT_CALL(*this, OnNavigateComplete2(_, _))
- .Times(cardinality);
- } else {
- navigation += EXPECT_CALL(*this, OnNavigateComplete2(_,
- testing::Field(&VARIANT::bstrVal,
- testing::StrCaseEq(url))))
- .Times(cardinality);
- }
-
- return navigation;
-}
-
-ExpectationSet MockWebBrowserEventSink::ExpectNavigation(
- const std::wstring& url) {
- // When the onhttpequiv patch is enabled, we will get two
- // BeforeNavigate2/OnNavigateComplete2 notifications due to
- // switching from IE to CF.
- // Note that when going backwards, we don't expect that since the extra
- // navigational entries in the travel log should have been removed.
- ExpectationSet navigation;
- navigation += EXPECT_CALL(*this, OnBeforeNavigate2(_,
- testing::Field(&VARIANT::bstrVal,
- testing::StrCaseEq(url)), _, _, _, _, _));
- navigation += EXPECT_CALL(*this, OnFileDownload(VARIANT_TRUE, _))
- .Times(testing::AnyNumber());
- navigation += EXPECT_CALL(*this, OnNavigateComplete2(_,
- testing::Field(&VARIANT::bstrVal,
- testing::StrCaseEq(url))))
- .Times(testing::AnyNumber());
-
- return navigation;
-}
-
-ExpectationSet MockWebBrowserEventSink::ExpectNavigationSequenceForAnchors(
- const std::wstring& url) {
- // When the onhttpequiv patch is enabled, we will get two
- // BeforeNavigate2/OnNavigateComplete2 notifications due to
- // switching from IE to CF.
- // Note that when going backwards, we don't expect that since the extra
- // navigational entries in the travel log should have been removed.
- // On IE6 we don't receive the BeforeNavigate notifications for anchors.
- ExpectationSet navigation;
- navigation += EXPECT_CALL(*this, OnBeforeNavigate2(_,
- testing::Field(&VARIANT::bstrVal,
- testing::StrCaseEq(url)), _, _, _, _, _))
- .Times(testing::AnyNumber());
- navigation += EXPECT_CALL(*this, OnFileDownload(VARIANT_TRUE, _))
- .Times(testing::AnyNumber());
- navigation += EXPECT_CALL(*this, OnNavigateComplete2(_,
- testing::Field(&VARIANT::bstrVal,
- testing::StrCaseEq(url))))
- .Times(testing::AnyNumber());
-
- return navigation;
-}
-
-ExpectationSet MockWebBrowserEventSink::ExpectNavigationAndSwitch(
- const std::wstring& url) {
- return ExpectNavigationCardinality(url, testing::AnyNumber());
-}
-
-ExpectationSet MockWebBrowserEventSink::ExpectNavigationAndSwitchSequence(
- const std::wstring& url) {
- // When navigation expectations occur in sequence the following order
- // is necessary. This is mainly based on observed quirks rather than
- // any theory.
- // TODO(joshia): Improve expectations here
- ExpectationSet navigation = ExpectNavigationCardinality(url,
- testing::Exactly(1));
- navigation += EXPECT_CALL(*this, OnBeforeNavigate2(_,
- testing::Field(&VARIANT::bstrVal,
- testing::StrCaseEq(url)), _, _, _, _, _))
- .Times(testing::AnyNumber());
- navigation += EXPECT_CALL(*this, OnFileDownload(VARIANT_TRUE, _))
- .Times(testing::AnyNumber());
- navigation += EXPECT_CALL(*this, OnNavigateComplete2(_,
- testing::Field(&VARIANT::bstrVal,
- testing::StrCaseEq(url))))
- .Times(testing::AnyNumber());
-
- return navigation;
-}
-
-ExpectationSet MockWebBrowserEventSink::ExpectNewWindow(
- MockWebBrowserEventSink* new_window_mock) {
- DCHECK(new_window_mock);
- ExpectationSet new_window;
- new_window += EXPECT_CALL(*this, OnNewWindow3(_, _, _, _, _));
- new_window += EXPECT_CALL(*this, OnNewBrowserWindow(_, _))
- .WillOnce(testing::WithArgs<0>(testing::Invoke(CreateFunctor(
- new_window_mock, &MockWebBrowserEventSink::Attach))));
-
- new_window_mock->ExpectNavigationAndSwitch(std::wstring());
- return new_window;
-}
-
-ExpectationSet MockWebBrowserEventSink::ExpectNavigationInIE(
- const std::wstring& url) {
- testing::InSequence sequence;
- ExpectationSet navigation;
- navigation += EXPECT_CALL(*this, OnBeforeNavigate2(_,
- testing::Field(&VARIANT::bstrVal,
- testing::StrCaseEq(url)), _, _, _, _, _));
- navigation += EXPECT_CALL(*this, OnFileDownload(VARIANT_TRUE, _))
- .Times(testing::AnyNumber());
- navigation += EXPECT_CALL(*this, OnNavigateComplete2(_,
- testing::Field(&VARIANT::bstrVal,
- testing::StrCaseEq(url))));
- return navigation;
-}
-
-ExpectationSet MockWebBrowserEventSink::ExpectNewWindowWithIE(
- const std::wstring& url, MockWebBrowserEventSink* new_window_mock) {
- DCHECK(new_window_mock);
- ExpectationSet new_window;
- new_window += EXPECT_CALL(*this, OnNewWindow3(_, _, _, _, _));
- new_window += EXPECT_CALL(*this, OnNewBrowserWindow(_, _))
- .WillOnce(testing::WithArgs<0>(testing::Invoke(CreateFunctor(
- new_window_mock, &MockWebBrowserEventSink::Attach))));
-
- new_window_mock->ExpectNavigationInIE(url);
- return new_window;
-}
-
-} // namespace chrome_frame_test
-
-ACTION_P(SetFocusToChrome, mock) {
- mock->SetFocusToChrome();
-}
-
-ACTION_P2(Navigate, mock, url) {
- mock->Navigate(url);
-}
-
-ACTION_P2(WatchWindow, mock, window_class) {
- mock->WatchChromeWindow(window_class);
-}
-
-ACTION_P(StopWindowWatching, mock) {
- mock->StopWatching();
-}
-
-ACTION_P6(DelaySendMouseClick, mock, loop, delay, x, y, button) {
- loop->PostDelayedTask(FROM_HERE, NewRunnableMethod(mock,
- &MockWebBrowserEventSink::SendMouseClick, x, y, button), delay);
-}
-
-ACTION_P3(DelaySendString, loop, delay, str) {
- loop->PostDelayedTask(FROM_HERE, NewRunnableFunction(
- simulate_input::SendStringW, str), delay);
-}
-
-ACTION_P5(SendExtendedKeysEnter, loop, delay, c, repeat, mod) {
- chrome_frame_test::DelaySendExtendedKeysEnter(loop, delay, c, repeat, mod);
-}
-
-ACTION(DoCloseWindow) {
- ::PostMessage(arg0, WM_SYSCOMMAND, SC_CLOSE, 0);
-}
-
-// This function selects the address bar via the Alt+d shortcut. This is done
-// via a delayed task which executes after the delay which is passed in.
-// The subsequent operations like typing in the actual url and then hitting
-// enter to force the browser to navigate to it each execute as delayed tasks
-// timed at the delay passed in. The recommended value for delay is 2000 ms
-// to account for the time taken for the accelerator keys to be reflected back
-// from Chrome.
-ACTION_P3(TypeUrlInAddressBar, loop, url, delay) {
- loop->PostDelayedTask(FROM_HERE, NewRunnableFunction(
- simulate_input::SendCharA, 'd', simulate_input::ALT),
- delay);
-
- const unsigned int kInterval = 500;
- int next_delay = delay + kInterval;
-
- loop->PostDelayedTask(FROM_HERE, NewRunnableFunction(
- simulate_input::SendStringW, url), next_delay);
-
- next_delay = next_delay + kInterval;
-
- loop->PostDelayedTask(FROM_HERE, NewRunnableFunction(
- simulate_input::SendCharA, VK_RETURN, simulate_input::NONE),
- next_delay);
-}
-
-ACTION_P(VerifyAddressBarUrlWithGcf, mock) {
- std::wstring expected_url = L"gcf:";
- expected_url += arg0;
- mock->ExpectAddressBarUrl(expected_url);
-}
-
-TEST(ChromeFrameTest, FullTabModeIE_DisallowedUrls) {
- CloseIeAtEndOfScope last_resort_close_ie;
- // If a navigation fails then IE issues a navigation to an interstitial
- // page. Catch this to track navigation errors as the NavigateError
- // notification does not seem to fire reliably.
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- chrome_frame_test::TimedMsgLoop loop;
-
- EXPECT_CALL(mock, OnBeforeNavigate2(_, testing::Field(&VARIANT::bstrVal,
- testing::StrCaseEq(kChromeFrameFileUrl)),
- _, _, _, _, _));
- EXPECT_CALL(mock, OnBeforeNavigate2(_, testing::Field(&VARIANT::bstrVal,
- testing::StartsWith(L"res:")),
- _, _, _, _, _));
- EXPECT_CALL(mock, OnFileDownload(VARIANT_TRUE, _))
- .Times(testing::AnyNumber()).WillRepeatedly(testing::Return());
- EXPECT_CALL(mock, OnNavigateComplete2(_, _))
- .WillOnce(CloseBrowserMock(&mock));
- EXPECT_CALL(mock, OnQuit())
- .Times(testing::AtMost(1)).WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kChromeFrameFileUrl);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock.web_browser2() != NULL);
-
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
-}
-
-const wchar_t kKeyEventUrl[] = L"http://localhost:1337/files/keyevent.html";
-
-// Marking this test FLAKY as it fails at times on the buildbot.
-// http://code.google.com/p/chromium/issues/detail?id=26549
-TEST_F(ChromeFrameTestWithWebServer, FLAKY_FullTabModeIE_KeyboardTest) {
- CloseIeAtEndOfScope last_resort_close_ie;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- chrome_frame_test::TimedMsgLoop loop;
-
- mock.ExpectNavigationAndSwitch(kKeyEventUrl);
-
- const wchar_t* input = L"Chrome";
- EXPECT_CALL(mock, OnLoad(testing::StrEq(kKeyEventUrl)))
- .WillOnce(testing::DoAll(
- DelaySendMouseClick(&mock, &loop, 0, 10, 10, simulate_input::LEFT),
- DelaySendString(&loop, 500, input)));
-
- EXPECT_CALL(mock, OnMessage(testing::StrEq(input), _, _))
- .WillOnce(CloseBrowserMock(&mock));
- EXPECT_CALL(mock, OnQuit())
- .Times(testing::AtMost(1))
- .WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kKeyEventUrl);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
-}
-
-const wchar_t kAboutVersionUrl[] = L"gcf:about:version";
-const wchar_t kAboutVersion[] = L"about:version";
-
-TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_FocusTest) {
- CloseIeAtEndOfScope last_resort_close_ie;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- chrome_frame_test::TimedMsgLoop loop;
-
- mock.ExpectNavigationAndSwitch(kAboutVersionUrl);
-
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kAboutVersion)))
- .WillOnce(testing::DoAll(
- testing::InvokeWithoutArgs(CreateFunctor(&mock,
- &MockWebBrowserEventSink::ExpectRendererWindowHasFocus)),
- VerifyAddressBarUrlWithGcf(&mock),
- CloseBrowserMock(&mock)));
-
- EXPECT_CALL(mock, OnQuit())
- .Times(testing::AtMost(1))
- .WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kAboutVersionUrl);
-
- // Allow some time for chrome to be launched.
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
-}
-
-const wchar_t kWindowOpenUrl[] =
- L"http://localhost:1337/files/chrome_frame_window_open.html";
-
-const wchar_t kWindowOpenPopupUrl[] =
- L"http://localhost:1337/files/chrome_frame_window_open_popup.html";
-
-// This test checks if window.open calls issued by a full tab mode ChromeFrame
-// instance make it back to IE and then transitions back to Chrome as the
-// window.open target page is supposed to render within Chrome.
-// Marking this test as FLAKY initially as it relies on getting focus and user
-// input which don't work correctly at times.
-// http://code.google.com/p/chromium/issues/detail?id=26549
-TEST_F(ChromeFrameTestWithWebServer, FLAKY_FullTabModeIE_WindowOpenInChrome) {
- CloseIeAtEndOfScope last_resort_close_ie;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> new_window_mock;
- chrome_frame_test::TimedMsgLoop loop;
-
- mock.ExpectNavigationAndSwitch(kWindowOpenUrl);
-
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kWindowOpenUrl)))
- .WillOnce(testing::DoAll(
- DelaySendMouseClick(&mock, &loop, 0, 10, 10, simulate_input::LEFT),
- DelaySendChar(&loop, 500, 'O', simulate_input::NONE)));
- // Watch for new window
- mock.ExpectNewWindow(&new_window_mock);
-
- EXPECT_CALL(new_window_mock, OnLoad(testing::StrCaseEq(kWindowOpenPopupUrl)))
- .WillOnce(testing::DoAll(
- VerifyAddressBarUrl(&new_window_mock),
- ValidateWindowSize(&new_window_mock, 10, 10, 250, 250),
- CloseBrowserMock(&new_window_mock)));
-
- EXPECT_CALL(new_window_mock, OnQuit())
- .Times(testing::AtMost(1))
- .WillOnce(CloseBrowserMock(&mock));
-
- EXPECT_CALL(mock, OnQuit())
- .Times(testing::AtMost(1))
- .WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kWindowOpenUrl);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock.web_browser2() != NULL);
-
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
-
- ASSERT_TRUE(new_window_mock.web_browser2() != NULL);
-}
-
-const wchar_t kSubFrameUrl1[] =
- L"http://localhost:1337/files/sub_frame1.html";
-const wchar_t kSubFrameUrl2[] =
- L"http://localhost:1337/files/sub_frame2.html";
-const wchar_t kSubFrameUrl3[] =
- L"http://localhost:1337/files/sub_frame3.html";
-
-// Test new window behavior with ctrl+N
-TEST_F(ChromeFrameTestWithWebServer, FLAKY_FullTabModeIE_CtrlN) {
- CloseIeAtEndOfScope last_resort_close_ie;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- chrome_frame_test::TimedMsgLoop loop;
-
- // Ideally we want to use a mock to watch for finer grained
- // events for New Window, but for Crl+N we don't get any
- // OnNewWindowX notifications. :(
- const wchar_t* kIEFrameClass = L"IEFrame";
- mock.ExpectNavigationAndSwitch(kKeyEventUrl);
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kKeyEventUrl)))
- .WillOnce(testing::DoAll(
- WatchWindow(&mock, kIEFrameClass),
- SetFocusToChrome(&mock),
- DelaySendChar(&loop, 1500, 'n', simulate_input::CONTROL)));
-
- // Watch for new window
- const char* kNewWindowTitle = "Internet Explorer";
- EXPECT_CALL(mock, OnWindowDetected(_, testing::HasSubstr(kNewWindowTitle)))
- .WillOnce(testing::DoAll(
- DoCloseWindow(),
- CloseBrowserMock(&mock)));
-
- EXPECT_CALL(mock, OnQuit())
- .Times(testing::AtMost(1))
- .WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kKeyEventUrl);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock.web_browser2() != NULL);
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
-}
-
-// Test page reload with ctrl+R
-TEST_F(ChromeFrameTestWithWebServer, FLAKY_FullTabModeIE_CtrlR) {
- CloseIeAtEndOfScope last_resort_close_ie;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- chrome_frame_test::TimedMsgLoop loop;
-
- // In sequence since we want to do different things on two loads
- // on the same mock for the same URLs
- ::testing::InSequence sequence;
-
- mock.ExpectNavigationAndSwitchSequence(kKeyEventUrl);
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kKeyEventUrl)))
- .WillOnce(testing::DoAll(
- SetFocusToChrome(&mock),
- DelaySendChar(&loop, 1500, 'r', simulate_input::CONTROL)));
-
- // mock.ExpectNavigation(kKeyEventUrl);
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kKeyEventUrl)))
- .WillOnce(testing::DoAll(
- VerifyAddressBarUrl(&mock),
- CloseBrowserMock(&mock)));
-
- EXPECT_CALL(mock, OnQuit())
- .Times(testing::AtMost(1))
- .WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kKeyEventUrl);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock.web_browser2() != NULL);
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
-}
-
-// Test window close with ctrl+w
-TEST_F(ChromeFrameTestWithWebServer, FLAKY_FullTabModeIE_CtrlW) {
- CloseIeAtEndOfScope last_resort_close_ie;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- chrome_frame_test::TimedMsgLoop loop;
-
- mock.ExpectNavigationAndSwitch(kKeyEventUrl);
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kKeyEventUrl)))
- .WillOnce(testing::DoAll(
- SetFocusToChrome(&mock),
- DelaySendChar(&loop, 1500, 'w', simulate_input::CONTROL)));
-
- EXPECT_CALL(mock, OnQuit()).WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kKeyEventUrl);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock.web_browser2() != NULL);
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
-}
-
-// Test address bar navigation with Alt+d and URL
-TEST_F(ChromeFrameTestWithWebServer, FLAKY_FullTabModeIE_AltD) {
- CloseIeAtEndOfScope last_resort_close_ie;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- chrome_frame_test::TimedMsgLoop loop;
- ::testing::InSequence sequence;
-
- mock.ExpectNavigationAndSwitchSequence(kSubFrameUrl1);
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kSubFrameUrl1)))
- .WillOnce(testing::DoAll(
- SetFocusToChrome(&mock),
- TypeUrlInAddressBar(&loop, kSubFrameUrl2, 1500)));
-
- mock.ExpectNavigationAndSwitchSequence(kSubFrameUrl2);
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kSubFrameUrl2)))
- .WillOnce(CloseBrowserMock(&mock));
-
- EXPECT_CALL(mock, OnQuit())
- .Times(testing::AtMost(1))
- .WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kSubFrameUrl1);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock.web_browser2() != NULL);
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
-}
-
-// This test launches chrome frame in full tab mode in IE by having IE navigate
-// to a url. It then looks for the chrome renderer window and posts
-// the WM_RBUTTONDOWN/WM_RBUTTONUP messages to it, which bring up the context
-// menu. This is followed by keyboard messages sent via SendInput to select
-// the About chrome frame menu option, which would then bring up a new window
-// with the chrome revision. The test finally checks for success by comparing
-// the URL of the window being opened with cf:about:version, which indicates
-// that the operation succeeded.
-// Marking this test FLAKY as it fails at times on the buildbot.
-// http://code.google.com/p/chromium/issues/detail?id=26549
-TEST_F(ChromeFrameTestWithWebServer, FLAKY_FullTabModeIE_AboutChromeFrame) {
- CloseIeAtEndOfScope last_resort_close_ie;
-
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> new_window_mock;
- chrome_frame_test::TimedMsgLoop loop;
-
- mock.ExpectNavigationAndSwitch(kSubFrameUrl1);
-
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kSubFrameUrl1)))
- .WillOnce(testing::DoAll(
- DelaySendMouseClick(&mock, &loop, 0, 10, 10, simulate_input::RIGHT),
- SendExtendedKeysEnter(&loop, 500, VK_UP, 1, simulate_input::NONE)));
-
- // Watch for new window
- mock.ExpectNewWindow(&new_window_mock);
-
- EXPECT_CALL(new_window_mock, OnLoad(testing::StrCaseEq(kAboutVersion)))
- .WillOnce(testing::DoAll(
- VerifyAddressBarUrlWithGcf(&new_window_mock),
- CloseBrowserMock(&new_window_mock)));
- EXPECT_CALL(new_window_mock, OnQuit())
- .Times(testing::AtMost(1))
- .WillOnce(CloseBrowserMock(&mock));
- EXPECT_CALL(mock, OnQuit())
- .Times(testing::AtMost(1))
- .WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kSubFrameUrl1);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock.web_browser2() != NULL);
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
-}
-
-// Hack to pass a reference to the argument instead of value. Passing by
-// value evaluates the argument at the mock specification time which is
-// not always ideal. For e.g. At the time of mock creation, web_browser2_
-// pointer is not set up yet so by passing a reference to it instead of
-// a value we allow it to be created later.
-template <typename T> T** ReceivePointer(scoped_refptr<T>& p) { // NOLINT
- return reinterpret_cast<T**>(&p);
-}
-
-// Full tab mode back/forward test
-// Launch and navigate chrome frame to a set of URLs and test back forward
-TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_BackForward) {
- CloseIeAtEndOfScope last_resort_close_ie;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- chrome_frame_test::TimedMsgLoop loop;
- ::testing::InSequence sequence; // Everything in sequence
-
- mock.ExpectNavigationAndSwitchSequence(kSubFrameUrl1);
-
- // Navigate to url 2 after the previous navigation is complete.
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kSubFrameUrl1)))
- .WillOnce(testing::DoAll(
- VerifyAddressBarUrl(&mock),
- Navigate(&mock, kSubFrameUrl2)));
- mock.ExpectNavigationAndSwitchSequence(kSubFrameUrl2);
-
- // Navigate to url 3 after the previous navigation is complete
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kSubFrameUrl2)))
- .WillOnce(testing::DoAll(
- VerifyAddressBarUrl(&mock),
- Navigate(&mock, kSubFrameUrl3)));
-
- // We have reached url 3 and have two back entries for url 1 & 2
- // Go back to url 2 now
- mock.ExpectNavigationAndSwitchSequence(kSubFrameUrl3);
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kSubFrameUrl3)))
- .WillOnce(testing::DoAll(
- VerifyAddressBarUrl(&mock),
- testing::IgnoreResult(testing::InvokeWithoutArgs(CreateFunctor(
- ReceivePointer(mock.web_browser2_), &IWebBrowser::GoBack)))));
-
- // We have reached url 2 and have 1 back & 1 forward entries for url 1 & 3
- // Go back to url 1 now
- mock.ExpectNavigation(kSubFrameUrl2);
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kSubFrameUrl2)))
- .WillOnce(testing::DoAll(
- VerifyAddressBarUrl(&mock),
- testing::IgnoreResult(testing::InvokeWithoutArgs(CreateFunctor(
- ReceivePointer(mock.web_browser2_), &IWebBrowser::GoBack)))));
-
- // We have reached url 1 and have 0 back & 2 forward entries for url 2 & 3
- // Go back to url 1 now
- mock.ExpectNavigation(kSubFrameUrl1);
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kSubFrameUrl1)))
- .WillOnce(testing::DoAll(
- VerifyAddressBarUrl(&mock),
- CloseBrowserMock(&mock)));
- EXPECT_CALL(mock, OnQuit())
- .Times(testing::AtMost(1))
- .WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kSubFrameUrl1);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock.web_browser2() != NULL);
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
-}
-
-const wchar_t kAnchorUrl[] = L"http://localhost:1337/files/anchor.html";
-const wchar_t kAnchor1Url[] = L"http://localhost:1337/files/anchor.html#a1";
-const wchar_t kAnchor2Url[] = L"http://localhost:1337/files/anchor.html#a2";
-const wchar_t kAnchor3Url[] = L"http://localhost:1337/files/anchor.html#a3";
-
-// Full tab mode back/forward test
-// Launch and navigate chrome frame to a set of URLs and test back forward
-// Marking this test FLAKY as it fails at times on the buildbot.
-// http://code.google.com/p/chromium/issues/detail?id=26549
-TEST_F(ChromeFrameTestWithWebServer, FLAKY_FullTabModeIE_BackForwardAnchor) {
- CloseIeAtEndOfScope last_resort_close_ie;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- chrome_frame_test::TimedMsgLoop loop;
- ::testing::InSequence sequence; // Everything in sequence
-
- // Back/Forward state at this point:
- // Back: 0
- // Forward: 0
- mock.ExpectNavigationAndSwitchSequence(kAnchorUrl);
-
- // Navigate to anchor 1:
- // - First set focus to chrome renderer window
- // Call WebBrowserEventSink::SetFocusToChrome only once
- // in the beginning. Calling it again will change focus from the
- // current location to an element near the simulated mouse.click.
- // - Then send keyboard input of TAB + ENTER to cause navigation.
- // It's better to send input as PostDelayedTask since the Activex
- // message loop on the other side might be blocked when we get
- // called in Onload.
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kAnchorUrl)))
- .WillOnce(testing::DoAll(
- SetFocusToChrome(&mock),
- DelaySendString(&loop, 200, tab_enter_keys)));
-
- mock.ExpectNavigationSequenceForAnchors(kAnchor1Url);
- // Navigate to anchor 2 after the previous navigation is complete
- // Back/Forward state at this point:
- // Back: 1 (kAnchorUrl)
- // Forward: 0
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kAnchor1Url)))
- .WillOnce(testing::DoAll(
- VerifyAddressBarUrl(&mock),
- DelaySendString(&loop, 200, tab_enter_keys)));
- mock.ExpectNavigationSequenceForAnchors(kAnchor2Url);
-
- // Navigate to anchor 3 after the previous navigation is complete
- // Back/Forward state at this point:
- // Back: 2 (kAnchorUrl, kAnchor1Url)
- // Forward: 0
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kAnchor2Url)))
- .WillOnce(testing::DoAll(
- VerifyAddressBarUrl(&mock),
- DelaySendString(&loop, 200, tab_enter_keys)));
- mock.ExpectNavigationSequenceForAnchors(kAnchor3Url);
-
- // We will reach anchor 3 once the navigation is complete,
- // then go back to anchor 2
- // Back/Forward state at this point:
- // Back: 3 (kAnchorUrl, kAnchor1Url, kAnchor2Url)
- // Forward: 0
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kAnchor3Url)))
- .WillOnce(testing::DoAll(
- VerifyAddressBarUrl(&mock),
- testing::IgnoreResult(testing::InvokeWithoutArgs(CreateFunctor(
- ReceivePointer(mock.web_browser2_), &IWebBrowser::GoBack)))));
- mock.ExpectNavigationSequenceForAnchors(kAnchor2Url);
-
- // We will reach anchor 2 once the navigation is complete,
- // then go back to anchor 1
- // Back/Forward state at this point:
- // Back: 3 (kAnchorUrl, kAnchor1Url, kAnchor2Url)
- // Forward: 1 (kAnchor3Url)
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kAnchor2Url)))
- .WillOnce(testing::DoAll(
- VerifyAddressBarUrl(&mock),
- testing::IgnoreResult(testing::InvokeWithoutArgs(CreateFunctor(
- ReceivePointer(mock.web_browser2_), &IWebBrowser::GoBack)))));
- mock.ExpectNavigationSequenceForAnchors(kAnchor1Url);
-
- // We will reach anchor 1 once the navigation is complete,
- // now go forward to anchor 2
- // Back/Forward state at this point:
- // Back: 2 (kAnchorUrl, kAnchor1Url)
- // Forward: 2 (kAnchor2Url, kAnchor3Url)
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kAnchor1Url)))
- .WillOnce(testing::DoAll(
- VerifyAddressBarUrl(&mock),
- testing::IgnoreResult(testing::InvokeWithoutArgs(CreateFunctor(
- ReceivePointer(mock.web_browser2_), &IWebBrowser::GoForward)))));
- mock.ExpectNavigationSequenceForAnchors(kAnchor2Url);
-
- // We have reached anchor 2, go forward to anchor 3 again
- // Back/Forward state at this point:
- // Back: 3 (kAnchorUrl, kAnchor1Url, kAnchor2Url)
- // Forward: 1 (kAnchor3Url)
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kAnchor2Url)))
- .WillOnce(testing::DoAll(
- VerifyAddressBarUrl(&mock),
- testing::IgnoreResult(testing::InvokeWithoutArgs(CreateFunctor(
- ReceivePointer(mock.web_browser2_), &IWebBrowser::GoForward)))));
- mock.ExpectNavigationSequenceForAnchors(kAnchor3Url);
-
- // We have gone a few steps back and forward, this should be enough for now.
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kAnchor3Url)))
- .WillOnce(CloseBrowserMock(&mock));
- EXPECT_CALL(mock, OnQuit())
- .Times(testing::AtMost(1))
- .WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kAnchorUrl);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock.web_browser2() != NULL);
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
-}
-
-// Full tab mode view source test
-// Launch and navigate chrome frame and invoke view source functionality
-// This test has been marked FLAKY
-// http://code.google.com/p/chromium/issues/detail?id=35370
-TEST_F(ChromeFrameTestWithWebServer, FLAKY_FullTabModeIE_ViewSource) {
- CloseIeAtEndOfScope last_resort_close_ie;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> view_source_mock;
- chrome_frame_test::TimedMsgLoop loop;
- ::testing::InSequence sequence; // Everything in sequence
-
- // After navigation invoke view soruce action using IWebBrowser2::ExecWB
- mock.ExpectNavigationAndSwitchSequence(kAnchorUrl);
-
- VARIANT empty = ScopedVariant::kEmptyVariant;
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kAnchorUrl)))
- .WillOnce(testing::InvokeWithoutArgs(
- CreateFunctor(&mock, &MockWebBrowserEventSink::Exec, &CGID_MSHTML,
- static_cast<OLECMDID>(IDM_VIEWSOURCE),
- OLECMDEXECOPT_DONTPROMPTUSER, &empty, &empty)));
-
- // Expect notification for view-source window, handle new window event
- // and attach a new mock to the received web browser
- std::wstring view_source_url;
- view_source_url += UTF8ToWide(chrome::kViewSourceScheme);
- view_source_url += L":";
- view_source_url += kAnchorUrl;
- std::wstring url_in_new_window = kChromeProtocolPrefix;
- url_in_new_window += view_source_url;
-
- mock.ExpectNewWindow(&view_source_mock);
- EXPECT_CALL(view_source_mock, OnLoad(testing::StrCaseEq(view_source_url)))
- .WillOnce(testing::DoAll(
- VerifyAddressBarUrlWithGcf(&view_source_mock),
- CloseBrowserMock(&view_source_mock)));
-
- EXPECT_CALL(view_source_mock, OnQuit())
- .Times(testing::AtMost(1))
- .WillOnce(CloseBrowserMock(&mock));
-
- EXPECT_CALL(mock, OnQuit())
- .Times(testing::AtMost(1))
- .WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kAnchorUrl);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock.web_browser2() != NULL);
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
-}
-
-const wchar_t kBeforeUnloadTest[] =
- L"http://localhost:1337/files/fulltab_before_unload_event_test.html";
-
-const wchar_t kBeforeUnloadMain[] =
- L"http://localhost:1337/files/fulltab_before_unload_event_main.html";
-
-TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_UnloadEventTest) {
- CloseIeAtEndOfScope last_resort_close_ie;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- chrome_frame_test::TimedMsgLoop loop;
- ::testing::InSequence sequence; // Everything in sequence
-
- mock.ExpectNavigationAndSwitchSequence(kBeforeUnloadTest);
- EXPECT_CALL(mock, OnLoad(_));
-
- mock.ExpectNavigationAndSwitchSequence(kBeforeUnloadMain);
- EXPECT_CALL(mock, OnLoad(_));
-
- EXPECT_CALL(mock, OnMessage(_, _, _))
- .WillOnce(CloseBrowserMock(&mock));
- EXPECT_CALL(mock, OnQuit())
- .Times(testing::AtMost(1))
- .WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kBeforeUnloadTest);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock.web_browser2() != NULL);
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
-}
-
-// NOTE: This test is currently disabled as we haven't finished implementing
-// support for this yet. The test (as written) works fine for IE. CF might
-// have a different set of requirements once we fully support this and hence
-// the test might need some refining before being enabled.
-TEST_F(ChromeFrameTestWithWebServer,
- DISABLED_FullTabModeIE_DownloadInNewWindow) {
- CloseIeAtEndOfScope last_resort_close_ie;
- const wchar_t kDownloadFromNewWin[] =
- L"http://localhost:1337/files/full_tab_download_from_new_window.html";
-
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- chrome_frame_test::TimedMsgLoop loop;
-
- mock.ExpectNavigationAndSwitch(kDownloadFromNewWin);
-
- EXPECT_CALL(mock, OnNewWindow3(_, _, _, _, _));
-
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> new_window_mock;
- EXPECT_CALL(mock, OnNewBrowserWindow(_, _))
- .WillOnce(testing::WithArgs<0>(testing::Invoke(CreateFunctor(
- &new_window_mock, &MockWebBrowserEventSink::Attach))));
- EXPECT_CALL(new_window_mock, OnBeforeNavigate2(_, _, _, _, _, _, _));
-
- EXPECT_CALL(new_window_mock, OnFileDownload(VARIANT_FALSE, _))
- .Times(2)
- .WillRepeatedly(CloseBrowserMock(&new_window_mock));
-
- EXPECT_CALL(new_window_mock, OnNavigateComplete2(_, _));
-
- EXPECT_CALL(new_window_mock, OnQuit()).WillOnce(CloseBrowserMock(&mock));
- EXPECT_CALL(mock, OnQuit()).WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kDownloadFromNewWin);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock.web_browser2() != NULL);
-
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
-}
-
-// Test Back/Forward from context menu. Loads page 1 in chrome and page 2
-// in IE. Then it tests back and forward using context menu
-// Disabling this test as it won't work as per the current chrome external tab
-// design.
-// http://code.google.com/p/chromium/issues/detail?id=46615
-TEST_F(ChromeFrameTestWithWebServer,
- DISABLED_FullTabModeIE_ContextMenuBackForward) {
- CloseIeAtEndOfScope last_resort_close_ie;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- chrome_frame_test::TimedMsgLoop loop;
-
- ::testing::InSequence sequence; // Everything in sequence
-
- // Navigate to url 2 after the previous navigation is complete.
- mock.ExpectNavigationAndSwitchSequence(kSubFrameUrl1);
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kSubFrameUrl1)))
- .WillOnce(Navigate(&mock, kSubFrameUrl2));
-
- mock.ExpectNavigationAndSwitchSequence(kSubFrameUrl2);
-
- // Go back using Rt-Click + DOWN + ENTER
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kSubFrameUrl2)))
- .WillOnce(testing::DoAll(
- DelaySendMouseClick(&mock, &loop, 0, 10, 10, simulate_input::RIGHT),
- SendExtendedKeysEnter(&loop, 500, VK_DOWN, 1, simulate_input::NONE)));
- mock.ExpectNavigation(kSubFrameUrl1);
-
- // Go forward using Rt-Click + DOWN + DOWN + ENTER
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kSubFrameUrl1)))
- .WillOnce(testing::DoAll(
- DelaySendMouseClick(&mock, &loop, 0, 10, 10, simulate_input::RIGHT),
- SendExtendedKeysEnter(&loop, 500, VK_DOWN, 2, simulate_input::NONE)));
- mock.ExpectNavigation(kSubFrameUrl2);
-
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kSubFrameUrl2)))
- .WillOnce(CloseBrowserMock(&mock));
- EXPECT_CALL(mock, OnQuit())
- .Times(testing::AtMost(1))
- .WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kSubFrameUrl1);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock.web_browser2() != NULL);
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
-}
-
-// Test Reload from context menu.
-// Marking this test FLAKY as it fails at times on the buildbot.
-// http://code.google.com/p/chromium/issues/detail?id=26549
-TEST_F(ChromeFrameTestWithWebServer, FLAKY_FullTabModeIE_ContextMenuReload) {
- CloseIeAtEndOfScope last_resort_close_ie;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- chrome_frame_test::TimedMsgLoop loop;
-
- ::testing::InSequence sequence; // Everything in sequence
-
- mock.ExpectNavigationAndSwitchSequence(kSubFrameUrl1);
-
- // Reload using Rt-Click + DOWN + DOWN + DOWN + ENTER
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kSubFrameUrl1)))
- .WillOnce(testing::DoAll(
- DelaySendMouseClick(&mock, &loop, 0, 10, 10, simulate_input::RIGHT),
- SendExtendedKeysEnter(&loop, 500, VK_DOWN, 3, simulate_input::NONE)));
-
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kSubFrameUrl1)))
- .WillOnce(CloseBrowserMock(&mock));
- EXPECT_CALL(mock, OnQuit())
- .Times(testing::AtMost(1))
- .WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kSubFrameUrl1);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock.web_browser2() != NULL);
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
-}
-
-// Test view source using context menu
-// Marking this test FLAKY as it fails at times on the buildbot.
-// http://code.google.com/p/chromium/issues/detail?id=26549
-TEST_F(ChromeFrameTestWithWebServer,
- FLAKY_FullTabModeIE_ContextMenuViewSource) {
- CloseIeAtEndOfScope last_resort_close_ie;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> view_source_mock;
- chrome_frame_test::TimedMsgLoop loop;
- ::testing::InSequence sequence; // Everything in sequence
-
- // View source using Rt-Click + UP + UP + UP + UP + ENTER
- mock.ExpectNavigationAndSwitchSequence(kAnchorUrl);
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kAnchorUrl)))
- .WillOnce(testing::DoAll(
- DelaySendMouseClick(&mock, &loop, 0, 10, 10, simulate_input::RIGHT),
- SendExtendedKeysEnter(&loop, 500, VK_UP, 4, simulate_input::NONE)));
-
- // Expect notification for view-source window, handle new window event
- // and attach a new mock to the received web browser
- std::wstring view_source_url;
- view_source_url += UTF8ToWide(chrome::kViewSourceScheme);
- view_source_url += L":";
- view_source_url += kAnchorUrl;
- std::wstring url_in_new_window = kChromeProtocolPrefix;
- url_in_new_window += view_source_url;
-
- mock.ExpectNewWindow(&view_source_mock);
- EXPECT_CALL(view_source_mock, OnLoad(testing::StrCaseEq(view_source_url)))
- .WillOnce(testing::DoAll(
- VerifyAddressBarUrlWithGcf(&view_source_mock),
- CloseBrowserMock(&view_source_mock)));
- EXPECT_CALL(view_source_mock, OnQuit())
- .Times(testing::AtMost(1))
- .WillOnce(CloseBrowserMock(&mock));
-
- EXPECT_CALL(mock, OnQuit())
- .Times(testing::AtMost(1))
- .WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kAnchorUrl);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock.web_browser2() != NULL);
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
-}
-
-TEST_F(ChromeFrameTestWithWebServer,
- FLAKY_FullTabModeIE_ContextMenuPageInfo) {
- CloseIeAtEndOfScope last_resort_close_ie;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- chrome_frame_test::TimedMsgLoop loop;
- ::testing::InSequence sequence; // Everything in sequence
-
- // View page information using Rt-Click + UP + UP + UP + ENTER
- const wchar_t* kPageInfoWindowClass = L"Chrome_WidgetWin_0";
- mock.ExpectNavigationAndSwitchSequence(kAnchorUrl);
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kAnchorUrl)))
- .WillOnce(testing::DoAll(
- WatchWindow(&mock, kPageInfoWindowClass),
- DelaySendMouseClick(&mock, &loop, 0, 10, 10, simulate_input::RIGHT),
- SendExtendedKeysEnter(&loop, 500, VK_UP, 3, simulate_input::NONE)));
-
- // Expect page info dialog to pop up. Dismiss the dialog with 'Esc' key
- const char* kPageInfoCaption = "Security Information";
- EXPECT_CALL(mock, OnWindowDetected(_, testing::StrCaseEq(kPageInfoCaption)))
- .WillOnce(testing::DoAll(
- DelaySendChar(&loop, 100, VK_ESCAPE, simulate_input::NONE),
- DelayCloseBrowserMock(&loop, 2000, &mock)));
-
- EXPECT_CALL(mock, OnQuit()).WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kAnchorUrl);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock.web_browser2() != NULL);
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
-}
-
-TEST_F(ChromeFrameTestWithWebServer,
- FLAKY_FullTabModeIE_ContextMenuInspector) {
- CloseIeAtEndOfScope last_resort_close_ie;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- chrome_frame_test::TimedMsgLoop loop;
- ::testing::InSequence sequence; // Everything in sequence
-
- // Open developer tools using Rt-Click + UP + UP + ENTER
- const wchar_t* kPageInfoWindowClass = L"Chrome_WidgetWin_0";
- mock.ExpectNavigationAndSwitchSequence(kAnchorUrl);
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kAnchorUrl)))
- .WillOnce(testing::DoAll(
- WatchWindow(&mock, kPageInfoWindowClass),
- DelaySendMouseClick(&mock, &loop, 0, 10, 10, simulate_input::RIGHT),
- SendExtendedKeysEnter(&loop, 500, VK_UP, 2, simulate_input::NONE)));
-
- // Devtools begins life with "Untitled" caption and it changes
- // later to the 'Developer Tools - <url> form.
- const char* kPageInfoCaption = "Untitled";
- EXPECT_CALL(mock, OnWindowDetected(_, testing::StartsWith(kPageInfoCaption)))
- .WillOnce(testing::DoAll(
- StopWindowWatching(&mock),
- SetFocusToChrome(&mock),
- DelayCloseBrowserMock(&loop, 2000, &mock)));
-
- EXPECT_CALL(mock, OnQuit()).WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kAnchorUrl);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock.web_browser2() != NULL);
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
-}
-
-TEST_F(ChromeFrameTestWithWebServer,
- FLAKY_FullTabModeIE_ContextMenuSaveAs) {
- CloseIeAtEndOfScope last_resort_close_ie;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- chrome_frame_test::TimedMsgLoop loop;
- ::testing::InSequence sequence; // Everything in sequence
-
- // Open'Save As' dialog using Rt-Click + DOWN + DOWN + DOWN + DOWN + ENTER
- const wchar_t* kSaveDlgClass = L"#32770";
- mock.ExpectNavigationAndSwitchSequence(kAnchorUrl);
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kAnchorUrl)))
- .WillOnce(testing::DoAll(
- WatchWindow(&mock, kSaveDlgClass),
- DelaySendMouseClick(&mock, &loop, 0, 10, 10, simulate_input::RIGHT),
- SendExtendedKeysEnter(&loop, 500, VK_DOWN, 4, simulate_input::NONE)));
-
- FilePath temp_file_path;
- EXPECT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
- temp_file_path = temp_file_path.ReplaceExtension(L".htm");
-
- const wchar_t* kSaveFileName = temp_file_path.value().c_str();
- DeleteFile(kSaveFileName);
-
- const char* kSaveDlgCaption = "Save As";
- EXPECT_CALL(mock, OnWindowDetected(_, testing::StrCaseEq(kSaveDlgCaption)))
- .WillOnce(testing::DoAll(
- StopWindowWatching(&mock),
- DelaySendString(&loop, 100, kSaveFileName),
- DelaySendChar(&loop, 200, VK_RETURN, simulate_input::NONE),
- DelayCloseBrowserMock(&loop, 4000, &mock)));
-
- EXPECT_CALL(mock, OnQuit()).WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kAnchorUrl);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock.web_browser2() != NULL);
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
-
- ASSERT_NE(INVALID_FILE_ATTRIBUTES, GetFileAttributes(kSaveFileName));
- ASSERT_TRUE(DeleteFile(kSaveFileName));
-}
-
-// Marking this test FLAKY as it fails at times on the buildbot.
-// http://code.google.com/p/chromium/issues/detail?id=26549
-TEST_F(ChromeFrameTestWithWebServer,
- FLAKY_FullTabModeIE_KeyboardBackForwardTest) {
- CloseIeAtEndOfScope last_resort_close_ie;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- chrome_frame_test::TimedMsgLoop loop;
-
- ::testing::InSequence sequence; // Everything in sequence
-
- // This test performs the following steps.
- // 1. Launches IE and navigates to
- // http://localhost:1337/files/sub_frame1.html
- // 2. It then navigates to
- // http://localhost:1337/files/sub_frame2.html
- // 3. Sends the VK_BACK keystroke to IE, which should navigate back to
- // http://localhost:1337/files/sub_frame1.html
- // 4. Sends the Shift + VK_BACK keystroke to IE which should navigate
- // forward to http://localhost:1337/files/sub_frame2.html
- mock.ExpectNavigationAndSwitchSequence(kSubFrameUrl1);
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kSubFrameUrl1)))
- .WillOnce(Navigate(&mock, kSubFrameUrl2));
-
- mock.ExpectNavigationAndSwitchSequence(kSubFrameUrl2);
-
- short bkspace = VkKeyScanA(VK_BACK); // NOLINT
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kSubFrameUrl2)))
- .WillOnce(testing::DoAll(
- SetFocusToChrome(&mock),
- DelaySendScanCode(&loop, 500, bkspace, simulate_input::NONE)));
-
- mock.ExpectNavigation(kSubFrameUrl1);
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kSubFrameUrl1)))
- .WillOnce(testing::DoAll(
- SetFocusToChrome(&mock),
- DelaySendScanCode(&loop, 1500, bkspace, simulate_input::SHIFT)));
-
- mock.ExpectNavigation(kSubFrameUrl2);
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kSubFrameUrl2)))
- .WillOnce(CloseBrowserMock(&mock));
-
- EXPECT_CALL(mock, OnQuit())
- .Times(testing::AtMost(1))
- .WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kSubFrameUrl1);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock.web_browser2() != NULL);
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
-}
-
-// http://code.google.com/p/chromium/issues/detail?id=38566
-TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_MenuSaveAs) {
- CloseIeAtEndOfScope last_resort_close_ie;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- chrome_frame_test::TimedMsgLoop loop;
- ::testing::InSequence sequence; // Everything in sequence
-
- // Open'Save As' dialog using Alt+F, a, note the small 'f'
- // in DelaySendChar (otherwise DelaySendChar will
- // OR in a shift.
- const wchar_t* kSaveDlgClass = L"#32770";
- mock.ExpectNavigationAndSwitchSequence(kKeyEventUrl);
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kKeyEventUrl)))
- .WillOnce(testing::DoAll(
- WatchWindow(&mock, kSaveDlgClass),
- SetFocusToChrome(&mock),
- DelaySendChar(&loop, 1500, 'f', simulate_input::ALT),
- DelaySendChar(&loop, 2500, 'a', simulate_input::NONE)));
-
- FilePath temp_file_path;
- EXPECT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
-
- const wchar_t* kSaveFileName = temp_file_path.value().c_str();
- const char* kSaveDlgCaption = "Save As";
- EXPECT_CALL(mock, OnWindowDetected(_, testing::StrCaseEq(kSaveDlgCaption)))
- .WillOnce(testing::DoAll(
- StopWindowWatching(&mock),
- DelaySendString(&loop, 100, kSaveFileName),
- DelaySendChar(&loop, 200, VK_RETURN, simulate_input::NONE),
- DelayCloseBrowserMock(&loop, 4000, &mock)));
-
- EXPECT_CALL(mock, OnQuit()).WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kKeyEventUrl);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock.web_browser2() != NULL);
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
-
- ASSERT_NE(INVALID_FILE_ATTRIBUTES, GetFileAttributes(kSaveFileName));
- ASSERT_TRUE(DeleteFile(kSaveFileName));
-}
-
-const wchar_t kHostBrowserUrl[] =
- L"http://localhost:1337/files/host_browser.html";
-
-TEST_F(ChromeFrameTestWithWebServer,
- FLAKY_FullTabMode_SwitchFromIEToChromeFrame) {
- CloseIeAtEndOfScope last_resort_close_ie;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- chrome_frame_test::TimedMsgLoop loop;
-
- EXPECT_CALL(mock, OnFileDownload(VARIANT_TRUE, _))
- .Times(testing::AnyNumber());
-
- ::testing::InSequence sequence; // Everything in sequence
-
- // This test performs the following steps.
- // 1. Launches IE and navigates to
- // http://localhost:1337/files/back_to_ie.html, which should render in IE.
- // 2. It then navigates to
- // http://localhost:1337/files/sub_frame1.html which should render in
- // ChromeFrame
- EXPECT_CALL(mock, OnBeforeNavigate2(_,
- testing::Field(&VARIANT::bstrVal,
- testing::StrCaseEq(kHostBrowserUrl)), _, _, _, _, _));
-
- // When we receive a navigate complete notification for the initial URL
- // initiate a navigation to a url which should be rendered in ChromeFrame.
- EXPECT_CALL(mock, OnNavigateComplete2(_,
- testing::Field(&VARIANT::bstrVal,
- testing::StrCaseEq(kHostBrowserUrl))))
- .Times(1)
- .WillOnce(TypeUrlInAddressBar(&loop, kSubFrameUrl1, 1500));
-
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kHostBrowserUrl)))
- .Times(0);
-
- mock.ExpectNavigationAndSwitch(kSubFrameUrl1);
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kSubFrameUrl1)))
- .WillOnce(testing::DoAll(
- VerifyAddressBarUrl(&mock),
- CloseBrowserMock(&mock)));
-
- EXPECT_CALL(mock, OnQuit())
- .Times(testing::AtMost(1))
- .WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kHostBrowserUrl);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock.web_browser2() != NULL);
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds * 2);
-}
-
-// Test has been disabled as it causes the IE8 bot to hang at times.
-// http://crbug.com/47596
-TEST(IEPrivacy, DISABLED_NavigationToRestrictedSite) {
- if (IsIBrowserServicePatchEnabled()) {
- LOG(ERROR) << "Not running test. IBrowserServicePatch is in place.";
- return;
- }
- CloseIeAtEndOfScope last_resort_close_ie;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- chrome_frame_test::TimedMsgLoop loop;
- ChromeFrameHTTPServer server;
- server.SetUp();
-
- ScopedComPtr<IInternetSecurityManager> security_manager;
- HRESULT hr = security_manager.CreateInstance(CLSID_InternetSecurityManager);
- ASSERT_HRESULT_SUCCEEDED(hr);
- // Add localhost to restricted sites zone.
- hr = security_manager->SetZoneMapping(URLZONE_UNTRUSTED,
- L"http://localhost:1337", SZM_CREATE);
-
- EXPECT_CALL(mock, OnFileDownload(_, _))
- .Times(testing::AnyNumber());
-
- ProtocolPatchMethod patch_method = GetPatchMethod();
-
- const wchar_t* url = L"http://localhost:1337/files/meta_tag.html";
- const wchar_t* kDialogClass = L"#32770";
-
- EXPECT_CALL(mock, OnBeforeNavigate2(_,
- testing::Field(&VARIANT::bstrVal,
- testing::StrCaseEq(url)), _, _, _, _, _))
- .Times(1)
- .WillOnce(WatchWindow(&mock, kDialogClass));
-
- if (patch_method == PATCH_METHOD_INET_PROTOCOL) {
- EXPECT_CALL(mock, OnBeforeNavigate2(_,
- testing::Field(&VARIANT::bstrVal,
- testing::HasSubstr(L"res://")), _, _, _, _, _))
- .Times(1);
- }
-
- EXPECT_CALL(mock, OnNavigateComplete2(_,
- testing::Field(&VARIANT::bstrVal, testing::StrCaseEq(url))))
- .Times(testing::AtMost(1));
-
- const char* kAlertDlgCaption = "Security Alert";
- EXPECT_CALL(mock, OnWindowDetected(_, testing::StrEq(kAlertDlgCaption)))
- .Times(1)
- .WillOnce(testing::DoAll(
- DoCloseWindow(),
- QUIT_LOOP_SOON(loop, 1)));
-
- EXPECT_CALL(mock, OnLoad(_)).Times(0);
-
- hr = mock.LaunchIEAndNavigate(url);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_OK) {
- ASSERT_TRUE(mock.web_browser2() != NULL);
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds * 2);
- }
-
- ASSERT_HRESULT_SUCCEEDED(security_manager->SetZoneMapping(URLZONE_UNTRUSTED,
- L"http://localhost:1337", SZM_DELETE));
-}
-
-// See bug 36694 for details. http://crbug.com/36694
-TEST_F(ChromeFrameTestWithWebServer,
- DISABLED_FullTabModeIE_TestDownloadFromForm) {
- if (IsIBrowserServicePatchEnabled()) {
- LOG(ERROR) << "Not running test. IBrowserServicePatch is in place.";
- return;
- }
-
- CloseIeAtEndOfScope last_resort_close_ie;
-
- // The content of our HTML test page. This will be returned whenever
- // we reply to a GET request.
- static const char kHtml[] =
- "<html><head>\n"
- "<title>ChromeFrame Form Download Test</title>\n"
- // To see how this test runs with only IE (no CF in the picture), comment
- // out this meta tag. The outcome of the test should be identical.
- "<meta http-equiv=\"X-UA-Compatible\" content=\"chrome=1\" />\n"
- "</head>\n"
- "<script language=\"javascript\">\n"
- "function SubmitForm() {\n"
- " var form = document.forms['myform'];\n"
- " form.action = document.location;\n"
- " form.submit();\n"
- " return true;\n"
- "}\n"
- "</script>\n"
- "<body onload=\"SubmitForm();\">\n"
- "<form method=\"post\" action=\"foo.html\" id=\"myform\">\n"
- " <input type=\"hidden\" name=\"Field1\" value=\"myvalue\" />\n"
- " <input type=\"button\" name=\"btn\" value=\"Test Download\" "
- "onclick=\"return SubmitForm();\" id=\"Button1\"/>\n"
- "</form></body></html>\n";
-
- // The content of our HTML test page. This will be returned whenever
- // we reply to a POST request.
- static const char kText[] =
- "This is a text file (in case you were wondering).";
-
- // This http response class will return an HTML document that contains
- // a form whenever it receives a GET request. Whenever it gets a POST
- // request, it will respond with a text file that needs to be downloaded
- // (content-disposition is "attachment").
- class CustomResponse : public test_server::ResponseForPath {
- public:
- explicit CustomResponse(const char* path)
- : test_server::ResponseForPath(path), is_post_(false),
- post_requests_(0), get_requests_(0) {
- }
-
- virtual bool GetContentType(std::string* content_type) const {
- DCHECK(!is_post_);
- return false;
- }
-
- virtual size_t ContentLength() const {
- DCHECK(!is_post_);
- return sizeof(kHtml) - 1;
- }
-
- virtual bool GetCustomHeaders(std::string* headers) const {
- if (!is_post_)
- return false;
- *headers = StringPrintf(
- "HTTP/1.1 200 OK\r\n"
- "Content-Disposition: attachment;filename=\"test.txt\"\r\n"
- "Content-Type: application/text\r\n"
- "Connection: close\r\n"
- "Content-Length: %i\r\n\r\n", sizeof(kText) - 1);
- return true;
- }
-
- virtual bool Matches(const test_server::Request& r) const {
- bool match = __super::Matches(r);
- if (match) {
- is_post_ = LowerCaseEqualsASCII(r.method().c_str(), "post");
- }
- return match;
- }
-
- virtual void WriteContents(ListenSocket* socket) const {
- if (is_post_) {
- socket->Send(kText, sizeof(kText) - 1, false);
- } else {
- socket->Send(kHtml, sizeof(kHtml) - 1, false);
- }
- }
-
- virtual void IncrementAccessCounter() {
- __super::IncrementAccessCounter();
- if (is_post_) {
- post_requests_++;
- } else {
- get_requests_++;
- }
- }
-
- size_t get_request_count() const {
- return get_requests_;
- }
-
- size_t post_request_count() const {
- return get_requests_;
- }
-
- protected:
- mutable bool is_post_;
- size_t post_requests_;
- size_t get_requests_;
- };
-
- chrome_frame_test::TimedMsgLoop loop; // must come before the server.
- SimpleWebServerTest server(46664);
- CustomResponse* response = new CustomResponse("/form.html");
- server.web_server()->AddResponse(response);
-
- std::wstring url(server.FormatHttpPath(L"form.html"));
-
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
-
- // Will get called twice. Once for HTML, once for the download.
- EXPECT_CALL(mock, OnBeforeNavigate2(_,
- testing::Field(&VARIANT::bstrVal,
- testing::StrCaseEq(url)), _, _, _, _, _)).Times(2);
- // Will get called twice in the case of CF, once if no CF.
- EXPECT_CALL(mock, OnFileDownload(VARIANT_TRUE, _))
- .Times(testing::AnyNumber());
- EXPECT_CALL(mock, OnNavigateComplete2(_,
- testing::Field(&VARIANT::bstrVal, testing::StrCaseEq(url))))
- .Times(testing::AnyNumber());
- EXPECT_CALL(mock, OnFileDownload(VARIANT_FALSE, _))
- .Times(testing::AnyNumber())
- .WillRepeatedly(CloseBrowserMock(&mock));
-
- EXPECT_CALL(mock, OnQuit()).WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(url);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_OK) {
- ASSERT_TRUE(mock.web_browser2() != NULL);
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds * 2);
- }
-
- EXPECT_EQ(1, response->get_request_count());
- EXPECT_EQ(1, response->post_request_count());
-}
-
-// This test validates that typing in URLs with a fragment in them switch to
-// to ChromeFrame correctly.
-TEST_F(ChromeFrameTestWithWebServer,
- FLAKY_FullTabModeIE_AltD_AnchorUrlNavigate) {
- if (IsIBrowserServicePatchEnabled()) {
- LOG(ERROR) << "Not running test. IBrowserServicePatch is in place.";
- return;
- }
-
- CloseIeAtEndOfScope last_resort_close_ie;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- chrome_frame_test::TimedMsgLoop loop;
- ::testing::InSequence sequence;
-
- mock.ExpectNavigationAndSwitchSequence(kSubFrameUrl1);
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kSubFrameUrl1)))
- .WillOnce(testing::DoAll(
- SetFocusToChrome(&mock),
- TypeUrlInAddressBar(&loop, kAnchor1Url, 1500)));
-
- mock.ExpectNavigationAndSwitchSequence(kAnchor1Url);
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kAnchor1Url)))
- .WillOnce(CloseBrowserMock(&mock));
-
- EXPECT_CALL(mock, OnQuit())
- .Times(testing::AtMost(1))
- .WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kSubFrameUrl1);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock.web_browser2() != NULL);
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
-}
-
-// This test checks if window.open calls issued by a full tab mode ChromeFrame
-// instance make it back to IE and then transitions back to Chrome as the
-// window.open target page is supposed to render within Chrome and whether this
-// window can be closed correctly.
-// Marking this test as FLAKY initially as it relies on getting focus and user
-// input which don't work correctly at times.
-// http://code.google.com/p/chromium/issues/detail?id=26549
-TEST_F(ChromeFrameTestWithWebServer, FLAKY_FullTabModeIE_WindowCloseInChrome) {
- CloseIeAtEndOfScope last_resort_close_ie;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> new_window_mock;
- chrome_frame_test::TimedMsgLoop loop;
-
- mock.ExpectNavigationAndSwitch(kWindowOpenUrl);
-
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kWindowOpenUrl)))
- .WillOnce(testing::DoAll(
- DelaySendMouseClick(&mock, &loop, 0, 10, 10, simulate_input::LEFT),
- DelaySendChar(&loop, 500, 'O', simulate_input::NONE)));
- // Watch for new window
- mock.ExpectNewWindow(&new_window_mock);
-
- EXPECT_CALL(new_window_mock, OnLoad(testing::StrCaseEq(kWindowOpenPopupUrl)))
- .WillOnce(testing::DoAll(
- VerifyAddressBarUrl(&new_window_mock),
- DelaySendMouseClick(&mock, &loop, 0, 10, 10, simulate_input::LEFT),
- DelaySendChar(&loop, 500, 'C', simulate_input::NONE)));
-
- EXPECT_CALL(new_window_mock, OnQuit())
- .Times(testing::AtMost(1))
- .WillOnce(CloseBrowserMock(&mock));
-
- EXPECT_CALL(mock, OnQuit())
- .Times(testing::AtMost(1))
- .WillOnce(QUIT_LOOP_SOON(loop, 2));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kWindowOpenUrl);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock.web_browser2() != NULL);
-
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
-}
-
-const wchar_t kWindowOpenTargetBlankUrl[] =
- L"http://localhost:1337/files/chrome_frame_target_blank.html";
-
-// This test checks if window.open calls with target blank issued for a
-// different domain make it back to IE instead of completing the navigation
-// within Chrome. We validate this by initiating a navigation to a non existent
-// url which ensures we would get an error during navigation.
-// Marking this test as FLAKY initially as it relies on getting focus and user
-// input which don't work correctly at times.
-// http://code.google.com/p/chromium/issues/detail?id=26549
-TEST_F(ChromeFrameTestWithWebServer,
- FLAKY_FullTabModeIE_WindowOpenTargetBlankInChrome) {
- CloseIeAtEndOfScope last_resort_close_ie;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> mock;
- ComStackObjectWithUninitialize<MockWebBrowserEventSink> new_window_mock;
- chrome_frame_test::TimedMsgLoop loop;
-
- mock.ExpectNavigationAndSwitch(kWindowOpenTargetBlankUrl);
-
- EXPECT_CALL(mock, OnLoad(testing::StrCaseEq(kWindowOpenTargetBlankUrl)))
- .WillOnce(testing::DoAll(
- DelaySendMouseClick(&mock, &loop, 0, 10, 10, simulate_input::LEFT),
- DelaySendChar(&loop, 500, 'O', simulate_input::NONE)));
- // Watch for new window
- mock.ExpectNewWindow(&new_window_mock);
-
- EXPECT_CALL(new_window_mock, OnBeforeNavigate2(_,
- testing::Field(&VARIANT::bstrVal,
- testing::HasSubstr(L"attach_external_tab")), _, _, _, _, _))
- .Times(testing::AtMost(1));
-
- EXPECT_CALL(new_window_mock, OnBeforeNavigate2(_,
- testing::Field(&VARIANT::bstrVal,
- testing::StrCaseEq(kHostBrowserUrl)), _, _, _, _, _))
- .Times(testing::AtMost(1));
-
- EXPECT_CALL(new_window_mock, OnNavigateError(_, _, _, _, _))
- .Times(1)
- .WillOnce(CloseBrowserMock(&new_window_mock));
-
- EXPECT_CALL(new_window_mock, OnQuit())
- .Times(1)
- .WillOnce(CloseBrowserMock(&mock));
-
- EXPECT_CALL(mock, OnQuit())
- .Times(1)
- .WillOnce(QUIT_LOOP(loop));
-
- HRESULT hr = mock.LaunchIEAndNavigate(kWindowOpenTargetBlankUrl);
- ASSERT_HRESULT_SUCCEEDED(hr);
- if (hr == S_FALSE)
- return;
-
- ASSERT_TRUE(mock.web_browser2() != NULL);
-
- loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds * 2);
-
- ASSERT_TRUE(new_window_mock.web_browser2() != NULL);
-}
-
diff --git a/chrome_frame/test/test_mock_with_web_server.h b/chrome_frame/test/test_mock_with_web_server.h
deleted file mode 100644
index fd684bb..0000000
--- a/chrome_frame/test/test_mock_with_web_server.h
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-#ifndef CHROME_FRAME_TEST_MOCK_WITH_WEB_SERVER_H_
-#define CHROME_FRAME_TEST_MOCK_WITH_WEB_SERVER_H_
-
-#include <windows.h>
-
-#include "gmock/gmock.h"
-#include "chrome_frame/chrome_frame_automation.h"
-#include "chrome_frame/test/chrome_frame_test_utils.h"
-
-#define GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING
-#include "testing/gmock_mutant.h"
-
-namespace chrome_frame_test {
-
-using ::testing::Expectation;
-using ::testing::ExpectationSet;
-
-// This class provides functionality to add expectations to IE full tab mode
-// tests.
-class MockWebBrowserEventSink : public chrome_frame_test::WebBrowserEventSink {
- public:
- // Needed to support PostTask.
- static bool ImplementsThreadSafeReferenceCounting() {
- return true;
- }
-
- MOCK_METHOD7_WITH_CALLTYPE(__stdcall, OnBeforeNavigate2,
- void (IDispatch* dispatch, // NOLINT
- VARIANT* url,
- VARIANT* flags,
- VARIANT* target_frame_name,
- VARIANT* post_data,
- VARIANT* headers,
- VARIANT_BOOL* cancel));
-
- MOCK_METHOD2_WITH_CALLTYPE(__stdcall, OnNavigateComplete2,
- void (IDispatch* dispatch, // NOLINT
- VARIANT* url));
-
- MOCK_METHOD5_WITH_CALLTYPE(__stdcall, OnNewWindow3,
- void (IDispatch** dispatch, // NOLINT
- VARIANT_BOOL* cancel,
- DWORD flags,
- BSTR url_context,
- BSTR url));
-
- MOCK_METHOD2_WITH_CALLTYPE(__stdcall, OnNewWindow2,
- void (IDispatch** dispatch, // NOLINT
- VARIANT_BOOL* cancel));
-
- MOCK_METHOD5_WITH_CALLTYPE(__stdcall, OnNavigateError,
- void (IDispatch* dispatch, // NOLINT
- VARIANT* url,
- VARIANT* frame_name,
- VARIANT* status_code,
- VARIANT* cancel));
-
- MOCK_METHOD2_WITH_CALLTYPE(__stdcall, OnFileDownload,
- void (VARIANT_BOOL active_doc,
- VARIANT_BOOL* cancel));
-
- MOCK_METHOD0_WITH_CALLTYPE(__stdcall, OnQuit,
- void ());
-
- MOCK_METHOD1(OnLoad, void (const wchar_t* url)); // NOLINT
- MOCK_METHOD1(OnLoadError, void (const wchar_t* url)); // NOLINT
- MOCK_METHOD3(OnMessage, void (const wchar_t* message,
- const wchar_t* origin,
- const wchar_t* source)); // NOLINT
- MOCK_METHOD2(OnNewBrowserWindow, void (IDispatch* dispatch, // NOLINT
- const wchar_t* url));
- MOCK_METHOD2(OnWindowDetected, void (HWND hwnd, // NOLINT
- const std::string& caption));
-
- // Test expectations for general navigations.
- ExpectationSet ExpectNavigationCardinality(const std::wstring& url,
- testing::Cardinality cardinality);
- ExpectationSet ExpectNavigation(const std::wstring& url);
- ExpectationSet ExpectNavigationAndSwitch(const std::wstring& url);
- ExpectationSet ExpectNavigationAndSwitchSequence(const std::wstring& url);
- ExpectationSet ExpectNewWindow(MockWebBrowserEventSink* new_window_mock);
- ExpectationSet ExpectNavigationSequenceForAnchors(const std::wstring& url);
-
- // Test expectations for navigations with an IE renderer.
- // Expect one navigation to occur.
- ExpectationSet ExpectNavigationInIE(const std::wstring& url);
- // Expect a new window to be opened to |url|. Set |new_window_mock| as the new
- // window.
- ExpectationSet ExpectNewWindowWithIE(
- const std::wstring& url, MockWebBrowserEventSink* new_window_mock);
-};
-
-ACTION_P(CloseBrowserMock, mock) {
- mock->CloseWebBrowser();
-}
-
-ACTION_P(VerifyAddressBarUrl, mock) {
- mock->ExpectAddressBarUrl(std::wstring(arg0));
-}
-
-ACTION_P4(DelaySendScanCode, loop, delay, c, mod) {
- loop->PostDelayedTask(FROM_HERE, NewRunnableFunction(
- simulate_input::SendScanCode, c, mod), delay);
-}
-
-ACTION_P5(ValidateWindowSize, mock, left, top, width, height) {
- long actual_left = 0;
- long actual_top = 0;
- long actual_width = 0;
- long actual_height = 0;
-
- mock->web_browser2()->get_Left(&actual_left);
- mock->web_browser2()->get_Top(&actual_top);
- mock->web_browser2()->get_Width(&actual_width);
- mock->web_browser2()->get_Height(&actual_height);
-
- EXPECT_EQ(actual_left, left);
- EXPECT_EQ(actual_top, top);
- EXPECT_EQ(actual_width, width);
- EXPECT_EQ(actual_height, height);
-}
-
-ACTION_P4(DelaySendChar, loop, delay, c, mod) {
- loop->PostDelayedTask(FROM_HERE, NewRunnableFunction(
- simulate_input::SendCharA, c, mod), delay);
-}
-
-ACTION_P3(DelayCloseBrowserMock, loop, delay, mock) {
- loop->PostDelayedTask(FROM_HERE, NewRunnableMethod(mock,
- &MockWebBrowserEventSink::CloseWebBrowser), delay);
-}
-
-} // namespace chrome_frame_test
-
-#endif // CHROME_FRAME_TEST_MOCK_WITH_WEB_SERVER_H_
-
diff --git a/chrome_frame/test/test_server.cc b/chrome_frame/test/test_server.cc
index 88672b8..8f0910d 100644
--- a/chrome_frame/test/test_server.cc
+++ b/chrome_frame/test/test_server.cc
@@ -5,6 +5,7 @@
#include "base/logging.h"
#include "base/registry.h"
#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
#include "chrome_frame/test/test_server.h"
@@ -217,9 +218,11 @@ void SimpleWebServer::DidClose(ListenSocket* sock) {
}
}
-HTTPTestServer::HTTPTestServer(int port, const char* address) {
+HTTPTestServer::HTTPTestServer(int port, const std::wstring& address,
+ FilePath root_dir)
+ : port_(port), address_(address), root_dir_(root_dir) {
net::EnsureWinsockInit();
- server_ = ListenSocket::Listen(address, port, this);
+ server_ = ListenSocket::Listen(WideToUTF8(address), port, this);
}
HTTPTestServer::~HTTPTestServer() {
@@ -258,10 +261,11 @@ void HTTPTestServer::DidRead(ListenSocket* socket,
std::string str(data, len);
connection->r_.OnDataReceived(str);
if (connection->r_.AllContentReceived()) {
+ std::wstring path = UTF8ToWide(connection->r_.path());
if (LowerCaseEqualsASCII(connection->r_.method(), "post"))
- this->Post(connection, connection->r_.path(), connection->r_);
+ this->Post(connection, path, connection->r_);
else
- this->Get(connection, connection->r_.path(), connection->r_);
+ this->Get(connection, path, connection->r_);
}
}
}
@@ -272,6 +276,29 @@ void HTTPTestServer::DidClose(ListenSocket* socket) {
connection_list_.erase(it);
}
+std::wstring HTTPTestServer::Resolve(const std::wstring& path) {
+ // Remove the first '/' if needed.
+ std::wstring stripped_path = path;
+ if (path.size() && path[0] == L'/')
+ stripped_path = path.substr(1);
+
+ if (port_ == 80) {
+ if (stripped_path.empty()) {
+ return StringPrintf(L"http://%ls", address_.c_str());
+ } else {
+ return StringPrintf(L"http://%ls/%ls", address_.c_str(),
+ stripped_path.c_str());
+ }
+ } else {
+ if (stripped_path.empty()) {
+ return StringPrintf(L"http://%ls:%d", address_.c_str(), port_);
+ } else {
+ return StringPrintf(L"http://%ls:%d/%ls", address_.c_str(), port_,
+ stripped_path.c_str());
+ }
+ }
+}
+
void ConfigurableConnection::SendChunk() {
int size = (int)data_.size();
const char* chunk_ptr = data_.c_str() + cur_pos_;
@@ -334,4 +361,5 @@ void ConfigurableConnection::SendWithOptions(const std::string& headers,
NewRunnableMethod(this, &ConfigurableConnection::SendChunk),
options.timeout_);
}
-} // namespace test_server
+
+} // namespace test_server \ No newline at end of file
diff --git a/chrome_frame/test/test_server.h b/chrome_frame/test/test_server.h
index c3fab96..2b8454a 100644
--- a/chrome_frame/test/test_server.h
+++ b/chrome_frame/test/test_server.h
@@ -370,16 +370,29 @@ class ConfigurableConnection : public base::RefCounted<ConfigurableConnection> {
// instance to send the response.
class HTTPTestServer : public ListenSocket::ListenSocketDelegate {
public:
- explicit HTTPTestServer(int port, const char* address);
+ explicit HTTPTestServer(int port, const std::wstring& address,
+ FilePath root_dir);
virtual ~HTTPTestServer();
+
// HTTP GET request is received. Override in derived classes.
// |connection| can be used to send the response.
virtual void Get(ConfigurableConnection* connection,
- const std::string& path, const Request& r) = 0;
+ const std::wstring& path, const Request& r) = 0;
+
// HTTP POST request is received. Override in derived classes.
// |connection| can be used to send the response
virtual void Post(ConfigurableConnection* connection,
- const std::string& path, const Request& r) = 0;
+ const std::wstring& path, const Request& r) = 0;
+
+ // Return the appropriate url with the specified path for this server.
+ std::wstring Resolve(const std::wstring& path);
+
+ FilePath root_dir() { return root_dir_; }
+
+ protected:
+ int port_;
+ std::wstring address_;
+ FilePath root_dir_;
private:
typedef std::list<scoped_refptr<ConfigurableConnection> > ConnectionList;
@@ -394,10 +407,10 @@ class HTTPTestServer : public ListenSocket::ListenSocketDelegate {
scoped_refptr<ListenSocket> server_;
ConnectionList connection_list_;
+
DISALLOW_COPY_AND_ASSIGN(HTTPTestServer);
};
-
} // namespace test_server
#endif // CHROME_FRAME_TEST_TEST_SERVER_H_
diff --git a/chrome_frame/test/test_with_web_server.cc b/chrome_frame/test/test_with_web_server.cc
index b7a5a22..d35dcf7 100644
--- a/chrome_frame/test/test_with_web_server.cc
+++ b/chrome_frame/test/test_with_web_server.cc
@@ -1,22 +1,47 @@
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+
#include "chrome_frame/test/test_with_web_server.h"
#include "base/file_version_info.h"
+#include "base/utf_string_conversions.h"
#include "base/win_util.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/installer/util/install_util.h"
#include "chrome/installer/util/helper.h"
#include "chrome_frame/utils.h"
#include "chrome_frame/test/chrome_frame_test_utils.h"
+#include "chrome_frame/test/mock_ie_event_sink_actions.h"
+#include "net/base/mime_util.h"
using chrome_frame_test::kChromeFrameLongNavigationTimeoutInSeconds;
+using testing::_;
+using testing::StrCaseEq;
const wchar_t kDocRoot[] = L"chrome_frame\\test\\data";
const int kLongWaitTimeout = 60 * 1000;
const int kShortWaitTimeout = 25 * 1000;
+namespace {
+
+// Helper method for creating the appropriate HTTP response headers.
+std::string CreateHttpHeaders(CFInvocation invocation,
+ bool add_no_cache_header,
+ const std::string& content_type) {
+ std::ostringstream ss;
+ ss << "HTTP/1.1 200 OK\r\n"
+ << "Connection: close\r\n"
+ << "Content-Type: " << content_type << "\r\n";
+ if (invocation.type() == CFInvocation::HTTP_HEADER)
+ ss << "X-UA-Compatible: chrome=1\r\n";
+ if (add_no_cache_header)
+ ss << "Cache-Control: no-cache\r\n";
+ return ss.str();
+}
+
+} // namespace
+
class ChromeFrameTestEnvironment: public testing::Environment {
public:
~ChromeFrameTestEnvironment() {}
@@ -236,6 +261,64 @@ void ChromeFrameTestWithWebServer::VersionTest(BrowserKind browser,
ASSERT_TRUE(CheckResultFile(result_file_to_check, WideToUTF8(version)));
}
+// MockWebServer methods
+void MockWebServer::ExpectAndServeRequest(CFInvocation invocation,
+ const std::wstring& url) {
+ EXPECT_CALL(*this, Get(_, chrome_frame_test::UrlPathEq(url), _))
+ .WillOnce(SendResponse(this, invocation));
+}
+
+void MockWebServer::ExpectAndServeRequestAllowCache(CFInvocation invocation,
+ const std::wstring &url) {
+ EXPECT_CALL(*this, Get(_, chrome_frame_test::UrlPathEq(url), _))
+ .WillOnce(SendResponse(this, invocation));
+}
+
+void MockWebServer::ExpectAndServeRequestAnyNumberTimes(
+ CFInvocation invocation, const std::wstring& path_prefix) {
+ EXPECT_CALL(*this, Get(_, testing::StartsWith(path_prefix), _))
+ .WillRepeatedly(SendResponse(this, invocation));
+}
+
+void MockWebServer::SendResponseHelper(
+ test_server::ConfigurableConnection* connection,
+ const std::wstring& request_uri,
+ CFInvocation invocation,
+ bool add_no_cache_header) {
+ // Convert |request_uri| to a path.
+ std::wstring path = request_uri;
+ size_t query_index = request_uri.find(L"?");
+ if (query_index != std::string::npos) {
+ path = path.erase(query_index);
+ }
+ FilePath file_path = root_dir_;
+ if (path.size())
+ file_path = file_path.Append(path.substr(1)); // remove first '/'
+
+ std::string headers, body;
+ if (file_util::PathExists(file_path)) {
+ std::string content_type;
+ EXPECT_TRUE(net::GetMimeTypeFromFile(file_path, &content_type));
+ DLOG(INFO) << "Going to send file (" << WideToUTF8(file_path.value())
+ << ") with content type (" << content_type << ")";
+ headers = CreateHttpHeaders(invocation, add_no_cache_header, content_type);
+
+ EXPECT_TRUE(file_util::ReadFileToString(file_path, &body))
+ << "Could not read file (" << WideToUTF8(file_path.value()) << ")";
+ if (invocation.type() == CFInvocation::META_TAG &&
+ StartsWithASCII(content_type, "text/html", false)) {
+ EXPECT_TRUE(chrome_frame_test::AddCFMetaTag(&body)) << "Could not add "
+ << "meta tag to HTML file.";
+ }
+ } else {
+ DLOG(INFO) << "Going to send 404 for non-existent file ("
+ << WideToUTF8(file_path.value()) << ")";
+ headers = "HTTP/1.1 404 Not Found";
+ body = "";
+ }
+ connection->Send(headers, body);
+}
+
const wchar_t kPostMessageBasicPage[] = L"files/postmessage_basic_host.html";
TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_PostMessageBasic) {
diff --git a/chrome_frame/test/test_with_web_server.h b/chrome_frame/test/test_with_web_server.h
index 30466b9b..18e7086 100644
--- a/chrome_frame/test/test_with_web_server.h
+++ b/chrome_frame/test/test_with_web_server.h
@@ -177,6 +177,66 @@ class SimpleWebServerTest {
int port_;
};
+// Specifies the invocation method for CF.
+class CFInvocation {
+ public:
+ enum Type {
+ NONE = 0,
+ META_TAG,
+ HTTP_HEADER
+ };
+
+ CFInvocation(): method_(NONE) {}
+ explicit CFInvocation(Type method): method_(method) {}
+
+ // Convience methods for creating this class.
+ static CFInvocation None() { return CFInvocation(NONE); }
+ static CFInvocation MetaTag() { return CFInvocation(META_TAG); }
+ static CFInvocation HttpHeader() { return CFInvocation(HTTP_HEADER); }
+
+ // Returns whether this page does invoke CF.
+ bool invokes_cf() const {
+ return method_ != NONE;
+ }
+
+ Type type() const { return method_; }
+
+ private:
+ Type method_;
+};
+
+ACTION_P2(SendFast, headers, content) {
+ arg0->Send(headers, content);
+}
+
+ACTION_P4(Send, headers, content, chunk, timeout) {
+ test_server::ConfigurableConnection::SendOptions options(
+ test_server::ConfigurableConnection::SendOptions::
+ IMMEDIATE_HEADERS_DELAYED_CONTENT, chunk, timeout);
+ arg0->SendWithOptions(std::string(headers),
+ std::string(content),
+ options);
+}
+
+ACTION_P4(SendSlow, headers, content, chunk, timeout) {
+ test_server::ConfigurableConnection::SendOptions options(
+ test_server::ConfigurableConnection::SendOptions::DELAYED, chunk, timeout);
+ arg0->SendWithOptions(std::string(headers),
+ std::string(content),
+ options);
+}
+
+// Sends a response with the file data for the given path, if the file exists,
+// or a 404 if the file does not. This response includes a no-cache header.
+ACTION_P2(SendResponse, server, invocation) {
+ server->SendResponseHelper(arg0, arg1, invocation, true);
+}
+
+// Same as above except that the response does not include the no-cache header.
+ACTION_P2(SendAllowCacheResponse, server, invocation) {
+ server->SendResponseHelper(arg0, arg1, invocation, false);
+}
+
// Simple Gmock friendly web server. Sample usage:
// MockWebServer mock(9999, "0.0.0.0");
// EXPECT_CALL(mock, Get(_, StrEq("/favicon.ico"), _)).WillRepeatedly(SendFast(
@@ -196,38 +256,47 @@ class SimpleWebServerTest {
// "Content-Type: text/html\r\n",
// "<html><meta http-equiv=\"X-UA-Compatible\" content=\"chrome=1\" />"
// "<body>Rendered in CF.</body></html>", 4, 1000));
-
class MockWebServer : public test_server::HTTPTestServer {
public:
- MockWebServer(int port, const char* address = "127.0.0.1")
- : test_server::HTTPTestServer(port, address) {}
+ MockWebServer(int port, const std::wstring& address, FilePath root_dir)
+ : test_server::HTTPTestServer(port, address, root_dir) {}
+
+ // Overriden from test_server::HTTPTestServer.
MOCK_METHOD3(Get, void(test_server::ConfigurableConnection* connection,
- const std::string& path,
+ const std::wstring& path,
const test_server::Request&r));
MOCK_METHOD3(Post, void(test_server::ConfigurableConnection* connection,
- const std::string& path,
+ const std::wstring& path,
const test_server::Request&r));
-};
-
-ACTION_P2(SendFast, headers, content) {
- arg0->Send(headers, content);
-}
-ACTION_P4(Send, headers, content, chunk, timeout) {
- test_server::ConfigurableConnection::SendOptions options(
- test_server::ConfigurableConnection::SendOptions::
- IMMEDIATE_HEADERS_DELAYED_CONTENT, chunk, timeout);
- arg0->SendWithOptions(std::string(headers),
- std::string(content),
- options);
-}
+ // Expect a GET request for |url|. Respond with the file appropriate for
+ // the given |url|. Modify the file to follow the given CFInvocation method.
+ // The response includes a no-cache header. |allow_meta_tag_double_req|
+ // specifies whether to allow the request to happen twice if the invocation
+ // is using the CF meta tag.
+ void ExpectAndServeRequest(CFInvocation invocation, const std::wstring& url);
+
+ // Same as above except do not include the no-cache header.
+ void ExpectAndServeRequestAllowCache(CFInvocation invocation,
+ const std::wstring& url);
+
+ // Expect any number of GETs for the given resource path (e.g, /favicon.ico)
+ // and respond with the file, if it exists, or a 404 if it does not.
+ void ExpectAndServeRequestAnyNumberTimes(CFInvocation invocation,
+ const std::wstring& path_prefix);
+
+ // Expect and serve all incoming GET requests.
+ void ExpectAndServeAnyRequests(CFInvocation invocation) {
+ ExpectAndServeRequestAnyNumberTimes(invocation, L"");
+ }
-ACTION_P4(SendSlow, headers, content, chunk, timeout) {
- test_server::ConfigurableConnection::SendOptions options(
- test_server::ConfigurableConnection::SendOptions::DELAYED, chunk, timeout);
- arg0->SendWithOptions(std::string(headers),
- std::string(content),
- options);
-}
+ // Send a response on the given connection appropriate for |resource_uri|.
+ // If the file referred to by |path| exists, send the file data, otherwise
+ // send 404. Modify the file data according to the given invocation method.
+ void SendResponseHelper(test_server::ConfigurableConnection* connection,
+ const std::wstring& resource_uri,
+ CFInvocation invocation,
+ bool add_no_cache_header);
+};
#endif // CHROME_FRAME_TEST_TEST_WITH_WEB_SERVER_H_
diff --git a/chrome_frame/test/ui_test.cc b/chrome_frame/test/ui_test.cc
new file mode 100644
index 0000000..19ad10a
--- /dev/null
+++ b/chrome_frame/test/ui_test.cc
@@ -0,0 +1,541 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <mshtmcid.h>
+#include <string>
+
+#include "chrome/common/url_constants.h"
+#include "chrome_frame/test/chrome_frame_test_utils.h"
+#include "chrome_frame/test/mock_ie_event_sink_actions.h"
+#include "chrome_frame/test/mock_ie_event_sink_test.h"
+
+using testing::_;
+using testing::InSequence;
+using testing::StrCaseEq;
+using testing::StrEq;
+
+namespace chrome_frame_test {
+
+// This parameterized test fixture uses the MockIEEventSink and is used by
+// UI-related tests.
+class FullTabUITest : public MockIEEventSinkTest,
+ public testing::TestWithParam<CFInvocation> {
+ public:
+ FullTabUITest() {}
+
+ virtual void SetUp() {
+ // These are UI-related tests, so we do not care about the exact requests
+ // and navigations that occur.
+ server_mock_.ExpectAndServeAnyRequests(GetParam());
+ ie_mock_.ExpectAnyNavigations();
+ }
+};
+
+// Instantiate each test case for the IE case and for CF meta tag case.
+// It does not seem too useful to also run the CF http header case since these
+// are UI, not navigation tests.
+INSTANTIATE_TEST_CASE_P(IE, FullTabUITest,
+ testing::Values(CFInvocation::None()));
+INSTANTIATE_TEST_CASE_P(CF, FullTabUITest,
+ testing::Values(CFInvocation::MetaTag()));
+
+// Tests keyboard input.
+// Marking this test FLAKY as it fails at times on the buildbot.
+// http://code.google.com/p/chromium/issues/detail?id=26549
+TEST_P(FullTabUITest, FLAKY_KeyboardInput) {
+ if (!GetParam().invokes_cf()) {
+ LOG(ERROR) << "Test not implemented for this configuration.";
+ return;
+ }
+ std::wstring key_event_url = GetTestUrl(L"keyevent.html");
+
+ const wchar_t* input = L"Chrome";
+ EXPECT_CALL(ie_mock_, OnLoad(GetParam().invokes_cf(), StrEq(key_event_url)))
+ .WillOnce(testing::DoAll(
+ SetFocusToRenderer(&ie_mock_),
+ DelaySendString(&loop_, 500, input)));
+
+ EXPECT_CALL(ie_mock_, OnMessage(StrCaseEq(input), _, _))
+ .WillOnce(CloseBrowserMock(&ie_mock_));
+
+ LaunchIEAndNavigate(key_event_url);
+}
+
+// Tests keyboard shortcuts for back and forward.
+// Marking this test FLAKY as it fails at times on the buildbot.
+// http://code.google.com/p/chromium/issues/detail?id=26549
+TEST_P(FullTabUITest, FLAKY_KeyboardBackForward) {
+ std::wstring page1 = GetSimplePageUrl();
+ std::wstring page2 = GetLinkPageUrl();
+ bool in_cf = GetParam().invokes_cf();
+ InSequence expect_in_sequence_for_scope;
+
+ // This test performs the following steps.
+ // 1. Launches IE and navigates to page1
+ // 2. It then navigates to page2
+ // 3. Sends the VK_BACK keystroke to IE, which should navigate back to
+ // page 1
+ // 4. Sends the Shift + VK_BACK keystroke to IE which should navigate
+ // forward to page2
+ EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(page1)))
+ .WillOnce(Navigate(&ie_mock_, page2));
+
+ short bkspace = VkKeyScanA(VK_BACK); // NOLINT
+ EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(page2)))
+ .WillOnce(testing::DoAll(
+ SetFocusToRenderer(&ie_mock_),
+ DelaySendScanCode(&loop_, 500, bkspace, simulate_input::NONE)));
+
+ EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(page1)))
+ .WillOnce(testing::DoAll(
+ SetFocusToRenderer(&ie_mock_),
+ DelaySendScanCode(&loop_, 1000, bkspace, simulate_input::SHIFT)));
+
+ EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(page2)))
+ .WillOnce(CloseBrowserMock(&ie_mock_));
+
+ LaunchIENavigateAndLoop(page1,
+ kChromeFrameLongNavigationTimeoutInSeconds * 2);
+}
+
+// Tests new window behavior with ctrl+N.
+TEST_P(FullTabUITest, FLAKY_CtrlN) {
+ bool is_cf = GetParam().invokes_cf();
+ if (!is_cf) {
+ LOG(ERROR) << "Test not implemented for this configuration.";
+ return;
+ }
+ // Ideally we want to use a ie_mock_ to watch for finer grained
+ // events for New Window, but for Crl+N we don't get any
+ // OnNewWindowX notifications. :(
+ MockWindowObserver win_observer_mock;
+ const wchar_t* kIEFrameClass = L"IEFrame";
+ EXPECT_CALL(ie_mock_, OnLoad(is_cf, StrEq(GetSimplePageUrl())))
+ .WillOnce(testing::DoAll(
+ WatchWindow(&win_observer_mock, kIEFrameClass),
+ SetFocusToRenderer(&ie_mock_),
+ DelaySendChar(&loop_, 1000, 'n', simulate_input::CONTROL)));
+
+ // Watch for new window
+ const char* kNewWindowTitle = "Internet Explorer";
+ EXPECT_CALL(win_observer_mock,
+ OnWindowDetected(_, testing::HasSubstr(kNewWindowTitle)))
+ .WillOnce(testing::DoAll(
+ DoCloseWindow(),
+ CloseBrowserMock(&ie_mock_)));
+
+ LaunchIEAndNavigate(GetSimplePageUrl());
+ // TODO(kkania): The new window does not close properly sometimes.
+}
+
+// Test that ctrl+r does cause a refresh.
+TEST_P(FullTabUITest, FLAKY_CtrlR) {
+ InSequence expect_in_sequence_for_scope;
+
+ EXPECT_CALL(ie_mock_, OnLoad(GetParam().invokes_cf(),
+ StrEq(GetSimplePageUrl())))
+ .WillOnce(testing::DoAll(
+ SetFocusToRenderer(&ie_mock_),
+ DelaySendChar(&loop_, 1000, 'r', simulate_input::CONTROL)));
+
+ EXPECT_CALL(server_mock_, Get(_, UrlPathEq(GetSimplePageUrl()), _))
+ .WillOnce(testing::DoAll(
+ SendResponse(&server_mock_, GetParam()),
+ CloseBrowserMock(&ie_mock_)));
+
+ LaunchIEAndNavigate(GetSimplePageUrl());
+}
+
+// Test window close with ctrl+w.
+TEST_P(FullTabUITest, FLAKY_CtrlW) {
+ EXPECT_CALL(ie_mock_, OnLoad(GetParam().invokes_cf(),
+ StrEq(GetSimplePageUrl())))
+ .WillOnce(testing::DoAll(
+ SetFocusToRenderer(&ie_mock_),
+ DelaySendChar(&loop_, 1000, 'w', simulate_input::CONTROL)));
+
+ LaunchIEAndNavigate(GetSimplePageUrl());
+}
+
+// Test address bar navigation with Alt+d and URL.
+TEST_P(FullTabUITest, FLAKY_AltD) {
+ if (IsIBrowserServicePatchEnabled()) {
+ LOG(ERROR) << "Not running test. IBrowserServicePatch is in place.";
+ return;
+ }
+ EXPECT_CALL(ie_mock_, OnLoad(GetParam().invokes_cf(),
+ StrEq(GetSimplePageUrl())))
+ .WillOnce(testing::DoAll(
+ SetFocusToRenderer(&ie_mock_),
+ TypeUrlInAddressBar(&loop_, GetLinkPageUrl(), 1500)));
+
+ EXPECT_CALL(ie_mock_, OnLoad(GetParam().invokes_cf(),
+ StrEq(GetLinkPageUrl())))
+ .WillOnce(CloseBrowserMock(&ie_mock_));
+
+ LaunchIEAndNavigate(GetSimplePageUrl());
+}
+
+// Tests that the renderer has focus after navigation.
+TEST_P(FullTabUITest, FLAKY_RendererHasFocus) {
+ EXPECT_CALL(ie_mock_, OnLoad(GetParam().invokes_cf(),
+ StrEq(GetSimplePageUrl())))
+ .WillOnce(testing::DoAll(
+ ExpectRendererHasFocus(&ie_mock_),
+ CloseBrowserMock(&ie_mock_)));
+
+ LaunchIEAndNavigate(GetSimplePageUrl());
+}
+
+// Tests that view source works.
+// This test has been marked FLAKY
+// http://code.google.com/p/chromium/issues/detail?id=35370
+TEST_P(FullTabUITest, FLAKY_ViewSource) {
+ bool in_cf = GetParam().invokes_cf();
+ if (!in_cf) {
+ LOG(ERROR) << "Test not implemented for this configuration.";
+ return;
+ }
+ MockIEEventSink view_source_mock;
+ view_source_mock.ExpectAnyNavigations();
+ InSequence expect_in_sequence_for_scope;
+
+ // After navigation invoke view soruce action using IWebBrowser2::ExecWB
+ VARIANT empty = ScopedVariant::kEmptyVariant;
+ EXPECT_CALL(ie_mock_, OnLoad(in_cf,
+ StrEq(GetSimplePageUrl())))
+ .WillOnce(DelayExecCommand(&ie_mock_, &loop_, 0, &CGID_MSHTML,
+ static_cast<OLECMDID>(IDM_VIEWSOURCE),
+ OLECMDEXECOPT_DONTPROMPTUSER, &empty, &empty));
+
+ // Expect notification for view-source window, handle new window event
+ // and attach a new ie_mock_ to the received web browser
+ std::wstring view_source_url;
+ view_source_url += UTF8ToWide(chrome::kViewSourceScheme);
+ view_source_url += L":";
+ view_source_url += GetSimplePageUrl();
+ std::wstring url_in_new_window = kChromeProtocolPrefix;
+ url_in_new_window += view_source_url;
+
+ ie_mock_.ExpectNewWindow(&view_source_mock);
+ // For some reason this happens occasionally at least on XP IE7.
+ EXPECT_CALL(view_source_mock, OnLoad(false, StrEq(url_in_new_window)))
+ .Times(testing::AtMost(1));
+ EXPECT_CALL(view_source_mock, OnLoad(in_cf, StrEq(view_source_url)))
+ .WillOnce(testing::DoAll(
+ VerifyAddressBarUrlWithGcf(&view_source_mock),
+ CloseBrowserMock(&view_source_mock)));
+
+ EXPECT_CALL(view_source_mock, OnQuit())
+ .Times(testing::AtMost(1))
+ .WillOnce(CloseBrowserMock(&ie_mock_));
+
+ LaunchIEAndNavigate(GetSimplePageUrl());
+}
+
+// Test fixture for tests related to the context menu UI. Since the context
+// menus for CF and IE are different, these tests are not parameterized.
+class ContextMenuTest : public MockIEEventSinkTest, public testing::Test {
+ public:
+ ContextMenuTest() {}
+
+ virtual void SetUp() {
+ // These are UI-related tests, so we do not care about the exact
+ // navigations that occur.
+ ie_mock_.ExpectAnyNavigations();
+ }
+};
+
+// Test Reload from context menu.
+// Marking this test FLAKY as it fails at times on the buildbot.
+// http://code.google.com/p/chromium/issues/detail?id=26549
+TEST_F(ContextMenuTest, FLAKY_CFReload) {
+ server_mock_.ExpectAndServeAnyRequests(CFInvocation::MetaTag());
+ InSequence expect_in_sequence_for_scope;
+
+ // Reload using Rt-Click + DOWN + DOWN + DOWN + ENTER
+ EXPECT_CALL(ie_mock_, OnLoad(IN_CF, StrEq(GetSimplePageUrl())))
+ .WillOnce(testing::DoAll(
+ DelaySendMouseClick(&ie_mock_, &loop_, 0, 10, 10,
+ simulate_input::RIGHT),
+ SendExtendedKeysEnter(&loop_, 500, VK_DOWN, 3,
+ simulate_input::NONE)));
+
+ EXPECT_CALL(ie_mock_, OnLoad(IN_CF, StrEq(GetSimplePageUrl())))
+ .WillOnce(CloseBrowserMock(&ie_mock_));
+
+ LaunchIEAndNavigate(GetSimplePageUrl());
+}
+
+// Test view source using context menu
+// Marking this test FLAKY as it fails at times on the buildbot.
+// http://code.google.com/p/chromium/issues/detail?id=26549
+TEST_F(ContextMenuTest, FLAKY_CFViewSource) {
+ server_mock_.ExpectAndServeAnyRequests(CFInvocation::MetaTag());
+ MockIEEventSink view_source_mock;
+ view_source_mock.ExpectAnyNavigations();
+ InSequence expect_in_sequence_for_scope;
+
+ // View source using Rt-Click + UP + UP + UP + UP + ENTER
+ EXPECT_CALL(ie_mock_, OnLoad(IN_CF, StrEq(GetSimplePageUrl())))
+ .WillOnce(testing::DoAll(
+ DelaySendMouseClick(&ie_mock_, &loop_, 0, 10, 10,
+ simulate_input::RIGHT),
+ SendExtendedKeysEnter(&loop_, 500, VK_UP, 4, simulate_input::NONE)));
+
+ // Expect notification for view-source window, handle new window event
+ // and attach a new ie_mock_ to the received web browser
+ std::wstring view_source_url;
+ view_source_url += UTF8ToWide(chrome::kViewSourceScheme);
+ view_source_url += L":";
+ view_source_url += GetSimplePageUrl();
+ std::wstring url_in_new_window = kChromeProtocolPrefix;
+ url_in_new_window += view_source_url;
+
+ ie_mock_.ExpectNewWindow(&view_source_mock);
+ EXPECT_CALL(view_source_mock, OnLoad(IN_CF, StrEq(view_source_url)))
+ .WillOnce(testing::DoAll(
+ VerifyAddressBarUrlWithGcf(&view_source_mock),
+ CloseBrowserMock(&view_source_mock)));
+ EXPECT_CALL(view_source_mock, OnQuit())
+ .Times(testing::AtMost(1))
+ .WillOnce(CloseBrowserMock(&ie_mock_));
+
+ LaunchIEAndNavigate(GetSimplePageUrl());
+}
+
+TEST_F(ContextMenuTest, FLAKY_CFPageInfo) {
+ server_mock_.ExpectAndServeAnyRequests(CFInvocation::MetaTag());
+ MockWindowObserver win_observer_mock;
+ InSequence expect_in_sequence_for_scope;
+
+ // View page information using Rt-Click + UP + UP + UP + ENTER
+ const wchar_t* kPageInfoWindowClass = L"Chrome_WidgetWin_0";
+ EXPECT_CALL(ie_mock_, OnLoad(IN_CF, StrEq(GetSimplePageUrl())))
+ .WillOnce(testing::DoAll(
+ WatchWindow(&win_observer_mock, kPageInfoWindowClass),
+ DelaySendMouseClick(&ie_mock_, &loop_, 0, 10, 10,
+ simulate_input::RIGHT),
+ SendExtendedKeysEnter(&loop_, 500, VK_UP, 3, simulate_input::NONE)));
+
+ // Expect page info dialog to pop up. Dismiss the dialog with 'Esc' key
+ const char* kPageInfoCaption = "Security Information";
+ EXPECT_CALL(win_observer_mock, OnWindowDetected(_, StrEq(kPageInfoCaption)))
+ .WillOnce(testing::DoAll(
+ DelaySendChar(&loop_, 100, VK_ESCAPE, simulate_input::NONE),
+ DelayCloseBrowserMock(&loop_, 2000, &ie_mock_)));
+
+ LaunchIEAndNavigate(GetSimplePageUrl());
+}
+
+TEST_F(ContextMenuTest, FLAKY_CFInspector) {
+ server_mock_.ExpectAndServeAnyRequests(CFInvocation::MetaTag());
+ MockWindowObserver win_observer_mock;
+ InSequence expect_in_sequence_for_scope;
+
+ // Open developer tools using Rt-Click + UP + UP + ENTER
+ const wchar_t* kPageInfoWindowClass = L"Chrome_WidgetWin_0";
+ EXPECT_CALL(ie_mock_, OnLoad(IN_CF, StrEq(GetSimplePageUrl())))
+ .WillOnce(testing::DoAll(
+ WatchWindow(&win_observer_mock, kPageInfoWindowClass),
+ DelaySendMouseClick(&ie_mock_, &loop_, 0, 10, 10,
+ simulate_input::RIGHT),
+ SendExtendedKeysEnter(&loop_, 500, VK_UP, 2, simulate_input::NONE)));
+
+ // Devtools begins life with "Untitled" caption and it changes
+ // later to the 'Developer Tools - <url> form.
+ const char* kPageInfoCaption = "Untitled";
+ EXPECT_CALL(win_observer_mock,
+ OnWindowDetected(_, testing::StartsWith(kPageInfoCaption)))
+ .WillOnce(testing::DoAll(
+ SetFocusToRenderer(&ie_mock_),
+ DelayCloseBrowserMock(&loop_, 2000, &ie_mock_)));
+
+ LaunchIEAndNavigate(GetSimplePageUrl());
+}
+
+TEST_F(ContextMenuTest, FLAKY_CFSaveAs) {
+ server_mock_.ExpectAndServeAnyRequests(CFInvocation::MetaTag());
+ MockWindowObserver win_observer_mock;
+ InSequence expect_in_sequence_for_scope;
+
+ // Open'Save As' dialog using Rt-Click + DOWN + DOWN + DOWN + DOWN + ENTER
+ const wchar_t* kSaveDlgClass = L"#32770";
+ EXPECT_CALL(ie_mock_, OnLoad(IN_CF, StrEq(GetSimplePageUrl())))
+ .WillOnce(testing::DoAll(
+ WatchWindow(&win_observer_mock, kSaveDlgClass),
+ DelaySendMouseClick(&ie_mock_, &loop_, 0, 10, 10,
+ simulate_input::RIGHT),
+ SendExtendedKeysEnter(&loop_, 500, VK_DOWN, 4,
+ simulate_input::NONE)));
+
+ FilePath temp_file_path;
+ EXPECT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
+ temp_file_path = temp_file_path.ReplaceExtension(L".htm");
+
+ const wchar_t* kSaveFileName = temp_file_path.value().c_str();
+ DeleteFile(kSaveFileName);
+
+ const char* kSaveDlgCaption = "Save As";
+ EXPECT_CALL(win_observer_mock, OnWindowDetected(_, StrEq(kSaveDlgCaption)))
+ .WillOnce(testing::DoAll(
+ DelaySendString(&loop_, 100, kSaveFileName),
+ DelaySendChar(&loop_, 200, VK_RETURN, simulate_input::NONE),
+ DelayCloseBrowserMock(&loop_, 4000, &ie_mock_)));
+
+ LaunchIEAndNavigate(GetSimplePageUrl());
+ ASSERT_NE(INVALID_FILE_ATTRIBUTES, GetFileAttributes(kSaveFileName));
+ ASSERT_TRUE(DeleteFile(kSaveFileName));
+}
+
+// This tests that the about:version page can be opened via the CF context menu.
+TEST_F(ContextMenuTest, FLAKY_CFAboutVersionLoads) {
+ server_mock_.ExpectAndServeAnyRequests(CFInvocation::MetaTag());
+ const wchar_t* kAboutVersionUrl = L"gcf:about:version";
+ const wchar_t* kAboutVersionWithoutProtoUrl = L"about:version";
+ MockIEEventSink new_window_mock;
+ new_window_mock.ExpectAnyNavigations();
+
+ ie_mock_.ExpectNavigation(IN_CF, GetSimplePageUrl());
+ EXPECT_CALL(ie_mock_, OnLoad(IN_CF, StrEq(GetSimplePageUrl())))
+ .WillOnce(testing::DoAll(
+ DelaySendMouseClick(&ie_mock_, &loop_, 0, 10, 10,
+ simulate_input::RIGHT),
+ SendExtendedKeysEnter(&loop_, 500, VK_UP, 1, simulate_input::NONE)));
+
+ ie_mock_.ExpectNewWindow(&new_window_mock);
+ EXPECT_CALL(new_window_mock,
+ OnLoad(IN_CF, StrEq(kAboutVersionWithoutProtoUrl)))
+ .WillOnce(testing::DoAll(
+ VerifyAddressBarUrlWithGcf(&new_window_mock),
+ CloseBrowserMock(&new_window_mock)));
+
+ EXPECT_CALL(new_window_mock, OnQuit())
+ .Times(testing::AtMost(1))
+ .WillOnce(CloseBrowserMock(&ie_mock_));
+
+ LaunchIEAndNavigate(GetSimplePageUrl());
+}
+
+TEST_F(ContextMenuTest, FLAKY_IEOpen) {
+ server_mock_.ExpectAndServeAnyRequests(CFInvocation::None());
+ // Focus the renderer window by clicking and then tab once to highlight the
+ // link.
+ EXPECT_CALL(ie_mock_, OnLoad(IN_IE, StrEq(GetLinkPageUrl())))
+ .WillOnce(testing::DoAll(
+ DelaySendMouseClick(&ie_mock_, &loop_, 0, 1, 1, simulate_input::LEFT),
+ DelaySendScanCode(&loop_, 1000, VK_TAB, simulate_input::NONE),
+ OpenContextMenu(&loop_, 2000),
+ SelectItem(&loop_, 3000, 0)));
+
+ EXPECT_CALL(ie_mock_, OnLoad(IN_IE, StrEq(GetSimplePageUrl())))
+ .WillOnce(testing::DoAll(
+ VerifyAddressBarUrl(&ie_mock_),
+ CloseBrowserMock(&ie_mock_)));
+
+ LaunchIEAndNavigate(GetLinkPageUrl());
+}
+
+TEST_F(ContextMenuTest, FLAKY_IEOpenInNewWindow) {
+ server_mock_.ExpectAndServeAnyRequests(CFInvocation::None());
+ MockIEEventSink new_window_mock;
+ new_window_mock.ExpectAnyNavigations();
+
+ int open_new_window_index = 2;
+ if (chrome_frame_test::GetInstalledIEVersion() == IE_6)
+ open_new_window_index = 1;
+
+ // Focus the renderer window by clicking and then tab once to highlight the
+ // link.
+ EXPECT_CALL(ie_mock_, OnLoad(IN_IE, StrEq(GetLinkPageUrl())))
+ .WillOnce(testing::DoAll(
+ DelaySendMouseClick(&ie_mock_, &loop_, 0, 1, 1, simulate_input::LEFT),
+ DelaySendScanCode(&loop_, 500, VK_TAB, simulate_input::NONE),
+ OpenContextMenu(&loop_, 1000),
+ SelectItem(&loop_, 1500, open_new_window_index)));
+
+ ie_mock_.ExpectNewWindow(&new_window_mock);
+ EXPECT_CALL(new_window_mock, OnLoad(IN_IE, StrEq(GetSimplePageUrl())))
+ // TODO(kkania): Verifying the address bar is flaky with this, at least
+ // on XP ie6. Fix.
+ .WillOnce(CloseBrowserMock(&new_window_mock));
+
+ EXPECT_CALL(new_window_mock, OnQuit())
+ .Times(testing::AtMost(1))
+ .WillOnce(CloseBrowserMock(&ie_mock_));
+
+ LaunchIEAndNavigate(GetLinkPageUrl());
+}
+
+// Test Back/Forward from context menu.
+// Marking this test FLAKY as it fails at times on the buildbot.
+// http://code.google.com/p/chromium/issues/detail?id=26549
+TEST_F(ContextMenuTest, FLAKY_IEBackForward) {
+ server_mock_.ExpectAndServeAnyRequests(CFInvocation::None());
+ std::wstring page1 = GetLinkPageUrl();
+ std::wstring page2 = GetSimplePageUrl();
+ InSequence expect_in_sequence_for_scope;
+
+ EXPECT_CALL(ie_mock_, OnLoad(IN_IE, StrEq(page1)))
+ .WillOnce(Navigate(&ie_mock_, page2));
+
+ // Go back using Rt-Click + DOWN + ENTER
+ EXPECT_CALL(ie_mock_, OnLoad(IN_IE, StrEq(page2)))
+ .WillOnce(testing::DoAll(
+ DelaySendMouseClick(&ie_mock_, &loop_, 0, 10, 10,
+ simulate_input::RIGHT),
+ SendExtendedKeysEnter(&loop_, 500, VK_DOWN, 1,
+ simulate_input::NONE)));
+
+ // Go forward using Rt-Click + DOWN + DOWN + ENTER
+ EXPECT_CALL(ie_mock_, OnLoad(IN_IE, StrEq(page1)))
+ .WillOnce(testing::DoAll(
+ DelaySendMouseClick(&ie_mock_, &loop_, 0, 10, 10,
+ simulate_input::RIGHT),
+ SendExtendedKeysEnter(&loop_, 500, VK_DOWN, 2,
+ simulate_input::NONE)));
+
+ EXPECT_CALL(ie_mock_, OnLoad(IN_IE, StrEq(page2)))
+ .WillOnce(CloseBrowserMock(&ie_mock_));
+
+ LaunchIEAndNavigate(page1);
+}
+
+// Test Back/Forward from context menu. Loads page 1 in chrome and page 2
+// in IE. Then it tests back and forward using context menu
+// Disabling this test as it won't work as per the current chrome external tab
+// design.
+// http://code.google.com/p/chromium/issues/detail?id=46615
+TEST_F(ContextMenuTest, DISABLED_BackForwardWithSwitch) {
+ std::wstring page1 = GetLinkPageUrl();
+ std::wstring page2 = GetSimplePageUrl();
+ InSequence expect_in_sequence_for_scope;
+
+ EXPECT_CALL(ie_mock_, OnLoad(IN_CF, StrEq(page1)))
+ .WillOnce(Navigate(&ie_mock_, page2));
+
+ server_mock_.ExpectAndServeRequest(CFInvocation::None(), page2);
+ // Go back using Rt-Click + DOWN + ENTER
+ EXPECT_CALL(ie_mock_, OnLoad(IN_IE, StrEq(page2)))
+ .WillOnce(testing::DoAll(
+ DelaySendMouseClick(&ie_mock_, &loop_, 0, 10, 10,
+ simulate_input::RIGHT),
+ SendExtendedKeysEnter(&loop_, 500, VK_DOWN, 1,
+ simulate_input::NONE)));
+
+ // Go forward using Rt-Click + DOWN + DOWN + ENTER
+ EXPECT_CALL(ie_mock_, OnLoad(IN_CF, StrEq(page1)))
+ .WillOnce(testing::DoAll(
+ DelaySendMouseClick(&ie_mock_, &loop_, 0, 10, 10,
+ simulate_input::RIGHT),
+ SendExtendedKeysEnter(&loop_, 500, VK_DOWN, 2,
+ simulate_input::NONE)));
+
+ EXPECT_CALL(ie_mock_, OnLoad(IN_IE, StrEq(page2)))
+ .WillOnce(CloseBrowserMock(&ie_mock_));
+
+ LaunchIEAndNavigate(page1);
+}
+
+} // namespace chrome_frame_test \ No newline at end of file