blob: 58535f5909d2a5d38efac86fd159bc2a0a306dd9 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/download/download_browsertest_utils.h"
#include <optional>
#include "base/compiler_specific.h"
#include "base/containers/span.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/memory/raw_ptr.h"
#include "base/path_service.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/test_file_util.h"
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/download_request_utils.h"
#include "content/public/test/browser_test_utils.h"
#include "net/dns/mock_host_resolver.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "third_party/blink/public/common/switches.h"
#include "ui/views/views_switches.h"
using content::DownloadManager;
using content::WebContents;
using download::DownloadItem;
using download::DownloadUrlParameters;
using extensions::Extension;
DownloadManager* DownloadManagerForBrowser(Browser* browser) {
return browser->profile()->GetDownloadManager();
}
void SetPromptForDownload(Browser* browser, bool prompt_for_download) {
browser->profile()->GetPrefs()->SetBoolean(prefs::kPromptForDownload,
prompt_for_download);
}
DownloadTestObserverResumable::DownloadTestObserverResumable(
DownloadManager* download_manager,
size_t transition_count)
: DownloadTestObserver(download_manager, 1, ON_DANGEROUS_DOWNLOAD_FAIL),
transitions_left_(transition_count) {
Init();
}
DownloadTestObserverResumable::~DownloadTestObserverResumable() = default;
bool DownloadTestObserverResumable::IsDownloadInFinalState(
DownloadItem* download) {
bool is_resumable_now = download->CanResume();
if (!was_previously_resumable_ && is_resumable_now) {
--transitions_left_;
}
was_previously_resumable_ = is_resumable_now;
return transitions_left_ == 0;
}
DownloadTestObserverNotInProgress::DownloadTestObserverNotInProgress(
DownloadManager* download_manager,
size_t count)
: DownloadTestObserver(download_manager, count, ON_DANGEROUS_DOWNLOAD_FAIL),
started_observing_(false) {
Init();
}
DownloadTestObserverNotInProgress::~DownloadTestObserverNotInProgress() =
default;
void DownloadTestObserverNotInProgress::StartObserving() {
started_observing_ = true;
}
bool DownloadTestObserverNotInProgress::IsDownloadInFinalState(
DownloadItem* download) {
return started_observing_ &&
download->GetState() != DownloadItem::IN_PROGRESS;
}
DownloadTestBase::DownloadTestBase() = default;
DownloadTestBase::~DownloadTestBase() = default;
void DownloadTestBase::SetUpOnMainThread() {
ASSERT_TRUE(CheckTestDir());
ASSERT_TRUE(InitialSetup());
https_test_server_ = std::make_unique<net::EmbeddedTestServer>(
net::EmbeddedTestServer::TYPE_HTTPS);
https_test_server()->SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);
host_resolver()->AddRule("www.a.com", "127.0.0.1");
host_resolver()->AddRule("www.a.test", "127.0.0.1");
host_resolver()->AddRule("www.b.test", "127.0.0.1");
host_resolver()->AddRule("a.test", "127.0.0.1");
host_resolver()->AddRule("b.test", "127.0.0.1");
host_resolver()->AddRule("foo.com", "127.0.0.1");
host_resolver()->AddRule("bar.com", "127.0.0.1");
content::SetupCrossSiteRedirector(embedded_test_server());
}
void DownloadTestBase::SetUpCommandLine(base::CommandLine* command_line) {
// Slower builders (linux-chromeos-rel, debug, and maybe others) are flaky
// due to slower loading interacting with deferred commits.
command_line->AppendSwitch(blink::switches::kAllowPreCommitInput);
// Clicks from tests should always be allowed, even on dialogs that have
// protection against accidental double-clicking/etc.
command_line->AppendSwitch(
views::switches::kDisableInputEventActivationProtectionForTesting);
}
void DownloadTestBase::TearDownOnMainThread() {
// Needs to be torn down on the main thread. file_activity_observer_ holds a
// reference to the ChromeDownloadManagerDelegate which should be destroyed
// on the UI thread.
file_activity_observer_.reset();
}
bool DownloadTestBase::CheckTestDir() {
bool have_test_dir =
base::PathService::Get(chrome::DIR_TEST_DATA, &test_dir_);
EXPECT_TRUE(have_test_dir);
return have_test_dir;
}
bool DownloadTestBase::InitialSetup() {
// Sanity check default values for window and tab count.
int window_count = chrome::GetTotalBrowserCount();
EXPECT_EQ(1, window_count);
EXPECT_EQ(1, browser()->tab_strip_model()->count());
SetPromptForDownload(browser(), false);
DownloadManager* manager = DownloadManagerForBrowser(browser());
DownloadPrefs::FromDownloadManager(manager)->ResetAutoOpenByUser();
file_activity_observer_ =
std::make_unique<DownloadTestFileActivityObserver>(browser()->profile());
return true;
}
base::FilePath DownloadTestBase::GetTestDataDirectory() {
base::FilePath test_file_directory;
base::PathService::Get(chrome::DIR_TEST_DATA, &test_file_directory);
return test_file_directory;
}
base::FilePath DownloadTestBase::OriginFile(const base::FilePath& file) {
return test_dir_.Append(file);
}
base::FilePath DownloadTestBase::DestinationFile(Browser* browser,
const base::FilePath& file) {
return GetDownloadDirectory(browser).Append(file.BaseName());
}
content::TestDownloadResponseHandler*
DownloadTestBase::test_response_handler() {
return &test_response_handler_;
}
DownloadPrefs* DownloadTestBase::GetDownloadPrefs(Browser* browser) {
return DownloadPrefs::FromDownloadManager(DownloadManagerForBrowser(browser));
}
base::FilePath DownloadTestBase::GetDownloadDirectory(Browser* browser) {
return GetDownloadPrefs(browser)->DownloadPath();
}
content::DownloadTestObserver* DownloadTestBase::CreateWaiter(
Browser* browser,
int num_downloads) {
DownloadManager* download_manager = DownloadManagerForBrowser(browser);
return new content::DownloadTestObserverTerminal(
download_manager, num_downloads,
content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
}
content::DownloadTestObserver* DownloadTestBase::CreateInProgressWaiter(
Browser* browser,
int num_downloads) {
DownloadManager* download_manager = DownloadManagerForBrowser(browser);
return new content::DownloadTestObserverInProgress(download_manager,
num_downloads);
}
content::DownloadTestObserver* DownloadTestBase::DangerousDownloadWaiter(
Browser* browser,
int num_downloads,
content::DownloadTestObserver::DangerousDownloadAction
dangerous_download_action) {
DownloadManager* download_manager = DownloadManagerForBrowser(browser);
return new content::DownloadTestObserverTerminal(
download_manager, num_downloads, dangerous_download_action);
}
void DownloadTestBase::CheckDownloadStatesForBrowser(
Browser* browser,
size_t num,
DownloadItem::DownloadState state) {
std::vector<raw_ptr<DownloadItem, VectorExperimental>> download_items;
GetDownloads(browser, &download_items);
EXPECT_EQ(num, download_items.size());
for (size_t i = 0; i < download_items.size(); ++i) {
EXPECT_EQ(state, download_items[i]->GetState()) << " Item " << i;
}
}
void DownloadTestBase::CheckDownloadStates(size_t num,
DownloadItem::DownloadState state) {
CheckDownloadStatesForBrowser(browser(), num, state);
}
bool DownloadTestBase::VerifyNoDownloads() const {
DownloadManager::DownloadVector items;
GetDownloads(browser(), &items);
return items.empty();
}
void DownloadTestBase::DownloadAndWaitWithDisposition(
Browser* browser,
const GURL& url,
WindowOpenDisposition disposition,
int browser_test_flags,
bool prompt_for_download) {
// Setup notification, navigate, and block.
std::unique_ptr<content::DownloadTestObserver> observer(
CreateWaiter(browser, 1));
SetPromptForDownload(browser, prompt_for_download);
// This call will block until the condition specified by
// |browser_test_flags|, but will not wait for the download to finish.
ui_test_utils::NavigateToURLWithDisposition(browser, url, disposition,
browser_test_flags);
// Waits for the download to complete.
observer->WaitForFinished();
EXPECT_EQ(1u, observer->NumDownloadsSeenInState(DownloadItem::COMPLETE));
// We don't expect a file chooser to be shown.
EXPECT_FALSE(DidShowFileChooser());
}
void DownloadTestBase::DownloadAndWait(Browser* browser,
const GURL& url,
bool prompt_for_download) {
DownloadAndWaitWithDisposition(
browser, url, WindowOpenDisposition::CURRENT_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP, prompt_for_download);
}
bool DownloadTestBase::CheckDownload(Browser* browser,
const base::FilePath& downloaded_filename,
const base::FilePath& origin_filename) {
// Find the path to which the data will be downloaded.
base::FilePath downloaded_file(DestinationFile(browser, downloaded_filename));
// Find the origin path (from which the data comes).
base::FilePath origin_file(OriginFile(origin_filename));
return CheckDownloadFullPaths(browser, downloaded_file, origin_file);
}
bool DownloadTestBase::CheckDownloadFullPaths(
Browser* browser,
const base::FilePath& downloaded_file,
const base::FilePath& origin_file) {
base::ScopedAllowBlockingForTesting allow_blocking;
bool origin_file_exists = base::PathExists(origin_file);
EXPECT_TRUE(origin_file_exists) << origin_file.value();
if (!origin_file_exists) {
return false;
}
// Confirm the downloaded data file exists.
bool downloaded_file_exists = base::PathExists(downloaded_file);
EXPECT_TRUE(downloaded_file_exists) << downloaded_file.value();
if (!downloaded_file_exists) {
return false;
}
std::optional<int64_t> origin_file_size = base::GetFileSize(origin_file);
if (!origin_file_size.has_value()) {
ADD_FAILURE() << "origin_file_size does not have a value";
return false;
}
std::string original_file_contents;
EXPECT_TRUE(base::ReadFileToString(origin_file, &original_file_contents));
EXPECT_TRUE(VerifyFile(downloaded_file, original_file_contents,
origin_file_size.value()));
// Delete the downloaded copy of the file.
bool downloaded_file_deleted = base::DieFileDie(downloaded_file, false);
EXPECT_TRUE(downloaded_file_deleted);
return downloaded_file_deleted;
}
DownloadItem* DownloadTestBase::CreateSlowTestDownload(Browser* browser) {
if (!browser) {
browser = DownloadTestBase::browser();
}
DownloadManager* manager = DownloadManagerForBrowser(browser);
std::unique_ptr<content::DownloadTestObserver> observer =
std::make_unique<content::DownloadTestObserverInProgress>(manager, 1);
embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
&content::SlowDownloadHttpResponse::HandleSlowDownloadRequest));
EXPECT_TRUE(embedded_test_server()->Start());
GURL slow_download_url = embedded_test_server()->GetURL(
content::SlowDownloadHttpResponse::kKnownSizeUrl);
EXPECT_EQ(0, manager->BlockingShutdownCount());
EXPECT_EQ(0, manager->InProgressCount());
if (manager->InProgressCount() != 0) {
return nullptr;
}
EXPECT_TRUE(ui_test_utils::NavigateToURL(browser, slow_download_url));
observer->WaitForFinished();
EXPECT_EQ(1u, observer->NumDownloadsSeenInState(DownloadItem::IN_PROGRESS));
DownloadManager::DownloadVector items;
manager->GetAllDownloads(&items);
DownloadItem* new_item = nullptr;
for (download::DownloadItem* item : items) {
if (item->GetState() == DownloadItem::IN_PROGRESS) {
// There should be only one IN_PROGRESS item.
EXPECT_FALSE(new_item);
new_item = item;
}
}
return new_item;
}
bool DownloadTestBase::RunSizeTest(Browser* browser,
SizeTestType type,
const std::string& partial_indication,
const std::string& total_indication) {
embedded_test_server()->ServeFilesFromDirectory(GetTestDataDirectory());
embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
&content::SlowDownloadHttpResponse::HandleSlowDownloadRequest));
EXPECT_TRUE(embedded_test_server()->Start());
base::ScopedAllowBlockingForTesting allow_blocking;
EXPECT_TRUE(type == SIZE_TEST_TYPE_UNKNOWN || type == SIZE_TEST_TYPE_KNOWN);
if (type != SIZE_TEST_TYPE_KNOWN && type != SIZE_TEST_TYPE_UNKNOWN) {
return false;
}
GURL url(type == SIZE_TEST_TYPE_KNOWN
? embedded_test_server()->GetURL(
content::SlowDownloadHttpResponse::kKnownSizeUrl)
: embedded_test_server()->GetURL(
content::SlowDownloadHttpResponse::kUnknownSizeUrl));
GURL finish_url = embedded_test_server()->GetURL(
content::SlowDownloadHttpResponse::kFinishSlowResponseUrl);
// TODO(ahendrickson) -- |expected_title_in_progress| and
// |expected_title_finished| need to be checked.
base::FilePath filename = base::FilePath::FromUTF8Unsafe(url.path());
std::u16string expected_title_in_progress(
base::ASCIIToUTF16(partial_indication) + filename.LossyDisplayName());
std::u16string expected_title_finished(base::ASCIIToUTF16(total_indication) +
filename.LossyDisplayName());
// Download a partial web page in a background tab and wait.
// The mock system will not complete until it gets a special URL.
std::unique_ptr<content::DownloadTestObserver> observer(
CreateWaiter(browser, 1));
EXPECT_TRUE(ui_test_utils::NavigateToURL(browser, url));
// TODO(ahendrickson): check download status text before downloading.
// Need to:
// - Add a member function to the |DownloadShelf| interface class, that
// indicates how many members it has.
// - Add a member function to |DownloadShelf| to get the status text
// of a given member (for example, via the name in |DownloadItemView|'s
// GetAccessibleNodeData() member function), by index.
// - Iterate over browser->window()->GetDownloadShelf()'s members
// to see if any match the status text we want. Start with the last one.
// Allow the request to finish. We do this by loading a second URL in a
// separate tab.
ui_test_utils::NavigateToURLWithDisposition(
browser, finish_url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
observer->WaitForFinished();
EXPECT_EQ(1u, observer->NumDownloadsSeenInState(DownloadItem::COMPLETE));
CheckDownloadStatesForBrowser(browser, 1, DownloadItem::COMPLETE);
EXPECT_EQ(2, browser->tab_strip_model()->count());
// TODO(ahendrickson): check download status text after downloading.
base::FilePath download_path =
GetDownloadDirectory(browser).Append(filename.BaseName());
bool downloaded_path_exists = base::PathExists(download_path);
EXPECT_TRUE(downloaded_path_exists);
if (!downloaded_path_exists) {
return false;
}
// Check the file contents.
size_t file_size = content::SlowDownloadHttpResponse::kFirstResponsePartSize +
content::SlowDownloadHttpResponse::kSecondResponsePartSize;
std::string expected_contents(file_size, '*');
EXPECT_TRUE(VerifyFile(download_path, expected_contents, file_size));
// Delete the file we just downloaded.
EXPECT_TRUE(base::DieFileDie(download_path, false));
EXPECT_FALSE(base::PathExists(download_path));
return true;
}
void DownloadTestBase::GetDownloads(
Browser* browser,
std::vector<raw_ptr<DownloadItem, VectorExperimental>>* downloads) const {
DCHECK(downloads);
DownloadManager* manager = DownloadManagerForBrowser(browser);
manager->GetAllDownloads(downloads);
}
// static
void DownloadTestBase::ExpectWindowCountAfterDownload(size_t expected) {
EXPECT_EQ(expected, chrome::GetTotalBrowserCount());
}
void DownloadTestBase::EnableFileChooser(bool enable) {
file_activity_observer_->EnableFileChooser(enable);
}
bool DownloadTestBase::DidShowFileChooser() {
return file_activity_observer_->TestAndResetDidShowFileChooser();
}
void DownloadTestBase::SetAllowOpenDownload(bool allow) {
file_activity_observer_->SetAllowOpenDownload(allow);
}
bool DownloadTestBase::VerifyFile(const base::FilePath& path,
const std::string& value,
const int64_t file_size) {
std::string file_contents;
base::ScopedAllowBlockingForTesting allow_blocking;
bool read = base::ReadFileToString(path, &file_contents);
EXPECT_TRUE(read) << "Failed reading file: " << path.value() << std::endl;
if (!read) {
return false; // Couldn't read the file.
}
// Note: we don't handle really large files (more than size_t can hold)
// so we will fail in that case.
size_t expected_size = static_cast<size_t>(file_size);
// Check the size.
EXPECT_EQ(expected_size, file_contents.size());
if (expected_size != file_contents.size()) {
return false;
}
// Check the contents.
EXPECT_EQ(value, file_contents);
if (UNSAFE_TODO(
memcmp(file_contents.c_str(), value.c_str(), expected_size)) != 0) {
return false;
}
return true;
}
void DownloadTestBase::DownloadFilesCheckErrorsSetup() {
embedded_test_server()->ServeFilesFromDirectory(GetTestDataDirectory());
ASSERT_TRUE(embedded_test_server()->Start());
std::vector<raw_ptr<DownloadItem, VectorExperimental>> download_items;
GetDownloads(browser(), &download_items);
ASSERT_TRUE(download_items.empty());
EnableFileChooser(true);
}
void DownloadTestBase::DownloadFilesCheckErrorsLoopBody(
const DownloadInfo& download_info,
size_t i) {
SCOPED_TRACE(testing::Message()
<< " " << __FUNCTION__ << "()"
<< " index = " << i << " starting_url = '"
<< download_info.starting_url << "'"
<< " download_url = '" << download_info.expected_download_url
<< "'"
<< " method = "
<< ((download_info.download_method == DOWNLOAD_DIRECT)
? "DOWNLOAD_DIRECT"
: "DOWNLOAD_NAVIGATE")
<< " show_item = " << download_info.show_download_item
<< " reason = "
<< DownloadInterruptReasonToString(download_info.reason));
std::vector<raw_ptr<DownloadItem, VectorExperimental>> download_items;
GetDownloads(browser(), &download_items);
size_t downloads_expected = download_items.size();
// GURL("http://foo/bar").Resolve("baz") => "http://foo/bar/baz"
// GURL("http://foo/bar").Resolve("http://baz") => "http://baz"
// I.e. both starting_url and expected_download_url can either be relative
// to the base test server URL or be an absolute URL.
GURL base_url = embedded_test_server()->GetURL("/downloads/");
GURL starting_url = base_url.Resolve(download_info.starting_url);
GURL download_url = base_url.Resolve(download_info.expected_download_url);
ASSERT_TRUE(starting_url.is_valid());
ASSERT_TRUE(download_url.is_valid());
DownloadManager* download_manager = DownloadManagerForBrowser(browser());
WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
ASSERT_TRUE(web_contents);
std::unique_ptr<content::DownloadTestObserver> observer;
if (download_info.reason == download::DOWNLOAD_INTERRUPT_REASON_NONE) {
observer = std::make_unique<content::DownloadTestObserverTerminal>(
download_manager, 1,
content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
} else {
observer = std::make_unique<content::DownloadTestObserverInterrupted>(
download_manager, 1,
content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
}
if (download_info.download_method == DOWNLOAD_DIRECT) {
// Go directly to download. Don't wait for navigation.
scoped_refptr<content::DownloadTestItemCreationObserver> creation_observer(
new content::DownloadTestItemCreationObserver);
std::unique_ptr<DownloadUrlParameters> params(
content::DownloadRequestUtils::CreateDownloadForWebContentsMainFrame(
web_contents, starting_url, TRAFFIC_ANNOTATION_FOR_TESTS));
params->set_callback(creation_observer->callback());
DownloadManagerForBrowser(browser())->DownloadUrl(std::move(params));
// Wait until the item is created, or we have determined that it
// won't be.
creation_observer->WaitForDownloadItemCreation();
EXPECT_NE(download::DownloadItem::kInvalidId,
creation_observer->download_id());
} else {
// Navigate to URL normally, wait until done.
ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(browser(),
starting_url, 1);
}
if (download_info.show_download_item) {
downloads_expected++;
observer->WaitForFinished();
DownloadItem::DownloadState final_state =
(download_info.reason == download::DOWNLOAD_INTERRUPT_REASON_NONE)
? DownloadItem::COMPLETE
: DownloadItem::INTERRUPTED;
EXPECT_EQ(1u, observer->NumDownloadsSeenInState(final_state));
}
// Wait till the |DownloadFile|s are destroyed.
content::RunAllTasksUntilIdle();
// Validate that the correct files were downloaded.
download_items.clear();
GetDownloads(browser(), &download_items);
ASSERT_EQ(downloads_expected, download_items.size());
if (download_info.show_download_item) {
// Find the last download item.
DownloadItem* item = download_items[0];
for (size_t d = 1; d < downloads_expected; ++d) {
if (download_items[d]->GetStartTime() > item->GetStartTime()) {
item = download_items[d];
}
}
EXPECT_EQ(download_url, item->GetURL());
EXPECT_EQ(download_info.reason, item->GetLastReason());
if (item->GetState() == download::DownloadItem::COMPLETE) {
// Clean up the file, in case it ended up in the My Documents folder.
base::ScopedAllowBlockingForTesting allow_blocking;
base::FilePath destination_folder = GetDownloadDirectory(browser());
base::FilePath my_downloaded_file = item->GetTargetFilePath();
EXPECT_TRUE(base::PathExists(my_downloaded_file));
EXPECT_TRUE(base::DeleteFile(my_downloaded_file));
item->Remove();
EXPECT_EQ(
download_info.should_redirect_to_documents ? std::string::npos : 0u,
my_downloaded_file.value().find(destination_folder.value()));
if (download_info.should_redirect_to_documents) {
// If it's not where we asked it to be, it should be in the
// My Documents folder.
base::FilePath my_docs_folder;
EXPECT_TRUE(base::PathService::Get(chrome::DIR_USER_DOCUMENTS,
&my_docs_folder));
EXPECT_EQ(0u, my_downloaded_file.value().find(my_docs_folder.value()));
}
}
}
}
void DownloadTestBase::DownloadFilesCheckErrors(
size_t spanification_suspected_redundant_count,
base::span<DownloadInfo> download_info) {
// TODO(crbug.com/431824301): Remove unneeded parameter once validated to be
// redundant in M143.
CHECK(spanification_suspected_redundant_count == download_info.size(),
base::NotFatalUntil::M143);
DownloadFilesCheckErrorsSetup();
for (size_t i = 0; i < spanification_suspected_redundant_count; ++i) {
DownloadFilesCheckErrorsLoopBody(download_info[i], i);
}
}
void DownloadTestBase::DownloadInsertFilesErrorCheckErrorsLoopBody(
scoped_refptr<content::TestFileErrorInjector> injector,
const FileErrorInjectInfo& info,
size_t i) {
SCOPED_TRACE(
::testing::Message()
<< " " << __FUNCTION__ << "()"
<< " index = " << i << " operation code = "
<< content::TestFileErrorInjector::DebugString(info.error_info.code)
<< " instance = " << info.error_info.operation_instance << " error = "
<< download::DownloadInterruptReasonToString(info.error_info.error));
injector->InjectError(info.error_info);
DownloadFilesCheckErrorsLoopBody(info.download_info, i);
size_t expected_successes = info.download_info.show_download_item ? 1u : 0u;
EXPECT_EQ(expected_successes, injector->TotalFileCount());
EXPECT_EQ(0u, injector->CurrentFileCount());
}
void DownloadTestBase::DownloadInsertFilesErrorCheckErrors(
size_t spanification_suspected_redundant_count,
base::span<FileErrorInjectInfo> info) {
// TODO(crbug.com/431824301): Remove unneeded parameter once validated to be
// redundant in M143.
CHECK(spanification_suspected_redundant_count == info.size(),
base::NotFatalUntil::M143);
DownloadFilesCheckErrorsSetup();
// Set up file failures.
scoped_refptr<content::TestFileErrorInjector> injector(
content::TestFileErrorInjector::Create(
DownloadManagerForBrowser(browser())));
for (size_t i = 0; i < spanification_suspected_redundant_count; ++i) {
DownloadInsertFilesErrorCheckErrorsLoopBody(injector, info[i], i);
}
}
// Attempts to download a file to a read-only folder, based on information
// in |download_info|.
void DownloadTestBase::DownloadFilesToReadonlyFolder(
size_t spanification_suspected_redundant_count,
base::span<DownloadInfo> download_info) {
// TODO(crbug.com/431824301): Remove unneeded parameter once validated to be
// redundant in M143.
CHECK(spanification_suspected_redundant_count == download_info.size(),
base::NotFatalUntil::M143);
DownloadFilesCheckErrorsSetup();
// Make the test folder unwritable.
base::FilePath destination_folder = GetDownloadDirectory(browser());
DVLOG(1) << " " << __FUNCTION__ << "()"
<< " folder = '" << destination_folder.value() << "'";
base::ScopedAllowBlockingForTesting allow_blocking;
base::FilePermissionRestorer permission_restorer(destination_folder);
EXPECT_TRUE(base::MakeFileUnwritable(destination_folder));
for (size_t i = 0; i < spanification_suspected_redundant_count; ++i) {
DownloadFilesCheckErrorsLoopBody(download_info[i], i);
}
}
DownloadItem* DownloadTestBase::StartMockDownloadAndInjectError(
content::TestFileErrorInjector* error_injector,
download::DownloadInterruptReason error) {
content::TestFileErrorInjector::FileErrorInfo error_info;
error_info.code = content::TestFileErrorInjector::FILE_OPERATION_WRITE;
error_info.operation_instance = 0;
error_info.error = error;
error_injector->InjectError(error_info);
std::unique_ptr<content::DownloadTestObserver> observer(
new DownloadTestObserverResumable(DownloadManagerForBrowser(browser()),
1));
if (!embedded_test_server()->Started()) {
embedded_test_server()->ServeFilesFromDirectory(GetTestDataDirectory());
EXPECT_TRUE(embedded_test_server()->Start());
}
GURL url =
embedded_test_server()->GetURL("/" + std::string(kDownloadTest1Path));
EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
observer->WaitForFinished();
content::DownloadManager::DownloadVector downloads;
DownloadManagerForBrowser(browser())->GetAllDownloads(&downloads);
EXPECT_EQ(1u, downloads.size());
if (downloads.size() != 1) {
return nullptr;
}
error_injector->ClearError();
DownloadItem* download = downloads[0];
EXPECT_EQ(DownloadItem::INTERRUPTED, download->GetState());
EXPECT_EQ(error, download->GetLastReason());
return download;
}