1 // Copyright (c) 2012 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_with_web_server.h" 6 7 #include "base/base_paths.h" 8 #include "base/file_util.h" 9 #include "base/file_version_info.h" 10 #include "base/files/memory_mapped_file.h" 11 #include "base/files/scoped_temp_dir.h" 12 #include "base/path_service.h" 13 #include "base/process/kill.h" 14 #include "base/strings/stringprintf.h" 15 #include "base/strings/utf_string_conversions.h" 16 #include "base/test/test_timeouts.h" 17 #include "base/win/windows_version.h" 18 #include "chrome/common/chrome_switches.h" 19 #include "chrome/installer/util/helper.h" 20 #include "chrome/installer/util/install_util.h" 21 #include "chrome/installer/util/product.h" 22 #include "chrome_frame/html_utils.h" 23 #include "chrome_frame/test/chrome_frame_test_utils.h" 24 #include "chrome_frame/test/mock_ie_event_sink_actions.h" 25 #include "chrome_frame/test/mock_ie_event_sink_test.h" 26 #include "chrome_frame/test/test_scrubber.h" 27 #include "chrome_frame/utils.h" 28 #include "net/base/mime_util.h" 29 #include "net/http/http_util.h" 30 #include "net/socket/stream_listen_socket.h" 31 32 using chrome_frame_test::kChromeFrameLongNavigationTimeout; 33 using chrome_frame_test::kChromeFrameVeryLongNavigationTimeout; 34 35 using testing::_; 36 using testing::StrCaseEq; 37 38 const wchar_t kDocRoot[] = L"chrome_frame\\test\\data"; 39 40 namespace { 41 42 // Helper method for creating the appropriate HTTP response headers. 43 std::string CreateHttpHeaders(CFInvocation invocation, 44 bool add_no_cache_header, 45 const std::string& content_type) { 46 std::ostringstream ss; 47 ss << "HTTP/1.1 200 OK\r\n" 48 << "Connection: close\r\n" 49 << "Content-Type: " << content_type << "\r\n"; 50 if (invocation.type() == CFInvocation::HTTP_HEADER) 51 ss << "X-UA-Compatible: chrome=1\r\n"; 52 if (add_no_cache_header) { 53 ss << "Cache-Control: no-cache\r\n"; 54 ss << "Expires: Tue, 15 Nov 1994 08:12:31 GMT\r\n"; 55 } 56 return ss.str(); 57 } 58 59 std::string GetMockHttpHeaders(const base::FilePath& mock_http_headers_path) { 60 std::string headers; 61 base::ReadFileToString(mock_http_headers_path, &headers); 62 return headers; 63 } 64 65 class ChromeFrameTestEnvironment: public testing::Environment { 66 public: 67 virtual ~ChromeFrameTestEnvironment() {} 68 virtual void SetUp() OVERRIDE { 69 ScopedChromeFrameRegistrar::RegisterDefaults(); 70 } 71 }; 72 73 ::testing::Environment* const chrome_frame_env = 74 ::testing::AddGlobalTestEnvironment(new ChromeFrameTestEnvironment); 75 76 } // namespace 77 78 base::FilePath ChromeFrameTestWithWebServer::test_file_path_; 79 base::FilePath ChromeFrameTestWithWebServer::results_dir_; 80 base::FilePath ChromeFrameTestWithWebServer::CFInstall_path_; 81 base::FilePath ChromeFrameTestWithWebServer::CFInstance_path_; 82 base::ScopedTempDir ChromeFrameTestWithWebServer::temp_dir_; 83 base::FilePath ChromeFrameTestWithWebServer::chrome_user_data_dir_; 84 chrome_frame_test::TimedMsgLoop* ChromeFrameTestWithWebServer::loop_; 85 std::string ChromeFrameTestWithWebServer::local_address_; 86 testing::StrictMock<MockWebServerListener>* 87 ChromeFrameTestWithWebServer::listener_mock_; 88 testing::StrictMock<MockWebServer>* ChromeFrameTestWithWebServer::server_mock_; 89 90 ChromeFrameTestWithWebServer::ChromeFrameTestWithWebServer() { 91 } 92 93 // static 94 void ChromeFrameTestWithWebServer::SetUpTestCase() { 95 base::FilePath chrome_frame_source_path; 96 PathService::Get(base::DIR_SOURCE_ROOT, &chrome_frame_source_path); 97 chrome_frame_source_path = chrome_frame_source_path.Append( 98 FILE_PATH_LITERAL("chrome_frame")); 99 100 test_file_path_ = chrome_frame_source_path 101 .Append(FILE_PATH_LITERAL("test")) 102 .Append(FILE_PATH_LITERAL("data")); 103 104 results_dir_ = chrome_frame_test::GetTestDataFolder().AppendASCII("dump"); 105 106 // Copy the CFInstance.js and CFInstall.js files from src\chrome_frame to 107 // src\chrome_frame\test\data. 108 base::FilePath CFInstance_src_path; 109 base::FilePath CFInstall_src_path; 110 111 CFInstance_src_path = chrome_frame_source_path.AppendASCII("CFInstance.js"); 112 CFInstance_path_ = test_file_path_.AppendASCII("CFInstance.js"); 113 114 ASSERT_TRUE(base::CopyFile(CFInstance_src_path, CFInstance_path_)); 115 116 CFInstall_src_path = chrome_frame_source_path.AppendASCII("CFInstall.js"); 117 CFInstall_path_ = test_file_path_.AppendASCII("CFInstall.js"); 118 119 ASSERT_TRUE(base::CopyFile(CFInstall_src_path, CFInstall_path_)); 120 121 loop_ = new chrome_frame_test::TimedMsgLoop(); 122 loop_->set_snapshot_on_timeout(true); 123 local_address_ = chrome_frame_test::GetLocalIPv4Address(); 124 listener_mock_ = new testing::StrictMock<MockWebServerListener>(); 125 server_mock_ = new testing::StrictMock<MockWebServer>( 126 1337, ASCIIToWide(local_address_), 127 chrome_frame_test::GetTestDataFolder()); 128 server_mock_->set_listener(listener_mock_); 129 } 130 131 // static 132 void ChromeFrameTestWithWebServer::TearDownTestCase() { 133 delete server_mock_; 134 server_mock_ = NULL; 135 delete listener_mock_; 136 listener_mock_ = NULL; 137 local_address_.clear(); 138 delete loop_; 139 loop_ = NULL; 140 base::DeleteFile(CFInstall_path_, false); 141 base::DeleteFile(CFInstance_path_, false); 142 if (temp_dir_.IsValid()) 143 EXPECT_TRUE(temp_dir_.Delete()); 144 } 145 146 // static 147 const base::FilePath& 148 ChromeFrameTestWithWebServer::GetChromeUserDataDirectory() { 149 if (!temp_dir_.IsValid()) { 150 EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); 151 chrome_user_data_dir_ = temp_dir_.path().AppendASCII("User Data"); 152 } 153 return chrome_user_data_dir_; 154 } 155 156 void ChromeFrameTestWithWebServer::SetUp() { 157 // Make sure that we are not accidentally enabling gcf protocol. 158 SetConfigBool(kAllowUnsafeURLs, false); 159 160 server_mock().ClearResults(); 161 server_mock().ExpectAndServeAnyRequests(CFInvocation(CFInvocation::NONE)); 162 server_mock().set_expected_result("OK"); 163 } 164 165 void ChromeFrameTestWithWebServer::TearDown() { 166 CloseBrowser(); 167 loop().RunUntilIdle(); 168 testing::Mock::VerifyAndClear(listener_mock_); 169 testing::Mock::VerifyAndClear(server_mock_); 170 } 171 172 bool ChromeFrameTestWithWebServer::LaunchBrowser(BrowserKind browser, 173 const wchar_t* page) { 174 std::wstring url = page; 175 176 // We should resolve the URL only if it is a relative url. 177 GURL parsed_url(WideToUTF8(page)); 178 if (!parsed_url.has_scheme()) { 179 url = server_mock().Resolve(page); 180 } 181 182 browser_ = browser; 183 if (browser == IE) { 184 browser_handle_.Set(chrome_frame_test::LaunchIE(url)); 185 } else if (browser == CHROME) { 186 const base::FilePath& user_data_dir = GetChromeUserDataDirectory(); 187 chrome_frame_test::OverrideDataDirectoryForThisTest(user_data_dir.value()); 188 browser_handle_.Set(chrome_frame_test::LaunchChrome(url, user_data_dir)); 189 } else { 190 NOTREACHED(); 191 } 192 193 return browser_handle_.IsValid(); 194 } 195 196 void ChromeFrameTestWithWebServer::CloseBrowser() { 197 if (!browser_handle_.IsValid()) 198 return; 199 200 int attempts = 0; 201 if (browser_ == IE) { 202 attempts = chrome_frame_test::CloseAllIEWindows(); 203 } else { 204 attempts = chrome_frame_test::CloseVisibleWindowsOnAllThreads( 205 browser_handle_); 206 } 207 208 if (attempts > 0) { 209 DWORD wait = ::WaitForSingleObject(browser_handle_, 20000); 210 if (wait == WAIT_OBJECT_0) { 211 browser_handle_.Close(); 212 } else { 213 LOG(ERROR) << "WaitForSingleObject returned " << wait; 214 } 215 } else { 216 LOG(ERROR) << "No attempts to close browser windows"; 217 } 218 219 if (browser_handle_.IsValid()) { 220 DWORD exit_code = 0; 221 if (!::GetExitCodeProcess(browser_handle_, &exit_code) || 222 exit_code == STILL_ACTIVE) { 223 LOG(ERROR) << L"Forcefully killing browser process. Exit:" << exit_code; 224 base::KillProcess(browser_handle_, 0, true); 225 } 226 browser_handle_.Close(); 227 } 228 } 229 230 bool ChromeFrameTestWithWebServer::BringBrowserToTop() { 231 return simulate_input::EnsureProcessInForeground( 232 GetProcessId(browser_handle_)); 233 } 234 235 bool ChromeFrameTestWithWebServer::WaitForTestToComplete( 236 base::TimeDelta duration) { 237 loop().RunFor(duration); 238 return !loop().WasTimedOut(); 239 } 240 241 bool ChromeFrameTestWithWebServer::WaitForOnLoad(int milliseconds) { 242 return false; 243 } 244 245 const wchar_t kPostedResultSubstring[] = L"/writefile/"; 246 247 void ChromeFrameTestWithWebServer::SimpleBrowserTestExpectedResult( 248 BrowserKind browser, const wchar_t* page, const char* result) { 249 if (browser == IE && chrome_frame_test::GetInstalledIEVersion() >= IE_9) { 250 LOG(INFO) << "Temporarily disabling IE9 web server tests. " 251 "See http://crbug.com/143699"; 252 return; 253 } 254 255 int tries = 0; 256 ExpectAndHandlePostedResult(); 257 // Retry tests that timeout once; see http://crbug.com/96449. 258 do { 259 // NOTE: Failed ASSERTs cause this function to exit immediately. 260 // Don't take a snapshot on the first try. 261 loop().set_snapshot_on_timeout(tries != 0); 262 ASSERT_TRUE(LaunchBrowser(browser, page)); 263 if (WaitForTestToComplete(TestTimeouts::action_max_timeout())) { 264 // The test exited without timing out. Confirm that the expected response 265 // was posted and return. 266 ASSERT_EQ(result, server_mock().posted_result()); 267 break; 268 } 269 ASSERT_EQ(std::string(), server_mock().posted_result()) 270 << "Test timed out yet provided a result."; 271 ASSERT_EQ(0, tries++) << "Failing test due to two timeouts."; 272 // Close the browser and try a second time. 273 CloseBrowser(); 274 LOG(ERROR) << "Retrying test once since it timed out."; 275 } while (true); 276 loop().set_snapshot_on_timeout(true); 277 } 278 279 void ChromeFrameTestWithWebServer::SimpleBrowserTest(BrowserKind browser, 280 const wchar_t* page) { 281 SimpleBrowserTestExpectedResult(browser, page, "OK"); 282 } 283 284 void ChromeFrameTestWithWebServer::ExpectAndHandlePostedResult() { 285 EXPECT_CALL(listener_mock(), OnExpectedResponse()) 286 .WillRepeatedly(QUIT_LOOP_SOON(loop(), 287 base::TimeDelta::FromMilliseconds(100))); 288 server_mock().ExpectAndHandlePostedResult(CFInvocation(CFInvocation::NONE), 289 kPostedResultSubstring); 290 } 291 292 void ChromeFrameTestWithWebServer::VersionTest(BrowserKind browser, 293 const wchar_t* page) { 294 base::FilePath plugin_path; 295 PathService::Get(base::DIR_MODULE, &plugin_path); 296 plugin_path = plugin_path.Append(kChromeFrameDllName); 297 298 static FileVersionInfo* version_info = 299 FileVersionInfo::CreateFileVersionInfo(plugin_path); 300 301 std::wstring version; 302 if (version_info) 303 version = version_info->product_version(); 304 305 // If we can't find the Chrome Frame DLL in the src tree, we turn to 306 // the directory where chrome is installed. 307 if (!version_info) { 308 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 309 Version ver_system; 310 InstallUtil::GetChromeVersion(dist, true, &ver_system); 311 Version ver_user; 312 InstallUtil::GetChromeVersion(dist, false, &ver_system); 313 ASSERT_TRUE(ver_system.IsValid() || ver_user.IsValid()); 314 315 bool system_install = ver_system.IsValid(); 316 base::FilePath cf_dll_path(installer::GetChromeInstallPath(system_install, dist)); 317 cf_dll_path = cf_dll_path.Append(UTF8ToWide( 318 ver_system.IsValid() ? ver_system.GetString() : ver_user.GetString())); 319 cf_dll_path = cf_dll_path.Append(kChromeFrameDllName); 320 version_info = FileVersionInfo::CreateFileVersionInfo(cf_dll_path); 321 if (version_info) 322 version = version_info->product_version(); 323 } 324 325 server_mock().set_expected_result(WideToUTF8(version)); 326 327 EXPECT_TRUE(version_info); 328 EXPECT_FALSE(version.empty()); 329 330 SimpleBrowserTestExpectedResult(browser, page, WideToASCII(version).c_str()); 331 } 332 333 // MockWebServer methods 334 void MockWebServer::ExpectAndServeRequest(CFInvocation invocation, 335 const std::wstring& url) { 336 ExpectAndServeRequestWithCardinality(invocation, url, testing::Exactly(1)); 337 } 338 339 void MockWebServer::ExpectAndServeRequestWithCardinality( 340 CFInvocation invocation, const std::wstring& url, 341 testing::Cardinality cardinality) { 342 EXPECT_CALL(*this, Get(_, chrome_frame_test::UrlPathEq(url), _)) 343 .Times(cardinality) 344 .WillRepeatedly(SendResponse(this, invocation)); 345 } 346 347 void MockWebServer::ExpectAndServeRequestAllowCache(CFInvocation invocation, 348 const std::wstring &url) { 349 EXPECT_CALL(*this, Get(_, chrome_frame_test::UrlPathEq(url), _)) 350 .WillOnce(SendResponse(this, invocation)); 351 } 352 353 void MockWebServer::ExpectAndServeRequestAnyNumberTimes( 354 CFInvocation invocation, const std::wstring& path_prefix) { 355 EXPECT_CALL(*this, Get(_, testing::StartsWith(path_prefix), _)) 356 .WillRepeatedly(SendResponse(this, invocation)); 357 } 358 359 void MockWebServer::ExpectAndHandlePostedResult( 360 CFInvocation invocation, const std::wstring& post_suffix) { 361 EXPECT_CALL(*this, Post(_, testing::HasSubstr(post_suffix), _)) 362 .WillRepeatedly(HandlePostedResponseHelper(this, invocation)); 363 } 364 365 void MockWebServer::HandlePostedResponse( 366 test_server::ConfigurableConnection* connection, 367 const test_server::Request& request) { 368 posted_result_ = request.content(); 369 if (listener_ && posted_result_ == expected_result_) 370 listener_->OnExpectedResponse(); 371 connection->Send("HTTP/1.1 200 OK\r\n", ""); 372 } 373 374 void MockWebServer::SendResponseHelper( 375 test_server::ConfigurableConnection* connection, 376 const std::wstring& request_uri, 377 const test_server::Request& request, 378 CFInvocation invocation, 379 bool add_no_cache_header) { 380 static const wchar_t kEchoHeader[] = L"/echoheader?"; 381 if (request_uri.find(kEchoHeader) != std::wstring::npos) { 382 std::wstring header = request_uri.substr( 383 wcslen(kEchoHeader), 384 request_uri.length() - wcslen(kEchoHeader)); 385 386 std::string header_value = http_utils::GetHttpHeaderFromHeaderList( 387 WideToUTF8(header), request.headers()); 388 connection->Send(header_value, ""); 389 return; 390 } 391 // Convert |request_uri| to a path. 392 std::wstring path = request_uri; 393 size_t query_index = request_uri.find(L"?"); 394 if (query_index != std::string::npos) { 395 path = path.erase(query_index); 396 } 397 base::FilePath file_path = root_dir_; 398 if (path.size()) 399 file_path = file_path.Append(path.substr(1)); // remove first '/' 400 401 std::string headers, body; 402 std::string content_type; 403 if (base::PathExists(file_path) && 404 !base::DirectoryExists(file_path)) { 405 base::FilePath mock_http_headers(file_path.value() + L".mock-http-headers"); 406 if (base::PathExists(mock_http_headers)) { 407 headers = GetMockHttpHeaders(mock_http_headers); 408 content_type = http_utils::GetHttpHeaderFromHeaderList("Content-type", 409 headers); 410 } else { 411 EXPECT_TRUE(net::GetMimeTypeFromFile(file_path, &content_type)); 412 VLOG(1) << "Going to send file (" << WideToUTF8(file_path.value()) 413 << ") with content type (" << content_type << ")"; 414 headers = CreateHttpHeaders(invocation, add_no_cache_header, 415 content_type); 416 } 417 418 EXPECT_FALSE(headers.empty()); 419 420 EXPECT_TRUE(base::ReadFileToString(file_path, &body)) 421 << "Could not read file (" << WideToUTF8(file_path.value()) << ")"; 422 if (invocation.type() == CFInvocation::META_TAG && 423 StartsWithASCII(content_type, "text/html", false)) { 424 EXPECT_TRUE(chrome_frame_test::AddCFMetaTag(&body)) << "Could not add " 425 << "meta tag to HTML file."; 426 } 427 } else { 428 VLOG(1) << "Going to send 404 for non-existent file (" 429 << WideToUTF8(file_path.value()) << ")"; 430 headers = "HTTP/1.1 404 Not Found"; 431 body = ""; 432 } 433 connection->Send(headers, body); 434 } 435 436 const wchar_t kPostMessageBasicPage[] = L"postmessage_basic_host.html"; 437 438 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_PostMessageBasic) { 439 SimpleBrowserTest(IE, kPostMessageBasicPage); 440 } 441 442 TEST_F(ChromeFrameTestWithWebServer, FullTabIE_MIMEFilterBasic) { 443 const wchar_t kMIMEFilterBasicPage[] = 444 L"chrome_frame_mime_filter_test.html"; 445 446 // If this test fails for IE8 then it is possible that prebinding is enabled. 447 // A known workaround is to disable it until CF properly handles it. 448 // 449 // HKCU\Software\Microsoft\Internet Explorer\Main 450 // Value name: EnablePreBinding (REG_DWORD) 451 // Value: 0 452 SimpleBrowserTest(IE, kMIMEFilterBasicPage); 453 } 454 455 // Times out: http://crbug.com/163728 456 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_Resize) { 457 SimpleBrowserTest(IE, L"chrome_frame_resize.html"); 458 } 459 460 const wchar_t kNavigateURLAbsolutePage[] = 461 L"navigateurl_absolute_host.html"; 462 463 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_NavigateURLAbsolute) { 464 SimpleBrowserTest(IE, kNavigateURLAbsolutePage); 465 } 466 467 const wchar_t kNavigateURLRelativePage[] = 468 L"navigateurl_relative_host.html"; 469 470 // Flaky, crbug.com/160497. 471 TEST_F(ChromeFrameTestWithWebServer, 472 DISABLED_WidgetModeIE_NavigateURLRelative) { 473 SimpleBrowserTest(IE, kNavigateURLRelativePage); 474 } 475 476 const wchar_t kNavigateSimpleObjectFocus[] = L"simple_object_focus.html"; 477 478 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_ObjectFocus) { 479 SimpleBrowserTest(IE, kNavigateSimpleObjectFocus); 480 } 481 482 const wchar_t kiframeBasicPage[] = L"iframe_basic_host.html"; 483 484 485 // Flaky, crbug.com/160497. 486 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_iframeBasic) { 487 SimpleBrowserTest(IE, kiframeBasicPage); 488 } 489 490 const wchar_t kSrcPropertyTestPage[] = L"src_property_host.html"; 491 492 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_SrcProperty) { 493 SimpleBrowserTest(IE, kSrcPropertyTestPage); 494 } 495 496 const wchar_t kCFInstanceBasicTestPage[] = L"CFInstance_basic_host.html"; 497 498 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceBasic) { 499 SimpleBrowserTest(IE, kCFInstanceBasicTestPage); 500 } 501 502 const wchar_t kCFISingletonPage[] = L"CFInstance_singleton_host.html"; 503 504 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceSingleton) { 505 SimpleBrowserTest(IE, kCFISingletonPage); 506 } 507 508 const wchar_t kCFIDelayPage[] = L"CFInstance_delay_host.html"; 509 510 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceDelay) { 511 SimpleBrowserTest(IE, kCFIDelayPage); 512 } 513 514 const wchar_t kCFIFallbackPage[] = L"CFInstance_fallback_host.html"; 515 516 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceFallback) { 517 SimpleBrowserTest(IE, kCFIFallbackPage); 518 } 519 520 const wchar_t kCFINoSrcPage[] = L"CFInstance_no_src_host.html"; 521 522 // Flaky, crbug.com/160497. 523 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_CFInstanceNoSrc) { 524 SimpleBrowserTest(IE, kCFINoSrcPage); 525 } 526 527 const wchar_t kCFIIfrOnLoadPage[] = L"CFInstance_iframe_onload_host.html"; 528 529 // disabled since it's unlikely that we care about this case 530 TEST_F(ChromeFrameTestWithWebServer, 531 DISABLED_WidgetModeIE_CFInstanceIfrOnLoad) { 532 SimpleBrowserTest(IE, kCFIIfrOnLoadPage); 533 } 534 535 const wchar_t kCFIZeroSizePage[] = L"CFInstance_zero_size_host.html"; 536 537 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceZeroSize) { 538 SimpleBrowserTest(IE, kCFIZeroSizePage); 539 } 540 541 const wchar_t kCFIIfrPostPage[] = L"CFInstance_iframe_post_host.html"; 542 543 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceIfrPost) { 544 SimpleBrowserTest(IE, kCFIIfrPostPage); 545 } 546 547 TEST_F(ChromeFrameTestWithWebServer, WidgetModeChrome_CFInstanceIfrPost) { 548 SimpleBrowserTest(CHROME, kCFIIfrPostPage); 549 } 550 551 const wchar_t kCFIPostPage[] = L"CFInstance_post_host.html"; 552 553 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstancePost) { 554 if (chrome_frame_test::GetInstalledIEVersion() == IE_9) { 555 LOG(INFO) << "Not running test on Vista/Windows 7 with IE9"; 556 return; 557 } 558 SimpleBrowserTest(IE, kCFIPostPage); 559 } 560 561 // This test randomly fails on the ChromeFrame builder. 562 TEST_F(ChromeFrameTestWithWebServer, WidgetModeChrome_CFInstancePost) { 563 SimpleBrowserTest(CHROME, kCFIPostPage); 564 } 565 566 const wchar_t kCFIRPCPage[] = L"CFInstance_rpc_host.html"; 567 568 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceRPC) { 569 if (chrome_frame_test::GetInstalledIEVersion() == IE_9) { 570 LOG(INFO) << "Not running test on Vista/Windows 7 with IE9"; 571 return; 572 } 573 SimpleBrowserTest(IE, kCFIRPCPage); 574 } 575 576 TEST_F(ChromeFrameTestWithWebServer, WidgetModeChrome_CFInstanceRPC) { 577 SimpleBrowserTest(CHROME, kCFIRPCPage); 578 } 579 580 const wchar_t kCFIRPCInternalPage[] = 581 L"CFInstance_rpc_internal_host.html"; 582 583 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceRPCInternal) { 584 if (chrome_frame_test::GetInstalledIEVersion() == IE_9) { 585 LOG(INFO) << "Not running test on Vista/Windows 7 with IE9"; 586 return; 587 } 588 SimpleBrowserTest(IE, kCFIRPCInternalPage); 589 } 590 591 TEST_F(ChromeFrameTestWithWebServer, WidgetModeChrome_CFInstanceRPCInternal) { 592 SimpleBrowserTest(CHROME, kCFIRPCInternalPage); 593 } 594 595 const wchar_t kCFIDefaultCtorPage[] = 596 L"CFInstance_default_ctor_host.html"; 597 598 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceDefaultCtor) { 599 SimpleBrowserTest(IE, kCFIDefaultCtorPage); 600 } 601 602 const wchar_t kCFInstallBasicTestPage[] = L"CFInstall_basic.html"; 603 604 TEST_F(ChromeFrameTestWithWebServer, FullTabIE_CFInstallBasic) { 605 SimpleBrowserTest(IE, kCFInstallBasicTestPage); 606 } 607 608 const wchar_t kCFInstallPlaceTestPage[] = L"CFInstall_place.html"; 609 610 TEST_F(ChromeFrameTestWithWebServer, FullTabIE_CFInstallPlace) { 611 SimpleBrowserTest(IE, kCFInstallPlaceTestPage); 612 } 613 614 const wchar_t kCFInstallOverlayTestPage[] = L"CFInstall_overlay.html"; 615 616 TEST_F(ChromeFrameTestWithWebServer, FullTabIE_CFInstallOverlay) { 617 SimpleBrowserTest(IE, kCFInstallOverlayTestPage); 618 } 619 620 const wchar_t kCFInstallDismissTestPage[] = L"CFInstall_dismiss.html"; 621 622 TEST_F(ChromeFrameTestWithWebServer, FullTabIE_CFInstallDismiss) { 623 SimpleBrowserTest(IE, kCFInstallDismissTestPage); 624 } 625 626 const wchar_t kInitializeHiddenPage[] = L"initialize_hidden.html"; 627 // Times out: http://crbug.com/163728 628 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_InitializeHidden) { 629 SimpleBrowserTest(IE, kInitializeHiddenPage); 630 } 631 632 const wchar_t kFullTabHttpHeaderPage[] = L"chrome_frame_http_header.html"; 633 634 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_CFHttpHeaderBasic) { 635 SimpleBrowserTest(IE, kFullTabHttpHeaderPage); 636 } 637 638 const wchar_t kFullTabHttpHeaderPageIFrame[] = 639 L"chrome_frame_http_header_host.html"; 640 641 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_CFHttpHeaderIFrame) { 642 SimpleBrowserTest(IE, kFullTabHttpHeaderPageIFrame); 643 } 644 645 const wchar_t kFullTabHttpHeaderPageFrameset[] = 646 L"chrome_frame_http_header_frameset.html"; 647 648 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_CFHttpHeaderFrameSet) { 649 SimpleBrowserTest(IE, kFullTabHttpHeaderPageFrameset); 650 } 651 652 const wchar_t kVersionPage[] = L"version.html"; 653 654 // Flaky, crbug.com/160497. 655 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_Version) { 656 VersionTest(IE, kVersionPage); 657 } 658 659 const wchar_t kEventListenerPage[] = L"event_listener.html"; 660 661 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_EventListener) { 662 SimpleBrowserTest(IE, kEventListenerPage); 663 } 664 665 const wchar_t kPrivilegedApisPage[] = L"privileged_apis_host.html"; 666 667 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_PrivilegedApis) { 668 SimpleBrowserTest(IE, kPrivilegedApisPage); 669 } 670 671 const wchar_t kMetaTagPage[] = L"meta_tag.html"; 672 // Flaky, crbug.com/160497. 673 TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_MetaTag) { 674 SimpleBrowserTest(IE, kMetaTagPage); 675 } 676 677 // Times out: http://crbug.com/163728 678 const wchar_t kCFProtocolPage[] = L"cf_protocol.html"; 679 TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_CFProtocol) { 680 // Temporarily enable gcf: protocol for this test. 681 SetConfigBool(kAllowUnsafeURLs, true); 682 SimpleBrowserTest(IE, kCFProtocolPage); 683 SetConfigBool(kAllowUnsafeURLs, false); 684 } 685 686 const wchar_t kPersistentCookieTest[] = 687 L"persistent_cookie_test_page.html"; 688 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_PersistentCookieTest) { 689 SimpleBrowserTest(IE, kPersistentCookieTest); 690 } 691 692 const wchar_t kNavigateOutPage[] = L"navigate_out.html"; 693 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_NavigateOut) { 694 SimpleBrowserTest(IE, kNavigateOutPage); 695 } 696 697 const wchar_t kReferrerMainTest[] = L"referrer_main.html"; 698 699 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_ReferrerTest) { 700 SimpleBrowserTest(IE, kReferrerMainTest); 701 } 702 703 // Times out: http://crbug.com/163728 704 const wchar_t kSubFrameTestPage[] = L"full_tab_sub_frame_main.html"; 705 TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_SubFrame) { 706 SimpleBrowserTest(IE, kSubFrameTestPage); 707 } 708 709 const wchar_t kSubIFrameTestPage[] = L"full_tab_sub_iframe_main.html"; 710 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_SubIFrame) { 711 SimpleBrowserTest(IE, kSubIFrameTestPage); 712 } 713 714 const wchar_t kXMLHttpRequestTestUrl[] = 715 L"xmlhttprequest_test.html"; 716 717 // Flaky, crbug.com/160497. 718 TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_XHRTest) { 719 SimpleBrowserTest(IE, kXMLHttpRequestTestUrl); 720 } 721 722 const wchar_t kInstallFlowTestUrl[] = 723 L"install_flow_test.html"; 724 725 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_InstallFlowTest) { 726 if (base::win::GetVersion() < base::win::VERSION_VISTA) { 727 ScopedChromeFrameRegistrar::UnregisterAtPath( 728 GetChromeFrameBuildPath().value(), 729 chrome_frame_test::GetTestBedType()); 730 731 ASSERT_TRUE(LaunchBrowser(IE, kInstallFlowTestUrl)); 732 733 loop().RunFor(kChromeFrameLongNavigationTimeout); 734 735 ScopedChromeFrameRegistrar::RegisterAtPath( 736 GetChromeFrameBuildPath().value(), 737 chrome_frame_test::GetTestBedType()); 738 739 ExpectAndHandlePostedResult(); 740 loop().RunFor(kChromeFrameLongNavigationTimeout); 741 742 chrome_frame_test::CloseAllIEWindows(); 743 ASSERT_EQ("OK", server_mock().posted_result()); 744 } 745 } 746 747 const wchar_t kMultipleCFInstancesTestUrl[] = 748 L"multiple_cf_instances_main.html"; 749 750 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_MultipleCFInstances) { 751 SimpleBrowserTest(IE, kMultipleCFInstancesTestUrl); 752 } 753 754 const wchar_t kXHRHeaderTestUrl[] = 755 L"xmlhttprequest_header_test.html"; 756 757 // Marking as flaky since it occasionally times out. crbug.com/127395. 758 TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_XHRHeaderTest) { 759 SimpleBrowserTest(IE, kXHRHeaderTestUrl); 760 } 761 762 const wchar_t kDeleteCookieTest[] = 763 L"fulltab_delete_cookie_test.html"; 764 765 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_DeleteCookieTest) { 766 SimpleBrowserTest(IE, kDeleteCookieTest); 767 } 768 769 const wchar_t kAnchorUrlNavigate[] = 770 L"fulltab_anchor_url_navigate.html#chrome_frame"; 771 772 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_AnchorUrlNavigateTest) { 773 SimpleBrowserTest(IE, kAnchorUrlNavigate); 774 } 775 776 // Test whether POST-ing a form from an mshtml page to a CF page will cause 777 // the request to get reissued. It should not. 778 // https://code.google.com/p/chromium/issues/detail?id=143699 779 TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_TestPostReissue) { 780 // The order of pages in this array is assumed to be mshtml, cf, script. 781 const wchar_t* kPages[] = { 782 L"full_tab_post_mshtml.html", 783 L"full_tab_post_target_cf.html", 784 L"chrome_frame_tester_helpers.js", 785 }; 786 787 SimpleWebServerTest server(local_address_, 46664); 788 server.PopulateStaticFileListT<test_server::FileResponse>(kPages, 789 arraysize(kPages), GetCFTestFilePath()); 790 791 ASSERT_TRUE(LaunchBrowser(IE, server.FormatHttpPath(kPages[0]).c_str())); 792 793 loop().RunFor(kChromeFrameLongNavigationTimeout); 794 795 const test_server::Request* request = NULL; 796 server.FindRequest("/quit?OK", &request); 797 ASSERT_TRUE(request != NULL); 798 EXPECT_EQ("OK", request->arguments()); 799 800 if (request->arguments().compare("OK") == 0) { 801 // Check how many requests we got for the cf page. Also expect it to be 802 // a POST. 803 int requests = server.GetRequestCountForPage(kPages[1], "POST"); 804 EXPECT_EQ(1, requests); 805 } 806 } 807 808 // Test whether following a link from an mshtml page to a CF page will cause 809 // multiple network requests. It should not. 810 // Flaky, crbug.com/160497. 811 TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_TestMultipleGet) { 812 // The order of pages in this array is assumed to be mshtml, cf, script. 813 const wchar_t* kPages[] = { 814 L"full_tab_get_mshtml.html", 815 L"full_tab_get_target_cf.html", 816 L"chrome_frame_tester_helpers.js", 817 }; 818 819 SimpleWebServerTest server(local_address_, 46664); 820 821 server.PopulateStaticFileListT<test_server::FileResponse>(kPages, 822 arraysize(kPages), GetCFTestFilePath()); 823 824 ASSERT_TRUE(LaunchBrowser(IE, server.FormatHttpPath(kPages[0]).c_str())); 825 826 loop().RunFor(kChromeFrameVeryLongNavigationTimeout); 827 828 const test_server::Request* request = NULL; 829 server.FindRequest("/quit?OK", &request); 830 ASSERT_TRUE(request != NULL); 831 EXPECT_EQ("OK", request->arguments()); 832 833 if (request->arguments().compare("OK") == 0) { 834 // Check how many requests we got for the cf page and check that it was 835 // a GET. 836 int requests = server.GetRequestCountForPage(kPages[1], "GET"); 837 EXPECT_EQ(1, requests); 838 } 839 } 840 841 const wchar_t kSetCookieTest[] = 842 L"fulltab_set_cookie_test.html"; 843 844 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_SetCookieTest) { 845 SimpleBrowserTest(IE, kSetCookieTest); 846 } 847 848 const wchar_t kXHRConditionalHeaderTestUrl[] = 849 L"xmlhttprequest_conditional_header_test.html"; 850 851 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_XHRConditionalHeaderTest) { 852 SimpleBrowserTest(IE, kXHRConditionalHeaderTestUrl); 853 } 854 855 const wchar_t kWindowCloseTestUrl[] = 856 L"window_close.html"; 857 858 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_WindowClose) { 859 SimpleBrowserTest(IE, kWindowCloseTestUrl); 860 } 861 862 std::string GetHeaderValue(const std::string& headers, 863 const char* header_name) { 864 net::HttpUtil::HeadersIterator it(headers.begin(), headers.end(), 865 "\r\n"); 866 while (it.GetNext()) { 867 if (lstrcmpiA(it.name().c_str(), header_name) == 0) { 868 return it.values(); 869 } 870 } 871 return ""; 872 } 873 874 // Specialized implementation of test_server::FileResponse that supports 875 // adding the request's User-Agent header to the returned document. 876 // The class also supports $request_id$ which will be replaced with an 877 // id that's incremented each time the response is sent over a socket. 878 class UaTemplateFileResponse : public test_server::FileResponse { 879 public: 880 typedef test_server::FileResponse SuperClass; 881 882 UaTemplateFileResponse(const char* request_path, 883 const base::FilePath& file_path) 884 : test_server::FileResponse(request_path, file_path), request_id_(0) { 885 } 886 887 virtual bool Matches(const test_server::Request& r) const { 888 bool ret = SuperClass::Matches(r); 889 if (ret) 890 ua_ = GetHeaderValue(r.headers(), "User-Agent"); 891 return ret; 892 } 893 894 virtual size_t ContentLength() const { 895 const char kRequestIdTemplate[] = "$request_id$"; 896 const char kUserAgentTemplate[] = "$UA$"; 897 898 size_t length = SuperClass::ContentLength(); 899 DCHECK(length); 900 content_.assign(reinterpret_cast<const char*>(file_->data()), 901 file_->length()); 902 size_t i = content_.find(kUserAgentTemplate); 903 if (i != std::string::npos) 904 content_.replace(i, arraysize(kUserAgentTemplate) - 1, ua_); 905 i = content_.find(kRequestIdTemplate); 906 if (i != std::string::npos) { 907 content_.replace(i, arraysize(kRequestIdTemplate) - 1, 908 base::StringPrintf("%i", request_id_)); 909 } 910 return content_.length(); 911 } 912 913 virtual void WriteContents(net::StreamListenSocket* socket) const { 914 DCHECK(content_.length()); 915 socket->Send(content_.c_str(), content_.length(), false); 916 request_id_++; 917 } 918 919 protected: 920 mutable std::string ua_; 921 mutable std::string content_; 922 mutable int request_id_; 923 }; 924 925 // This test simulates a URL that on first request returns a document 926 // that should be rendered in mshtml, then pops up a sign-in page that 927 // after signing in, refreshes the original page that should then return 928 // a page that needs to be rendered in GCF. 929 // 930 // This test currently fails because GCF does not add the chromeframe header 931 // to requests that mshtml initiates via IInternetSession::CreateBinding. 932 TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_RefreshMshtmlTest) { 933 const wchar_t* kPages[] = { 934 L"mshtml_refresh_test.html", 935 L"mshtml_refresh_test_popup.html", 936 }; 937 938 SimpleWebServerTest server(local_address_, 46664); 939 server.PopulateStaticFileListT<UaTemplateFileResponse>(kPages, 940 arraysize(kPages), GetCFTestFilePath()); 941 942 ASSERT_TRUE(LaunchBrowser(IE, server.FormatHttpPath(kPages[0]).c_str())); 943 944 loop().RunFor(kChromeFrameLongNavigationTimeout); 945 946 test_server::SimpleWebServer* ws = server.web_server(); 947 const test_server::ConnectionList& connections = ws->connections(); 948 test_server::ConnectionList::const_iterator it = connections.begin(); 949 int requests_for_first_page = 0; 950 for (; it != connections.end(); ++it) { 951 test_server::Connection* c = (*it); 952 const test_server::Request& r = c->request(); 953 if (!r.path().empty() && 954 ASCIIToWide(r.path().substr(1)).compare(kPages[0]) == 0) { 955 requests_for_first_page++; 956 std::string ua(GetHeaderValue(r.headers(), "User-Agent")); 957 EXPECT_NE(std::string::npos, ua.find("chromeframe")); 958 } 959 } 960 EXPECT_GT(requests_for_first_page, 1); 961 } 962 963 // See bug 36694 for details. http://crbug.com/36694 964 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_TestDownloadFromForm) { 965 chrome_frame_test::MockWindowObserver win_observer_mock; 966 win_observer_mock.WatchWindow("File Download", ""); 967 win_observer_mock.WatchWindow("View Downloads*", ""); 968 969 // The content of our HTML test page. This will be returned whenever 970 // we reply to a GET request. 971 static const char kHtml[] = 972 "<html><head>\n" 973 "<title>ChromeFrame Form Download Test</title>\n" 974 // To see how this test runs with only IE (no CF in the picture), comment 975 // out this meta tag. The outcome of the test should be identical. 976 "<meta http-equiv=\"X-UA-Compatible\" content=\"chrome=1\" />\n" 977 "</head>\n" 978 "<script language=\"javascript\">\n" 979 "function SubmitForm() {\n" 980 " var form = document.forms['myform'];\n" 981 " form.action = document.location;\n" 982 " form.submit();\n" 983 " return true;\n" 984 "}\n" 985 "</script>\n" 986 "<body onload=\"SubmitForm();\">\n" 987 "<form method=\"post\" action=\"foo.html\" id=\"myform\">\n" 988 " <input type=\"hidden\" name=\"Field1\" value=\"myvalue\" />\n" 989 " <input type=\"button\" name=\"btn\" value=\"Test Download\" " 990 "onclick=\"return SubmitForm();\" id=\"Button1\"/>\n" 991 "</form></body></html>\n"; 992 993 // The content of our HTML test page. This will be returned whenever 994 // we reply to a POST request. 995 static const char kText[] = 996 "This is a text file (in case you were wondering)."; 997 998 // This http response class will return an HTML document that contains 999 // a form whenever it receives a GET request. Whenever it gets a POST 1000 // request, it will respond with a text file that needs to be downloaded 1001 // (content-disposition is "attachment"). 1002 class CustomResponse : public test_server::ResponseForPath { 1003 public: 1004 explicit CustomResponse(const char* path) 1005 : test_server::ResponseForPath(path), is_post_(false), 1006 post_requests_(0), get_requests_(0) { 1007 } 1008 1009 virtual bool GetContentType(std::string* content_type) const { 1010 DCHECK(!is_post_); 1011 return false; 1012 } 1013 1014 virtual size_t ContentLength() const { 1015 DCHECK(!is_post_); 1016 return sizeof(kHtml) - 1; 1017 } 1018 1019 virtual bool GetCustomHeaders(std::string* headers) const { 1020 if (!is_post_) 1021 return false; 1022 *headers = base::StringPrintf( 1023 "HTTP/1.1 200 OK\r\n" 1024 "Content-Disposition: attachment;filename=\"test.txt\"\r\n" 1025 "Content-Type: application/text\r\n" 1026 "Connection: close\r\n" 1027 "Content-Length: %i\r\n\r\n", sizeof(kText) - 1); 1028 return true; 1029 } 1030 1031 virtual bool Matches(const test_server::Request& r) const { 1032 bool match = __super::Matches(r); 1033 if (match) { 1034 is_post_ = LowerCaseEqualsASCII(r.method().c_str(), "post"); 1035 } 1036 return match; 1037 } 1038 1039 virtual void WriteContents(net::StreamListenSocket* socket) const { 1040 if (is_post_) { 1041 socket->Send(kText, sizeof(kText) - 1, false); 1042 } else { 1043 socket->Send(kHtml, sizeof(kHtml) - 1, false); 1044 } 1045 } 1046 1047 virtual void IncrementAccessCounter() { 1048 __super::IncrementAccessCounter(); 1049 if (is_post_) { 1050 post_requests_++; 1051 } else { 1052 get_requests_++; 1053 } 1054 } 1055 1056 size_t get_request_count() const { 1057 return get_requests_; 1058 } 1059 1060 size_t post_request_count() const { 1061 return get_requests_; 1062 } 1063 1064 protected: 1065 mutable bool is_post_; 1066 size_t post_requests_; 1067 size_t get_requests_; 1068 }; 1069 1070 EXPECT_CALL(win_observer_mock, OnWindowOpen(_)) 1071 .Times(testing::AtMost(1)) 1072 .WillOnce(chrome_frame_test::DoCloseWindow()); 1073 1074 EXPECT_CALL(win_observer_mock, OnWindowClose(_)) 1075 .Times(testing::AtMost(1)) 1076 .WillOnce(QUIT_LOOP(loop())); 1077 1078 SimpleWebServerTest server(local_address_, 46664); 1079 CustomResponse* response = new CustomResponse("/form.html"); 1080 server.web_server()->AddResponse(response); 1081 1082 std::wstring url(server.FormatHttpPath(L"form.html")); 1083 1084 ASSERT_TRUE(LaunchBrowser(IE, url.c_str())); 1085 loop().RunFor(kChromeFrameLongNavigationTimeout); 1086 1087 EXPECT_EQ(1, response->get_request_count()); 1088 EXPECT_EQ(1, response->post_request_count()); 1089 } 1090 1091 // This test loads a large page and ensures that the full page contents are 1092 // actually loaded via a self-validating HTML page. This is done due to a bug 1093 // whereby the middle of the response stream would sometimes be truncated when 1094 // loading a CF document. See http://crbug.com/178421 for details. 1095 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_LargePageLoad) { 1096 const wchar_t kLargePageLoadPage[] = 1097 L"chrome_frame_large_page.html"; 1098 1099 SimpleBrowserTest(IE, kLargePageLoadPage); 1100 } 1101