// Copyright (c) 2006-2008 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 #include #include #include "base/command_line.h" #include "base/file_util.h" #include "base/path_service.h" #include "base/string_util.h" #include "chrome/browser/automation/url_request_mock_http_job.h" #include "chrome/browser/automation/url_request_slow_download_job.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/ui/ui_test.h" #include "chrome/test/automation/tab_proxy.h" #include "chrome/test/automation/browser_proxy.h" #include "net/url_request/url_request_unittest.h" using std::wstring; namespace { const wchar_t kDocRoot[] = L"chrome/test/data"; // Checks if the volume supports Alternate Data Streams. This is required for // the Zone Identifier implementation. bool VolumeSupportsADS(const std::wstring path) { wchar_t drive[MAX_PATH] = {0}; wcscpy_s(drive, MAX_PATH, path.c_str()); EXPECT_TRUE(PathStripToRootW(drive)); DWORD fs_flags = 0; EXPECT_TRUE(GetVolumeInformationW(drive, NULL, 0, 0, NULL, &fs_flags, NULL, 0)); if (fs_flags & FILE_NAMED_STREAMS) return true; return false; } // Checks if the ZoneIdentifier is correctly set to "Internet" (3) void CheckZoneIdentifier(const std::wstring full_path) { const DWORD kShare = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; std::wstring path = full_path + L":Zone.Identifier"; HANDLE file = CreateFile(path.c_str(), GENERIC_READ, kShare, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); ASSERT_TRUE(INVALID_HANDLE_VALUE != file); char buffer[100] = {0}; DWORD read = 0; ASSERT_TRUE(ReadFile(file, buffer, 100, &read, NULL)); CloseHandle(file); const char kIdentifier[] = "[ZoneTransfer]\nZoneId=3"; ASSERT_EQ(arraysize(kIdentifier), read); ASSERT_EQ(0, strcmp(kIdentifier, buffer)); } class DownloadTest : public UITest { protected: DownloadTest() : UITest() {} void CleanUpDownload(const std::wstring& client_filename, const std::wstring& server_filename) { // Find the path on the client. std::wstring file_on_client(download_prefix_); file_on_client.append(client_filename); EXPECT_PRED1(file_util::PathExists, file_on_client); // Find the path on the server. std::wstring file_on_server; ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &file_on_server)); file_on_server.append(L"\\"); file_on_server.append(server_filename); ASSERT_TRUE(file_util::PathExists(file_on_server)); // Check that we downloaded the file correctly. EXPECT_PRED2(file_util::ContentsEqual, file_on_server, file_on_client); // Check if the Zone Identifier is correclty set. if (VolumeSupportsADS(file_on_client)) CheckZoneIdentifier(file_on_client); // Delete the client copy of the file. EXPECT_PRED2(file_util::Delete, file_on_client, false); } void CleanUpDownload(const std::wstring& file) { CleanUpDownload(file, file); } virtual void SetUp() { UITest::SetUp(); download_prefix_ = GetDownloadDirectory(); download_prefix_ += file_util::kPathSeparator; } protected: void RunSizeTest(const wstring& url, const wstring& expected_title_in_progress, const wstring& expected_title_finished) { { EXPECT_EQ(1, GetTabCount()); NavigateToURL(GURL(url)); // Downloads appear in the shelf WaitUntilTabCount(1); // TODO(tc): check download status text // Complete sending the request. We do this by loading a second URL in a // separate tab. scoped_ptr window(automation()->GetBrowserWindow(0)); EXPECT_TRUE(window->AppendTab(GURL( URLRequestSlowDownloadJob::kFinishDownloadUrl))); EXPECT_EQ(2, GetTabCount()); // TODO(tc): check download status text // Make sure the download shelf is showing. scoped_ptr dl_tab(window->GetTab(0)); ASSERT_TRUE(dl_tab.get()); EXPECT_TRUE(WaitForDownloadShelfVisible(dl_tab.get())); } std::wstring filename = file_util::GetFilenameFromPath(url); EXPECT_PRED1(file_util::PathExists, download_prefix_ + filename); // Delete the file we just downloaded. for (int i = 0; i < 10; ++i) { if (file_util::Delete(download_prefix_ + filename, false)) break; Sleep(kWaitForActionMaxMsec / 10); } EXPECT_FALSE(file_util::PathExists(download_prefix_ + filename)); } wstring download_prefix_; }; } // namespace // Download a file with non-viewable content, verify that the // download tab opened and the file exists. TEST_F(DownloadTest, DownloadMimeType) { wstring file = L"download-test1.lib"; wstring expected_title = L"100% - " + file; EXPECT_EQ(1, GetTabCount()); NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(file)); // No new tabs created, downloads appear in the current tab's download shelf. WaitUntilTabCount(1); // Wait until the file is downloaded. Sleep(1000); CleanUpDownload(file); scoped_ptr tab_proxy(GetActiveTab()); ASSERT_TRUE(tab_proxy.get()); EXPECT_TRUE(WaitForDownloadShelfVisible(tab_proxy.get())); } // Access a file with a viewable mime-type, verify that a download // did not initiate. TEST_F(DownloadTest, NoDownload) { wstring file = L"download-test2.html"; wstring file_path = download_prefix_; file_util::AppendToPath(&file_path, file); if (file_util::PathExists(file_path)) ASSERT_TRUE(file_util::Delete(file_path, false)); EXPECT_EQ(1, GetTabCount()); NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(file)); WaitUntilTabCount(1); // Wait to see if the file will be downloaded. Sleep(1000); EXPECT_FALSE(file_util::PathExists(file_path)); if (file_util::PathExists(file_path)) ASSERT_TRUE(file_util::Delete(file_path, false)); scoped_ptr tab_proxy(GetActiveTab()); ASSERT_TRUE(tab_proxy.get()); EXPECT_FALSE(WaitForDownloadShelfVisible(tab_proxy.get())); } // Download a 0-size file with a content-disposition header, verify that the // download tab opened and the file exists as the filename specified in the // header. This also ensures we properly handle empty file downloads. TEST_F(DownloadTest, ContentDisposition) { wstring file = L"download-test3.html"; wstring download_file = L"download-test3-attachment.html"; wstring expected_title = L"100% - " + download_file; EXPECT_EQ(1, GetTabCount()); NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(file)); WaitUntilTabCount(1); // Wait until the file is downloaded. Sleep(1000); CleanUpDownload(download_file, file); // Ensure the download shelf is visible on the current tab. scoped_ptr tab_proxy(GetActiveTab()); ASSERT_TRUE(tab_proxy.get()); EXPECT_TRUE(WaitForDownloadShelfVisible(tab_proxy.get())); } // UnknownSize and KnownSize are tests which depend on // URLRequestSlowDownloadJob to serve content in a certain way. Data will be // sent in two chunks where the first chunk is 35K and the second chunk is 10K. // The test will first attempt to download a file; but the server will "pause" // in the middle until the server receives a second request for // "download-finish. At that time, the download will finish. TEST_F(DownloadTest, UnknownSize) { std::wstring url(URLRequestSlowDownloadJob::kUnknownSizeUrl); std::wstring filename = file_util::GetFilenameFromPath(url); RunSizeTest(url, L"32.0 KB - " + filename, L"100% - " + filename); } // http://b/1158253 TEST_F(DownloadTest, DISABLED_KnownSize) { std::wstring url(URLRequestSlowDownloadJob::kKnownSizeUrl); std::wstring filename = file_util::GetFilenameFromPath(url); RunSizeTest(url, L"71% - " + filename, L"100% - " + filename); }