// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome_frame/test/test_with_web_server.h" #include "base/base_paths.h" #include "base/file_version_info.h" #include "base/files/scoped_temp_dir.h" #include "base/path_service.h" #include "base/stringprintf.h" #include "base/test/test_timeouts.h" #include "base/utf_string_conversions.h" #include "base/win/windows_version.h" #include "chrome/common/chrome_switches.h" #include "chrome/installer/util/product.h" #include "chrome/installer/util/install_util.h" #include "chrome/installer/util/helper.h" #include "chrome_frame/html_utils.h" #include "chrome_frame/utils.h" #include "chrome_frame/test/chrome_frame_test_utils.h" #include "chrome_frame/test/mock_ie_event_sink_actions.h" #include "chrome_frame/test/mock_ie_event_sink_test.h" #include "chrome_frame/test/test_scrubber.h" #include "net/base/mime_util.h" #include "net/base/stream_listen_socket.h" #include "net/http/http_util.h" using chrome_frame_test::kChromeFrameLongNavigationTimeout; using chrome_frame_test::kChromeFrameVeryLongNavigationTimeout; using testing::_; using testing::StrCaseEq; const wchar_t kDocRoot[] = L"chrome_frame\\test\\data"; namespace { // Helper method for creating the appropriate HTTP response headers. std::string CreateHttpHeaders(CFInvocation invocation, bool add_no_cache_header, const std::string& content_type) { std::ostringstream ss; ss << "HTTP/1.1 200 OK\r\n" << "Connection: close\r\n" << "Content-Type: " << content_type << "\r\n"; if (invocation.type() == CFInvocation::HTTP_HEADER) ss << "X-UA-Compatible: chrome=1\r\n"; if (add_no_cache_header) { ss << "Cache-Control: no-cache\r\n"; ss << "Expires: Tue, 15 Nov 1994 08:12:31 GMT\r\n"; } return ss.str(); } std::string GetMockHttpHeaders(const base::FilePath& mock_http_headers_path) { std::string headers; file_util::ReadFileToString(mock_http_headers_path, &headers); return headers; } class ChromeFrameTestEnvironment: public testing::Environment { public: virtual ~ChromeFrameTestEnvironment() {} virtual void SetUp() OVERRIDE { ScopedChromeFrameRegistrar::RegisterDefaults(); } }; ::testing::Environment* const chrome_frame_env = ::testing::AddGlobalTestEnvironment(new ChromeFrameTestEnvironment); } // namespace base::FilePath ChromeFrameTestWithWebServer::test_file_path_; base::FilePath ChromeFrameTestWithWebServer::results_dir_; base::FilePath ChromeFrameTestWithWebServer::CFInstall_path_; base::FilePath ChromeFrameTestWithWebServer::CFInstance_path_; base::ScopedTempDir ChromeFrameTestWithWebServer::temp_dir_; base::FilePath ChromeFrameTestWithWebServer::chrome_user_data_dir_; chrome_frame_test::TimedMsgLoop* ChromeFrameTestWithWebServer::loop_; std::string ChromeFrameTestWithWebServer::local_address_; testing::StrictMock* ChromeFrameTestWithWebServer::listener_mock_; testing::StrictMock* ChromeFrameTestWithWebServer::server_mock_; ChromeFrameTestWithWebServer::ChromeFrameTestWithWebServer() { } // static void ChromeFrameTestWithWebServer::SetUpTestCase() { base::FilePath chrome_frame_source_path; PathService::Get(base::DIR_SOURCE_ROOT, &chrome_frame_source_path); chrome_frame_source_path = chrome_frame_source_path.Append( FILE_PATH_LITERAL("chrome_frame")); test_file_path_ = chrome_frame_source_path .Append(FILE_PATH_LITERAL("test")) .Append(FILE_PATH_LITERAL("data")); results_dir_ = chrome_frame_test::GetTestDataFolder().AppendASCII("dump"); // Copy the CFInstance.js and CFInstall.js files from src\chrome_frame to // src\chrome_frame\test\data. base::FilePath CFInstance_src_path; base::FilePath CFInstall_src_path; CFInstance_src_path = chrome_frame_source_path.AppendASCII("CFInstance.js"); CFInstance_path_ = test_file_path_.AppendASCII("CFInstance.js"); ASSERT_TRUE(file_util::CopyFile(CFInstance_src_path, CFInstance_path_)); CFInstall_src_path = chrome_frame_source_path.AppendASCII("CFInstall.js"); CFInstall_path_ = test_file_path_.AppendASCII("CFInstall.js"); ASSERT_TRUE(file_util::CopyFile(CFInstall_src_path, CFInstall_path_)); loop_ = new chrome_frame_test::TimedMsgLoop(); loop_->set_snapshot_on_timeout(true); local_address_ = chrome_frame_test::GetLocalIPv4Address(); listener_mock_ = new testing::StrictMock(); server_mock_ = new testing::StrictMock( 1337, ASCIIToWide(local_address_), chrome_frame_test::GetTestDataFolder()); server_mock_->set_listener(listener_mock_); } // static void ChromeFrameTestWithWebServer::TearDownTestCase() { delete server_mock_; server_mock_ = NULL; delete listener_mock_; listener_mock_ = NULL; local_address_.clear(); delete loop_; loop_ = NULL; file_util::Delete(CFInstall_path_, false); file_util::Delete(CFInstance_path_, false); if (temp_dir_.IsValid()) EXPECT_TRUE(temp_dir_.Delete()); } // static const base::FilePath& ChromeFrameTestWithWebServer::GetChromeUserDataDirectory() { if (!temp_dir_.IsValid()) { EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); chrome_user_data_dir_ = temp_dir_.path().AppendASCII("User Data"); } return chrome_user_data_dir_; } void ChromeFrameTestWithWebServer::SetUp() { // Make sure that we are not accidentally enabling gcf protocol. SetConfigBool(kAllowUnsafeURLs, false); server_mock().ClearResults(); server_mock().ExpectAndServeAnyRequests(CFInvocation(CFInvocation::NONE)); server_mock().set_expected_result("OK"); } void ChromeFrameTestWithWebServer::TearDown() { CloseBrowser(); loop().RunUntilIdle(); testing::Mock::VerifyAndClear(listener_mock_); testing::Mock::VerifyAndClear(server_mock_); } bool ChromeFrameTestWithWebServer::LaunchBrowser(BrowserKind browser, const wchar_t* page) { std::wstring url = page; // We should resolve the URL only if it is a relative url. GURL parsed_url(WideToUTF8(page)); if (!parsed_url.has_scheme()) { url = server_mock().Resolve(page); } browser_ = browser; if (browser == IE) { browser_handle_.Set(chrome_frame_test::LaunchIE(url)); } else if (browser == CHROME) { const base::FilePath& user_data_dir = GetChromeUserDataDirectory(); chrome_frame_test::OverrideDataDirectoryForThisTest(user_data_dir.value()); browser_handle_.Set(chrome_frame_test::LaunchChrome(url, user_data_dir)); } else { NOTREACHED(); } return browser_handle_.IsValid(); } void ChromeFrameTestWithWebServer::CloseBrowser() { if (!browser_handle_.IsValid()) return; int attempts = 0; if (browser_ == IE) { attempts = chrome_frame_test::CloseAllIEWindows(); } else { attempts = chrome_frame_test::CloseVisibleWindowsOnAllThreads( browser_handle_); } if (attempts > 0) { DWORD wait = ::WaitForSingleObject(browser_handle_, 20000); if (wait == WAIT_OBJECT_0) { browser_handle_.Close(); } else { LOG(ERROR) << "WaitForSingleObject returned " << wait; } } else { LOG(ERROR) << "No attempts to close browser windows"; } if (browser_handle_.IsValid()) { DWORD exit_code = 0; if (!::GetExitCodeProcess(browser_handle_, &exit_code) || exit_code == STILL_ACTIVE) { LOG(ERROR) << L"Forcefully killing browser process. Exit:" << exit_code; base::KillProcess(browser_handle_, 0, true); } browser_handle_.Close(); } } bool ChromeFrameTestWithWebServer::BringBrowserToTop() { return simulate_input::EnsureProcessInForeground( GetProcessId(browser_handle_)); } bool ChromeFrameTestWithWebServer::WaitForTestToComplete( base::TimeDelta duration) { loop().RunFor(duration); return !loop().WasTimedOut(); } bool ChromeFrameTestWithWebServer::WaitForOnLoad(int milliseconds) { return false; } const wchar_t kPostedResultSubstring[] = L"/writefile/"; void ChromeFrameTestWithWebServer::SimpleBrowserTestExpectedResult( BrowserKind browser, const wchar_t* page, const char* result) { if (browser == IE && chrome_frame_test::GetInstalledIEVersion() >= IE_9) { LOG(INFO) << "Temporarily disabling IE9 web server tests. " "See http://crbug.com/143699"; return; } int tries = 0; ExpectAndHandlePostedResult(); // Retry tests that timeout once; see http://crbug.com/96449. do { // NOTE: Failed ASSERTs cause this function to exit immediately. // Don't take a snapshot on the first try. loop().set_snapshot_on_timeout(tries != 0); ASSERT_TRUE(LaunchBrowser(browser, page)); if (WaitForTestToComplete(TestTimeouts::action_max_timeout())) { // The test exited without timing out. Confirm that the expected response // was posted and return. ASSERT_EQ(result, server_mock().posted_result()); break; } ASSERT_EQ(std::string(), server_mock().posted_result()) << "Test timed out yet provided a result."; ASSERT_EQ(0, tries++) << "Failing test due to two timeouts."; // Close the browser and try a second time. CloseBrowser(); LOG(ERROR) << "Retrying test once since it timed out."; } while (true); loop().set_snapshot_on_timeout(true); } void ChromeFrameTestWithWebServer::SimpleBrowserTest(BrowserKind browser, const wchar_t* page) { SimpleBrowserTestExpectedResult(browser, page, "OK"); } void ChromeFrameTestWithWebServer::ExpectAndHandlePostedResult() { EXPECT_CALL(listener_mock(), OnExpectedResponse()) .WillRepeatedly(QUIT_LOOP_SOON(loop(), base::TimeDelta::FromMilliseconds(100))); server_mock().ExpectAndHandlePostedResult(CFInvocation(CFInvocation::NONE), kPostedResultSubstring); } void ChromeFrameTestWithWebServer::VersionTest(BrowserKind browser, const wchar_t* page) { base::FilePath plugin_path; PathService::Get(base::DIR_MODULE, &plugin_path); plugin_path = plugin_path.Append(kChromeFrameDllName); static FileVersionInfo* version_info = FileVersionInfo::CreateFileVersionInfo(plugin_path); std::wstring version; if (version_info) version = version_info->product_version(); // If we can't find the Chrome Frame DLL in the src tree, we turn to // the directory where chrome is installed. if (!version_info) { BrowserDistribution* dist = BrowserDistribution::GetDistribution(); Version ver_system; InstallUtil::GetChromeVersion(dist, true, &ver_system); Version ver_user; InstallUtil::GetChromeVersion(dist, false, &ver_system); ASSERT_TRUE(ver_system.IsValid() || ver_user.IsValid()); bool system_install = ver_system.IsValid(); base::FilePath cf_dll_path(installer::GetChromeInstallPath(system_install, dist)); cf_dll_path = cf_dll_path.Append(UTF8ToWide( ver_system.IsValid() ? ver_system.GetString() : ver_user.GetString())); cf_dll_path = cf_dll_path.Append(kChromeFrameDllName); version_info = FileVersionInfo::CreateFileVersionInfo(cf_dll_path); if (version_info) version = version_info->product_version(); } server_mock().set_expected_result(WideToUTF8(version)); EXPECT_TRUE(version_info); EXPECT_FALSE(version.empty()); SimpleBrowserTestExpectedResult(browser, page, WideToASCII(version).c_str()); } // MockWebServer methods void MockWebServer::ExpectAndServeRequest(CFInvocation invocation, const std::wstring& url) { ExpectAndServeRequestWithCardinality(invocation, url, testing::Exactly(1)); } void MockWebServer::ExpectAndServeRequestWithCardinality( CFInvocation invocation, const std::wstring& url, testing::Cardinality cardinality) { EXPECT_CALL(*this, Get(_, chrome_frame_test::UrlPathEq(url), _)) .Times(cardinality) .WillRepeatedly(SendResponse(this, invocation)); } void MockWebServer::ExpectAndServeRequestAllowCache(CFInvocation invocation, const std::wstring &url) { EXPECT_CALL(*this, Get(_, chrome_frame_test::UrlPathEq(url), _)) .WillOnce(SendResponse(this, invocation)); } void MockWebServer::ExpectAndServeRequestAnyNumberTimes( CFInvocation invocation, const std::wstring& path_prefix) { EXPECT_CALL(*this, Get(_, testing::StartsWith(path_prefix), _)) .WillRepeatedly(SendResponse(this, invocation)); } void MockWebServer::ExpectAndHandlePostedResult( CFInvocation invocation, const std::wstring& post_suffix) { EXPECT_CALL(*this, Post(_, testing::HasSubstr(post_suffix), _)) .WillRepeatedly(HandlePostedResponseHelper(this, invocation)); } void MockWebServer::HandlePostedResponse( test_server::ConfigurableConnection* connection, const test_server::Request& request) { posted_result_ = request.content(); if (listener_ && posted_result_ == expected_result_) listener_->OnExpectedResponse(); connection->Send("HTTP/1.1 200 OK\r\n", ""); } void MockWebServer::SendResponseHelper( test_server::ConfigurableConnection* connection, const std::wstring& request_uri, const test_server::Request& request, CFInvocation invocation, bool add_no_cache_header) { static const wchar_t kEchoHeader[] = L"/echoheader?"; if (request_uri.find(kEchoHeader) != std::wstring::npos) { std::wstring header = request_uri.substr( wcslen(kEchoHeader), request_uri.length() - wcslen(kEchoHeader)); std::string header_value = http_utils::GetHttpHeaderFromHeaderList( WideToUTF8(header), request.headers()); connection->Send(header_value, ""); return; } // Convert |request_uri| to a path. std::wstring path = request_uri; size_t query_index = request_uri.find(L"?"); if (query_index != std::string::npos) { path = path.erase(query_index); } base::FilePath file_path = root_dir_; if (path.size()) file_path = file_path.Append(path.substr(1)); // remove first '/' std::string headers, body; std::string content_type; if (file_util::PathExists(file_path) && !file_util::DirectoryExists(file_path)) { base::FilePath mock_http_headers(file_path.value() + L".mock-http-headers"); if (file_util::PathExists(mock_http_headers)) { headers = GetMockHttpHeaders(mock_http_headers); content_type = http_utils::GetHttpHeaderFromHeaderList("Content-type", headers); } else { EXPECT_TRUE(net::GetMimeTypeFromFile(file_path, &content_type)); VLOG(1) << "Going to send file (" << WideToUTF8(file_path.value()) << ") with content type (" << content_type << ")"; headers = CreateHttpHeaders(invocation, add_no_cache_header, content_type); } EXPECT_FALSE(headers.empty()); EXPECT_TRUE(file_util::ReadFileToString(file_path, &body)) << "Could not read file (" << WideToUTF8(file_path.value()) << ")"; if (invocation.type() == CFInvocation::META_TAG && StartsWithASCII(content_type, "text/html", false)) { EXPECT_TRUE(chrome_frame_test::AddCFMetaTag(&body)) << "Could not add " << "meta tag to HTML file."; } } else { VLOG(1) << "Going to send 404 for non-existent file (" << WideToUTF8(file_path.value()) << ")"; headers = "HTTP/1.1 404 Not Found"; body = ""; } connection->Send(headers, body); } const wchar_t kPostMessageBasicPage[] = L"postmessage_basic_host.html"; TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_PostMessageBasic) { SimpleBrowserTest(IE, kPostMessageBasicPage); } TEST_F(ChromeFrameTestWithWebServer, FullTabIE_MIMEFilterBasic) { const wchar_t kMIMEFilterBasicPage[] = L"chrome_frame_mime_filter_test.html"; // If this test fails for IE8 then it is possible that prebinding is enabled. // A known workaround is to disable it until CF properly handles it. // // HKCU\Software\Microsoft\Internet Explorer\Main // Value name: EnablePreBinding (REG_DWORD) // Value: 0 SimpleBrowserTest(IE, kMIMEFilterBasicPage); } // Times out: http://crbug.com/163728 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_Resize) { SimpleBrowserTest(IE, L"chrome_frame_resize.html"); } const wchar_t kNavigateURLAbsolutePage[] = L"navigateurl_absolute_host.html"; TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_NavigateURLAbsolute) { SimpleBrowserTest(IE, kNavigateURLAbsolutePage); } const wchar_t kNavigateURLRelativePage[] = L"navigateurl_relative_host.html"; // Flaky, crbug.com/160497. TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_NavigateURLRelative) { SimpleBrowserTest(IE, kNavigateURLRelativePage); } const wchar_t kNavigateSimpleObjectFocus[] = L"simple_object_focus.html"; TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_ObjectFocus) { SimpleBrowserTest(IE, kNavigateSimpleObjectFocus); } const wchar_t kiframeBasicPage[] = L"iframe_basic_host.html"; // Flaky, crbug.com/160497. TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_iframeBasic) { SimpleBrowserTest(IE, kiframeBasicPage); } const wchar_t kSrcPropertyTestPage[] = L"src_property_host.html"; TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_SrcProperty) { SimpleBrowserTest(IE, kSrcPropertyTestPage); } const wchar_t kCFInstanceBasicTestPage[] = L"CFInstance_basic_host.html"; TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceBasic) { SimpleBrowserTest(IE, kCFInstanceBasicTestPage); } const wchar_t kCFISingletonPage[] = L"CFInstance_singleton_host.html"; TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceSingleton) { SimpleBrowserTest(IE, kCFISingletonPage); } const wchar_t kCFIDelayPage[] = L"CFInstance_delay_host.html"; TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceDelay) { SimpleBrowserTest(IE, kCFIDelayPage); } const wchar_t kCFIFallbackPage[] = L"CFInstance_fallback_host.html"; TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceFallback) { SimpleBrowserTest(IE, kCFIFallbackPage); } const wchar_t kCFINoSrcPage[] = L"CFInstance_no_src_host.html"; // Flaky, crbug.com/160497. TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_CFInstanceNoSrc) { SimpleBrowserTest(IE, kCFINoSrcPage); } const wchar_t kCFIIfrOnLoadPage[] = L"CFInstance_iframe_onload_host.html"; // disabled since it's unlikely that we care about this case TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_CFInstanceIfrOnLoad) { SimpleBrowserTest(IE, kCFIIfrOnLoadPage); } const wchar_t kCFIZeroSizePage[] = L"CFInstance_zero_size_host.html"; TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceZeroSize) { SimpleBrowserTest(IE, kCFIZeroSizePage); } const wchar_t kCFIIfrPostPage[] = L"CFInstance_iframe_post_host.html"; TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceIfrPost) { SimpleBrowserTest(IE, kCFIIfrPostPage); } TEST_F(ChromeFrameTestWithWebServer, WidgetModeChrome_CFInstanceIfrPost) { SimpleBrowserTest(CHROME, kCFIIfrPostPage); } const wchar_t kCFIPostPage[] = L"CFInstance_post_host.html"; TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstancePost) { if (chrome_frame_test::GetInstalledIEVersion() == IE_9) { LOG(INFO) << "Not running test on Vista/Windows 7 with IE9"; return; } SimpleBrowserTest(IE, kCFIPostPage); } // This test randomly fails on the ChromeFrame builder. TEST_F(ChromeFrameTestWithWebServer, WidgetModeChrome_CFInstancePost) { SimpleBrowserTest(CHROME, kCFIPostPage); } const wchar_t kCFIRPCPage[] = L"CFInstance_rpc_host.html"; TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceRPC) { if (chrome_frame_test::GetInstalledIEVersion() == IE_9) { LOG(INFO) << "Not running test on Vista/Windows 7 with IE9"; return; } SimpleBrowserTest(IE, kCFIRPCPage); } TEST_F(ChromeFrameTestWithWebServer, WidgetModeChrome_CFInstanceRPC) { SimpleBrowserTest(CHROME, kCFIRPCPage); } const wchar_t kCFIRPCInternalPage[] = L"CFInstance_rpc_internal_host.html"; TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceRPCInternal) { if (chrome_frame_test::GetInstalledIEVersion() == IE_9) { LOG(INFO) << "Not running test on Vista/Windows 7 with IE9"; return; } SimpleBrowserTest(IE, kCFIRPCInternalPage); } TEST_F(ChromeFrameTestWithWebServer, WidgetModeChrome_CFInstanceRPCInternal) { SimpleBrowserTest(CHROME, kCFIRPCInternalPage); } const wchar_t kCFIDefaultCtorPage[] = L"CFInstance_default_ctor_host.html"; TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceDefaultCtor) { SimpleBrowserTest(IE, kCFIDefaultCtorPage); } const wchar_t kCFInstallBasicTestPage[] = L"CFInstall_basic.html"; TEST_F(ChromeFrameTestWithWebServer, FullTabIE_CFInstallBasic) { SimpleBrowserTest(IE, kCFInstallBasicTestPage); } const wchar_t kCFInstallPlaceTestPage[] = L"CFInstall_place.html"; TEST_F(ChromeFrameTestWithWebServer, FullTabIE_CFInstallPlace) { SimpleBrowserTest(IE, kCFInstallPlaceTestPage); } const wchar_t kCFInstallOverlayTestPage[] = L"CFInstall_overlay.html"; TEST_F(ChromeFrameTestWithWebServer, FullTabIE_CFInstallOverlay) { SimpleBrowserTest(IE, kCFInstallOverlayTestPage); } const wchar_t kCFInstallDismissTestPage[] = L"CFInstall_dismiss.html"; TEST_F(ChromeFrameTestWithWebServer, FullTabIE_CFInstallDismiss) { SimpleBrowserTest(IE, kCFInstallDismissTestPage); } const wchar_t kInitializeHiddenPage[] = L"initialize_hidden.html"; // Times out: http://crbug.com/163728 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_InitializeHidden) { SimpleBrowserTest(IE, kInitializeHiddenPage); } const wchar_t kFullTabHttpHeaderPage[] = L"chrome_frame_http_header.html"; TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_CFHttpHeaderBasic) { SimpleBrowserTest(IE, kFullTabHttpHeaderPage); } const wchar_t kFullTabHttpHeaderPageIFrame[] = L"chrome_frame_http_header_host.html"; TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_CFHttpHeaderIFrame) { SimpleBrowserTest(IE, kFullTabHttpHeaderPageIFrame); } const wchar_t kFullTabHttpHeaderPageFrameset[] = L"chrome_frame_http_header_frameset.html"; TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_CFHttpHeaderFrameSet) { SimpleBrowserTest(IE, kFullTabHttpHeaderPageFrameset); } const wchar_t kVersionPage[] = L"version.html"; // Flaky, crbug.com/160497. TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_Version) { VersionTest(IE, kVersionPage); } const wchar_t kEventListenerPage[] = L"event_listener.html"; TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_EventListener) { SimpleBrowserTest(IE, kEventListenerPage); } const wchar_t kPrivilegedApisPage[] = L"privileged_apis_host.html"; TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_PrivilegedApis) { SimpleBrowserTest(IE, kPrivilegedApisPage); } const wchar_t kMetaTagPage[] = L"meta_tag.html"; // Flaky, crbug.com/160497. TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_MetaTag) { SimpleBrowserTest(IE, kMetaTagPage); } // Times out: http://crbug.com/163728 const wchar_t kCFProtocolPage[] = L"cf_protocol.html"; TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_CFProtocol) { // Temporarily enable gcf: protocol for this test. SetConfigBool(kAllowUnsafeURLs, true); SimpleBrowserTest(IE, kCFProtocolPage); SetConfigBool(kAllowUnsafeURLs, false); } const wchar_t kPersistentCookieTest[] = L"persistent_cookie_test_page.html"; TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_PersistentCookieTest) { SimpleBrowserTest(IE, kPersistentCookieTest); } const wchar_t kNavigateOutPage[] = L"navigate_out.html"; TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_NavigateOut) { SimpleBrowserTest(IE, kNavigateOutPage); } const wchar_t kReferrerMainTest[] = L"referrer_main.html"; TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_ReferrerTest) { SimpleBrowserTest(IE, kReferrerMainTest); } // Times out: http://crbug.com/163728 const wchar_t kSubFrameTestPage[] = L"full_tab_sub_frame_main.html"; TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_SubFrame) { SimpleBrowserTest(IE, kSubFrameTestPage); } const wchar_t kSubIFrameTestPage[] = L"full_tab_sub_iframe_main.html"; TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_SubIFrame) { SimpleBrowserTest(IE, kSubIFrameTestPage); } const wchar_t kXMLHttpRequestTestUrl[] = L"xmlhttprequest_test.html"; // Flaky, crbug.com/160497. TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_XHRTest) { SimpleBrowserTest(IE, kXMLHttpRequestTestUrl); } const wchar_t kInstallFlowTestUrl[] = L"install_flow_test.html"; TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_InstallFlowTest) { if (base::win::GetVersion() < base::win::VERSION_VISTA) { ScopedChromeFrameRegistrar::UnregisterAtPath( GetChromeFrameBuildPath().value(), chrome_frame_test::GetTestBedType()); ASSERT_TRUE(LaunchBrowser(IE, kInstallFlowTestUrl)); loop().RunFor(kChromeFrameLongNavigationTimeout); ScopedChromeFrameRegistrar::RegisterAtPath( GetChromeFrameBuildPath().value(), chrome_frame_test::GetTestBedType()); ExpectAndHandlePostedResult(); loop().RunFor(kChromeFrameLongNavigationTimeout); chrome_frame_test::CloseAllIEWindows(); ASSERT_EQ("OK", server_mock().posted_result()); } } const wchar_t kMultipleCFInstancesTestUrl[] = L"multiple_cf_instances_main.html"; TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_MultipleCFInstances) { SimpleBrowserTest(IE, kMultipleCFInstancesTestUrl); } const wchar_t kXHRHeaderTestUrl[] = L"xmlhttprequest_header_test.html"; // Marking as flaky since it occasionally times out. crbug.com/127395. TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_XHRHeaderTest) { SimpleBrowserTest(IE, kXHRHeaderTestUrl); } const wchar_t kDeleteCookieTest[] = L"fulltab_delete_cookie_test.html"; TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_DeleteCookieTest) { SimpleBrowserTest(IE, kDeleteCookieTest); } const wchar_t kAnchorUrlNavigate[] = L"fulltab_anchor_url_navigate.html#chrome_frame"; TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_AnchorUrlNavigateTest) { SimpleBrowserTest(IE, kAnchorUrlNavigate); } // Test whether POST-ing a form from an mshtml page to a CF page will cause // the request to get reissued. It should not. // https://code.google.com/p/chromium/issues/detail?id=143699 TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_TestPostReissue) { // The order of pages in this array is assumed to be mshtml, cf, script. const wchar_t* kPages[] = { L"full_tab_post_mshtml.html", L"full_tab_post_target_cf.html", L"chrome_frame_tester_helpers.js", }; SimpleWebServerTest server(local_address_, 46664); server.PopulateStaticFileListT(kPages, arraysize(kPages), GetCFTestFilePath()); ASSERT_TRUE(LaunchBrowser(IE, server.FormatHttpPath(kPages[0]).c_str())); loop().RunFor(kChromeFrameLongNavigationTimeout); const test_server::Request* request = NULL; server.FindRequest("/quit?OK", &request); ASSERT_TRUE(request != NULL); EXPECT_EQ("OK", request->arguments()); if (request->arguments().compare("OK") == 0) { // Check how many requests we got for the cf page. Also expect it to be // a POST. int requests = server.GetRequestCountForPage(kPages[1], "POST"); EXPECT_EQ(1, requests); } } // Test whether following a link from an mshtml page to a CF page will cause // multiple network requests. It should not. // Flaky, crbug.com/160497. TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_TestMultipleGet) { // The order of pages in this array is assumed to be mshtml, cf, script. const wchar_t* kPages[] = { L"full_tab_get_mshtml.html", L"full_tab_get_target_cf.html", L"chrome_frame_tester_helpers.js", }; SimpleWebServerTest server(local_address_, 46664); server.PopulateStaticFileListT(kPages, arraysize(kPages), GetCFTestFilePath()); ASSERT_TRUE(LaunchBrowser(IE, server.FormatHttpPath(kPages[0]).c_str())); loop().RunFor(kChromeFrameVeryLongNavigationTimeout); const test_server::Request* request = NULL; server.FindRequest("/quit?OK", &request); ASSERT_TRUE(request != NULL); EXPECT_EQ("OK", request->arguments()); if (request->arguments().compare("OK") == 0) { // Check how many requests we got for the cf page and check that it was // a GET. int requests = server.GetRequestCountForPage(kPages[1], "GET"); EXPECT_EQ(1, requests); } } const wchar_t kSetCookieTest[] = L"fulltab_set_cookie_test.html"; TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_SetCookieTest) { SimpleBrowserTest(IE, kSetCookieTest); } const wchar_t kXHRConditionalHeaderTestUrl[] = L"xmlhttprequest_conditional_header_test.html"; TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_XHRConditionalHeaderTest) { SimpleBrowserTest(IE, kXHRConditionalHeaderTestUrl); } const wchar_t kWindowCloseTestUrl[] = L"window_close.html"; TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_WindowClose) { SimpleBrowserTest(IE, kWindowCloseTestUrl); } std::string GetHeaderValue(const std::string& headers, const char* header_name) { net::HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n"); while (it.GetNext()) { if (lstrcmpiA(it.name().c_str(), header_name) == 0) { return it.values(); } } return ""; } // Specialized implementation of test_server::FileResponse that supports // adding the request's User-Agent header to the returned document. // The class also supports $request_id$ which will be replaced with an // id that's incremented each time the response is sent over a socket. class UaTemplateFileResponse : public test_server::FileResponse { public: typedef test_server::FileResponse SuperClass; UaTemplateFileResponse(const char* request_path, const base::FilePath& file_path) : test_server::FileResponse(request_path, file_path), request_id_(0) { } virtual bool Matches(const test_server::Request& r) const { bool ret = SuperClass::Matches(r); if (ret) ua_ = GetHeaderValue(r.headers(), "User-Agent"); return ret; } virtual size_t ContentLength() const { const char kRequestIdTemplate[] = "$request_id$"; const char kUserAgentTemplate[] = "$UA$"; size_t length = SuperClass::ContentLength(); DCHECK(length); content_.assign(reinterpret_cast(file_->data()), file_->length()); size_t i = content_.find(kUserAgentTemplate); if (i != std::string::npos) content_.replace(i, arraysize(kUserAgentTemplate) - 1, ua_); i = content_.find(kRequestIdTemplate); if (i != std::string::npos) { content_.replace(i, arraysize(kRequestIdTemplate) - 1, base::StringPrintf("%i", request_id_)); } return content_.length(); } virtual void WriteContents(net::StreamListenSocket* socket) const { DCHECK(content_.length()); socket->Send(content_.c_str(), content_.length(), false); request_id_++; } protected: mutable std::string ua_; mutable std::string content_; mutable int request_id_; }; // This test simulates a URL that on first request returns a document // that should be rendered in mshtml, then pops up a sign-in page that // after signing in, refreshes the original page that should then return // a page that needs to be rendered in GCF. // // This test currently fails because GCF does not add the chromeframe header // to requests that mshtml initiates via IInternetSession::CreateBinding. TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_RefreshMshtmlTest) { const wchar_t* kPages[] = { L"mshtml_refresh_test.html", L"mshtml_refresh_test_popup.html", }; SimpleWebServerTest server(local_address_, 46664); server.PopulateStaticFileListT(kPages, arraysize(kPages), GetCFTestFilePath()); ASSERT_TRUE(LaunchBrowser(IE, server.FormatHttpPath(kPages[0]).c_str())); loop().RunFor(kChromeFrameLongNavigationTimeout); test_server::SimpleWebServer* ws = server.web_server(); const test_server::ConnectionList& connections = ws->connections(); test_server::ConnectionList::const_iterator it = connections.begin(); int requests_for_first_page = 0; for (; it != connections.end(); ++it) { test_server::Connection* c = (*it); const test_server::Request& r = c->request(); if (!r.path().empty() && ASCIIToWide(r.path().substr(1)).compare(kPages[0]) == 0) { requests_for_first_page++; std::string ua(GetHeaderValue(r.headers(), "User-Agent")); EXPECT_NE(std::string::npos, ua.find("chromeframe")); } } EXPECT_GT(requests_for_first_page, 1); } // See bug 36694 for details. http://crbug.com/36694 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_TestDownloadFromForm) { chrome_frame_test::MockWindowObserver win_observer_mock; win_observer_mock.WatchWindow("File Download", ""); win_observer_mock.WatchWindow("View Downloads*", ""); // The content of our HTML test page. This will be returned whenever // we reply to a GET request. static const char kHtml[] = "\n" "ChromeFrame Form Download Test\n" // To see how this test runs with only IE (no CF in the picture), comment // out this meta tag. The outcome of the test should be identical. "\n" "\n" "\n" "\n" "
\n" " \n" " \n" "
\n"; // The content of our HTML test page. This will be returned whenever // we reply to a POST request. static const char kText[] = "This is a text file (in case you were wondering)."; // This http response class will return an HTML document that contains // a form whenever it receives a GET request. Whenever it gets a POST // request, it will respond with a text file that needs to be downloaded // (content-disposition is "attachment"). class CustomResponse : public test_server::ResponseForPath { public: explicit CustomResponse(const char* path) : test_server::ResponseForPath(path), is_post_(false), post_requests_(0), get_requests_(0) { } virtual bool GetContentType(std::string* content_type) const { DCHECK(!is_post_); return false; } virtual size_t ContentLength() const { DCHECK(!is_post_); return sizeof(kHtml) - 1; } virtual bool GetCustomHeaders(std::string* headers) const { if (!is_post_) return false; *headers = StringPrintf( "HTTP/1.1 200 OK\r\n" "Content-Disposition: attachment;filename=\"test.txt\"\r\n" "Content-Type: application/text\r\n" "Connection: close\r\n" "Content-Length: %i\r\n\r\n", sizeof(kText) - 1); return true; } virtual bool Matches(const test_server::Request& r) const { bool match = __super::Matches(r); if (match) { is_post_ = LowerCaseEqualsASCII(r.method().c_str(), "post"); } return match; } virtual void WriteContents(net::StreamListenSocket* socket) const { if (is_post_) { socket->Send(kText, sizeof(kText) - 1, false); } else { socket->Send(kHtml, sizeof(kHtml) - 1, false); } } virtual void IncrementAccessCounter() { __super::IncrementAccessCounter(); if (is_post_) { post_requests_++; } else { get_requests_++; } } size_t get_request_count() const { return get_requests_; } size_t post_request_count() const { return get_requests_; } protected: mutable bool is_post_; size_t post_requests_; size_t get_requests_; }; EXPECT_CALL(win_observer_mock, OnWindowOpen(_)) .Times(testing::AtMost(1)) .WillOnce(chrome_frame_test::DoCloseWindow()); EXPECT_CALL(win_observer_mock, OnWindowClose(_)) .Times(testing::AtMost(1)) .WillOnce(QUIT_LOOP(loop())); SimpleWebServerTest server(local_address_, 46664); CustomResponse* response = new CustomResponse("/form.html"); server.web_server()->AddResponse(response); std::wstring url(server.FormatHttpPath(L"form.html")); ASSERT_TRUE(LaunchBrowser(IE, url.c_str())); loop().RunFor(kChromeFrameLongNavigationTimeout); EXPECT_EQ(1, response->get_request_count()); EXPECT_EQ(1, response->post_request_count()); }