blob: 4143c738d51e3a8d2a2447ec7ae564b9d7ebd3f9 [file] [log] [blame]
// 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 <stddef.h>
#include <memory>
#include <string>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/ref_counted.h"
#include "content/public/browser/download_interrupt_reasons.h"
#include "url/gurl.h"
namespace content {
class DownloadId;
class DownloadFileWithErrorFactory;
class DownloadManager;
class DownloadManagerImpl;
// Test helper for injecting errors into download file operations. All errors
// for a download must be injected before it starts. This class needs to be
// |RefCountedThreadSafe| because the implementation is referenced by other
// classes that live past the time when the user is nominally done with it.
// Once created, an error injected via InjectError() will cause any
// DownloadFiles created to fail with that error. Call ClearError() to stop
// injecting errors.
// Example:
// FileErrorInfo a = { ... };
// scoped_refptr<TestFileErrorInjector> injector =
// TestFileErrorInjector::Create(download_manager);
// injector->InjectError(a);
// download_manager->DownloadUrl(url1, ...); // Will be interrupted due to |a|.
// download_manager->DownloadUrl(url2, ...); // Will be interrupted due to |a|.
// injector->ClearError();
// download_manager->DownloadUrl(url3, ...); // Won't be interrupted due to |a|.
class TestFileErrorInjector
: public base::RefCountedThreadSafe<TestFileErrorInjector> {
enum FileOperationCode {
// Structure that encapsulates the information needed to inject a file error.
struct FileErrorInfo {
FileOperationCode code; // Operation to affect.
int operation_instance; // 0-based count of operation calls, for each code.
DownloadInterruptReason error; // Error to inject.
// Creates an instance. May only be called once.
// Lives until all callbacks (in the implementation) are complete and the
// creator goes out of scope.
// TODO(rdsmith): Allow multiple calls for different download managers.
static scoped_refptr<TestFileErrorInjector> Create(
DownloadManager* download_manager);
// Injects the errors such that new download files will be affected.
// The download system must already be initialized before calling this.
// Multiple calls are allowed, but only useful if the errors have changed.
// Replaces the injected error list.
bool InjectError(const FileErrorInfo& error_to_inject);
// Clears all errors.
// Only affects files created after the next call to InjectErrors().
void ClearError();
// Tells how many files are currently open.
size_t CurrentFileCount() const;
// Tells how many files have ever been open (since construction or the
// last call to |ClearTotalFileCount()|).
size_t TotalFileCount() const;
// Resets the total file count. Doesn't affect what's returned by
// CurrentFileCount().
void ClearTotalFileCount();
static std::string DebugString(FileOperationCode code);
friend class base::RefCountedThreadSafe<TestFileErrorInjector>;
explicit TestFileErrorInjector(DownloadManager* download_manager);
virtual ~TestFileErrorInjector();
// Callbacks from the download file, to record lifetimes.
// These may be called on any thread.
void RecordDownloadFileConstruction();
void RecordDownloadFileDestruction();
// These run on the UI thread.
void DownloadFileCreated();
void DestroyingDownloadFile();
// All the data is used on the UI thread.
// Keep track of active DownloadFiles.
size_t active_file_count_ = 0;
// Keep track of found DownloadFiles.
size_t total_file_count_ = 0;
// The factory we created. May outlive this class.
DownloadFileWithErrorFactory* created_factory_ = nullptr;
// The download manager we set the factory on.
DownloadManagerImpl* download_manager_ = nullptr;
} // namespace content