OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2006-2008 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 #include <windows.h> |
| 5 #include <stdarg.h> |
| 6 |
| 7 // IShellWindows includes. Unfortunately we can't keep these in |
| 8 // alphabetic order since exdisp will bark if some interfaces aren't fully |
| 9 // defined. |
| 10 #include <mshtml.h> |
| 11 #include <exdisp.h> |
| 12 |
| 13 #include "base/basictypes.h" |
| 14 #include "base/file_version_info.h" |
| 15 #include "base/file_util.h" |
| 16 #include "base/scoped_bstr_win.h" |
| 17 #include "base/scoped_comptr_win.h" |
| 18 #include "base/scoped_variant_win.h" |
| 19 #include "base/sys_info.h" |
| 20 #include "gmock/gmock.h" |
| 21 #include "net/url_request/url_request_unittest.h" |
| 22 #include "chrome_frame/test/chrome_frame_unittests.h" |
| 23 #include "chrome_frame/chrome_frame_automation.h" |
| 24 #include "chrome_frame/chrome_frame_delegate.h" |
| 25 #include "chrome_frame/test/chrome_frame_test_utils.h" |
| 26 #include "chrome_frame/test/helper_gmock.h" |
| 27 #include "chrome_frame/test_utils.h" |
| 28 #include "chrome_frame/utils.h" |
| 29 #include "chrome_frame/vectored_handler-impl.h" |
| 30 #include "chrome/installer/util/install_util.h" |
| 31 #include "chrome/installer/util/helper.h" |
| 32 |
| 33 const wchar_t kDocRoot[] = L"chrome_frame\\test\\data"; |
| 34 const int kLongWaitTimeout = 60 * 1000; |
| 35 const int kShortWaitTimeout = 25 * 1000; |
| 36 |
| 37 _ATL_FUNC_INFO WebBrowserEventSink::kNavigateErrorInfo = { |
| 38 CC_STDCALL, VT_EMPTY, 5, { |
| 39 VT_DISPATCH, |
| 40 VT_VARIANT | VT_BYREF, |
| 41 VT_VARIANT | VT_BYREF, |
| 42 VT_VARIANT | VT_BYREF, |
| 43 VT_BOOL | VT_BYREF, |
| 44 } |
| 45 }; |
| 46 |
| 47 _ATL_FUNC_INFO WebBrowserEventSink::kNavigateComplete2Info = { |
| 48 CC_STDCALL, VT_EMPTY, 2, { |
| 49 VT_DISPATCH, |
| 50 VT_VARIANT | VT_BYREF |
| 51 } |
| 52 }; |
| 53 |
| 54 _ATL_FUNC_INFO WebBrowserEventSink::kBeforeNavigate2Info = { |
| 55 CC_STDCALL, VT_EMPTY, 7, { |
| 56 VT_DISPATCH, |
| 57 VT_VARIANT | VT_BYREF, |
| 58 VT_VARIANT | VT_BYREF, |
| 59 VT_VARIANT | VT_BYREF, |
| 60 VT_VARIANT | VT_BYREF, |
| 61 VT_VARIANT | VT_BYREF, |
| 62 VT_BOOL | VT_BYREF |
| 63 } |
| 64 }; |
| 65 |
| 66 |
| 67 |
| 68 void ChromeFrameTestWithWebServer::SetUp() { |
| 69 server_.SetUp(); |
| 70 results_dir_ = server_.GetDataDir(); |
| 71 file_util::AppendToPath(&results_dir_, L"dump"); |
| 72 } |
| 73 |
| 74 void ChromeFrameTestWithWebServer::TearDown() { |
| 75 CloseBrowser(); |
| 76 |
| 77 // Web browsers tend to relaunch themselves in other processes, meaning the |
| 78 // KillProcess stuff above might not have actually cleaned up all our browser |
| 79 // instances, so make really sure browsers are dead. |
| 80 base::KillProcesses(chrome_frame_test::kIEImageName, 0, NULL); |
| 81 base::KillProcesses(chrome_frame_test::kIEBrokerImageName, 0, NULL); |
| 82 base::KillProcesses(chrome_frame_test::kFirefoxImageName, 0, NULL); |
| 83 base::KillProcesses(chrome_frame_test::kSafariImageName, 0, NULL); |
| 84 base::KillProcesses(chrome_frame_test::kChromeImageName, 0, NULL); |
| 85 |
| 86 server_.TearDown(); |
| 87 } |
| 88 |
| 89 bool ChromeFrameTestWithWebServer::LaunchBrowser(BrowserKind browser, |
| 90 const wchar_t* page) { |
| 91 std::wstring url = UTF8ToWide(server_.Resolve(page).spec()); |
| 92 browser_ = browser; |
| 93 if (browser == IE) { |
| 94 browser_handle_.Set(chrome_frame_test::LaunchIE(url)); |
| 95 } else if (browser == FIREFOX) { |
| 96 browser_handle_.Set(chrome_frame_test::LaunchFirefox(url)); |
| 97 } else if (browser == OPERA) { |
| 98 browser_handle_.Set(chrome_frame_test::LaunchOpera(url)); |
| 99 } else if (browser == SAFARI) { |
| 100 browser_handle_.Set(chrome_frame_test::LaunchSafari(url)); |
| 101 } else if (browser == CHROME) { |
| 102 browser_handle_.Set(chrome_frame_test::LaunchChrome(url)); |
| 103 } else { |
| 104 NOTREACHED(); |
| 105 } |
| 106 |
| 107 return browser_handle_.IsValid(); |
| 108 } |
| 109 |
| 110 void ChromeFrameTestWithWebServer::CloseBrowser() { |
| 111 if (!browser_handle_.IsValid()) |
| 112 return; |
| 113 |
| 114 int attempts = 0; |
| 115 if (browser_ == IE) { |
| 116 attempts = chrome_frame_test::CloseAllIEWindows(); |
| 117 } else { |
| 118 attempts = chrome_frame_test::CloseVisibleWindowsOnAllThreads( |
| 119 browser_handle_); |
| 120 } |
| 121 |
| 122 if (attempts > 0) { |
| 123 DWORD wait = ::WaitForSingleObject(browser_handle_, 20000); |
| 124 if (wait == WAIT_OBJECT_0) { |
| 125 browser_handle_.Close(); |
| 126 } else { |
| 127 DLOG(ERROR) << "WaitForSingleObject returned " << wait; |
| 128 } |
| 129 } else { |
| 130 DLOG(ERROR) << "No attempts to close browser windows"; |
| 131 } |
| 132 |
| 133 if (browser_handle_.IsValid()) { |
| 134 DWORD exit_code = 0; |
| 135 if (!::GetExitCodeProcess(browser_handle_, &exit_code) || |
| 136 exit_code == STILL_ACTIVE) { |
| 137 DLOG(ERROR) << L"Forcefully killing browser process. Exit:" << exit_code; |
| 138 base::KillProcess(browser_handle_, 0, true); |
| 139 } |
| 140 browser_handle_.Close(); |
| 141 } |
| 142 } |
| 143 |
| 144 bool ChromeFrameTestWithWebServer::BringBrowserToTop() { |
| 145 return chrome_frame_test::EnsureProcessInForeground(GetProcessId( |
| 146 browser_handle_)); |
| 147 } |
| 148 |
| 149 bool ChromeFrameTestWithWebServer::WaitForTestToComplete(int milliseconds) { |
| 150 return server_.WaitToFinish(milliseconds); |
| 151 } |
| 152 |
| 153 bool ChromeFrameTestWithWebServer::WaitForOnLoad(int milliseconds) { |
| 154 DWORD start = ::GetTickCount(); |
| 155 std::string data; |
| 156 while (!ReadResultFile(L"OnLoadEvent", &data) || data.length() == 0) { |
| 157 DWORD now = ::GetTickCount(); |
| 158 if (start > now) { |
| 159 // Very simple check for overflow. In that case we just restart the |
| 160 // wait. |
| 161 start = now; |
| 162 } else if (static_cast<int>(now - start) > milliseconds) { |
| 163 break; |
| 164 } |
| 165 Sleep(100); |
| 166 } |
| 167 |
| 168 return data.compare("loaded") == 0; |
| 169 } |
| 170 |
| 171 bool ChromeFrameTestWithWebServer::ReadResultFile(const std::wstring& file_name, |
| 172 std::string* data) { |
| 173 std::wstring full_path = results_dir_; |
| 174 file_util::AppendToPath(&full_path, file_name); |
| 175 return file_util::ReadFileToString(full_path, data); |
| 176 } |
| 177 |
| 178 bool ChromeFrameTestWithWebServer::CheckResultFile( |
| 179 const std::wstring& file_name, const std::string& expected_result) { |
| 180 std::string data; |
| 181 bool ret = ReadResultFile(file_name, &data); |
| 182 if (ret) |
| 183 ret = (data == expected_result); |
| 184 |
| 185 if (!ret) { |
| 186 DLOG(ERROR) << "Error text: " << (data.empty() ? "<empty>" : data.c_str()); |
| 187 } |
| 188 |
| 189 return ret; |
| 190 } |
| 191 |
| 192 void ChromeFrameTestWithWebServer::SimpleBrowserTest(BrowserKind browser, |
| 193 const wchar_t* page, const wchar_t* result_file_to_check) { |
| 194 EXPECT_TRUE(LaunchBrowser(browser, page)); |
| 195 ASSERT_TRUE(WaitForTestToComplete(kLongWaitTimeout)); |
| 196 ASSERT_TRUE(CheckResultFile(result_file_to_check, "OK")); |
| 197 } |
| 198 |
| 199 void ChromeFrameTestWithWebServer::OptionalBrowserTest(BrowserKind browser, |
| 200 const wchar_t* page, const wchar_t* result_file_to_check) { |
| 201 if (!LaunchBrowser(browser, page)) { |
| 202 DLOG(ERROR) << "Failed to launch browser " << ToString(browser); |
| 203 } else { |
| 204 ASSERT_TRUE(WaitForTestToComplete(kLongWaitTimeout)); |
| 205 ASSERT_TRUE(CheckResultFile(result_file_to_check, "OK")); |
| 206 } |
| 207 } |
| 208 |
| 209 void ChromeFrameTestWithWebServer::VersionTest(BrowserKind browser, |
| 210 const wchar_t* page, const wchar_t* result_file_to_check) { |
| 211 std::wstring plugin_path; |
| 212 PathService::Get(base::DIR_MODULE, &plugin_path); |
| 213 file_util::AppendToPath(&plugin_path, L"servers/npchrome_tab.dll"); |
| 214 |
| 215 static FileVersionInfo* version_info = |
| 216 FileVersionInfo::CreateFileVersionInfo(plugin_path); |
| 217 |
| 218 std::wstring version; |
| 219 if (version_info) |
| 220 version = version_info->product_version(); |
| 221 |
| 222 // If we can't find the npchrome_tab.dll in the src tree, we turn to |
| 223 // the directory where chrome is installed. |
| 224 if (!version_info) { |
| 225 installer::Version* ver_system = InstallUtil::GetChromeVersion(true); |
| 226 installer::Version* ver_user = InstallUtil::GetChromeVersion(false); |
| 227 ASSERT_TRUE(ver_system || ver_user); |
| 228 |
| 229 bool system_install = ver_system ? true : false; |
| 230 std::wstring npchrome_path(installer::GetChromeInstallPath(system_install)); |
| 231 file_util::AppendToPath(&npchrome_path, |
| 232 ver_system ? ver_system->GetString() : ver_user->GetString()); |
| 233 file_util::AppendToPath(&npchrome_path, L"npchrome_tab.dll"); |
| 234 version_info = FileVersionInfo::CreateFileVersionInfo(npchrome_path); |
| 235 if (version_info) |
| 236 version = version_info->product_version(); |
| 237 } |
| 238 |
| 239 EXPECT_TRUE(version_info); |
| 240 EXPECT_FALSE(version.empty()); |
| 241 EXPECT_TRUE(LaunchBrowser(browser, page)); |
| 242 ASSERT_TRUE(WaitForTestToComplete(kLongWaitTimeout)); |
| 243 ASSERT_TRUE(CheckResultFile(result_file_to_check, WideToUTF8(version))); |
| 244 } |
| 245 |
| 246 const wchar_t kPostMessageBasicPage[] = L"files/postmessage_basic_host.html"; |
| 247 |
| 248 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_PostMessageBasic) { |
| 249 SimpleBrowserTest(IE, kPostMessageBasicPage, L"PostMessage"); |
| 250 } |
| 251 |
| 252 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_PostMessageBasic) { |
| 253 SimpleBrowserTest(FIREFOX, kPostMessageBasicPage, L"PostMessage"); |
| 254 } |
| 255 |
| 256 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_PostMessageBasic) { |
| 257 OptionalBrowserTest(OPERA, kPostMessageBasicPage, L"PostMessage"); |
| 258 } |
| 259 |
| 260 TEST_F(ChromeFrameTestWithWebServer, FullTabIE_MIMEFilterBasic) { |
| 261 const wchar_t kMIMEFilterBasicPage[] = |
| 262 L"files/chrome_frame_mime_filter_test.html"; |
| 263 |
| 264 SimpleBrowserTest(IE, kMIMEFilterBasicPage, L"MIMEFilter"); |
| 265 } |
| 266 |
| 267 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_Resize) { |
| 268 SimpleBrowserTest(IE, L"files/chrome_frame_resize.html", L"Resize"); |
| 269 } |
| 270 |
| 271 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_Resize) { |
| 272 SimpleBrowserTest(FIREFOX, L"files/chrome_frame_resize.html", L"Resize"); |
| 273 } |
| 274 |
| 275 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_Resize) { |
| 276 OptionalBrowserTest(OPERA, L"files/chrome_frame_resize.html", L"Resize"); |
| 277 } |
| 278 |
| 279 const wchar_t kNavigateURLAbsolutePage[] = |
| 280 L"files/navigateurl_absolute_host.html"; |
| 281 |
| 282 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_NavigateURLAbsolute) { |
| 283 SimpleBrowserTest(IE, kNavigateURLAbsolutePage, L"NavigateURL"); |
| 284 } |
| 285 |
| 286 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_NavigateURLAbsolute) { |
| 287 SimpleBrowserTest(FIREFOX, kNavigateURLAbsolutePage, L"NavigateURL"); |
| 288 } |
| 289 |
| 290 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_NavigateURLAbsolute) { |
| 291 OptionalBrowserTest(OPERA, kNavigateURLAbsolutePage, L"NavigateURL"); |
| 292 } |
| 293 |
| 294 const wchar_t kNavigateURLRelativePage[] = |
| 295 L"files/navigateurl_relative_host.html"; |
| 296 |
| 297 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_NavigateURLRelative) { |
| 298 SimpleBrowserTest(IE, kNavigateURLRelativePage, L"NavigateURL"); |
| 299 } |
| 300 |
| 301 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_NavigateURLRelative) { |
| 302 SimpleBrowserTest(FIREFOX, kNavigateURLRelativePage, L"NavigateURL"); |
| 303 } |
| 304 |
| 305 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_NavigateURLRelative) { |
| 306 OptionalBrowserTest(OPERA, kNavigateURLRelativePage, L"NavigateURL"); |
| 307 } |
| 308 |
| 309 const wchar_t kNavigateSimpleObjectFocus[] = L"files/simple_object_focus.html"; |
| 310 |
| 311 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_ObjectFocus) { |
| 312 SimpleBrowserTest(FIREFOX, kNavigateSimpleObjectFocus, L"ObjectFocus"); |
| 313 } |
| 314 |
| 315 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_ObjectFocus) { |
| 316 SimpleBrowserTest(IE, kNavigateSimpleObjectFocus, L"ObjectFocus"); |
| 317 } |
| 318 |
| 319 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_ObjectFocus) { |
| 320 if (!LaunchBrowser(OPERA, kNavigateSimpleObjectFocus)) { |
| 321 DLOG(ERROR) << "Failed to launch browser " << ToString(OPERA); |
| 322 } else { |
| 323 ASSERT_TRUE(WaitForOnLoad(kLongWaitTimeout)); |
| 324 BringBrowserToTop(); |
| 325 // Tab through a couple of times. Once should be enough in theory |
| 326 // but in practice activating the browser can take a few milliseconds more. |
| 327 bool ok; |
| 328 for (int i = 0; |
| 329 i < 5 && (ok = CheckResultFile(L"ObjectFocus", "OK")) == false; |
| 330 ++i) { |
| 331 Sleep(300); |
| 332 chrome_frame_test::SendMnemonic(VK_TAB, false, false, false); |
| 333 } |
| 334 ASSERT_TRUE(ok); |
| 335 } |
| 336 } |
| 337 |
| 338 const wchar_t kiframeBasicPage[] = L"files/iframe_basic_host.html"; |
| 339 |
| 340 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_iframeBasic) { |
| 341 SimpleBrowserTest(IE, kiframeBasicPage, L"PostMessage"); |
| 342 } |
| 343 |
| 344 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_iframeBasic) { |
| 345 SimpleBrowserTest(FIREFOX, kiframeBasicPage, L"PostMessage"); |
| 346 } |
| 347 |
| 348 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_iframeBasic) { |
| 349 OptionalBrowserTest(OPERA, kiframeBasicPage, L"PostMessage"); |
| 350 } |
| 351 |
| 352 const wchar_t kSrcPropertyTestPage[] = L"files/src_property_host.html"; |
| 353 |
| 354 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_SrcProperty) { |
| 355 SimpleBrowserTest(IE, kSrcPropertyTestPage, L"SrcProperty"); |
| 356 } |
| 357 |
| 358 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_SrcProperty) { |
| 359 SimpleBrowserTest(FIREFOX, kSrcPropertyTestPage, L"SrcProperty"); |
| 360 } |
| 361 |
| 362 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_SrcProperty) { |
| 363 OptionalBrowserTest(OPERA, kSrcPropertyTestPage, L"SrcProperty"); |
| 364 } |
| 365 |
| 366 const wchar_t kCFInstanceBasicTestPage[] = L"files/CFInstance_basic_host.html"; |
| 367 |
| 368 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceBasic) { |
| 369 SimpleBrowserTest(IE, kCFInstanceBasicTestPage, L"CFInstanceBasic"); |
| 370 } |
| 371 |
| 372 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_CFInstanceBasic) { |
| 373 SimpleBrowserTest(FIREFOX, kCFInstanceBasicTestPage, L"CFInstanceBasic"); |
| 374 } |
| 375 |
| 376 const wchar_t kCFISingletonPage[] = L"files/CFInstance_singleton_host.html"; |
| 377 |
| 378 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceSingleton) { |
| 379 SimpleBrowserTest(IE, kCFISingletonPage, L"CFInstanceSingleton"); |
| 380 } |
| 381 |
| 382 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_CFInstanceSingleton) { |
| 383 SimpleBrowserTest(FIREFOX, kCFISingletonPage, L"CFInstanceSingleton"); |
| 384 } |
| 385 |
| 386 const wchar_t kCFIDelayPage[] = L"files/CFInstance_delay_host.html"; |
| 387 |
| 388 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_CFInstanceDelay) { |
| 389 SimpleBrowserTest(IE, kCFIDelayPage, L"CFInstanceDelay"); |
| 390 } |
| 391 |
| 392 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeFF_CFInstanceDelay) { |
| 393 SimpleBrowserTest(FIREFOX, kCFIDelayPage, L"CFInstanceDelay"); |
| 394 } |
| 395 |
| 396 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeOpera_CFInstanceDelay) { |
| 397 OptionalBrowserTest(OPERA, kCFIDelayPage, L"CFInstanceDelay"); |
| 398 } |
| 399 |
| 400 const wchar_t kCFIFallbackPage[] = L"files/CFInstance_fallback_host.html"; |
| 401 |
| 402 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceFallback) { |
| 403 SimpleBrowserTest(IE, kCFIFallbackPage, L"CFInstanceFallback"); |
| 404 } |
| 405 |
| 406 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_CFInstanceFallback) { |
| 407 SimpleBrowserTest(FIREFOX, kCFIFallbackPage, L"CFInstanceFallback"); |
| 408 } |
| 409 |
| 410 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_CFInstanceFallback) { |
| 411 OptionalBrowserTest(OPERA, kCFIFallbackPage, L"CFInstanceFallback"); |
| 412 } |
| 413 |
| 414 const wchar_t kCFINoSrcPage[] = L"files/CFInstance_no_src_host.html"; |
| 415 |
| 416 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceNoSrc) { |
| 417 SimpleBrowserTest(IE, kCFINoSrcPage, L"CFInstanceNoSrc"); |
| 418 } |
| 419 |
| 420 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_CFInstanceNoSrc) { |
| 421 SimpleBrowserTest(FIREFOX, kCFINoSrcPage, L"CFInstanceNoSrc"); |
| 422 } |
| 423 |
| 424 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_CFInstanceNoSrc) { |
| 425 OptionalBrowserTest(OPERA, kCFINoSrcPage, L"CFInstanceNoSrc"); |
| 426 } |
| 427 |
| 428 const wchar_t kCFIIfrOnLoadPage[] = L"files/CFInstance_iframe_onload_host.html"; |
| 429 |
| 430 // disabled since it's unlikely that we care about this case |
| 431 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_CFInstanceIfrOnLoad)
{ |
| 432 SimpleBrowserTest(IE, kCFIIfrOnLoadPage, L"CFInstanceIfrOnLoad"); |
| 433 } |
| 434 |
| 435 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_CFInstanceIfrOnLoad) { |
| 436 SimpleBrowserTest(FIREFOX, kCFIIfrOnLoadPage, L"CFInstanceIfrOnLoad"); |
| 437 } |
| 438 |
| 439 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_CFInstanceIfrOnLoad) { |
| 440 OptionalBrowserTest(OPERA, kCFIIfrOnLoadPage, L"CFInstanceIfrOnLoad"); |
| 441 } |
| 442 |
| 443 const wchar_t kCFIZeroSizePage[] = L"files/CFInstance_zero_size_host.html"; |
| 444 |
| 445 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceZeroSize) { |
| 446 SimpleBrowserTest(IE, kCFIZeroSizePage, L"CFInstanceZeroSize"); |
| 447 } |
| 448 |
| 449 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_CFInstanceZeroSize) { |
| 450 SimpleBrowserTest(FIREFOX, kCFIZeroSizePage, L"CFInstanceZeroSize"); |
| 451 } |
| 452 |
| 453 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_CFInstanceZeroSize) { |
| 454 OptionalBrowserTest(OPERA, kCFIZeroSizePage, L"CFInstanceZeroSize"); |
| 455 } |
| 456 |
| 457 const wchar_t kCFIIfrPostPage[] = L"files/CFInstance_iframe_post_host.html"; |
| 458 |
| 459 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceIfrPost) { |
| 460 SimpleBrowserTest(IE, kCFIIfrPostPage, L"CFInstanceIfrPost"); |
| 461 } |
| 462 |
| 463 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_CFInstanceIfrPost) { |
| 464 SimpleBrowserTest(FIREFOX, kCFIIfrPostPage, L"CFInstanceIfrPost"); |
| 465 } |
| 466 |
| 467 TEST_F(ChromeFrameTestWithWebServer, WidgetModeChrome_CFInstanceIfrPost) { |
| 468 OptionalBrowserTest(CHROME, kCFIIfrPostPage, L"CFInstanceIfrPost"); |
| 469 } |
| 470 |
| 471 TEST_F(ChromeFrameTestWithWebServer, WidgetModeSafari_CFInstanceIfrPost) { |
| 472 OptionalBrowserTest(SAFARI, kCFIIfrPostPage, L"CFInstanceIfrPost"); |
| 473 } |
| 474 |
| 475 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_CFInstanceIfrPost) { |
| 476 OptionalBrowserTest(OPERA, kCFIIfrPostPage, L"CFInstanceIfrPost"); |
| 477 } |
| 478 |
| 479 const wchar_t kCFIPostPage[] = L"files/CFInstance_post_host.html"; |
| 480 |
| 481 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstancePost) { |
| 482 SimpleBrowserTest(IE, kCFIPostPage, L"CFInstancePost"); |
| 483 } |
| 484 |
| 485 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_CFInstancePost) { |
| 486 SimpleBrowserTest(FIREFOX, kCFIPostPage, L"CFInstancePost"); |
| 487 } |
| 488 |
| 489 TEST_F(ChromeFrameTestWithWebServer, WidgetModeChrome_CFInstancePost) { |
| 490 OptionalBrowserTest(CHROME, kCFIPostPage, L"CFInstancePost"); |
| 491 } |
| 492 |
| 493 TEST_F(ChromeFrameTestWithWebServer, WidgetModeSafari_CFInstancePost) { |
| 494 OptionalBrowserTest(SAFARI, kCFIPostPage, L"CFInstancePost"); |
| 495 } |
| 496 |
| 497 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeOpera_CFInstancePost) { |
| 498 OptionalBrowserTest(OPERA, kCFIPostPage, L"CFInstancePost"); |
| 499 } |
| 500 |
| 501 const wchar_t kCFIRPCPage[] = L"files/CFInstance_rpc_host.html"; |
| 502 |
| 503 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceRPC) { |
| 504 SimpleBrowserTest(IE, kCFIRPCPage, L"CFInstanceRPC"); |
| 505 } |
| 506 |
| 507 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_CFInstanceRPC) { |
| 508 SimpleBrowserTest(FIREFOX, kCFIRPCPage, L"CFInstanceRPC"); |
| 509 } |
| 510 |
| 511 TEST_F(ChromeFrameTestWithWebServer, WidgetModeChrome_CFInstanceRPC) { |
| 512 OptionalBrowserTest(CHROME, kCFIRPCPage, L"CFInstanceRPC"); |
| 513 } |
| 514 |
| 515 TEST_F(ChromeFrameTestWithWebServer, WidgetModeSafari_CFInstanceRPC) { |
| 516 OptionalBrowserTest(SAFARI, kCFIRPCPage, L"CFInstanceRPC"); |
| 517 } |
| 518 |
| 519 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeOpera_CFInstanceRPC) { |
| 520 OptionalBrowserTest(OPERA, kCFIRPCPage, L"CFInstanceRPC"); |
| 521 } |
| 522 |
| 523 const wchar_t kCFIRPCInternalPage[] = |
| 524 L"files/CFInstance_rpc_internal_host.html"; |
| 525 |
| 526 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceRPCInternal) { |
| 527 SimpleBrowserTest(IE, kCFIRPCInternalPage, L"CFInstanceRPCInternal"); |
| 528 } |
| 529 |
| 530 // Disabled: http://b/issue?id=2050201 |
| 531 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeFF_CFInstanceRPCInternal
) { |
| 532 SimpleBrowserTest(FIREFOX, kCFIRPCInternalPage, L"CFInstanceRPCInternal"); |
| 533 } |
| 534 |
| 535 TEST_F(ChromeFrameTestWithWebServer, WidgetModeChrome_CFInstanceRPCInternal) { |
| 536 OptionalBrowserTest(CHROME, kCFIRPCInternalPage, L"CFInstanceRPCInternal"); |
| 537 } |
| 538 |
| 539 TEST_F(ChromeFrameTestWithWebServer, WidgetModeSafari_CFInstanceRPCInternal) { |
| 540 OptionalBrowserTest(SAFARI, kCFIRPCInternalPage, L"CFInstanceRPCInternal"); |
| 541 } |
| 542 |
| 543 const wchar_t kCFIDefaultCtorPage[] = |
| 544 L"files/CFInstance_default_ctor_host.html"; |
| 545 |
| 546 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceDefaultCtor) { |
| 547 SimpleBrowserTest(IE, kCFIDefaultCtorPage, L"CFInstanceDefaultCtor"); |
| 548 } |
| 549 |
| 550 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_CFInstanceDefaultCtor) { |
| 551 SimpleBrowserTest(FIREFOX, kCFIDefaultCtorPage, L"CFInstanceDefaultCtor"); |
| 552 } |
| 553 |
| 554 // Class that mocks external call from VectoredHandlerT for testing purposes. |
| 555 class EMock : public VEHTraitsBase { |
| 556 public: |
| 557 static inline bool WriteDump(EXCEPTION_POINTERS* p) { |
| 558 g_dump_made = true; |
| 559 return true; |
| 560 } |
| 561 |
| 562 static inline void* Register(PVECTORED_EXCEPTION_HANDLER func, |
| 563 const void* module_start, |
| 564 const void* module_end) { |
| 565 VEHTraitsBase::SetModule(module_start, module_end); |
| 566 // Return some arbitrary number, expecting to get the same on Unregister() |
| 567 return reinterpret_cast<void*>(4); |
| 568 } |
| 569 |
| 570 static inline ULONG Unregister(void* handle) { |
| 571 EXPECT_EQ(handle, reinterpret_cast<void*>(4)); |
| 572 return 1; |
| 573 } |
| 574 |
| 575 static inline WORD RtlCaptureStackBackTrace(DWORD FramesToSkip, |
| 576 DWORD FramesToCapture, void** BackTrace, DWORD* BackTraceHash) { |
| 577 EXPECT_EQ(2, FramesToSkip); |
| 578 EXPECT_LE(FramesToSkip + FramesToCapture, |
| 579 VectoredHandlerBase::max_back_trace); |
| 580 memcpy(BackTrace, g_stack, g_stack_entries * sizeof(BackTrace[0])); |
| 581 return g_stack_entries; |
| 582 } |
| 583 |
| 584 static inline EXCEPTION_REGISTRATION_RECORD* RtlpGetExceptionList() { |
| 585 return g_seh_chain; |
| 586 } |
| 587 |
| 588 // Test helpers |
| 589 |
| 590 // Create fake SEH chain of random filters - with and without our module. |
| 591 static void SetHaveSEHFilter() { |
| 592 SetSEHChain(reinterpret_cast<const char*>(g_module_start) - 0x1000, |
| 593 reinterpret_cast<const char*>(g_module_start) + 0x1000, |
| 594 reinterpret_cast<const char*>(g_module_end) + 0x7127, |
| 595 NULL); |
| 596 } |
| 597 |
| 598 static void SetNoSEHFilter() { |
| 599 SetSEHChain(reinterpret_cast<const char*>(g_module_start) - 0x1000, |
| 600 reinterpret_cast<const char*>(g_module_end) + 0x7127, |
| 601 NULL); |
| 602 } |
| 603 |
| 604 // Create fake stack - with and without our module. |
| 605 static void SetOnStack() { |
| 606 SetStack(reinterpret_cast<const char*>(g_module_start) - 0x11283, |
| 607 reinterpret_cast<const char*>(g_module_start) - 0x278361, |
| 608 reinterpret_cast<const char*>(g_module_start) + 0x9171, |
| 609 reinterpret_cast<const char*>(g_module_end) + 1231, |
| 610 NULL); |
| 611 } |
| 612 |
| 613 static void SetNotOnStack() { |
| 614 SetStack(reinterpret_cast<const char*>(g_module_start) - 0x11283, |
| 615 reinterpret_cast<const char*>(g_module_start) - 0x278361, |
| 616 reinterpret_cast<const char*>(g_module_end) + 1231, |
| 617 NULL); |
| 618 } |
| 619 |
| 620 // Populate stack array |
| 621 static void SetStack(const void* p, ...) { |
| 622 va_list vl; |
| 623 va_start(vl, p); |
| 624 g_stack_entries = 0; |
| 625 for (; p; ++g_stack_entries) { |
| 626 CHECK(g_stack_entries < arraysize(g_stack)); |
| 627 g_stack[g_stack_entries] = p; |
| 628 p = va_arg(vl, const void*); |
| 629 } |
| 630 } |
| 631 |
| 632 static void SetSEHChain(const void* p, ...) { |
| 633 va_list vl; |
| 634 va_start(vl, p); |
| 635 int i = 0; |
| 636 for (; p; ++i) { |
| 637 CHECK(i + 1 < arraysize(g_seh_chain)); |
| 638 g_seh_chain[i].Handler = const_cast<void*>(p); |
| 639 g_seh_chain[i].Next = &g_seh_chain[i + 1]; |
| 640 p = va_arg(vl, const void*); |
| 641 } |
| 642 |
| 643 g_seh_chain[i].Next = EXCEPTION_CHAIN_END; |
| 644 } |
| 645 |
| 646 static EXCEPTION_REGISTRATION_RECORD g_seh_chain[25]; |
| 647 static const void* g_stack[VectoredHandlerBase::max_back_trace]; |
| 648 static WORD g_stack_entries; |
| 649 static bool g_dump_made; |
| 650 }; |
| 651 |
| 652 EXCEPTION_REGISTRATION_RECORD EMock::g_seh_chain[25]; |
| 653 const void* EMock::g_stack[VectoredHandlerBase::max_back_trace]; |
| 654 WORD EMock::g_stack_entries; |
| 655 bool EMock::g_dump_made; |
| 656 |
| 657 typedef VectoredHandlerT<EMock> VectoredHandlerMock; |
| 658 |
| 659 class ExPtrsHelper : public _EXCEPTION_POINTERS { |
| 660 public: |
| 661 ExPtrsHelper() { |
| 662 ExceptionRecord = &er_; |
| 663 ContextRecord = &ctx_; |
| 664 ZeroMemory(&er_, sizeof(er_)); |
| 665 ZeroMemory(&ctx_, sizeof(ctx_)); |
| 666 } |
| 667 |
| 668 void Set(DWORD code, void* address, DWORD flags) { |
| 669 er_.ExceptionCode = code; |
| 670 er_.ExceptionAddress = address; |
| 671 er_.ExceptionFlags = flags; |
| 672 } |
| 673 |
| 674 EXCEPTION_RECORD er_; |
| 675 CONTEXT ctx_; |
| 676 }; |
| 677 |
| 678 |
| 679 TEST(ChromeFrame, ExceptionReport) { |
| 680 char* s = reinterpret_cast<char*>(0x30000000); |
| 681 char* e = s + 0x10000; |
| 682 void* handler = VectoredHandlerMock::Register(s, e); |
| 683 char* our_code = s + 0x1111; |
| 684 char* not_our_code = s - 0x5555; |
| 685 char* not_our_code2 = e + 0x5555; |
| 686 |
| 687 ExPtrsHelper ex; |
| 688 // Exception in our code, but we have SEH filter |
| 689 ex.Set(STATUS_ACCESS_VIOLATION, our_code, 0); |
| 690 EMock::SetHaveSEHFilter(); |
| 691 EMock::SetOnStack(); |
| 692 EXPECT_EQ(ExceptionContinueSearch, VectoredHandlerMock::VectoredHandler(&ex)); |
| 693 EXPECT_EQ(1, VectoredHandlerMock::g_exceptions_seen); |
| 694 EXPECT_FALSE(EMock::g_dump_made); |
| 695 |
| 696 // RPC_E_DISCONNECTED (0x80010108) is "The object invoked has disconnected |
| 697 // from its clients", shall not be caught since it's a warning only. |
| 698 ex.Set(RPC_E_DISCONNECTED, our_code, 0); |
| 699 EMock::SetHaveSEHFilter(); |
| 700 EMock::SetOnStack(); |
| 701 EXPECT_EQ(ExceptionContinueSearch, VectoredHandlerMock::VectoredHandler(&ex)); |
| 702 EXPECT_EQ(1, VectoredHandlerMock::g_exceptions_seen); |
| 703 EXPECT_FALSE(EMock::g_dump_made); |
| 704 |
| 705 |
| 706 // Exception, not in our code, we do not have SEH and we are not in stack. |
| 707 ex.Set(STATUS_INTEGER_DIVIDE_BY_ZERO, not_our_code, 0); |
| 708 EMock::SetNoSEHFilter(); |
| 709 EMock::SetNotOnStack(); |
| 710 EXPECT_EQ(ExceptionContinueSearch, VectoredHandlerMock::VectoredHandler(&ex)); |
| 711 EXPECT_EQ(2, VectoredHandlerMock::g_exceptions_seen); |
| 712 EXPECT_FALSE(EMock::g_dump_made); |
| 713 |
| 714 // Exception, not in our code, no SEH, but we are on the stack. |
| 715 ex.Set(STATUS_INTEGER_DIVIDE_BY_ZERO, not_our_code2, 0); |
| 716 EMock::SetNoSEHFilter(); |
| 717 EMock::SetOnStack(); |
| 718 EXPECT_EQ(ExceptionContinueSearch, VectoredHandlerMock::VectoredHandler(&ex)); |
| 719 EXPECT_EQ(3, VectoredHandlerMock::g_exceptions_seen); |
| 720 EXPECT_TRUE(EMock::g_dump_made); |
| 721 EMock::g_dump_made = false; |
| 722 |
| 723 |
| 724 // Exception, in our code, no SEH, not on stack (assume FPO screwed us) |
| 725 ex.Set(STATUS_INTEGER_DIVIDE_BY_ZERO, our_code, 0); |
| 726 EMock::SetNoSEHFilter(); |
| 727 EMock::SetNotOnStack(); |
| 728 EXPECT_EQ(ExceptionContinueSearch, VectoredHandlerMock::VectoredHandler(&ex)); |
| 729 EXPECT_EQ(4, VectoredHandlerMock::g_exceptions_seen); |
| 730 EXPECT_TRUE(EMock::g_dump_made); |
| 731 EMock::g_dump_made = false; |
| 732 |
| 733 VectoredHandlerMock::Unregister(); |
| 734 } |
| 735 |
| 736 const wchar_t kInitializeHiddenPage[] = L"files/initialize_hidden.html"; |
| 737 |
| 738 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_InitializeHidden) { |
| 739 SimpleBrowserTest(IE, kInitializeHiddenPage, L"InitializeHidden"); |
| 740 } |
| 741 |
| 742 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_InitializeHidden) { |
| 743 SimpleBrowserTest(FIREFOX, kInitializeHiddenPage, L"InitializeHidden"); |
| 744 } |
| 745 |
| 746 // Disabled due to a problem with Opera. |
| 747 // http://b/issue?id=1708275 |
| 748 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeOpera_InitializeHidden)
{ |
| 749 OptionalBrowserTest(OPERA, kInitializeHiddenPage, L"InitializeHidden"); |
| 750 } |
| 751 |
| 752 const wchar_t kInHeadPage[] = L"files/in_head.html"; |
| 753 |
| 754 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_InHead) { |
| 755 SimpleBrowserTest(FIREFOX, kInHeadPage, L"InHead"); |
| 756 } |
| 757 |
| 758 const wchar_t kVersionPage[] = L"files/version.html"; |
| 759 |
| 760 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_Version) { |
| 761 VersionTest(IE, kVersionPage, L"version"); |
| 762 } |
| 763 |
| 764 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_Version) { |
| 765 VersionTest(FIREFOX, kVersionPage, L"version"); |
| 766 } |
| 767 |
| 768 const wchar_t kEventListenerPage[] = L"files/event_listener.html"; |
| 769 |
| 770 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_EventListener) { |
| 771 SimpleBrowserTest(IE, kEventListenerPage, L"EventListener"); |
| 772 } |
| 773 |
| 774 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_EventListener) { |
| 775 SimpleBrowserTest(FIREFOX, kEventListenerPage, L"EventListener"); |
| 776 } |
| 777 |
| 778 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_EventListener) { |
| 779 OptionalBrowserTest(OPERA, kEventListenerPage, L"EventListener"); |
| 780 } |
| 781 |
| 782 const wchar_t kPrivilegedApisPage[] = L"files/privileged_apis_host.html"; |
| 783 |
| 784 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_PrivilegedApis) { |
| 785 SimpleBrowserTest(IE, kPrivilegedApisPage, L"PrivilegedApis"); |
| 786 } |
| 787 |
| 788 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_PrivilegedApis) { |
| 789 SimpleBrowserTest(FIREFOX, kPrivilegedApisPage, L"PrivilegedApis"); |
| 790 } |
| 791 |
| 792 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_PrivilegedApis) { |
| 793 OptionalBrowserTest(OPERA, kPrivilegedApisPage, L"PrivilegedApis"); |
| 794 } |
| 795 |
| 796 class ChromeFrameTestEnvironment: public testing::Environment { |
| 797 public: |
| 798 ~ChromeFrameTestEnvironment() { |
| 799 } |
| 800 |
| 801 void SetUp() { |
| 802 ScopedChromeFrameRegistrar::RegisterDefaults(); |
| 803 } |
| 804 |
| 805 void TearDown() { |
| 806 } |
| 807 }; |
| 808 |
| 809 ::testing::Environment* const chrome_frame_env = |
| 810 ::testing::AddGlobalTestEnvironment(new ChromeFrameTestEnvironment); |
| 811 |
| 812 // TODO(stoyan): - Move everything below in separate file(s). |
| 813 struct LaunchDelegateMock : public ProxyFactory::LaunchDelegate { |
| 814 MOCK_METHOD2(LaunchComplete, void(ChromeFrameAutomationProxy*, |
| 815 AutomationLaunchResult)); |
| 816 }; |
| 817 |
| 818 TEST(ProxyFactoryTest, CreateDestroy) { |
| 819 ProxyFactory f; |
| 820 LaunchDelegateMock d; |
| 821 EXPECT_CALL(d, LaunchComplete(testing::NotNull(), testing::_)).Times(1); |
| 822 void* id = f.GetAutomationServer(0, L"Adam.N.Epilinter", L"", false, &d); |
| 823 f.ReleaseAutomationServer(id); |
| 824 } |
| 825 |
| 826 TEST(ProxyFactoryTest, CreateSameProfile) { |
| 827 ProxyFactory f; |
| 828 LaunchDelegateMock d; |
| 829 EXPECT_CALL(d, LaunchComplete(testing::NotNull(), testing::_)).Times(2); |
| 830 void* i1 = f.GetAutomationServer(0, L"Dr. Gratiano Forbeson", L"", false, &d); |
| 831 void* i2 = f.GetAutomationServer(0, L"Dr. Gratiano Forbeson", L"", false, &d); |
| 832 EXPECT_EQ(i1, i2); |
| 833 f.ReleaseAutomationServer(i2); |
| 834 f.ReleaseAutomationServer(i1); |
| 835 } |
| 836 |
| 837 TEST(ProxyFactoryTest, CreateDifferentProfiles) { |
| 838 ProxyFactory f; |
| 839 LaunchDelegateMock d; |
| 840 EXPECT_CALL(d, LaunchComplete(testing::NotNull(), testing::_)).Times(2); |
| 841 void* i1 = f.GetAutomationServer(0, L"Adam.N.Epilinter", L"", false, &d); |
| 842 void* i2 = f.GetAutomationServer(0, L"Dr. Gratiano Forbeson", L"", false, &d); |
| 843 EXPECT_NE(i1, i2); |
| 844 f.ReleaseAutomationServer(i2); |
| 845 f.ReleaseAutomationServer(i1); |
| 846 } |
| 847 |
| 848 // ChromeFrameAutomationClient [CFAC] tests. |
| 849 struct MockCFDelegate : public ChromeFrameDelegateImpl { |
| 850 MOCK_CONST_METHOD0(GetWindow, WindowType()); |
| 851 MOCK_METHOD1(GetBounds, void(RECT* bounds)); |
| 852 MOCK_METHOD0(GetDocumentUrl, std::string()); |
| 853 MOCK_METHOD2(ExecuteScript, bool(const std::string& script, |
| 854 std::string* result)); |
| 855 MOCK_METHOD0(OnAutomationServerReady, void()); |
| 856 MOCK_METHOD2(OnAutomationServerLaunchFailed, void( |
| 857 AutomationLaunchResult reason, const std::string& server_version)); |
| 858 // This remains in interface since we call it if Navigate() |
| 859 // returns immediate error. |
| 860 MOCK_METHOD2(OnLoadFailed, void(int error_code, const std::string& url)); |
| 861 |
| 862 // Do not mock this method. :) Use it as message demuxer and dispatcher |
| 863 // to the following methods (which we mock) |
| 864 // MOCK_METHOD1(OnMessageReceived, void(const IPC::Message&)); |
| 865 |
| 866 |
| 867 MOCK_METHOD2(OnNavigationStateChanged, void(int tab_handle, int flags)); |
| 868 MOCK_METHOD2(OnUpdateTargetUrl, void(int tab_handle, |
| 869 const std::wstring& new_target_url)); |
| 870 MOCK_METHOD2(OnAcceleratorPressed, void(int tab_handle, |
| 871 const MSG& accel_message)); |
| 872 MOCK_METHOD2(OnTabbedOut, void(int tab_handle, bool reverse)); |
| 873 MOCK_METHOD3(OnOpenURL, void(int tab_handle, const GURL& url, |
| 874 int open_disposition)); |
| 875 MOCK_METHOD2(OnDidNavigate, void(int tab_handle, |
| 876 const IPC::NavigationInfo& navigation_info)); |
| 877 MOCK_METHOD3(OnNavigationFailed, void(int tab_handle, int error_code, |
| 878 const GURL& gurl)); |
| 879 MOCK_METHOD2(OnLoad, void(int tab_handle, const GURL& url)); |
| 880 MOCK_METHOD4(OnMessageFromChromeFrame, void(int tab_handle, |
| 881 const std::string& message, |
| 882 const std::string& origin, |
| 883 const std::string& target)); |
| 884 MOCK_METHOD5(OnHandleContextMenu, void(int tab_handle, HANDLE menu_handle, |
| 885 int x_pos, int y_pos, int align_flags)); |
| 886 MOCK_METHOD3(OnRequestStart, void(int tab_handle, int request_id, |
| 887 const IPC::AutomationURLRequest& request)); |
| 888 MOCK_METHOD3(OnRequestRead, void(int tab_handle, int request_id, |
| 889 int bytes_to_read)); |
| 890 MOCK_METHOD3(OnRequestEnd, void(int tab_handle, int request_id, |
| 891 const URLRequestStatus& status)); |
| 892 MOCK_METHOD3(OnSetCookieAsync, void(int tab_handle, const GURL& url, |
| 893 const std::string& cookie)); |
| 894 |
| 895 // Use for sending network responses |
| 896 void SetAutomationSender(IPC::Message::Sender* automation) { |
| 897 automation_ = automation; |
| 898 } |
| 899 |
| 900 // Set-expectation helpers |
| 901 void SetOnNavigationStateChanged(int tab_handle) { |
| 902 EXPECT_CALL(*this, |
| 903 OnNavigationStateChanged(testing::Eq(tab_handle), testing::_)) |
| 904 .Times(testing::AnyNumber()); |
| 905 } |
| 906 |
| 907 // Response sender helpers |
| 908 void ReplyStarted(const IPC::AutomationURLResponse* response, |
| 909 int tab_handle, int request_id, |
| 910 const IPC::AutomationURLRequest& request) { |
| 911 automation_->Send(new AutomationMsg_RequestStarted(0, tab_handle, |
| 912 request_id, *response)); |
| 913 } |
| 914 |
| 915 void ReplyData(const std::string* data, int tab_handle, int request_id, |
| 916 int bytes_to_read) { |
| 917 automation_->Send(new AutomationMsg_RequestData(0, tab_handle, |
| 918 request_id, *data)); |
| 919 } |
| 920 |
| 921 void ReplyEOF(int tab_handle, int request_id) { |
| 922 automation_->Send(new AutomationMsg_RequestEnd(0, tab_handle, |
| 923 request_id, URLRequestStatus())); |
| 924 } |
| 925 |
| 926 void Reply404(int tab_handle, int request_id, |
| 927 const IPC::AutomationURLRequest& request) { |
| 928 const IPC::AutomationURLResponse notfound = {"", "HTTP/1.1 404\r\n\r\n"}; |
| 929 automation_->Send(new AutomationMsg_RequestStarted(0, tab_handle, |
| 930 request_id, notfound)); |
| 931 automation_->Send(new AutomationMsg_RequestEnd(0, tab_handle, |
| 932 request_id, URLRequestStatus())); |
| 933 } |
| 934 |
| 935 IPC::Message::Sender* automation_; |
| 936 }; |
| 937 |
| 938 class MockProxyFactory : public ProxyFactory { |
| 939 public: |
| 940 MOCK_METHOD5(GetAutomationServer, void*(int, const std::wstring&, |
| 941 const std::wstring& extra_argument, bool, ProxyFactory::LaunchDelegate*)); |
| 942 MOCK_METHOD1(ReleaseAutomationServer, bool(void* id)); |
| 943 |
| 944 MockProxyFactory() : thread_("mock factory worker") { |
| 945 thread_.Start(); |
| 946 loop_ = thread_.message_loop(); |
| 947 } |
| 948 |
| 949 // Fake implementation |
| 950 void GetServerImpl(ChromeFrameAutomationProxy* pxy, |
| 951 AutomationLaunchResult result, |
| 952 int timeout, |
| 953 ProxyFactory::LaunchDelegate* d) { |
| 954 Task* task = NewRunnableMethod(d, |
| 955 &ProxyFactory::LaunchDelegate::LaunchComplete, pxy, result); |
| 956 loop_->PostDelayedTask(FROM_HERE, task, timeout/2); |
| 957 } |
| 958 |
| 959 base::Thread thread_; |
| 960 MessageLoop* loop_; |
| 961 }; |
| 962 |
| 963 class MockAutomationProxy : public ChromeFrameAutomationProxy { |
| 964 public: |
| 965 MOCK_METHOD1(Send, bool(IPC::Message*)); |
| 966 MOCK_METHOD3(SendAsAsync, void(IPC::SyncMessage* msg, void* callback, |
| 967 void* key)); |
| 968 MOCK_METHOD1(CancelAsync, void(void* key)); |
| 969 MOCK_METHOD1(CreateTabProxy, scoped_refptr<TabProxy>(int handle)); |
| 970 MOCK_METHOD0(server_version, std::string(void)); |
| 971 MOCK_METHOD1(SendProxyConfig, void(const std::string&)); |
| 972 MOCK_METHOD1(SetEnableExtensionAutomation, void(bool enable)); |
| 973 |
| 974 ~MockAutomationProxy() {} |
| 975 }; |
| 976 |
| 977 struct MockAutomationMessageSender : public AutomationMessageSender { |
| 978 MOCK_METHOD1(Send, bool(IPC::Message*)); |
| 979 MOCK_METHOD3(SendWithTimeout, bool(IPC::Message* , int , bool*)); |
| 980 |
| 981 void ForwardTo(MockAutomationProxy *p) { |
| 982 proxy_ = p; |
| 983 ON_CALL(*this, Send(testing::_)) |
| 984 .WillByDefault(testing::Invoke(proxy_, &MockAutomationProxy::Send)); |
| 985 } |
| 986 |
| 987 MockAutomationProxy* proxy_; |
| 988 }; |
| 989 |
| 990 template <> struct RunnableMethodTraits<ProxyFactory::LaunchDelegate> { |
| 991 static void RetainCallee(ProxyFactory::LaunchDelegate* obj) {} |
| 992 static void ReleaseCallee(ProxyFactory::LaunchDelegate* obj) {} |
| 993 }; |
| 994 |
| 995 template <> struct RunnableMethodTraits<MockProxyFactory> { |
| 996 static void RetainCallee(MockProxyFactory* obj) {} |
| 997 static void ReleaseCallee(MockProxyFactory* obj) {} |
| 998 }; |
| 999 |
| 1000 template <> struct RunnableMethodTraits<ChromeFrameAutomationClient> { |
| 1001 static void RetainCallee(ChromeFrameAutomationClient* obj) {} |
| 1002 static void ReleaseCallee(ChromeFrameAutomationClient* obj) {} |
| 1003 }; |
| 1004 |
| 1005 // MessageLoopForUI wrapper that runs only for a limited time. |
| 1006 // We need a UI message loop in the main thread. |
| 1007 struct TimedMsgLoop { |
| 1008 public: |
| 1009 void RunFor(int seconds) { |
| 1010 loop_.PostDelayedTask(FROM_HERE, new MessageLoop::QuitTask, 1000 * seconds); |
| 1011 loop_.MessageLoop::Run(); |
| 1012 } |
| 1013 |
| 1014 void Quit() { |
| 1015 loop_.PostTask(FROM_HERE, new MessageLoop::QuitTask); |
| 1016 } |
| 1017 |
| 1018 MessageLoopForUI loop_; |
| 1019 }; |
| 1020 |
| 1021 template <> struct RunnableMethodTraits<TimedMsgLoop> { |
| 1022 static void RetainCallee(TimedMsgLoop* obj) {} |
| 1023 static void ReleaseCallee(TimedMsgLoop* obj) {} |
| 1024 }; |
| 1025 |
| 1026 // Saves typing. It's somewhat hard to create a wrapper around |
| 1027 // testing::InvokeWithoutArgs since it returns a |
| 1028 // non-public (testing::internal) type. |
| 1029 #define QUIT_LOOP(loop) testing::InvokeWithoutArgs(TaskHolder(\ |
| 1030 NewRunnableMethod(&loop, &TimedMsgLoop::Quit))) |
| 1031 |
| 1032 // We mock ChromeFrameDelegate only. The rest is with real AutomationProxy |
| 1033 TEST(CFACWithChrome, CreateTooFast) { |
| 1034 MockCFDelegate cfd; |
| 1035 TimedMsgLoop loop; |
| 1036 int timeout = 0; // Chrome cannot send Hello message so fast. |
| 1037 const std::wstring profile = L"Adam.N.Epilinter"; |
| 1038 |
| 1039 scoped_ptr<ChromeFrameAutomationClient> client; |
| 1040 client.reset(new ChromeFrameAutomationClient()); |
| 1041 |
| 1042 EXPECT_CALL(cfd, OnAutomationServerLaunchFailed(AUTOMATION_TIMEOUT, |
| 1043 testing::_)) |
| 1044 .Times(1) |
| 1045 .WillOnce(QUIT_LOOP(loop)); |
| 1046 |
| 1047 EXPECT_TRUE(client->Initialize(&cfd, timeout, false, profile, L"", false)); |
| 1048 loop.RunFor(10); |
| 1049 client->Uninitialize(); |
| 1050 } |
| 1051 |
| 1052 // This test may fail if Chrome take more that 10 seconds (timeout var) to |
| 1053 // launch. In this case GMock shall print something like "unexpected call to |
| 1054 // OnAutomationServerLaunchFailed". I'm yet to find out how to specify |
| 1055 // that this is an unexpected call, and still to execute and action. |
| 1056 TEST(CFACWithChrome, CreateNotSoFast) { |
| 1057 MockCFDelegate cfd; |
| 1058 TimedMsgLoop loop; |
| 1059 const std::wstring profile = L"Adam.N.Epilinter"; |
| 1060 int timeout = 10000; |
| 1061 |
| 1062 scoped_ptr<ChromeFrameAutomationClient> client; |
| 1063 client.reset(new ChromeFrameAutomationClient); |
| 1064 |
| 1065 EXPECT_CALL(cfd, OnAutomationServerReady()) |
| 1066 .Times(1) |
| 1067 .WillOnce(QUIT_LOOP(loop)); |
| 1068 |
| 1069 EXPECT_CALL(cfd, OnAutomationServerLaunchFailed(testing::_, testing::_)) |
| 1070 .Times(0); |
| 1071 |
| 1072 EXPECT_TRUE(client->Initialize(&cfd, timeout, false, profile, L"", false)); |
| 1073 |
| 1074 loop.RunFor(11); |
| 1075 client->Uninitialize(); |
| 1076 client.reset(NULL); |
| 1077 } |
| 1078 |
| 1079 MATCHER_P(MsgType, msg_type, "IPC::Message::type()") { |
| 1080 const IPC::Message& m = arg; |
| 1081 return (m.type() == msg_type); |
| 1082 } |
| 1083 |
| 1084 MATCHER_P(EqNavigationInfoUrl, url, "IPC::NavigationInfo matcher") { |
| 1085 if (url.is_valid() && url != arg.url) |
| 1086 return false; |
| 1087 // TODO: other members |
| 1088 return true; |
| 1089 } |
| 1090 |
| 1091 TEST(CFACWithChrome, NavigateOk) { |
| 1092 MockCFDelegate cfd; |
| 1093 TimedMsgLoop loop; |
| 1094 const std::wstring profile = L"Adam.N.Epilinter"; |
| 1095 const std::string url = "about:version"; |
| 1096 int timeout = 10000; |
| 1097 |
| 1098 scoped_ptr<ChromeFrameAutomationClient> client; |
| 1099 client.reset(new ChromeFrameAutomationClient); |
| 1100 |
| 1101 EXPECT_CALL(cfd, OnAutomationServerReady()) |
| 1102 .WillOnce(testing::InvokeWithoutArgs(TaskHolder(NewRunnableMethod( |
| 1103 client.get(), &ChromeFrameAutomationClient::InitiateNavigation, |
| 1104 url)))); |
| 1105 |
| 1106 // cfd.SetOnNavigationStateChanged(); |
| 1107 EXPECT_CALL(cfd, |
| 1108 OnNavigationStateChanged(testing::_, testing::_)) |
| 1109 .Times(testing::AnyNumber()); |
| 1110 |
| 1111 { |
| 1112 testing::InSequence s; |
| 1113 |
| 1114 EXPECT_CALL(cfd, OnDidNavigate(testing::_, EqNavigationInfoUrl(GURL()))) |
| 1115 .Times(1); |
| 1116 |
| 1117 EXPECT_CALL(cfd, OnUpdateTargetUrl(testing::_, testing::_)).Times(1); |
| 1118 |
| 1119 EXPECT_CALL(cfd, OnLoad(testing::_, testing::_)) |
| 1120 .Times(1) |
| 1121 .WillOnce(QUIT_LOOP(loop)); |
| 1122 } |
| 1123 |
| 1124 EXPECT_TRUE(client->Initialize(&cfd, timeout, false, profile, L"", false)); |
| 1125 loop.RunFor(10); |
| 1126 client->Uninitialize(); |
| 1127 client.reset(NULL); |
| 1128 } |
| 1129 |
| 1130 // Bug: http://b/issue?id=2033644 |
| 1131 TEST(CFACWithChrome, DISABLED_NavigateFailed) { |
| 1132 MockCFDelegate cfd; |
| 1133 TimedMsgLoop loop; |
| 1134 const std::wstring profile = L"Adam.N.Epilinter"; |
| 1135 const std::string url = "http://127.0.0.3:65412/"; |
| 1136 int timeout = 10000; |
| 1137 |
| 1138 scoped_ptr<ChromeFrameAutomationClient> client; |
| 1139 client.reset(new ChromeFrameAutomationClient); |
| 1140 |
| 1141 EXPECT_CALL(cfd, OnAutomationServerReady()) |
| 1142 .WillOnce(testing::InvokeWithoutArgs(TaskHolder(NewRunnableMethod( |
| 1143 client.get(), &ChromeFrameAutomationClient::InitiateNavigation, |
| 1144 url)))); |
| 1145 |
| 1146 EXPECT_CALL(cfd, |
| 1147 OnNavigationStateChanged(testing::_, testing::_)) |
| 1148 .Times(testing::AnyNumber()); |
| 1149 |
| 1150 EXPECT_CALL(cfd, OnNavigationFailed(testing::_, testing::_, testing::_)) |
| 1151 .Times(1); |
| 1152 |
| 1153 EXPECT_CALL(cfd, OnUpdateTargetUrl(testing::_, testing::_)) |
| 1154 .Times(testing::AnyNumber()); |
| 1155 |
| 1156 EXPECT_CALL(cfd, OnLoad(testing::_, testing::_)) |
| 1157 .Times(0); |
| 1158 |
| 1159 EXPECT_TRUE(client->Initialize(&cfd, timeout, false, profile, L"", false)); |
| 1160 |
| 1161 loop.RunFor(10); |
| 1162 client->Uninitialize(); |
| 1163 client.reset(NULL); |
| 1164 } |
| 1165 |
| 1166 MATCHER_P(EqURLRequest, x, "IPC::AutomationURLRequest matcher") { |
| 1167 if (arg.url != x.url) |
| 1168 return false; |
| 1169 if (arg.method != x.method) |
| 1170 return false; |
| 1171 if (arg.referrer != x.referrer) |
| 1172 return false; |
| 1173 if (arg.extra_request_headers != x.extra_request_headers) |
| 1174 return false; |
| 1175 // TODO: uploaddata member |
| 1176 return true; |
| 1177 } |
| 1178 |
| 1179 MATCHER_P(EqUrlGet, url, "Quick URL matcher for 'HTTP GET' request") { |
| 1180 if (arg.url != url) |
| 1181 return false; |
| 1182 if (arg.method != "GET") |
| 1183 return false; |
| 1184 return true; |
| 1185 } |
| 1186 |
| 1187 TEST(CFACWithChrome, UseHostNetworkStack) { |
| 1188 MockCFDelegate cfd; |
| 1189 TimedMsgLoop loop; |
| 1190 const std::wstring profile = L"Adam.N.Epilinter"; |
| 1191 const std::string url = "http://bongo.com"; |
| 1192 int timeout = 10000; |
| 1193 |
| 1194 scoped_ptr<ChromeFrameAutomationClient> client; |
| 1195 client.reset(new ChromeFrameAutomationClient); |
| 1196 client->set_use_chrome_network(false); |
| 1197 cfd.SetAutomationSender(client.get()); |
| 1198 |
| 1199 EXPECT_CALL(cfd, OnAutomationServerReady()) |
| 1200 .WillOnce(testing::InvokeWithoutArgs(TaskHolder(NewRunnableMethod( |
| 1201 client.get(), &ChromeFrameAutomationClient::InitiateNavigation, |
| 1202 url)))); |
| 1203 |
| 1204 EXPECT_CALL(cfd, OnNavigationStateChanged(testing::_, testing::_)) |
| 1205 .Times(testing::AnyNumber()); |
| 1206 |
| 1207 EXPECT_CALL(cfd, GetBounds(testing::_)) |
| 1208 .Times(testing::AtMost(1)); |
| 1209 |
| 1210 EXPECT_CALL(cfd, OnUpdateTargetUrl(testing::_, testing::_)) |
| 1211 .Times(testing::AnyNumber()); |
| 1212 |
| 1213 // Note slash appending to the url string, because of GURL inside chrome |
| 1214 const IPC::AutomationURLResponse found = {"", "HTTP/0.9 200\r\n\r\n\r\n", }; |
| 1215 |
| 1216 // Hard coded tab and request ids |
| 1217 static const int tab_id = 1; |
| 1218 int request_id = 2; |
| 1219 |
| 1220 EXPECT_CALL(cfd, OnRequestStart(tab_id, request_id, EqUrlGet(url + '/'))) |
| 1221 .Times(1) |
| 1222 .WillOnce(testing::Invoke(CBF(&cfd, &MockCFDelegate::ReplyStarted, |
| 1223 &found))); |
| 1224 |
| 1225 // Return some trivial page, that have a link to a "logo.gif" image |
| 1226 const std::string data = "<!DOCTYPE html><title>Hello</title>" |
| 1227 "<img src=\"logo.gif\">"; |
| 1228 EXPECT_CALL(cfd, OnRequestRead(tab_id, request_id, testing::Ge(0))) |
| 1229 .Times(2) |
| 1230 .WillOnce(testing::Invoke(CBF(&cfd, &MockCFDelegate::ReplyData, &data))) |
| 1231 .WillOnce(testing::WithArgs<0, 1>(testing::Invoke(CBF(&cfd, |
| 1232 &MockCFDelegate::ReplyEOF)))); |
| 1233 |
| 1234 EXPECT_CALL(cfd, OnDidNavigate(tab_id, EqNavigationInfoUrl(GURL(url)))) |
| 1235 .Times(1); |
| 1236 EXPECT_CALL(cfd, OnLoad(tab_id, GURL(url))) |
| 1237 .Times(1); |
| 1238 |
| 1239 // Expect request for logo.gif |
| 1240 request_id++; |
| 1241 EXPECT_CALL(cfd, |
| 1242 OnRequestStart(tab_id, request_id, EqUrlGet(url + "/logo.gif"))) |
| 1243 .Times(1) |
| 1244 .WillOnce(testing::Invoke(CBF(&cfd, &MockCFDelegate::Reply404))); |
| 1245 |
| 1246 EXPECT_CALL(cfd, OnRequestRead(tab_id, request_id, testing::_)) |
| 1247 .Times(testing::AtMost(1)); |
| 1248 |
| 1249 // Chrome makes a brave request for favicon.ico |
| 1250 request_id++; |
| 1251 EXPECT_CALL(cfd, |
| 1252 OnRequestStart(tab_id, request_id, EqUrlGet(url + "/favicon.ico"))) |
| 1253 .Times(1) |
| 1254 .WillOnce(testing::Invoke(CBF(&cfd, &MockCFDelegate::Reply404))); |
| 1255 |
| 1256 EXPECT_CALL(cfd, OnRequestRead(tab_id, request_id, testing::_)) |
| 1257 .Times(testing::AtMost(1)); |
| 1258 |
| 1259 bool incognito = true; |
| 1260 EXPECT_TRUE(client->Initialize(&cfd, timeout, false, profile, L"", |
| 1261 incognito)); |
| 1262 |
| 1263 loop.RunFor(10); |
| 1264 client->Uninitialize(); |
| 1265 client.reset(NULL); |
| 1266 } |
| 1267 |
| 1268 |
| 1269 // [CFAC] -- uses a ProxyFactory for creation of ChromeFrameAutomationProxy |
| 1270 // -- uses ChromeFrameAutomationProxy |
| 1271 // -- uses TabProxy obtained from ChromeFrameAutomationProxy |
| 1272 // -- uses ChromeFrameDelegate as outgoing interface |
| 1273 // |
| 1274 // We mock ProxyFactory to return mock object (MockAutomationProxy) implementing |
| 1275 // ChromeFrameAutomationProxy interface. |
| 1276 // Since CFAC uses TabProxy for few calls and TabProxy is not easy mockable, |
| 1277 // we create 'real' TabProxy but with fake AutomationSender (the one responsible |
| 1278 // for sending messages over channel). |
| 1279 // Additionally we have mock implementation ChromeFrameDelagate interface - |
| 1280 // MockCFDelegate. |
| 1281 |
| 1282 // Test fixture, saves typing all of it's members. |
| 1283 class CFACMockTest : public testing::Test { |
| 1284 public: |
| 1285 MockProxyFactory factory_; |
| 1286 MockCFDelegate cfd_; |
| 1287 TimedMsgLoop loop_; |
| 1288 MockAutomationProxy proxy_; |
| 1289 scoped_ptr<AutomationHandleTracker> tracker_; |
| 1290 MockAutomationMessageSender dummy_sender_; |
| 1291 scoped_refptr<TabProxy> tab_; |
| 1292 scoped_ptr<ChromeFrameAutomationClient> client_; // the victim of all tests |
| 1293 |
| 1294 std::wstring profile_; |
| 1295 int timeout_; |
| 1296 void* id_; // Automation server id we are going to return |
| 1297 int tab_handle_; // Tab handle. Any non-zero value is Ok. |
| 1298 |
| 1299 inline ChromeFrameAutomationProxy* get_proxy() { |
| 1300 return static_cast<ChromeFrameAutomationProxy*>(&proxy_); |
| 1301 } |
| 1302 |
| 1303 inline void CreateTab() { |
| 1304 ASSERT_EQ(NULL, tab_.get()); |
| 1305 tab_ = new TabProxy(&dummy_sender_, tracker_.get(), tab_handle_); |
| 1306 } |
| 1307 |
| 1308 // Easy methods to set expectations. |
| 1309 void SetAutomationServerOk() { |
| 1310 EXPECT_CALL(factory_, GetAutomationServer(testing::Eq(timeout_), |
| 1311 testing::StrEq(profile_), |
| 1312 testing::_, |
| 1313 testing::_, |
| 1314 testing::NotNull())) |
| 1315 .Times(1) |
| 1316 .WillOnce(testing::DoAll( |
| 1317 testing::WithArgs<0, 4>( |
| 1318 testing::Invoke(CBF(&factory_, &MockProxyFactory::GetServerImpl, |
| 1319 get_proxy(), AUTOMATION_SUCCESS))), |
| 1320 testing::Return(id_))); |
| 1321 |
| 1322 EXPECT_CALL(factory_, ReleaseAutomationServer(testing::Eq(id_))).Times(1); |
| 1323 } |
| 1324 |
| 1325 void Set_CFD_LaunchFailed(AutomationLaunchResult result) { |
| 1326 EXPECT_CALL(cfd_, OnAutomationServerLaunchFailed( |
| 1327 testing::Eq(result), testing::_)) |
| 1328 .Times(1) |
| 1329 .WillOnce(QUIT_LOOP(loop_)); |
| 1330 } |
| 1331 |
| 1332 protected: |
| 1333 CFACMockTest() : tracker_(NULL), timeout_(500), |
| 1334 profile_(L"Adam.N.Epilinter") { |
| 1335 id_ = reinterpret_cast<void*>(5); |
| 1336 tab_handle_ = 3; |
| 1337 } |
| 1338 |
| 1339 virtual void SetUp() { |
| 1340 dummy_sender_.ForwardTo(&proxy_); |
| 1341 tracker_.reset(new AutomationHandleTracker(&dummy_sender_)); |
| 1342 |
| 1343 client_.reset(new ChromeFrameAutomationClient); |
| 1344 client_->set_proxy_factory(&factory_); |
| 1345 } |
| 1346 }; |
| 1347 |
| 1348 // Could be implemented as MockAutomationProxy member (we have WithArgs<>!) |
| 1349 ACTION_P3(HandleCreateTab, tab_handle, external_tab_container, tab_wnd) { |
| 1350 // arg0 - message |
| 1351 // arg1 - callback |
| 1352 // arg2 - key |
| 1353 CallbackRunner<Tuple3<HWND, HWND, int> >* c = |
| 1354 reinterpret_cast<CallbackRunner<Tuple3<HWND, HWND, int> >*>(arg1); |
| 1355 c->Run(external_tab_container, tab_wnd, tab_handle); |
| 1356 delete c; |
| 1357 delete arg0; |
| 1358 } |
| 1359 |
| 1360 TEST_F(CFACMockTest, MockedCreateTabOk) { |
| 1361 int timeout = 500; |
| 1362 CreateTab(); |
| 1363 SetAutomationServerOk(); |
| 1364 |
| 1365 EXPECT_CALL(proxy_, server_version()).Times(testing::AnyNumber()) |
| 1366 .WillRepeatedly(testing::Return("")); |
| 1367 |
| 1368 // We need some valid HWNDs, when responding to CreateExternalTab |
| 1369 HWND h1 = ::GetDesktopWindow(); |
| 1370 HWND h2 = ::GetDesktopWindow(); |
| 1371 EXPECT_CALL(proxy_, SendAsAsync(testing::Property(&IPC::SyncMessage::type, |
| 1372 AutomationMsg_CreateExternalTab__ID), |
| 1373 testing::NotNull(), testing::_)) |
| 1374 .Times(1) |
| 1375 .WillOnce(HandleCreateTab(tab_handle_, h1, h2)); |
| 1376 |
| 1377 EXPECT_CALL(proxy_, CreateTabProxy(testing::Eq(tab_handle_))) |
| 1378 .WillOnce(testing::Return(tab_)); |
| 1379 |
| 1380 EXPECT_CALL(cfd_, OnAutomationServerReady()) |
| 1381 .WillOnce(QUIT_LOOP(loop_)); |
| 1382 |
| 1383 // Here we go! |
| 1384 EXPECT_TRUE(client_->Initialize(&cfd_, timeout, false, profile_, L"", false)); |
| 1385 loop_.RunFor(10); |
| 1386 client_->Uninitialize(); |
| 1387 } |
| 1388 |
| 1389 TEST_F(CFACMockTest, MockedCreateTabFailed) { |
| 1390 HWND null_wnd = NULL; |
| 1391 SetAutomationServerOk(); |
| 1392 |
| 1393 EXPECT_CALL(proxy_, server_version()).Times(testing::AnyNumber()) |
| 1394 .WillRepeatedly(testing::Return("")); |
| 1395 |
| 1396 EXPECT_CALL(proxy_, SendAsAsync(testing::Property(&IPC::SyncMessage::type, |
| 1397 AutomationMsg_CreateExternalTab__ID), |
| 1398 testing::NotNull(), testing::_)) |
| 1399 .Times(1) |
| 1400 .WillOnce(HandleCreateTab(tab_handle_, null_wnd, null_wnd)); |
| 1401 |
| 1402 EXPECT_CALL(proxy_, CreateTabProxy(testing::_)).Times(0); |
| 1403 |
| 1404 Set_CFD_LaunchFailed(AUTOMATION_CREATE_TAB_FAILED); |
| 1405 |
| 1406 // Here we go! |
| 1407 EXPECT_TRUE(client_->Initialize(&cfd_, timeout_, false, profile_, L"", |
| 1408 false)); |
| 1409 loop_.RunFor(4); |
| 1410 client_->Uninitialize(); |
| 1411 } |
| 1412 |
| 1413 const wchar_t kMetaTagPage[] = L"files/meta_tag.html"; |
| 1414 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_MetaTag) { |
| 1415 SimpleBrowserTest(IE, kMetaTagPage, L"meta_tag"); |
| 1416 } |
| 1417 |
| 1418 const wchar_t kCFProtocolPage[] = L"files/chrome_frame_protocol.html"; |
| 1419 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_CFProtocol) { |
| 1420 SimpleBrowserTest(IE, kCFProtocolPage, L"chrome_frame_protocol"); |
| 1421 } |
| 1422 |
| 1423 const wchar_t kPersistentCookieTest[] = |
| 1424 L"files/persistent_cookie_test_page.html"; |
| 1425 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_PersistentCookieTest) { |
| 1426 SimpleBrowserTest(IE, kPersistentCookieTest, L"PersistentCookieTest"); |
| 1427 } |
| 1428 |
| 1429 const wchar_t kNavigateOutPage[] = L"files/navigate_out.html"; |
| 1430 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_NavigateOut) { |
| 1431 SimpleBrowserTest(IE, kNavigateOutPage, L"navigate_out"); |
| 1432 } |
| 1433 |
| 1434 HRESULT LaunchIEAsComServer(IWebBrowser2** web_browser) { |
| 1435 if (!web_browser) |
| 1436 return E_INVALIDARG; |
| 1437 |
| 1438 ScopedComPtr<IWebBrowser2> web_browser2; |
| 1439 HRESULT hr = CoCreateInstance( |
| 1440 CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER, IID_IWebBrowser2, |
| 1441 reinterpret_cast<void**>(web_browser2.Receive())); |
| 1442 |
| 1443 if (SUCCEEDED(hr)) { |
| 1444 *web_browser = web_browser2.Detach(); |
| 1445 } |
| 1446 |
| 1447 return hr; |
| 1448 } |
| 1449 |
| 1450 TEST(ChromeFrameTest, FullTabModeIE_DisallowedUrls) { |
| 1451 int major_version = 0; |
| 1452 int minor_version = 0; |
| 1453 int bugfix_version = 0; |
| 1454 |
| 1455 base::SysInfo::OperatingSystemVersionNumbers(&major_version, &minor_version, |
| 1456 &bugfix_version); |
| 1457 if (major_version > 5) { |
| 1458 DLOG(INFO) << __FUNCTION__ << " Not running test on Windows version: " |
| 1459 << major_version; |
| 1460 return; |
| 1461 } |
| 1462 |
| 1463 IEVersion ie_version = GetIEVersion(); |
| 1464 if (ie_version == IE_8) { |
| 1465 DLOG(INFO) << __FUNCTION__ << " Not running test on IE8"; |
| 1466 return; |
| 1467 } |
| 1468 |
| 1469 HRESULT hr = CoInitialize(NULL); |
| 1470 bool should_uninit = SUCCEEDED(hr); |
| 1471 |
| 1472 ScopedComPtr<IWebBrowser2> web_browser2; |
| 1473 EXPECT_TRUE(S_OK == LaunchIEAsComServer(web_browser2.Receive())); |
| 1474 web_browser2->put_Visible(VARIANT_TRUE); |
| 1475 |
| 1476 CComObject<WebBrowserEventSink>* web_browser_sink = NULL; |
| 1477 CComObject<WebBrowserEventSink>::CreateInstance(&web_browser_sink); |
| 1478 |
| 1479 // Pass the main thread id to the browser sink so that it can notify |
| 1480 // us about test completion. |
| 1481 web_browser_sink->set_main_thread_id(GetCurrentThreadId()); |
| 1482 |
| 1483 hr = web_browser_sink->DispEventAdvise(web_browser2, |
| 1484 &DIID_DWebBrowserEvents2); |
| 1485 EXPECT_TRUE(hr == S_OK); |
| 1486 |
| 1487 VARIANT empty = ScopedVariant::kEmptyVariant; |
| 1488 ScopedVariant url; |
| 1489 url.Set(L"cf:file:///C:/"); |
| 1490 |
| 1491 TimedMsgLoop loop; |
| 1492 |
| 1493 hr = web_browser2->Navigate2(url.AsInput(), &empty, &empty, &empty, &empty); |
| 1494 EXPECT_TRUE(hr == S_OK); |
| 1495 |
| 1496 loop.RunFor(10); |
| 1497 |
| 1498 EXPECT_TRUE(web_browser_sink->navigation_failed()); |
| 1499 |
| 1500 hr = web_browser_sink->DispEventUnadvise(web_browser2); |
| 1501 EXPECT_TRUE(hr == S_OK); |
| 1502 |
| 1503 web_browser2.Release(); |
| 1504 chrome_frame_test::CloseAllIEWindows(); |
| 1505 |
| 1506 if (should_uninit) { |
| 1507 CoUninitialize(); |
| 1508 } |
| 1509 } |
| 1510 |
OLD | NEW |