| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome_frame/test/test_mock_with_web_server.h" | |
| 6 | |
| 7 #include "base/scoped_variant_win.h" | |
| 8 #include "base/utf_string_conversions.h" | |
| 9 #include "chrome_frame/test/simulate_input.h" | |
| 10 #include "chrome_frame/test/test_with_web_server.h" | |
| 11 | |
| 12 using chrome_frame_test::CloseIeAtEndOfScope; | |
| 13 using chrome_frame_test::ComStackObjectWithUninitialize; | |
| 14 using chrome_frame_test::kChromeFrameLongNavigationTimeoutInSeconds; | |
| 15 using testing::_; | |
| 16 | |
| 17 namespace { | |
| 18 | |
| 19 // The same as MockWebBrowserEventSink, except OnDocumentComplete is added. | |
| 20 // This class can be merged with its base class, but it would require some | |
| 21 // modification to most of the test cases. | |
| 22 class MockWebBrowserEventSink | |
| 23 : public chrome_frame_test::MockWebBrowserEventSink { | |
| 24 public: | |
| 25 // This method is called for each OnDocumentComplete event in which the | |
| 26 // document is rendered by IE and not CF. | |
| 27 MOCK_METHOD1(OnIELoad, void (const wchar_t* url)); // NOLINT | |
| 28 | |
| 29 // The OnDocumentComplete event is received for every document load, | |
| 30 // regardless of whether IE or CF is hosting. This method will call | |
| 31 // OnIELoad iff the document was loaded in an IE renderer. | |
| 32 STDMETHOD_(void, OnDocumentComplete)(IDispatch* dispatch, | |
| 33 VARIANT* url_variant) { | |
| 34 ScopedVariant url; | |
| 35 if (url_variant) | |
| 36 url.Reset(*url_variant); | |
| 37 // To determine if the document is loaded in IE or CF, check if | |
| 38 // IHTMLDocument2 can be retrieved. If so, call OnIELoad. | |
| 39 ScopedComPtr<IWebBrowser2> web_browser2; | |
| 40 web_browser2.QueryFrom(dispatch); | |
| 41 EXPECT_TRUE(web_browser2); | |
| 42 if (web_browser2) { | |
| 43 ScopedComPtr<IDispatch> doc_dispatch; | |
| 44 HRESULT hr = web_browser2->get_Document(doc_dispatch.Receive()); | |
| 45 EXPECT_HRESULT_SUCCEEDED(hr); | |
| 46 EXPECT_TRUE(doc_dispatch); | |
| 47 if (doc_dispatch) { | |
| 48 ScopedComPtr<IHTMLDocument2> doc; | |
| 49 doc.QueryFrom(doc_dispatch); | |
| 50 if (doc) { | |
| 51 OnIELoad(V_BSTR(&url)); | |
| 52 } | |
| 53 } | |
| 54 } | |
| 55 } | |
| 56 }; | |
| 57 | |
| 58 // Fixture for tests which ensure that Chrome Frame does not interfere with | |
| 59 // normal IE operation. | |
| 60 // TODO(kkania): Move this fixture to test_mock_with_web_server.h and change | |
| 61 // those tests to use this too. | |
| 62 class NoInterferenceTest : public ChromeFrameTestWithWebServer { | |
| 63 protected: | |
| 64 // Launches IE and navigates to |url|, then waits until receiving a quit | |
| 65 // message or the timeout is exceeded. | |
| 66 void LaunchIEAndNavigate(const std::wstring& url) { | |
| 67 EXPECT_CALL(mock_, OnQuit()) | |
| 68 .Times(testing::AtMost(1)) | |
| 69 .WillOnce(QUIT_LOOP(loop_)); | |
| 70 HRESULT hr = mock_.LaunchIEAndNavigate(url); | |
| 71 ASSERT_HRESULT_SUCCEEDED(hr); | |
| 72 if (hr == S_FALSE) | |
| 73 return; | |
| 74 | |
| 75 ASSERT_TRUE(mock_.web_browser2() != NULL); | |
| 76 loop_.RunFor(kChromeFrameLongNavigationTimeoutInSeconds); | |
| 77 mock_.Uninitialize(); | |
| 78 } | |
| 79 | |
| 80 const std::wstring GetTestUrl(const wchar_t* relative_path) { | |
| 81 std::wstring path = std::wstring(L"files/no_interference/") + | |
| 82 relative_path; | |
| 83 return UTF8ToWide(server_.Resolve(path.c_str()).spec()); | |
| 84 } | |
| 85 | |
| 86 const std::wstring empty_page_url() { | |
| 87 return GetTestUrl(L"empty.html"); | |
| 88 } | |
| 89 | |
| 90 // Returns the url for a page with a single link, which points to the | |
| 91 // empty page. | |
| 92 const std::wstring link_page_url() { | |
| 93 return GetTestUrl(L"link.html"); | |
| 94 } | |
| 95 | |
| 96 CloseIeAtEndOfScope last_resort_close_ie; | |
| 97 chrome_frame_test::TimedMsgLoop loop_; | |
| 98 CComObjectStackEx<testing::StrictMock<MockWebBrowserEventSink> > mock_; | |
| 99 }; | |
| 100 | |
| 101 ACTION_P(ExpectIERendererWindowHasFocus, mock) { | |
| 102 mock->ExpectIERendererWindowHasFocus(); | |
| 103 } | |
| 104 | |
| 105 ACTION_P6(DelaySendMouseClickToIE, mock, loop, delay, x, y, button) { | |
| 106 loop->PostDelayedTask(FROM_HERE, NewRunnableMethod(mock, | |
| 107 &MockWebBrowserEventSink::SendMouseClickToIE, x, y, button), delay); | |
| 108 } | |
| 109 | |
| 110 ACTION_P2(OpenContextMenu, loop, delay) { | |
| 111 loop->PostDelayedTask(FROM_HERE, NewRunnableFunction( | |
| 112 simulate_input::SendScanCode, VK_F10, simulate_input::SHIFT), delay); | |
| 113 } | |
| 114 | |
| 115 ACTION_P3(SelectItem, loop, delay, index) { | |
| 116 chrome_frame_test::DelaySendExtendedKeysEnter(loop, delay, VK_DOWN, index + 1, | |
| 117 simulate_input::NONE); | |
| 118 } | |
| 119 | |
| 120 // A new IE renderer window should have focus. | |
| 121 TEST_F(NoInterferenceTest, FLAKY_SimpleFocus) { | |
| 122 mock_.ExpectNavigationInIE(empty_page_url()); | |
| 123 EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(empty_page_url()))) | |
| 124 .WillOnce(testing::DoAll( | |
| 125 ExpectIERendererWindowHasFocus(&mock_), | |
| 126 VerifyAddressBarUrl(&mock_), | |
| 127 CloseBrowserMock(&mock_))); | |
| 128 | |
| 129 LaunchIEAndNavigate(empty_page_url()); | |
| 130 } | |
| 131 | |
| 132 // Javascript window.open should open a new window with an IE renderer. | |
| 133 TEST_F(NoInterferenceTest, FLAKY_JavascriptWindowOpen) { | |
| 134 const std::wstring kWindowOpenUrl = GetTestUrl(L"window_open.html"); | |
| 135 ComStackObjectWithUninitialize< | |
| 136 testing::StrictMock<MockWebBrowserEventSink> > new_window_mock; | |
| 137 | |
| 138 mock_.ExpectNavigationInIE(kWindowOpenUrl); | |
| 139 EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(kWindowOpenUrl))) | |
| 140 .WillOnce(testing::DoAll( | |
| 141 DelaySendMouseClickToIE(&mock_, &loop_, 0, 100, 100, | |
| 142 simulate_input::LEFT), | |
| 143 DelaySendMouseClickToIE(&mock_, &loop_, 0, 100, 100, | |
| 144 simulate_input::LEFT))); | |
| 145 | |
| 146 EXPECT_CALL(mock_, OnNewWindow3(_, _, _, _, _)); | |
| 147 | |
| 148 EXPECT_CALL(mock_, OnNewBrowserWindow(_, _)) | |
| 149 .WillOnce(testing::WithArgs<0>(testing::Invoke(CreateFunctor( | |
| 150 &new_window_mock, &MockWebBrowserEventSink::Attach)))); | |
| 151 | |
| 152 EXPECT_CALL(new_window_mock, OnBeforeNavigate2(_, | |
| 153 testing::Field(&VARIANT::bstrVal, | |
| 154 testing::StrCaseEq(empty_page_url())), | |
| 155 _, _, _, _, _)); | |
| 156 | |
| 157 EXPECT_CALL(new_window_mock, OnFileDownload(VARIANT_TRUE, _)) | |
| 158 .Times(testing::AnyNumber()); | |
| 159 | |
| 160 EXPECT_CALL(new_window_mock, OnNavigateComplete2(_, | |
| 161 testing::Field(&VARIANT::bstrVal, | |
| 162 testing::StrCaseEq(empty_page_url())))) | |
| 163 .WillOnce(testing::DoAll( | |
| 164 testing::InvokeWithoutArgs(CreateFunctor(&new_window_mock, | |
| 165 &chrome_frame_test::MockWebBrowserEventSink::ExpectAddressBarUrl, | |
| 166 empty_page_url())), | |
| 167 DelayCloseBrowserMock(&loop_, 2000, &new_window_mock))); | |
| 168 | |
| 169 // The DocumentComplete at times fires twice for new windows. Hack to account | |
| 170 // for that. | |
| 171 EXPECT_CALL(new_window_mock, | |
| 172 OnIELoad(testing::StrCaseEq(empty_page_url()))) | |
| 173 .Times(testing::AtMost(2)); | |
| 174 | |
| 175 EXPECT_CALL(new_window_mock, OnQuit()) | |
| 176 .WillOnce(DelayCloseBrowserMock(&loop_, 2000, &mock_)); | |
| 177 | |
| 178 LaunchIEAndNavigate(kWindowOpenUrl); | |
| 179 } | |
| 180 | |
| 181 // Redirecting with window.location in Javascript should work. | |
| 182 TEST_F(NoInterferenceTest, JavascriptRedirect) { | |
| 183 const std::wstring kRedirectUrl = GetTestUrl(L"javascript_redirect.html"); | |
| 184 mock_.ExpectNavigationInIE(kRedirectUrl); | |
| 185 EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(kRedirectUrl))) | |
| 186 .WillOnce(VerifyAddressBarUrl(&mock_)); | |
| 187 | |
| 188 mock_.ExpectNavigationInIE(empty_page_url()); | |
| 189 EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(empty_page_url()))) | |
| 190 .WillOnce(testing::DoAll( | |
| 191 VerifyAddressBarUrl(&mock_), | |
| 192 CloseBrowserMock(&mock_))); | |
| 193 | |
| 194 LaunchIEAndNavigate(kRedirectUrl); | |
| 195 } | |
| 196 | |
| 197 TEST_F(NoInterferenceTest, FLAKY_FollowLink) { | |
| 198 mock_.ExpectNavigationInIE(link_page_url()); | |
| 199 EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(link_page_url()))) | |
| 200 .WillOnce(testing::DoAll( | |
| 201 DelaySendMouseClickToIE(&mock_, &loop_, 0, 1, 1, | |
| 202 simulate_input::LEFT), | |
| 203 DelaySendScanCode(&loop_, 500, VK_TAB, simulate_input::NONE), | |
| 204 DelaySendScanCode(&loop_, 1000, VK_RETURN, simulate_input::NONE))); | |
| 205 | |
| 206 mock_.ExpectNavigationInIE(empty_page_url()); | |
| 207 EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(empty_page_url()))) | |
| 208 .WillOnce(testing::DoAll( | |
| 209 VerifyAddressBarUrl(&mock_), | |
| 210 CloseBrowserMock(&mock_))); | |
| 211 | |
| 212 LaunchIEAndNavigate(link_page_url()); | |
| 213 } | |
| 214 | |
| 215 TEST_F(NoInterferenceTest, FLAKY_SelectContextMenuOpen) { | |
| 216 mock_.ExpectNavigationInIE(link_page_url()); | |
| 217 // Focus the renderer window by clicking and then tab once to highlight the | |
| 218 // link. | |
| 219 EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(link_page_url()))) | |
| 220 .WillOnce(testing::DoAll( | |
| 221 DelaySendMouseClickToIE(&mock_, &loop_, 0, 1, 1, | |
| 222 simulate_input::LEFT), | |
| 223 DelaySendScanCode(&loop_, 500, VK_TAB, simulate_input::NONE), | |
| 224 OpenContextMenu(&loop_, 1000), | |
| 225 SelectItem(&loop_, 1500, 0))); | |
| 226 | |
| 227 mock_.ExpectNavigationInIE(empty_page_url()); | |
| 228 EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(empty_page_url()))) | |
| 229 .WillOnce(testing::DoAll( | |
| 230 VerifyAddressBarUrl(&mock_), | |
| 231 CloseBrowserMock(&mock_))); | |
| 232 | |
| 233 LaunchIEAndNavigate(link_page_url()); | |
| 234 } | |
| 235 | |
| 236 TEST_F(NoInterferenceTest, FLAKY_SelectContextMenuOpenInNewWindow) { | |
| 237 ComStackObjectWithUninitialize< | |
| 238 testing::StrictMock<MockWebBrowserEventSink> > new_window_mock; | |
| 239 int open_new_window_index = 2; | |
| 240 if (chrome_frame_test::GetInstalledIEVersion() == IE_6) | |
| 241 open_new_window_index = 1; | |
| 242 | |
| 243 // Focus the renderer window by clicking and then tab once to highlight the | |
| 244 // link. | |
| 245 mock_.ExpectNavigationInIE(link_page_url()); | |
| 246 EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(link_page_url()))) | |
| 247 .WillOnce(testing::DoAll( | |
| 248 DelaySendMouseClickToIE(&mock_, &loop_, 0, 1, 1, | |
| 249 simulate_input::LEFT), | |
| 250 DelaySendScanCode(&loop_, 500, VK_TAB, simulate_input::NONE), | |
| 251 OpenContextMenu(&loop_, 1000), | |
| 252 SelectItem(&loop_, 1500, open_new_window_index))); | |
| 253 | |
| 254 mock_.ExpectNewWindowWithIE(empty_page_url(), &new_window_mock); | |
| 255 // The DocumentComplete at times fires twice for new windows. Hack to account | |
| 256 // for that. | |
| 257 // TODO(kkania): Verifying the address bar is flaky with this, at least | |
| 258 // on XP ie6. Fix. | |
| 259 EXPECT_CALL(new_window_mock, | |
| 260 OnIELoad(testing::StrCaseEq(empty_page_url()))) | |
| 261 .Times(testing::AtMost(2)) | |
| 262 .WillOnce(DelayCloseBrowserMock(&loop_, 2000, &new_window_mock)); | |
| 263 | |
| 264 EXPECT_CALL(new_window_mock, OnQuit()).WillOnce(CloseBrowserMock(&mock_)); | |
| 265 | |
| 266 LaunchIEAndNavigate(link_page_url()); | |
| 267 } | |
| 268 | |
| 269 } // namespace | |
| OLD | NEW |