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 32using chrome_frame_test::kChromeFrameLongNavigationTimeout; 33using chrome_frame_test::kChromeFrameVeryLongNavigationTimeout; 34 35using testing::_; 36using testing::StrCaseEq; 37 38const wchar_t kDocRoot[] = L"chrome_frame\\test\\data"; 39 40namespace { 41 42// Helper method for creating the appropriate HTTP response headers. 43std::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 59std::string GetMockHttpHeaders(const base::FilePath& mock_http_headers_path) { 60 std::string headers; 61 file_util::ReadFileToString(mock_http_headers_path, &headers); 62 return headers; 63} 64 65class 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 78base::FilePath ChromeFrameTestWithWebServer::test_file_path_; 79base::FilePath ChromeFrameTestWithWebServer::results_dir_; 80base::FilePath ChromeFrameTestWithWebServer::CFInstall_path_; 81base::FilePath ChromeFrameTestWithWebServer::CFInstance_path_; 82base::ScopedTempDir ChromeFrameTestWithWebServer::temp_dir_; 83base::FilePath ChromeFrameTestWithWebServer::chrome_user_data_dir_; 84chrome_frame_test::TimedMsgLoop* ChromeFrameTestWithWebServer::loop_; 85std::string ChromeFrameTestWithWebServer::local_address_; 86testing::StrictMock<MockWebServerListener>* 87 ChromeFrameTestWithWebServer::listener_mock_; 88testing::StrictMock<MockWebServer>* ChromeFrameTestWithWebServer::server_mock_; 89 90ChromeFrameTestWithWebServer::ChromeFrameTestWithWebServer() { 91} 92 93// static 94void 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 132void 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 147const base::FilePath& 148ChromeFrameTestWithWebServer::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 156void 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 165void ChromeFrameTestWithWebServer::TearDown() { 166 CloseBrowser(); 167 loop().RunUntilIdle(); 168 testing::Mock::VerifyAndClear(listener_mock_); 169 testing::Mock::VerifyAndClear(server_mock_); 170} 171 172bool 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 196void 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 230bool ChromeFrameTestWithWebServer::BringBrowserToTop() { 231 return simulate_input::EnsureProcessInForeground( 232 GetProcessId(browser_handle_)); 233} 234 235bool ChromeFrameTestWithWebServer::WaitForTestToComplete( 236 base::TimeDelta duration) { 237 loop().RunFor(duration); 238 return !loop().WasTimedOut(); 239} 240 241bool ChromeFrameTestWithWebServer::WaitForOnLoad(int milliseconds) { 242 return false; 243} 244 245const wchar_t kPostedResultSubstring[] = L"/writefile/"; 246 247void 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 279void ChromeFrameTestWithWebServer::SimpleBrowserTest(BrowserKind browser, 280 const wchar_t* page) { 281 SimpleBrowserTestExpectedResult(browser, page, "OK"); 282} 283 284void 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 292void 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 334void MockWebServer::ExpectAndServeRequest(CFInvocation invocation, 335 const std::wstring& url) { 336 ExpectAndServeRequestWithCardinality(invocation, url, testing::Exactly(1)); 337} 338 339void 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 347void 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 353void 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 359void 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 365void 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 374void 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(file_util::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 436const wchar_t kPostMessageBasicPage[] = L"postmessage_basic_host.html"; 437 438TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_PostMessageBasic) { 439 SimpleBrowserTest(IE, kPostMessageBasicPage); 440} 441 442TEST_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 456TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_Resize) { 457 SimpleBrowserTest(IE, L"chrome_frame_resize.html"); 458} 459 460const wchar_t kNavigateURLAbsolutePage[] = 461 L"navigateurl_absolute_host.html"; 462 463TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_NavigateURLAbsolute) { 464 SimpleBrowserTest(IE, kNavigateURLAbsolutePage); 465} 466 467const wchar_t kNavigateURLRelativePage[] = 468 L"navigateurl_relative_host.html"; 469 470// Flaky, crbug.com/160497. 471TEST_F(ChromeFrameTestWithWebServer, 472 DISABLED_WidgetModeIE_NavigateURLRelative) { 473 SimpleBrowserTest(IE, kNavigateURLRelativePage); 474} 475 476const wchar_t kNavigateSimpleObjectFocus[] = L"simple_object_focus.html"; 477 478TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_ObjectFocus) { 479 SimpleBrowserTest(IE, kNavigateSimpleObjectFocus); 480} 481 482const wchar_t kiframeBasicPage[] = L"iframe_basic_host.html"; 483 484 485// Flaky, crbug.com/160497. 486TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_iframeBasic) { 487 SimpleBrowserTest(IE, kiframeBasicPage); 488} 489 490const wchar_t kSrcPropertyTestPage[] = L"src_property_host.html"; 491 492TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_SrcProperty) { 493 SimpleBrowserTest(IE, kSrcPropertyTestPage); 494} 495 496const wchar_t kCFInstanceBasicTestPage[] = L"CFInstance_basic_host.html"; 497 498TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceBasic) { 499 SimpleBrowserTest(IE, kCFInstanceBasicTestPage); 500} 501 502const wchar_t kCFISingletonPage[] = L"CFInstance_singleton_host.html"; 503 504TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceSingleton) { 505 SimpleBrowserTest(IE, kCFISingletonPage); 506} 507 508const wchar_t kCFIDelayPage[] = L"CFInstance_delay_host.html"; 509 510TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceDelay) { 511 SimpleBrowserTest(IE, kCFIDelayPage); 512} 513 514const wchar_t kCFIFallbackPage[] = L"CFInstance_fallback_host.html"; 515 516TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceFallback) { 517 SimpleBrowserTest(IE, kCFIFallbackPage); 518} 519 520const wchar_t kCFINoSrcPage[] = L"CFInstance_no_src_host.html"; 521 522// Flaky, crbug.com/160497. 523TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_CFInstanceNoSrc) { 524 SimpleBrowserTest(IE, kCFINoSrcPage); 525} 526 527const wchar_t kCFIIfrOnLoadPage[] = L"CFInstance_iframe_onload_host.html"; 528 529// disabled since it's unlikely that we care about this case 530TEST_F(ChromeFrameTestWithWebServer, 531 DISABLED_WidgetModeIE_CFInstanceIfrOnLoad) { 532 SimpleBrowserTest(IE, kCFIIfrOnLoadPage); 533} 534 535const wchar_t kCFIZeroSizePage[] = L"CFInstance_zero_size_host.html"; 536 537TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceZeroSize) { 538 SimpleBrowserTest(IE, kCFIZeroSizePage); 539} 540 541const wchar_t kCFIIfrPostPage[] = L"CFInstance_iframe_post_host.html"; 542 543TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceIfrPost) { 544 SimpleBrowserTest(IE, kCFIIfrPostPage); 545} 546 547TEST_F(ChromeFrameTestWithWebServer, WidgetModeChrome_CFInstanceIfrPost) { 548 SimpleBrowserTest(CHROME, kCFIIfrPostPage); 549} 550 551const wchar_t kCFIPostPage[] = L"CFInstance_post_host.html"; 552 553TEST_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. 562TEST_F(ChromeFrameTestWithWebServer, WidgetModeChrome_CFInstancePost) { 563 SimpleBrowserTest(CHROME, kCFIPostPage); 564} 565 566const wchar_t kCFIRPCPage[] = L"CFInstance_rpc_host.html"; 567 568TEST_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 576TEST_F(ChromeFrameTestWithWebServer, WidgetModeChrome_CFInstanceRPC) { 577 SimpleBrowserTest(CHROME, kCFIRPCPage); 578} 579 580const wchar_t kCFIRPCInternalPage[] = 581 L"CFInstance_rpc_internal_host.html"; 582 583TEST_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 591TEST_F(ChromeFrameTestWithWebServer, WidgetModeChrome_CFInstanceRPCInternal) { 592 SimpleBrowserTest(CHROME, kCFIRPCInternalPage); 593} 594 595const wchar_t kCFIDefaultCtorPage[] = 596 L"CFInstance_default_ctor_host.html"; 597 598TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceDefaultCtor) { 599 SimpleBrowserTest(IE, kCFIDefaultCtorPage); 600} 601 602const wchar_t kCFInstallBasicTestPage[] = L"CFInstall_basic.html"; 603 604TEST_F(ChromeFrameTestWithWebServer, FullTabIE_CFInstallBasic) { 605 SimpleBrowserTest(IE, kCFInstallBasicTestPage); 606} 607 608const wchar_t kCFInstallPlaceTestPage[] = L"CFInstall_place.html"; 609 610TEST_F(ChromeFrameTestWithWebServer, FullTabIE_CFInstallPlace) { 611 SimpleBrowserTest(IE, kCFInstallPlaceTestPage); 612} 613 614const wchar_t kCFInstallOverlayTestPage[] = L"CFInstall_overlay.html"; 615 616TEST_F(ChromeFrameTestWithWebServer, FullTabIE_CFInstallOverlay) { 617 SimpleBrowserTest(IE, kCFInstallOverlayTestPage); 618} 619 620const wchar_t kCFInstallDismissTestPage[] = L"CFInstall_dismiss.html"; 621 622TEST_F(ChromeFrameTestWithWebServer, FullTabIE_CFInstallDismiss) { 623 SimpleBrowserTest(IE, kCFInstallDismissTestPage); 624} 625 626const wchar_t kInitializeHiddenPage[] = L"initialize_hidden.html"; 627// Times out: http://crbug.com/163728 628TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_InitializeHidden) { 629 SimpleBrowserTest(IE, kInitializeHiddenPage); 630} 631 632const wchar_t kFullTabHttpHeaderPage[] = L"chrome_frame_http_header.html"; 633 634TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_CFHttpHeaderBasic) { 635 SimpleBrowserTest(IE, kFullTabHttpHeaderPage); 636} 637 638const wchar_t kFullTabHttpHeaderPageIFrame[] = 639 L"chrome_frame_http_header_host.html"; 640 641TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_CFHttpHeaderIFrame) { 642 SimpleBrowserTest(IE, kFullTabHttpHeaderPageIFrame); 643} 644 645const wchar_t kFullTabHttpHeaderPageFrameset[] = 646 L"chrome_frame_http_header_frameset.html"; 647 648TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_CFHttpHeaderFrameSet) { 649 SimpleBrowserTest(IE, kFullTabHttpHeaderPageFrameset); 650} 651 652const wchar_t kVersionPage[] = L"version.html"; 653 654// Flaky, crbug.com/160497. 655TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_Version) { 656 VersionTest(IE, kVersionPage); 657} 658 659const wchar_t kEventListenerPage[] = L"event_listener.html"; 660 661TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_EventListener) { 662 SimpleBrowserTest(IE, kEventListenerPage); 663} 664 665const wchar_t kPrivilegedApisPage[] = L"privileged_apis_host.html"; 666 667TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_PrivilegedApis) { 668 SimpleBrowserTest(IE, kPrivilegedApisPage); 669} 670 671const wchar_t kMetaTagPage[] = L"meta_tag.html"; 672// Flaky, crbug.com/160497. 673TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_MetaTag) { 674 SimpleBrowserTest(IE, kMetaTagPage); 675} 676 677// Times out: http://crbug.com/163728 678const wchar_t kCFProtocolPage[] = L"cf_protocol.html"; 679TEST_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 686const wchar_t kPersistentCookieTest[] = 687 L"persistent_cookie_test_page.html"; 688TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_PersistentCookieTest) { 689 SimpleBrowserTest(IE, kPersistentCookieTest); 690} 691 692const wchar_t kNavigateOutPage[] = L"navigate_out.html"; 693TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_NavigateOut) { 694 SimpleBrowserTest(IE, kNavigateOutPage); 695} 696 697const wchar_t kReferrerMainTest[] = L"referrer_main.html"; 698 699TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_ReferrerTest) { 700 SimpleBrowserTest(IE, kReferrerMainTest); 701} 702 703// Times out: http://crbug.com/163728 704const wchar_t kSubFrameTestPage[] = L"full_tab_sub_frame_main.html"; 705TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_SubFrame) { 706 SimpleBrowserTest(IE, kSubFrameTestPage); 707} 708 709const wchar_t kSubIFrameTestPage[] = L"full_tab_sub_iframe_main.html"; 710TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_SubIFrame) { 711 SimpleBrowserTest(IE, kSubIFrameTestPage); 712} 713 714const wchar_t kXMLHttpRequestTestUrl[] = 715 L"xmlhttprequest_test.html"; 716 717// Flaky, crbug.com/160497. 718TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_XHRTest) { 719 SimpleBrowserTest(IE, kXMLHttpRequestTestUrl); 720} 721 722const wchar_t kInstallFlowTestUrl[] = 723 L"install_flow_test.html"; 724 725TEST_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 747const wchar_t kMultipleCFInstancesTestUrl[] = 748 L"multiple_cf_instances_main.html"; 749 750TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_MultipleCFInstances) { 751 SimpleBrowserTest(IE, kMultipleCFInstancesTestUrl); 752} 753 754const wchar_t kXHRHeaderTestUrl[] = 755 L"xmlhttprequest_header_test.html"; 756 757// Marking as flaky since it occasionally times out. crbug.com/127395. 758TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_XHRHeaderTest) { 759 SimpleBrowserTest(IE, kXHRHeaderTestUrl); 760} 761 762const wchar_t kDeleteCookieTest[] = 763 L"fulltab_delete_cookie_test.html"; 764 765TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_DeleteCookieTest) { 766 SimpleBrowserTest(IE, kDeleteCookieTest); 767} 768 769const wchar_t kAnchorUrlNavigate[] = 770 L"fulltab_anchor_url_navigate.html#chrome_frame"; 771 772TEST_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 779TEST_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. 811TEST_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 841const wchar_t kSetCookieTest[] = 842 L"fulltab_set_cookie_test.html"; 843 844TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_SetCookieTest) { 845 SimpleBrowserTest(IE, kSetCookieTest); 846} 847 848const wchar_t kXHRConditionalHeaderTestUrl[] = 849 L"xmlhttprequest_conditional_header_test.html"; 850 851TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_XHRConditionalHeaderTest) { 852 SimpleBrowserTest(IE, kXHRConditionalHeaderTestUrl); 853} 854 855const wchar_t kWindowCloseTestUrl[] = 856 L"window_close.html"; 857 858TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_WindowClose) { 859 SimpleBrowserTest(IE, kWindowCloseTestUrl); 860} 861 862std::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. 878class 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. 932TEST_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 964TEST_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. 1095TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_LargePageLoad) { 1096 const wchar_t kLargePageLoadPage[] = 1097 L"chrome_frame_large_page.html"; 1098 1099 SimpleBrowserTest(IE, kLargePageLoadPage); 1100} 1101