| // 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_util.h" |
| #include "base/file_version_info.h" |
| #include "base/files/memory_mapped_file.h" |
| #include "base/files/scoped_temp_dir.h" |
| #include "base/path_service.h" |
| #include "base/process/kill.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/test/test_timeouts.h" |
| #include "base/win/windows_version.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/installer/util/helper.h" |
| #include "chrome/installer/util/install_util.h" |
| #include "chrome/installer/util/product.h" |
| #include "chrome_frame/html_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 "chrome_frame/utils.h" |
| #include "net/base/mime_util.h" |
| #include "net/http/http_util.h" |
| #include "net/socket/stream_listen_socket.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; |
| base::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<MockWebServerListener>* |
| ChromeFrameTestWithWebServer::listener_mock_; |
| testing::StrictMock<MockWebServer>* 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(base::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(base::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<MockWebServerListener>(); |
| server_mock_ = new testing::StrictMock<MockWebServer>( |
| 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; |
| base::DeleteFile(CFInstall_path_, false); |
| base::DeleteFile(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 (base::PathExists(file_path) && |
| !base::DirectoryExists(file_path)) { |
| base::FilePath mock_http_headers(file_path.value() + L".mock-http-headers"); |
| if (base::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(base::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<test_server::FileResponse>(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<test_server::FileResponse>(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<const char*>(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<UaTemplateFileResponse>(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[] = |
| "<html><head>\n" |
| "<title>ChromeFrame Form Download Test</title>\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. |
| "<meta http-equiv=\"X-UA-Compatible\" content=\"chrome=1\" />\n" |
| "</head>\n" |
| "<script language=\"javascript\">\n" |
| "function SubmitForm() {\n" |
| " var form = document.forms['myform'];\n" |
| " form.action = document.location;\n" |
| " form.submit();\n" |
| " return true;\n" |
| "}\n" |
| "</script>\n" |
| "<body onload=\"SubmitForm();\">\n" |
| "<form method=\"post\" action=\"foo.html\" id=\"myform\">\n" |
| " <input type=\"hidden\" name=\"Field1\" value=\"myvalue\" />\n" |
| " <input type=\"button\" name=\"btn\" value=\"Test Download\" " |
| "onclick=\"return SubmitForm();\" id=\"Button1\"/>\n" |
| "</form></body></html>\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 = base::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()); |
| } |
| |
| // This test loads a large page and ensures that the full page contents are |
| // actually loaded via a self-validating HTML page. This is done due to a bug |
| // whereby the middle of the response stream would sometimes be truncated when |
| // loading a CF document. See http://crbug.com/178421 for details. |
| TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_LargePageLoad) { |
| const wchar_t kLargePageLoadPage[] = |
| L"chrome_frame_large_page.html"; |
| |
| SimpleBrowserTest(IE, kLargePageLoadPage); |
| } |