diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-07-16 11:45:35 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-07-17 08:59:23 +0000 |
commit | 552906b0f222c5d5dd11b9fd73829d510980461a (patch) | |
tree | 3a11e6ed0538a81dd83b20cf3a4783e297f26d91 /chromium/components/update_client | |
parent | 1b05827804eaf047779b597718c03e7d38344261 (diff) | |
download | qtwebengine-chromium-552906b0f222c5d5dd11b9fd73829d510980461a.tar.gz |
BASELINE: Update Chromium to 83.0.4103.122
Change-Id: Ie3a82f5bb0076eec2a7c6a6162326b4301ee291e
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/components/update_client')
48 files changed, 1139 insertions, 395 deletions
diff --git a/chromium/components/update_client/BUILD.gn b/chromium/components/update_client/BUILD.gn index 0cd3c22a430..dabba2b0510 100644 --- a/chromium/components/update_client/BUILD.gn +++ b/chromium/components/update_client/BUILD.gn @@ -148,9 +148,7 @@ static_library("test_support") { "test_installer.h", ] - public_deps = [ - ":update_client", - ] + public_deps = [ ":update_client" ] deps = [ ":network_impl", @@ -188,22 +186,16 @@ bundle_data("unit_tests_bundle_data") { "//components/test/data/update_client/updatecheck_reply_parse_error.json", "//components/test/data/update_client/updatecheck_reply_unknownapp.json", ] - outputs = [ - "{{bundle_resources_dir}}/" + - "{{source_root_relative_dir}}/{{source_file_part}}", - ] + outputs = [ "{{bundle_resources_dir}}/" + + "{{source_root_relative_dir}}/{{source_file_part}}" ] } bundle_data("recovery_component_tests_bundle_data") { visibility = [ "//chrome/test:unit_tests" ] testonly = true - sources = [ - "//components/test/data/update_client/ChromeRecovery.crx3", - ] - outputs = [ - "{{bundle_resources_dir}}/" + - "{{source_root_relative_dir}}/{{source_file_part}}", - ] + sources = [ "//components/test/data/update_client/ChromeRecovery.crx3" ] + outputs = [ "{{bundle_resources_dir}}/" + + "{{source_root_relative_dir}}/{{source_file_part}}" ] } source_set("unit_tests") { @@ -255,9 +247,7 @@ source_set("unit_tests") { } fuzzer_test("update_client_protocol_serializer_fuzzer") { - sources = [ - "protocol_serializer_fuzzer.cc", - ] + sources = [ "protocol_serializer_fuzzer.cc" ] deps = [ ":update_client", "//base:base", @@ -266,9 +256,7 @@ fuzzer_test("update_client_protocol_serializer_fuzzer") { } fuzzer_test("update_client_protocol_parser_fuzzer") { - sources = [ - "protocol_parser_fuzzer.cc", - ] + sources = [ "protocol_parser_fuzzer.cc" ] deps = [ ":update_client", "//base:base", diff --git a/chromium/components/update_client/action_runner.cc b/chromium/components/update_client/action_runner.cc index 54a43f1913c..6bf6d808ade 100644 --- a/chromium/components/update_client/action_runner.cc +++ b/chromium/components/update_client/action_runner.cc @@ -9,7 +9,7 @@ #include "base/bind.h" #include "base/files/file_path.h" #include "base/location.h" -#include "base/task/post_task.h" +#include "base/task/thread_pool.h" #include "base/threading/thread_task_runner_handle.h" #include "components/update_client/component.h" #include "components/update_client/task_traits.h" @@ -38,7 +38,7 @@ void ActionRunner::Run(Callback callback) { callback_ = std::move(callback); // Resolve an absolute path for the file referred by the run action. - base::PostTaskAndReplyWithResult( + base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, kTaskTraits, base::BindOnce( [](const Component* component) { diff --git a/chromium/components/update_client/activity_data_service.h b/chromium/components/update_client/activity_data_service.h index 5d3744cb678..cf60602be1e 100644 --- a/chromium/components/update_client/activity_data_service.h +++ b/chromium/components/update_client/activity_data_service.h @@ -34,7 +34,7 @@ class ActivityDataService { virtual int GetDaysSinceLastActive(const std::string& id) const = 0; virtual int GetDaysSinceLastRollCall(const std::string& id) const = 0; - virtual ~ActivityDataService() {} + virtual ~ActivityDataService() = default; }; } // namespace update_client diff --git a/chromium/components/update_client/background_downloader_win.cc b/chromium/components/update_client/background_downloader_win.cc index 5e165799a31..4804cfd862b 100644 --- a/chromium/components/update_client/background_downloader_win.cc +++ b/chromium/components/update_client/background_downloader_win.cc @@ -24,8 +24,7 @@ #include "base/sequenced_task_runner.h" #include "base/strings/string_piece.h" #include "base/strings/sys_string_conversions.h" -#include "base/task/post_task.h" -#include "base/task/task_traits.h" +#include "base/task/thread_pool.h" #include "base/win/atl.h" #include "base/win/scoped_co_mem.h" #include "components/update_client/task_traits.h" @@ -399,8 +398,8 @@ void CleanupJob(const ComPtr<IBackgroundCopyJob>& job) { BackgroundDownloader::BackgroundDownloader( std::unique_ptr<CrxDownloader> successor) : CrxDownloader(std::move(successor)), - com_task_runner_( - base::CreateCOMSTATaskRunner(kTaskTraitsBackgroundDownloader)), + com_task_runner_(base::ThreadPool::CreateCOMSTATaskRunner( + kTaskTraitsBackgroundDownloader)), git_cookie_bits_manager_(0), git_cookie_job_(0) {} diff --git a/chromium/components/update_client/command_line_config_policy.h b/chromium/components/update_client/command_line_config_policy.h index 2d201a526ba..27ccc20fc38 100644 --- a/chromium/components/update_client/command_line_config_policy.h +++ b/chromium/components/update_client/command_line_config_policy.h @@ -36,7 +36,7 @@ class CommandLineConfigPolicy { // update check. virtual int InitialDelay() const; - virtual ~CommandLineConfigPolicy() {} + virtual ~CommandLineConfigPolicy() = default; }; } // namespace update_client diff --git a/chromium/components/update_client/component.cc b/chromium/components/update_client/component.cc index 36e11d57380..68a5befbe42 100644 --- a/chromium/components/update_client/component.cc +++ b/chromium/components/update_client/component.cc @@ -15,6 +15,7 @@ #include "base/single_thread_task_runner.h" #include "base/strings/string_number_conversions.h" #include "base/task/post_task.h" +#include "base/task/thread_pool.h" #include "base/threading/thread_task_runner_handle.h" #include "base/values.h" #include "components/update_client/action_runner.h" @@ -22,6 +23,7 @@ #include "components/update_client/configurator.h" #include "components/update_client/network.h" #include "components/update_client/patcher.h" +#include "components/update_client/persisted_data.h" #include "components/update_client/protocol_definition.h" #include "components/update_client/protocol_serializer.h" #include "components/update_client/task_traits.h" @@ -75,9 +77,8 @@ void InstallComplete( InstallOnBlockingTaskRunnerCompleteCallback callback, const base::FilePath& unpack_path, const CrxInstaller::Result& result) { - base::PostTask( - FROM_HERE, - {base::ThreadPool(), base::TaskPriority::BEST_EFFORT, base::MayBlock()}, + base::ThreadPool::PostTask( + FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()}, base::BindOnce( [](scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, InstallOnBlockingTaskRunnerCompleteCallback callback, @@ -99,6 +100,7 @@ void InstallOnBlockingTaskRunner( const base::FilePath& unpack_path, const std::string& public_key, const std::string& fingerprint, + std::unique_ptr<CrxInstaller::InstallParams> install_params, scoped_refptr<CrxInstaller> installer, InstallOnBlockingTaskRunnerCompleteCallback callback) { DCHECK(base::DirectoryExists(unpack_path)); @@ -120,7 +122,7 @@ void InstallOnBlockingTaskRunner( } installer->Install( - unpack_path, public_key, + unpack_path, public_key, std::move(install_params), base::BindOnce(&InstallComplete, main_task_runner, std::move(callback), unpack_path_owner.Take())); } @@ -129,6 +131,7 @@ void UnpackCompleteOnBlockingTaskRunner( scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, const base::FilePath& crx_path, const std::string& fingerprint, + std::unique_ptr<CrxInstaller::InstallParams> install_params, scoped_refptr<CrxInstaller> installer, InstallOnBlockingTaskRunnerCompleteCallback callback, const ComponentUnpacker::Result& result) { @@ -142,10 +145,12 @@ void UnpackCompleteOnBlockingTaskRunner( return; } - base::PostTask(FROM_HERE, kTaskTraits, - base::BindOnce(&InstallOnBlockingTaskRunner, main_task_runner, - result.unpack_path, result.public_key, - fingerprint, installer, std::move(callback))); + base::ThreadPool::PostTask( + FROM_HERE, kTaskTraits, + base::BindOnce(&InstallOnBlockingTaskRunner, main_task_runner, + result.unpack_path, result.public_key, fingerprint, + std::move(install_params), installer, + std::move(callback))); } void StartInstallOnBlockingTaskRunner( @@ -153,6 +158,7 @@ void StartInstallOnBlockingTaskRunner( const std::vector<uint8_t>& pk_hash, const base::FilePath& crx_path, const std::string& fingerprint, + std::unique_ptr<CrxInstaller::InstallParams> install_params, scoped_refptr<CrxInstaller> installer, std::unique_ptr<Unzipper> unzipper_, scoped_refptr<Patcher> patcher_, @@ -162,9 +168,9 @@ void StartInstallOnBlockingTaskRunner( pk_hash, crx_path, installer, std::move(unzipper_), std::move(patcher_), crx_format); - unpacker->Unpack(base::BindOnce(&UnpackCompleteOnBlockingTaskRunner, - main_task_runner, crx_path, fingerprint, - installer, std::move(callback))); + unpacker->Unpack(base::BindOnce( + &UnpackCompleteOnBlockingTaskRunner, main_task_runner, crx_path, + fingerprint, std::move(install_params), installer, std::move(callback))); } // Returns a string literal corresponding to the value of the downloader |d|. @@ -186,7 +192,7 @@ Component::Component(const UpdateContext& update_context, const std::string& id) state_(std::make_unique<StateNew>(this)), update_context_(update_context) {} -Component::~Component() {} +Component::~Component() = default; scoped_refptr<Configurator> Component::config() const { return update_context_.config; @@ -237,6 +243,7 @@ CrxUpdateItem Component::GetCrxUpdateItem() const { crx_update_item.error_category = error_category_; crx_update_item.error_code = error_code_; crx_update_item.extra_code1 = extra_code1_; + crx_update_item.custom_updatecheck_data = custom_attrs_; return crx_update_item; } @@ -248,6 +255,7 @@ void Component::SetParseResult(const ProtocolParser::Result& result) { status_ = result.status; action_run_ = result.action_run; + custom_attrs_ = result.custom_attributes; if (result.manifest.packages.empty()) return; @@ -270,6 +278,11 @@ void Component::SetParseResult(const ProtocolParser::Result& result) { hash_sha256_ = package.hash_sha256; hashdiff_sha256_ = package.hashdiff_sha256; + + if (!result.manifest.run.empty()) { + install_params_ = base::make_optional(CrxInstaller::InstallParams( + result.manifest.run, result.manifest.arguments)); + } } void Component::Uninstall(const base::Version& version, int reason) { @@ -296,6 +309,7 @@ void Component::SetUpdateCheckResult( error_category_ = error_category; error_code_ = error; + if (result) SetParseResult(result.value()); @@ -303,6 +317,11 @@ void Component::SetUpdateCheckResult( FROM_HERE, std::move(update_check_complete_)); } +void Component::NotifyWait() { + DCHECK(thread_checker_.CalledOnValidThread()); + NotifyObservers(Events::COMPONENT_WAIT); +} + bool Component::CanDoBackgroundDownload() const { // Foreground component updates are always downloaded in foreground. return !is_foreground() && @@ -316,6 +335,15 @@ void Component::AppendEvent(base::Value event) { void Component::NotifyObservers(UpdateClient::Observer::Events event) const { DCHECK(thread_checker_.CalledOnValidThread()); + + // There is no corresponding component state for the COMPONENT_WAIT event. + if (update_context_.crx_state_change_callback && + event != UpdateClient::Observer::Events::COMPONENT_WAIT) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindRepeating(update_context_.crx_state_change_callback, + GetCrxUpdateItem())); + } update_context_.notify_observers_callback.Run(event, id_); } @@ -429,10 +457,16 @@ std::vector<base::Value> Component::GetEvents() const { return events; } +std::unique_ptr<CrxInstaller::InstallParams> Component::install_params() const { + return install_params_ + ? std::make_unique<CrxInstaller::InstallParams>(*install_params_) + : nullptr; +} + Component::State::State(Component* component, ComponentState state) : state_(state), component_(*component) {} -Component::State::~State() {} +Component::State::~State() = default; void Component::State::Handle(CallbackNextState callback_next_state) { DCHECK(thread_checker_.CalledOnValidThread()); @@ -629,8 +663,8 @@ void Component::StateDownloadingDiff::DoHandle() { const auto& id = component.id_; crx_downloader_->set_progress_callback( - base::Bind(&Component::StateDownloadingDiff::DownloadProgress, - base::Unretained(this), id)); + base::BindRepeating(&Component::StateDownloadingDiff::DownloadProgress, + base::Unretained(this), id)); crx_downloader_->StartDownload( component.crx_diffurls_, component.hashdiff_sha256_, base::BindOnce(&Component::StateDownloadingDiff::DownloadComplete, @@ -694,8 +728,8 @@ void Component::StateDownloading::DoHandle() { const auto& id = component.id_; crx_downloader_->set_progress_callback( - base::Bind(&Component::StateDownloading::DownloadProgress, - base::Unretained(this), id)); + base::BindRepeating(&Component::StateDownloading::DownloadProgress, + base::Unretained(this), id)); crx_downloader_->StartDownload( component.crx_urls_, component.hash_sha256_, base::BindOnce(&Component::StateDownloading::DownloadComplete, @@ -756,14 +790,15 @@ void Component::StateUpdatingDiff::DoHandle() { component.NotifyObservers(Events::COMPONENT_UPDATE_READY); - base::CreateSequencedTaskRunner(kTaskTraits) + base::ThreadPool::CreateSequencedTaskRunner(kTaskTraits) ->PostTask( FROM_HERE, base::BindOnce( &update_client::StartInstallOnBlockingTaskRunner, base::ThreadTaskRunnerHandle::Get(), component.crx_component()->pk_hash, component.crx_path_, - component.next_fp_, component.crx_component()->installer, + component.next_fp_, component.install_params(), + component.crx_component()->installer, update_context.config->GetUnzipperFactory()->Create(), update_context.config->GetPatcherFactory()->Create(), component.crx_component()->crx_format_requirement, @@ -818,13 +853,14 @@ void Component::StateUpdating::DoHandle() { component.NotifyObservers(Events::COMPONENT_UPDATE_READY); - base::CreateSequencedTaskRunner(kTaskTraits) + base::ThreadPool::CreateSequencedTaskRunner(kTaskTraits) ->PostTask(FROM_HERE, base::BindOnce( &update_client::StartInstallOnBlockingTaskRunner, base::ThreadTaskRunnerHandle::Get(), component.crx_component()->pk_hash, component.crx_path_, - component.next_fp_, component.crx_component()->installer, + component.next_fp_, component.install_params(), + component.crx_component()->installer, update_context.config->GetUnzipperFactory()->Create(), update_context.config->GetPatcherFactory()->Create(), component.crx_component()->crx_format_requirement, @@ -876,6 +912,11 @@ void Component::StateUpdated::DoHandle() { component.crx_component_->version = component.next_version_; component.crx_component_->fingerprint = component.next_fp_; + component.update_context_.persisted_data->SetProductVersion( + component.id(), component.crx_component_->version); + component.update_context_.persisted_data->SetFingerprint( + component.id(), component.crx_component_->fingerprint); + component.AppendEvent(component.MakeEventUpdateComplete()); component.NotifyObservers(Events::COMPONENT_UPDATED); diff --git a/chromium/components/update_client/component.h b/chromium/components/update_client/component.h index 1e8ed14ad53..b360fd1e58b 100644 --- a/chromium/components/update_client/component.h +++ b/chromium/components/update_client/component.h @@ -36,8 +36,8 @@ class Configurator; struct CrxUpdateItem; struct UpdateContext; -// Describes a CRX component managed by the UpdateEngine. Each |Component| is -// associated with an UpdateContext. +// Describes a CRX component managed by the UpdateEngine. Each instance of +// this class is associated with one instance of UpdateContext. class Component { public: using Events = UpdateClient::Observer::Events; @@ -62,6 +62,10 @@ class Component { ErrorCategory error_category, int error); + // Called by the UpdateEngine when a component enters a wait for throttling + // purposes. + void NotifyWait(); + // Returns true if the component has reached a final state and no further // handling and state transitions are possible. bool IsHandled() const { return is_handled_; } @@ -370,6 +374,9 @@ class Component { void ChangeState(std::unique_ptr<State> next_state); // Notifies registered observers about changes in the state of the component. + // If an UpdateClient::CrxStateChangeCallback is provided as an argument to + // UpdateClient::Install or UpdateClient::Update function calls, then the + // callback is invoked as well. void NotifyObservers(Events event) const; void SetParseResult(const ProtocolParser::Result& result); @@ -384,6 +391,8 @@ class Component { int error_code, int extra_code1) const; + std::unique_ptr<CrxInstaller::InstallParams> install_params() const; + base::ThreadChecker thread_checker_; const std::string id_; @@ -437,6 +446,14 @@ class Component { int diff_error_code_ = 0; int diff_extra_code1_ = 0; + // Contains app-specific custom response attributes from the server, sent in + // the last update check. + std::map<std::string, std::string> custom_attrs_; + + // Contains the optional |run| and |arguments| values in the update response + // manifest. This data is provided as an argument to the |Install| call. + base::Optional<CrxInstaller::InstallParams> install_params_; + // Contains the events which are therefore serialized in the requests. std::vector<base::Value> events_; diff --git a/chromium/components/update_client/component_patcher.cc b/chromium/components/update_client/component_patcher.cc index ba81f1d8138..8e55a56e1c8 100644 --- a/chromium/components/update_client/component_patcher.cc +++ b/chromium/components/update_client/component_patcher.cc @@ -53,8 +53,7 @@ ComponentPatcher::ComponentPatcher(const base::FilePath& input_dir, installer_(installer), patcher_(patcher) {} -ComponentPatcher::~ComponentPatcher() { -} +ComponentPatcher::~ComponentPatcher() = default; void ComponentPatcher::Start(Callback callback) { callback_ = std::move(callback); diff --git a/chromium/components/update_client/component_patcher_operation.cc b/chromium/components/update_client/component_patcher_operation.cc index c54a30e19f2..682b23aa373 100644 --- a/chromium/components/update_client/component_patcher_operation.cc +++ b/chromium/components/update_client/component_patcher_operation.cc @@ -53,11 +53,9 @@ DeltaUpdateOp* CreateDeltaUpdateOp(const std::string& operation, return nullptr; } -DeltaUpdateOp::DeltaUpdateOp() { -} +DeltaUpdateOp::DeltaUpdateOp() = default; -DeltaUpdateOp::~DeltaUpdateOp() { -} +DeltaUpdateOp::~DeltaUpdateOp() = default; void DeltaUpdateOp::Run(const base::DictionaryValue* command_args, const base::FilePath& input_dir, @@ -108,11 +106,9 @@ UnpackerError DeltaUpdateOp::CheckHash() { : UnpackerError::kDeltaVerificationFailure; } -DeltaUpdateOpCopy::DeltaUpdateOpCopy() { -} +DeltaUpdateOpCopy::DeltaUpdateOpCopy() = default; -DeltaUpdateOpCopy::~DeltaUpdateOpCopy() { -} +DeltaUpdateOpCopy::~DeltaUpdateOpCopy() = default; UnpackerError DeltaUpdateOpCopy::DoParseArguments( const base::DictionaryValue* command_args, @@ -135,11 +131,9 @@ void DeltaUpdateOpCopy::DoRun(ComponentPatcher::Callback callback) { std::move(callback).Run(UnpackerError::kNone, 0); } -DeltaUpdateOpCreate::DeltaUpdateOpCreate() { -} +DeltaUpdateOpCreate::DeltaUpdateOpCreate() = default; -DeltaUpdateOpCreate::~DeltaUpdateOpCreate() { -} +DeltaUpdateOpCreate::~DeltaUpdateOpCreate() = default; UnpackerError DeltaUpdateOpCreate::DoParseArguments( const base::DictionaryValue* command_args, @@ -168,8 +162,7 @@ DeltaUpdateOpPatch::DeltaUpdateOpPatch(const std::string& operation, DCHECK(operation == kBsdiff || operation == kCourgette); } -DeltaUpdateOpPatch::~DeltaUpdateOpPatch() { -} +DeltaUpdateOpPatch::~DeltaUpdateOpPatch() = default; UnpackerError DeltaUpdateOpPatch::DoParseArguments( const base::DictionaryValue* command_args, diff --git a/chromium/components/update_client/component_patcher_unittest.cc b/chromium/components/update_client/component_patcher_unittest.cc index 78b1cc8043a..17a14758397 100644 --- a/chromium/components/update_client/component_patcher_unittest.cc +++ b/chromium/components/update_client/component_patcher_unittest.cc @@ -27,7 +27,7 @@ namespace { class TestCallback { public: TestCallback(); - virtual ~TestCallback() {} + virtual ~TestCallback() = default; void Set(update_client::UnpackerError error, int extra_code); update_client::UnpackerError error_; @@ -72,8 +72,7 @@ ComponentPatcherOperationTest::ComponentPatcherOperationTest() base::MakeRefCounted<ReadOnlyTestInstaller>(installed_dir_.GetPath()); } -ComponentPatcherOperationTest::~ComponentPatcherOperationTest() { -} +ComponentPatcherOperationTest::~ComponentPatcherOperationTest() = default; // Verify that a 'create' delta update operation works correctly. TEST_F(ComponentPatcherOperationTest, CheckCreateOperation) { diff --git a/chromium/components/update_client/component_unpacker.cc b/chromium/components/update_client/component_unpacker.cc index e57d2f728f5..1365353df2e 100644 --- a/chromium/components/update_client/component_unpacker.cc +++ b/chromium/components/update_client/component_unpacker.cc @@ -29,7 +29,7 @@ namespace update_client { -ComponentUnpacker::Result::Result() {} +ComponentUnpacker::Result::Result() = default; ComponentUnpacker::ComponentUnpacker(const std::vector<uint8_t>& pk_hash, const base::FilePath& path, @@ -47,7 +47,7 @@ ComponentUnpacker::ComponentUnpacker(const std::vector<uint8_t>& pk_hash, error_(UnpackerError::kNone), extended_error_(0) {} -ComponentUnpacker::~ComponentUnpacker() {} +ComponentUnpacker::~ComponentUnpacker() = default; void ComponentUnpacker::Unpack(Callback callback) { callback_ = std::move(callback); diff --git a/chromium/components/update_client/component_unpacker_unittest.cc b/chromium/components/update_client/component_unpacker_unittest.cc index 1a53f3c4f32..bc0f054dd3f 100644 --- a/chromium/components/update_client/component_unpacker_unittest.cc +++ b/chromium/components/update_client/component_unpacker_unittest.cc @@ -32,7 +32,7 @@ namespace { class TestCallback { public: TestCallback(); - virtual ~TestCallback() {} + virtual ~TestCallback() = default; void Set(update_client::UnpackerError error, int extra_code); update_client::UnpackerError error_; diff --git a/chromium/components/update_client/configurator.h b/chromium/components/update_client/configurator.h index 642f78573dd..ac9181e818a 100644 --- a/chromium/components/update_client/configurator.h +++ b/chromium/components/update_client/configurator.h @@ -146,7 +146,7 @@ class Configurator : public base::RefCountedThreadSafe<Configurator> { protected: friend class base::RefCountedThreadSafe<Configurator>; - virtual ~Configurator() {} + virtual ~Configurator() = default; }; } // namespace update_client diff --git a/chromium/components/update_client/crx_downloader.cc b/chromium/components/update_client/crx_downloader.cc index cf45d4cf5c8..96a2d844dc8 100644 --- a/chromium/components/update_client/crx_downloader.cc +++ b/chromium/components/update_client/crx_downloader.cc @@ -10,8 +10,7 @@ #include "base/files/file_util.h" #include "base/location.h" #include "base/logging.h" -#include "base/task/post_task.h" -#include "base/task/task_traits.h" +#include "base/task/thread_pool.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #if defined(OS_WIN) @@ -30,8 +29,7 @@ CrxDownloader::DownloadMetrics::DownloadMetrics() error(0), downloaded_bytes(-1), total_bytes(-1), - download_time_ms(0) { -} + download_time_ms(0) {} // On Windows, the first downloader in the chain is a background downloader, // which uses the BITS service. @@ -55,7 +53,7 @@ CrxDownloader::CrxDownloader(std::unique_ptr<CrxDownloader> successor) : main_task_runner_(base::ThreadTaskRunnerHandle::Get()), successor_(std::move(successor)) {} -CrxDownloader::~CrxDownloader() {} +CrxDownloader::~CrxDownloader() = default; void CrxDownloader::set_progress_callback( const ProgressCallback& progress_callback) { @@ -120,7 +118,7 @@ void CrxDownloader::OnDownloadComplete( DCHECK(thread_checker_.CalledOnValidThread()); if (!result.error) - base::PostTask( + base::ThreadPool::PostTask( FROM_HERE, kTaskTraits, base::BindOnce(&CrxDownloader::VerifyResponse, base::Unretained(this), is_handled, result, download_metrics)); diff --git a/chromium/components/update_client/crx_downloader_unittest.cc b/chromium/components/update_client/crx_downloader_unittest.cc index de729cc7661..865c968f907 100644 --- a/chromium/components/update_client/crx_downloader_unittest.cc +++ b/chromium/components/update_client/crx_downloader_unittest.cc @@ -103,9 +103,10 @@ CrxDownloaderTest::CrxDownloaderTest() : callback_(base::BindOnce(&CrxDownloaderTest::DownloadComplete, base::Unretained(this), kExpectedContext)), - progress_callback_(base::Bind(&CrxDownloaderTest::DownloadProgress, - base::Unretained(this), - kExpectedContext)), + progress_callback_( + base::BindRepeating(&CrxDownloaderTest::DownloadProgress, + base::Unretained(this), + kExpectedContext)), crx_context_(0), num_download_complete_calls_(0), num_progress_calls_(0), @@ -114,7 +115,7 @@ CrxDownloaderTest::CrxDownloaderTest() base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( &test_url_loader_factory_)) {} -CrxDownloaderTest::~CrxDownloaderTest() {} +CrxDownloaderTest::~CrxDownloaderTest() = default; void CrxDownloaderTest::SetUp() { num_download_complete_calls_ = 0; diff --git a/chromium/components/update_client/crx_update_item.h b/chromium/components/update_client/crx_update_item.h index ac645b592bb..89de40feda2 100644 --- a/chromium/components/update_client/crx_update_item.h +++ b/chromium/components/update_client/crx_update_item.h @@ -44,6 +44,7 @@ struct CrxUpdateItem { ErrorCategory error_category = ErrorCategory::kNone; int error_code = 0; int extra_code1 = 0; + std::map<std::string, std::string> custom_updatecheck_data; }; } // namespace update_client diff --git a/chromium/components/update_client/net/network_impl.cc b/chromium/components/update_client/net/network_impl.cc index 7bda2b6c84d..d2a99abddd9 100644 --- a/chromium/components/update_client/net/network_impl.cc +++ b/chromium/components/update_client/net/network_impl.cc @@ -13,7 +13,6 @@ #include "net/http/http_response_headers.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "services/network/public/cpp/is_potentially_trustworthy.h" -#include "services/network/public/cpp/resource_response.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/simple_url_loader.h" #include "services/network/public/mojom/url_response_head.mojom.h" diff --git a/chromium/components/update_client/net/url_loader_post_interceptor.cc b/chromium/components/update_client/net/url_loader_post_interceptor.cc index 11a2af87933..f6a48340963 100644 --- a/chromium/components/update_client/net/url_loader_post_interceptor.cc +++ b/chromium/components/update_client/net/url_loader_post_interceptor.cc @@ -48,7 +48,7 @@ URLLoaderPostInterceptor::URLLoaderPostInterceptor( InitializeWithRequestHandler(); } -URLLoaderPostInterceptor::~URLLoaderPostInterceptor() {} +URLLoaderPostInterceptor::~URLLoaderPostInterceptor() = default; bool URLLoaderPostInterceptor::ExpectRequest( std::unique_ptr<RequestMatcher> request_matcher) { diff --git a/chromium/components/update_client/net/url_loader_post_interceptor.h b/chromium/components/update_client/net/url_loader_post_interceptor.h index 9907f499dd1..1d460ace336 100644 --- a/chromium/components/update_client/net/url_loader_post_interceptor.h +++ b/chromium/components/update_client/net/url_loader_post_interceptor.h @@ -51,7 +51,7 @@ class URLLoaderPostInterceptor { class RequestMatcher { public: virtual bool Match(const std::string& actual) const = 0; - virtual ~RequestMatcher() {} + virtual ~RequestMatcher() = default; }; explicit URLLoaderPostInterceptor( diff --git a/chromium/components/update_client/persisted_data.cc b/chromium/components/update_client/persisted_data.cc index ea1ad1e860f..5801a75d07f 100644 --- a/chromium/components/update_client/persisted_data.cc +++ b/chromium/components/update_client/persisted_data.cc @@ -12,6 +12,7 @@ #include "base/strings/stringprintf.h" #include "base/threading/thread_checker.h" #include "base/values.h" +#include "base/version.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" @@ -168,6 +169,25 @@ int PersistedData::GetDaysSinceLastActive(const std::string& id) const { : kDaysUnknown; } +base::Version PersistedData::GetProductVersion(const std::string& id) const { + return base::Version(GetString(id, "pv")); +} + +void PersistedData::SetProductVersion(const std::string& id, + const base::Version& pv) { + DCHECK(pv.IsValid()); + SetString(id, "pv", pv.GetString()); +} + +std::string PersistedData::GetFingerprint(const std::string& id) const { + return GetString(id, "fp"); +} + +void PersistedData::SetFingerprint(const std::string& id, + const std::string& fingerprint) { + SetString(id, "fp", fingerprint); +} + void PersistedData::RegisterPrefs(PrefRegistrySimple* registry) { registry->RegisterDictionaryPref(kPersistedDataPreference); } diff --git a/chromium/components/update_client/persisted_data.h b/chromium/components/update_client/persisted_data.h index d35bd1506e1..73fd92d62ae 100644 --- a/chromium/components/update_client/persisted_data.h +++ b/chromium/components/update_client/persisted_data.h @@ -15,6 +15,10 @@ class PrefRegistrySimple; class PrefService; +namespace base { +class Version; +} // namespace base + namespace update_client { class ActivityDataService; @@ -99,6 +103,15 @@ class PersistedData { int GetDaysSinceLastRollCall(const std::string& id) const; int GetDaysSinceLastActive(const std::string& id) const; + // These functions access |pv| data for the specified |id|. Returns an empty + // version, if the version is not found. + base::Version GetProductVersion(const std::string& id) const; + void SetProductVersion(const std::string& id, const base::Version& pv); + + // These functions access the fingerprint for the specified |id|. + std::string GetFingerprint(const std::string& id) const; + void SetFingerprint(const std::string& id, const std::string& fingerprint); + private: int GetInt(const std::string& id, const std::string& key, int fallback) const; std::string GetString(const std::string& id, const std::string& key) const; diff --git a/chromium/components/update_client/persisted_data_unittest.cc b/chromium/components/update_client/persisted_data_unittest.cc index 7f7ae6e90ef..6b107d1aa53 100644 --- a/chromium/components/update_client/persisted_data_unittest.cc +++ b/chromium/components/update_client/persisted_data_unittest.cc @@ -7,6 +7,7 @@ #include <string> #include <vector> +#include "base/version.h" #include "components/prefs/testing_pref_service.h" #include "components/update_client/activity_data_service.h" #include "components/update_client/persisted_data.h" @@ -50,6 +51,15 @@ TEST(PersistedDataTest, Simple) { EXPECT_FALSE(pf2.empty()); // The following has a 1 / 2^128 chance of being flaky. EXPECT_NE(pf1, pf2); + + EXPECT_FALSE(metadata->GetProductVersion("someappid").IsValid()); + metadata->SetProductVersion("someappid", base::Version("1.0")); + EXPECT_EQ(base::Version("1.0"), metadata->GetProductVersion("someappid")); + + EXPECT_TRUE(metadata->GetFingerprint("someappid").empty()); + metadata->SetFingerprint("someappid", "somefingerprint"); + EXPECT_STREQ("somefingerprint", + metadata->GetFingerprint("someappid").c_str()); } TEST(PersistedDataTest, SharedPref) { diff --git a/chromium/components/update_client/ping_manager_unittest.cc b/chromium/components/update_client/ping_manager_unittest.cc index 0277b9b36fd..e7e3242186b 100644 --- a/chromium/components/update_client/ping_manager_unittest.cc +++ b/chromium/components/update_client/ping_manager_unittest.cc @@ -36,7 +36,7 @@ class PingManagerTest : public testing::Test, public testing::WithParamInterface<bool> { public: PingManagerTest(); - ~PingManagerTest() override {} + ~PingManagerTest() override = default; PingManager::Callback MakePingCallback(); scoped_refptr<UpdateContext> MakeMockUpdateContext() const; @@ -103,8 +103,9 @@ void PingManagerTest::PingSentCallback(int error, const std::string& response) { scoped_refptr<UpdateContext> PingManagerTest::MakeMockUpdateContext() const { return base::MakeRefCounted<UpdateContext>( config_, false, std::vector<std::string>(), - UpdateClient::CrxDataCallback(), UpdateEngine::NotifyObserversCallback(), - UpdateEngine::Callback(), nullptr); + UpdateClient::CrxDataCallback(), UpdateClient::CrxStateChangeCallback(), + UpdateEngine::NotifyObserversCallback(), UpdateEngine::Callback(), + nullptr, nullptr); } // This test is parameterized for using JSON or XML serialization. |true| means diff --git a/chromium/components/update_client/protocol_parser.h b/chromium/components/update_client/protocol_parser.h index 471fd6db4b4..029493a8c37 100644 --- a/chromium/components/update_client/protocol_parser.h +++ b/chromium/components/update_client/protocol_parser.h @@ -48,6 +48,13 @@ class ProtocolParser { std::string version; std::string browser_min_version; std::vector<Package> packages; + + // A path within the CRX archive to an executable to run as part of the + // update. The executable is typically an application installer. + std::string run; + + // Command-line arguments for the binary specified by |run|. + std::string arguments; }; Result(); @@ -59,6 +66,11 @@ class ProtocolParser { // The updatecheck response status. std::string status; + // App-specific additions in the updatecheck response, including the + // mandatory '_' prefix (which prevents collision with formal protocol + // elements). + std::map<std::string, std::string> custom_attributes; + // The list of fallback urls, for full and diff updates respectively. // These urls are base urls; they don't include the filename. std::vector<GURL> crx_urls; @@ -76,7 +88,8 @@ class ProtocolParser { static const char kCohortName[]; // Contains the run action returned by the server as part of an update - // check response. + // check response. This indicates the need to trigger the execution of + // something bound to a component which is already installed. std::string action_run; }; diff --git a/chromium/components/update_client/protocol_parser_json.cc b/chromium/components/update_client/protocol_parser_json.cc index eb022e4316c..71d3e54e6b2 100644 --- a/chromium/components/update_client/protocol_parser_json.cc +++ b/chromium/components/update_client/protocol_parser_json.cc @@ -17,6 +17,11 @@ namespace update_client { namespace { +std::string GetValueString(const base::Value& node, const char* key) { + const auto* value = node.FindKey(key); + return (value && value->is_string()) ? value->GetString() : std::string(); +} + bool ParseManifest(const base::Value& manifest_node, ProtocolParser::Result* result, std::string* error) { @@ -47,6 +52,9 @@ bool ParseManifest(const base::Value& manifest_node, } } + result->manifest.run = GetValueString(manifest_node, "run"); + result->manifest.arguments = GetValueString(manifest_node, "arguments"); + const auto* packages_node = manifest_node.FindKey("packages"); if (!packages_node || !packages_node->is_dict()) { *error = "Missing packages in manifest or 'packages' is not a dictionary."; @@ -71,17 +79,10 @@ bool ParseManifest(const base::Value& manifest_node, } p.name = name->GetString(); - const auto* namediff = package.FindKey("namediff"); - if (namediff && namediff->is_string()) - p.namediff = namediff->GetString(); - - const auto* fingerprint = package.FindKey("fp"); - if (fingerprint && fingerprint->is_string()) - p.fingerprint = fingerprint->GetString(); - - const auto* hash_sha256 = package.FindKey("hash_sha256"); - if (hash_sha256 && hash_sha256->is_string()) - p.hash_sha256 = hash_sha256->GetString(); + p.namediff = GetValueString(package, "namediff"); + p.fingerprint = GetValueString(package, "fp"); + p.hash_sha256 = GetValueString(package, "hash_sha256"); + p.hashdiff_sha256 = GetValueString(package, "hashdiff_sha256"); const auto* size = package.FindKey("size"); if (size && (size->is_int() || size->is_double())) { @@ -90,10 +91,6 @@ bool ParseManifest(const base::Value& manifest_node, p.size = size->GetDouble(); } - const auto* hashdiff_sha256 = package.FindKey("hashdiff_sha256"); - if (hashdiff_sha256 && hashdiff_sha256->is_string()) - p.hashdiff_sha256 = hashdiff_sha256->GetString(); - const auto* sizediff = package.FindKey("sizediff"); if (sizediff && (sizediff->is_int() || sizediff->is_double())) { const auto val = sizediff->GetDouble(); @@ -120,9 +117,7 @@ void ParseActions(const base::Value& actions_node, if (action_list.empty() || !action_list[0].is_dict()) return; - const auto* run = action_list[0].FindKey("run"); - if (run && run->is_string()) - result->action_run = run->GetString(); + result->action_run = GetValueString(action_list[0], "run"); } bool ParseUrls(const base::Value& urls_node, @@ -171,6 +166,13 @@ bool ParseUpdateCheck(const base::Value& updatecheck_node, *error = "'updatecheck' is not a dictionary."; return false; } + + for (const auto& kv : updatecheck_node.DictItems()) { + if (kv.first.front() == '_' && kv.second.is_string()) { + result->custom_attributes[kv.first] = kv.second.GetString(); + } + } + const auto* status = updatecheck_node.FindKey("status"); if (!status || !status->is_string()) { *error = "Missing status on updatecheck node"; diff --git a/chromium/components/update_client/protocol_parser_json_unittest.cc b/chromium/components/update_client/protocol_parser_json_unittest.cc index 5bf114a3bc2..991e2bb75f0 100644 --- a/chromium/components/update_client/protocol_parser_json_unittest.cc +++ b/chromium/components/update_client/protocol_parser_json_unittest.cc @@ -328,6 +328,44 @@ const char* kJSONAppsStatusError = R"()]}' ] }})"; +// Includes a manifest |run| value for an update check with status='ok'. +const char* kJSONManifestRun = R"()]}' + {"response":{ + "protocol":"3.1", + "app":[ + {"appid":"12345", + "updatecheck":{ + "status":"ok", + "urls":{"url":[{"codebase":"http://example.com/"}, + {"codebasediff":"http://diff.example.com/"}]}, + "manifest":{ + "version":"1.2.3.4", + "prodversionmin":"2.0.143.0", + "run":"UpdaterSetup.exe", + "arguments":"--arg1 --arg2", + "packages":{"package":[{"name":"extension_1_2_3_4.crx"}]}} + } + } + ] + }})"; + +// Includes two custom response attributes in the update_check. +const char* kJSONCustomAttributes = R"()]}' + {"response":{ + "protocol":"3.1", + "app":[ + {"appid":"12345", + "updatecheck":{ + "_example1":"example_value1", + "_example2":"example_value2", + "_example_bad": {"value": "bad-non-string-value"}, + "_example_bad2": 15, + "status":"noupdate" + } + } + ] + }})"; + TEST(UpdateClientProtocolParserJSONTest, Parse) { const auto parser = std::make_unique<ProtocolParserJSON>(); @@ -501,6 +539,34 @@ TEST(UpdateClientProtocolParserJSONTest, Parse) { EXPECT_STREQ("error-invalidAppId", third_result->status.c_str()); EXPECT_TRUE(third_result->manifest.version.empty()); } + { + EXPECT_TRUE(parser->Parse(kJSONManifestRun)); + EXPECT_TRUE(parser->errors().empty()); + EXPECT_EQ(1u, parser->results().list.size()); + const auto& result = parser->results().list[0]; + EXPECT_STREQ("UpdaterSetup.exe", result.manifest.run.c_str()); + EXPECT_STREQ("--arg1 --arg2", result.manifest.arguments.c_str()); + } +} + +TEST(UpdateClientProtocolParserJSONTest, ParseAttrs) { + const auto parser = std::make_unique<ProtocolParserJSON>(); + { // No custom attrs in kJSONManifestRun + EXPECT_TRUE(parser->Parse(kJSONManifestRun)); + EXPECT_TRUE(parser->errors().empty()); + EXPECT_EQ(1u, parser->results().list.size()); + const auto& result = parser->results().list[0]; + EXPECT_EQ(0u, result.custom_attributes.size()); + } + { // Two custom attrs in kJSONCustomAttributes + EXPECT_TRUE(parser->Parse(kJSONCustomAttributes)); + EXPECT_TRUE(parser->errors().empty()); + EXPECT_EQ(1u, parser->results().list.size()); + const auto& result = parser->results().list[0]; + EXPECT_EQ(2u, result.custom_attributes.size()); + EXPECT_EQ("example_value1", result.custom_attributes.at("_example1")); + EXPECT_EQ("example_value2", result.custom_attributes.at("_example2")); + } } } // namespace update_client diff --git a/chromium/components/update_client/request_sender.cc b/chromium/components/update_client/request_sender.cc index 3deaec0d7d7..47cac690b3e 100644 --- a/chromium/components/update_client/request_sender.cc +++ b/chromium/components/update_client/request_sender.cc @@ -24,10 +24,10 @@ namespace update_client { namespace { // This is an ECDSA prime256v1 named-curve key. -constexpr int kKeyVersion = 9; +constexpr int kKeyVersion = 10; const char kKeyPubBytesBase64[] = - "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEsVwVMmIJaWBjktSx9m1JrZWYBvMm" - "bsrGGQPhScDtao+DloD871YmEeunAaQvRMZgDh1nCaWkVG6wo75+yDbKDA=="; + "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEzOqC8cKNUYIi0UkNu0smZKDW8w5/" + "0EmEw1KQ6Aj/5JWBMdUVm13EIVwFwPlkO/U6vXa+iu4wyUB89GFaldJ7Bg=="; } // namespace @@ -84,7 +84,7 @@ void RequestSender::SendInternal() { url = BuildUpdateUrl(url, request_query_string); } - DVLOG(2) << "Sending Omaha request: " << request_body_; + VLOG(2) << "Sending Omaha request: " << request_body_; network_fetcher_ = config_->GetNetworkFetcherFactory()->Create(); if (!network_fetcher_) { @@ -107,6 +107,8 @@ void RequestSender::SendInternalComplete(int error, const std::string& response_body, const std::string& response_etag, int retry_after_sec) { + VLOG(2) << "Omaha response received: " << response_body; + if (!error) { if (!use_signing_) { base::ThreadTaskRunnerHandle::Get()->PostTask( @@ -154,7 +156,7 @@ void RequestSender::OnNetworkFetcherComplete( int64_t xheader_retry_after_sec) { DCHECK(thread_checker_.CalledOnValidThread()); - VLOG(1) << "request completed from url: " << original_url.spec(); + VLOG(1) << "Request completed from url: " << original_url.spec(); int error = -1; if (!net_error && response_code_ == 200) diff --git a/chromium/components/update_client/request_sender_unittest.cc b/chromium/components/update_client/request_sender_unittest.cc index cb0e09c4728..790a98846b7 100644 --- a/chromium/components/update_client/request_sender_unittest.cc +++ b/chromium/components/update_client/request_sender_unittest.cc @@ -78,7 +78,7 @@ INSTANTIATE_TEST_SUITE_P(IsForeground, RequestSenderTest, ::testing::Bool()); RequestSenderTest::RequestSenderTest() : task_environment_(base::test::TaskEnvironment::MainThreadType::IO) {} -RequestSenderTest::~RequestSenderTest() {} +RequestSenderTest::~RequestSenderTest() = default; void RequestSenderTest::SetUp() { config_ = base::MakeRefCounted<TestConfigurator>(); diff --git a/chromium/components/update_client/task_traits.h b/chromium/components/update_client/task_traits.h index 1f675e7af86..53e1337cfa7 100644 --- a/chromium/components/update_client/task_traits.h +++ b/chromium/components/update_client/task_traits.h @@ -9,17 +9,19 @@ namespace update_client { +// Task traits for tasks posted to base::ThreadPool from update_client. + constexpr base::TaskTraits kTaskTraits = { - base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT, + base::MayBlock(), base::TaskPriority::BEST_EFFORT, base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}; constexpr base::TaskTraits kTaskTraitsBackgroundDownloader = { - base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT, + base::MayBlock(), base::TaskPriority::BEST_EFFORT, base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}; // This task joins a process, hence .WithBaseSyncPrimitives(). constexpr base::TaskTraits kTaskTraitsRunCommand = { - base::ThreadPool(), base::MayBlock(), base::WithBaseSyncPrimitives(), + base::MayBlock(), base::WithBaseSyncPrimitives(), base::TaskPriority::BEST_EFFORT, base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}; diff --git a/chromium/components/update_client/task_update.cc b/chromium/components/update_client/task_update.cc index ab445b582e6..733649b5711 100644 --- a/chromium/components/update_client/task_update.cc +++ b/chromium/components/update_client/task_update.cc @@ -13,15 +13,18 @@ namespace update_client { -TaskUpdate::TaskUpdate(scoped_refptr<UpdateEngine> update_engine, - bool is_foreground, - const std::vector<std::string>& ids, - UpdateClient::CrxDataCallback crx_data_callback, - Callback callback) +TaskUpdate::TaskUpdate( + scoped_refptr<UpdateEngine> update_engine, + bool is_foreground, + const std::vector<std::string>& ids, + UpdateClient::CrxDataCallback crx_data_callback, + UpdateClient::CrxStateChangeCallback crx_state_change_callback, + Callback callback) : update_engine_(update_engine), is_foreground_(is_foreground), ids_(ids), crx_data_callback_(std::move(crx_data_callback)), + crx_state_change_callback_(crx_state_change_callback), callback_(std::move(callback)) {} TaskUpdate::~TaskUpdate() { @@ -37,6 +40,7 @@ void TaskUpdate::Run() { } update_engine_->Update(is_foreground_, ids_, std::move(crx_data_callback_), + std::move(crx_state_change_callback_), base::BindOnce(&TaskUpdate::TaskComplete, this)); } @@ -54,8 +58,8 @@ void TaskUpdate::TaskComplete(Error error) { DCHECK(thread_checker_.CalledOnValidThread()); base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback_), - scoped_refptr<TaskUpdate>(this), error)); + FROM_HERE, + base::BindOnce(std::move(callback_), base::WrapRefCounted(this), error)); } } // namespace update_client diff --git a/chromium/components/update_client/task_update.h b/chromium/components/update_client/task_update.h index 4df796b618e..79b07c8d859 100644 --- a/chromium/components/update_client/task_update.h +++ b/chromium/components/update_client/task_update.h @@ -9,8 +9,8 @@ #include <vector> #include "base/callback.h" -#include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_refptr.h" #include "base/threading/thread_checker.h" #include "components/update_client/task.h" #include "components/update_client/update_client.h" @@ -36,12 +36,14 @@ class TaskUpdate : public Task { bool is_foreground, const std::vector<std::string>& ids, UpdateClient::CrxDataCallback crx_data_callback, + UpdateClient::CrxStateChangeCallback crx_state_change_callback, Callback callback); + TaskUpdate(const TaskUpdate&) = delete; + TaskUpdate& operator=(const TaskUpdate&) = delete; + // Overrides for Task. void Run() override; - void Cancel() override; - std::vector<std::string> GetIds() const override; private: @@ -56,9 +58,8 @@ class TaskUpdate : public Task { const bool is_foreground_; const std::vector<std::string> ids_; UpdateClient::CrxDataCallback crx_data_callback_; + UpdateClient::CrxStateChangeCallback crx_state_change_callback_; Callback callback_; - - DISALLOW_COPY_AND_ASSIGN(TaskUpdate); }; } // namespace update_client diff --git a/chromium/components/update_client/test_configurator.cc b/chromium/components/update_client/test_configurator.cc index 13fa7ca5237..fe412bb4a55 100644 --- a/chromium/components/update_client/test_configurator.cc +++ b/chromium/components/update_client/test_configurator.cc @@ -34,12 +34,13 @@ std::vector<GURL> MakeDefaultUrls() { } // namespace -TestConfigurator::TestConfigurator() +TestConfigurator::TestConfigurator(PrefService* pref_service) : brand_("TEST"), initial_time_(0), ondemand_time_(0), enabled_cup_signing_(false), enabled_component_updates_(true), + pref_service_(pref_service), unzip_factory_(base::MakeRefCounted<update_client::UnzipChromiumFactory>( base::BindRepeating(&unzip::LaunchInProcessUnzipper))), patch_factory_(base::MakeRefCounted<update_client::PatchChromiumFactory>( @@ -52,8 +53,7 @@ TestConfigurator::TestConfigurator() test_shared_loader_factory_, base::BindRepeating([](const GURL& url) { return false; }))) {} -TestConfigurator::~TestConfigurator() { -} +TestConfigurator::~TestConfigurator() = default; int TestConfigurator::InitialDelay() const { return initial_time_; @@ -183,7 +183,7 @@ void TestConfigurator::SetPingUrl(const GURL& url) { } PrefService* TestConfigurator::GetPrefService() const { - return nullptr; + return pref_service_; } ActivityDataService* TestConfigurator::GetActivityDataService() const { diff --git a/chromium/components/update_client/test_configurator.h b/chromium/components/update_client/test_configurator.h index 518fa3e166c..55fb880fdc8 100644 --- a/chromium/components/update_client/test_configurator.h +++ b/chromium/components/update_client/test_configurator.h @@ -13,7 +13,6 @@ #include <vector> #include "base/containers/flat_map.h" -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "components/update_client/configurator.h" #include "services/network/test/test_url_loader_factory.h" @@ -69,9 +68,11 @@ const uint8_t gjpm_hash[] = {0x69, 0xfc, 0x41, 0xf6, 0x17, 0x20, 0xc6, 0x36, class TestConfigurator : public Configurator { public: - TestConfigurator(); + explicit TestConfigurator(PrefService* pref_service = nullptr); + TestConfigurator(const TestConfigurator&) = delete; + TestConfigurator& operator=(const TestConfigurator&) = delete; - // Overrrides for Configurator. + // Overrides for Configurator. int InitialDelay() const override; int NextCheckDelay() const override; int OnDemandDelay() const override; @@ -123,6 +124,7 @@ class TestConfigurator : public Configurator { std::string download_preference_; bool enabled_cup_signing_; bool enabled_component_updates_; + PrefService* pref_service_; // Not owned by this class. GURL update_check_url_; GURL ping_url_; @@ -132,8 +134,6 @@ class TestConfigurator : public Configurator { scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_; network::TestURLLoaderFactory test_url_loader_factory_; scoped_refptr<NetworkFetcherFactory> network_fetcher_factory_; - - DISALLOW_COPY_AND_ASSIGN(TestConfigurator); }; } // namespace update_client diff --git a/chromium/components/update_client/test_installer.cc b/chromium/components/update_client/test_installer.cc index 92359cc2671..46fdd4ff69f 100644 --- a/chromium/components/update_client/test_installer.cc +++ b/chromium/components/update_client/test_installer.cc @@ -5,12 +5,14 @@ #include "components/update_client/test_installer.h" #include <string> +#include <utility> #include "base/bind.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/task/post_task.h" #include "base/task/task_traits.h" +#include "base/task/thread_pool.h" #include "base/values.h" #include "components/update_client/update_client_errors.h" #include "components/update_client/utils.h" @@ -18,8 +20,7 @@ namespace update_client { -TestInstaller::TestInstaller() : error_(0), install_count_(0) { -} +TestInstaller::TestInstaller() : error_(0), install_count_(0) {} TestInstaller::~TestInstaller() { // The unpack path is deleted unconditionally by the component state code, @@ -35,17 +36,19 @@ void TestInstaller::OnUpdateError(int error) { void TestInstaller::Install(const base::FilePath& unpack_path, const std::string& /*public_key*/, + std::unique_ptr<InstallParams> install_params, Callback callback) { ++install_count_; unpack_path_ = unpack_path; + install_params_ = std::move(install_params); InstallComplete(std::move(callback), Result(InstallError::NONE)); } void TestInstaller::InstallComplete(Callback callback, const Result& result) const { - base::PostTask(FROM_HERE, {base::ThreadPool(), base::MayBlock()}, - base::BindOnce(std::move(callback), result)); + base::ThreadPool::PostTask(FROM_HERE, {base::MayBlock()}, + base::BindOnce(std::move(callback), result)); } bool TestInstaller::GetInstalledFile(const std::string& file, @@ -58,11 +61,9 @@ bool TestInstaller::Uninstall() { } ReadOnlyTestInstaller::ReadOnlyTestInstaller(const base::FilePath& install_dir) - : install_directory_(install_dir) { -} + : install_directory_(install_dir) {} -ReadOnlyTestInstaller::~ReadOnlyTestInstaller() { -} +ReadOnlyTestInstaller::~ReadOnlyTestInstaller() = default; bool ReadOnlyTestInstaller::GetInstalledFile(const std::string& file, base::FilePath* installed_file) { @@ -78,9 +79,11 @@ VersionedTestInstaller::~VersionedTestInstaller() { base::DeleteFileRecursively(install_directory_); } -void VersionedTestInstaller::Install(const base::FilePath& unpack_path, - const std::string& public_key, - Callback callback) { +void VersionedTestInstaller::Install( + const base::FilePath& unpack_path, + const std::string& public_key, + std::unique_ptr<InstallParams> /*install_params*/, + Callback callback) { const auto manifest = update_client::ReadManifest(unpack_path); std::string version_string; manifest->GetStringASCII("version", &version_string); diff --git a/chromium/components/update_client/test_installer.h b/chromium/components/update_client/test_installer.h index a12baf9bb7c..3e27ff8d094 100644 --- a/chromium/components/update_client/test_installer.h +++ b/chromium/components/update_client/test_installer.h @@ -25,6 +25,7 @@ class TestInstaller : public CrxInstaller { void Install(const base::FilePath& unpack_path, const std::string& public_key, + std::unique_ptr<InstallParams> install_params, Callback callback) override; bool GetInstalledFile(const std::string& file, @@ -36,6 +37,8 @@ class TestInstaller : public CrxInstaller { int install_count() const { return install_count_; } + const InstallParams* install_params() const { return install_params_.get(); } + protected: ~TestInstaller() override; @@ -47,6 +50,9 @@ class TestInstaller : public CrxInstaller { private: // Contains the |unpack_path| argument of the Install call. base::FilePath unpack_path_; + + // Contains the |install_params| argument of the Install call. + std::unique_ptr<InstallParams> install_params_; }; // A ReadOnlyTestInstaller is an installer that knows about files in an existing @@ -72,6 +78,7 @@ class VersionedTestInstaller : public TestInstaller { void Install(const base::FilePath& unpack_path, const std::string& public_key, + std::unique_ptr<InstallParams> install_params, Callback callback) override; bool GetInstalledFile(const std::string& file, diff --git a/chromium/components/update_client/update_checker.cc b/chromium/components/update_client/update_checker.cc index cfc25787280..51c685e7b4e 100644 --- a/chromium/components/update_client/update_checker.cc +++ b/chromium/components/update_client/update_checker.cc @@ -19,6 +19,7 @@ #include "base/macros.h" #include "base/strings/stringprintf.h" #include "base/task/post_task.h" +#include "base/task/thread_pool.h" #include "base/threading/thread_checker.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" @@ -130,7 +131,7 @@ void UpdateCheckerImpl::CheckForUpdates( ids_checked_ = ids_checked; update_check_callback_ = std::move(update_check_callback); - base::PostTaskAndReply( + base::ThreadPool::PostTaskAndReply( FROM_HERE, kTaskTraits, base::BindOnce(&UpdateCheckerImpl::ReadUpdaterStateAttributes, base::Unretained(this)), diff --git a/chromium/components/update_client/update_checker_unittest.cc b/chromium/components/update_client/update_checker_unittest.cc index 001bdd019a1..9e571f1c0c7 100644 --- a/chromium/components/update_client/update_checker_unittest.cc +++ b/chromium/components/update_client/update_checker_unittest.cc @@ -164,8 +164,7 @@ INSTANTIATE_TEST_SUITE_P(Parameterized, UpdateCheckerTest, testing::Bool()); UpdateCheckerTest::UpdateCheckerTest() : task_environment_(base::test::TaskEnvironment::MainThreadType::IO) {} -UpdateCheckerTest::~UpdateCheckerTest() { -} +UpdateCheckerTest::~UpdateCheckerTest() = default; void UpdateCheckerTest::SetUp() { is_foreground_ = GetParam(); @@ -228,8 +227,9 @@ void UpdateCheckerTest::UpdateCheckComplete( scoped_refptr<UpdateContext> UpdateCheckerTest::MakeMockUpdateContext() const { return base::MakeRefCounted<UpdateContext>( config_, false, std::vector<std::string>(), - UpdateClient::CrxDataCallback(), UpdateEngine::NotifyObserversCallback(), - UpdateEngine::Callback(), nullptr); + UpdateClient::CrxDataCallback(), UpdateClient::CrxStateChangeCallback(), + UpdateEngine::NotifyObserversCallback(), UpdateEngine::Callback(), + nullptr, nullptr); } std::unique_ptr<Component> UpdateCheckerTest::MakeComponent() const { diff --git a/chromium/components/update_client/update_client.cc b/chromium/components/update_client/update_client.cc index 1a12e472757..07f8454eb12 100644 --- a/chromium/components/update_client/update_client.cc +++ b/chromium/components/update_client/update_client.cc @@ -37,6 +37,10 @@ namespace update_client { +CrxInstaller::InstallParams::InstallParams(const std::string& run, + const std::string& arguments) + : run(run), arguments(arguments) {} + CrxUpdateItem::CrxUpdateItem() : state(ComponentState::kNew) {} CrxUpdateItem::~CrxUpdateItem() = default; CrxUpdateItem::CrxUpdateItem(const CrxUpdateItem& other) = default; @@ -69,8 +73,8 @@ UpdateClientImpl::UpdateClientImpl( update_checker_factory, crx_downloader_factory, ping_manager_.get(), - base::Bind(&UpdateClientImpl::NotifyObservers, - base::Unretained(this)))) {} + base::BindRepeating(&UpdateClientImpl::NotifyObservers, + base::Unretained(this)))) {} UpdateClientImpl::~UpdateClientImpl() { DCHECK(thread_checker_.CalledOnValidThread()); @@ -83,6 +87,7 @@ UpdateClientImpl::~UpdateClientImpl() { void UpdateClientImpl::Install(const std::string& id, CrxDataCallback crx_data_callback, + CrxStateChangeCallback crx_state_change_callback, Callback callback) { DCHECK(thread_checker_.CalledOnValidThread()); @@ -98,18 +103,21 @@ void UpdateClientImpl::Install(const std::string& id, constexpr bool kIsForeground = true; RunTask(base::MakeRefCounted<TaskUpdate>( update_engine_.get(), kIsForeground, ids, std::move(crx_data_callback), + crx_state_change_callback, base::BindOnce(&UpdateClientImpl::OnTaskComplete, this, std::move(callback)))); } void UpdateClientImpl::Update(const std::vector<std::string>& ids, CrxDataCallback crx_data_callback, + CrxStateChangeCallback crx_state_change_callback, bool is_foreground, Callback callback) { DCHECK(thread_checker_.CalledOnValidThread()); auto task = base::MakeRefCounted<TaskUpdate>( update_engine_.get(), is_foreground, ids, std::move(crx_data_callback), + crx_state_change_callback, base::BindOnce(&UpdateClientImpl::OnTaskComplete, this, std::move(callback))); @@ -140,6 +148,7 @@ void UpdateClientImpl::OnTaskComplete(Callback callback, // Remove the task from the set of the running tasks. Only tasks handled by // the update engine can be in this data structure. + DCHECK_EQ(1u, tasks_.count(task)); tasks_.erase(task); if (is_stopped_) @@ -179,14 +188,14 @@ bool UpdateClientImpl::GetCrxUpdateState(const std::string& id, bool UpdateClientImpl::IsUpdating(const std::string& id) const { DCHECK(thread_checker_.CalledOnValidThread()); - for (const auto task : tasks_) { + for (const auto& task : tasks_) { const auto ids = task->GetIds(); if (base::Contains(ids, id)) { return true; } } - for (const auto task : task_queue_) { + for (const auto& task : task_queue_) { const auto ids = task->GetIds(); if (base::Contains(ids, id)) { return true; diff --git a/chromium/components/update_client/update_client.h b/chromium/components/update_client/update_client.h index d88837b95eb..00d41a58d9a 100644 --- a/chromium/components/update_client/update_client.h +++ b/chromium/components/update_client/update_client.h @@ -8,6 +8,7 @@ #include <stdint.h> #include <map> +#include <memory> #include <string> #include <vector> @@ -176,6 +177,12 @@ class CrxInstaller : public base::RefCountedThreadSafe<CrxInstaller> { int extended_error = 0; }; + struct InstallParams { + InstallParams(const std::string& run, const std::string& arguments); + std::string run; + std::string arguments; + }; + using Callback = base::OnceCallback<void(const Result& result)>; // Called on the main thread when there was a problem unpacking or @@ -187,10 +194,15 @@ class CrxInstaller : public base::RefCountedThreadSafe<CrxInstaller> { // and it is ready to be installed. |unpack_path| contains the // temporary directory with all the unpacked CRX files. |pubkey| contains the // public key of the CRX in the PEM format, without the header and the footer. + // |install_params| is an optional parameter which provides the name and + // the arguments for a binary program which is invoked as part of the + // install or update flows. To avoid forcing the callers to depend on + // base::Optional, an std::unique_ptr type is used. // The caller must invoke the |callback| when the install flow has completed. // This method may be called from a thread other than the main thread. virtual void Install(const base::FilePath& unpack_path, const std::string& public_key, + std::unique_ptr<InstallParams> install_params, Callback callback) = 0; // Sets |installed_file| to the full path to the installed |file|. |file| is @@ -208,7 +220,7 @@ class CrxInstaller : public base::RefCountedThreadSafe<CrxInstaller> { protected: friend class base::RefCountedThreadSafe<CrxInstaller>; - virtual ~CrxInstaller() {} + virtual ~CrxInstaller() = default; }; // Defines an interface to handle |action| elements in the update response. @@ -311,6 +323,10 @@ class UpdateClient : public base::RefCounted<UpdateClient> { base::OnceCallback<std::vector<base::Optional<CrxComponent>>( const std::vector<std::string>& ids)>; + // Called when state changes occur during an Install or Update call. + using CrxStateChangeCallback = + base::RepeatingCallback<void(CrxUpdateItem item)>; + // Defines an interface to observe the UpdateClient. It provides // notifications when state changes occur for the service itself or for the // registered CRXs. @@ -350,7 +366,7 @@ class UpdateClient : public base::RefCounted<UpdateClient> { COMPONENT_UPDATE_DOWNLOADING, }; - virtual ~Observer() {} + virtual ~Observer() = default; // Called by the update client when a state change happens. // If an |id| is specified, then the event is fired on behalf of the @@ -368,29 +384,36 @@ class UpdateClient : public base::RefCounted<UpdateClient> { virtual void RemoveObserver(Observer* observer) = 0; // Installs the specified CRX. Calls back on |callback| after the - // update has been handled. The |error| parameter of the |callback| - // contains an error code in the case of a run-time error, or 0 if the - // install has been handled successfully. Overlapping calls of this function - // are executed concurrently, as long as the id parameter is different, - // meaning that installs of different components are parallelized. + // update has been handled. Provides state change notifications through + // invocations of the optional |crx_state_change_callback| callback. + // The |error| parameter of the |callback| contains an error code in the case + // of a run-time error, or 0 if the install has been handled successfully. + // Overlapping calls of this function are executed concurrently, as long as + // the id parameter is different, meaning that installs of different + // components are parallelized. // The |Install| function is intended to be used for foreground installs of // one CRX. These cases are usually associated with on-demand install // scenarios, which are triggered by user actions. Installs are never // queued up. virtual void Install(const std::string& id, CrxDataCallback crx_data_callback, + CrxStateChangeCallback crx_state_change_callback, Callback callback) = 0; // Updates the specified CRXs. Calls back on |crx_data_callback| before the // update is attempted to give the caller the opportunity to provide the - // instances of CrxComponent to be used for this update. The |Update| function - // is intended to be used for background updates of several CRXs. Overlapping - // calls to this function result in a queuing behavior, and the execution - // of each call is serialized. In addition, updates are always queued up when - // installs are running. The |is_foreground| parameter must be set to true if - // the invocation of this function is a result of a user initiated update. + // instances of CrxComponent to be used for this update. Provides state change + // notifications through invocations of the optional + // |crx_state_change_callback| callback. + // The |Update| function is intended to be used for background updates of + // several CRXs. Overlapping calls to this function result in a queuing + // behavior, and the execution of each call is serialized. In addition, + // updates are always queued up when installs are running. The |is_foreground| + // parameter must be set to true if the invocation of this function is a + // result of a user initiated update. virtual void Update(const std::vector<std::string>& ids, CrxDataCallback crx_data_callback, + CrxStateChangeCallback crx_state_change_callback, bool is_foreground, Callback callback) = 0; @@ -422,7 +445,7 @@ class UpdateClient : public base::RefCounted<UpdateClient> { protected: friend class base::RefCounted<UpdateClient>; - virtual ~UpdateClient() {} + virtual ~UpdateClient() = default; }; // Creates an instance of the update client. diff --git a/chromium/components/update_client/update_client_errors.h b/chromium/components/update_client/update_client_errors.h index 3ee05098ecb..1cf13a8c05f 100644 --- a/chromium/components/update_client/update_client_errors.h +++ b/chromium/components/update_client/update_client_errors.h @@ -83,6 +83,7 @@ enum class InstallError { NO_DIR_COMPONENT_USER = 14, CLEAN_INSTALL_DIR_FAILED = 15, INSTALL_VERIFICATION_FAILED = 16, + MISSING_INSTALL_PARAMS = 17, CUSTOM_ERROR_BASE = 100, // Specific installer errors go above this value. }; diff --git a/chromium/components/update_client/update_client_internal.h b/chromium/components/update_client/update_client_internal.h index 2b6158c1b2f..676c23afaa3 100644 --- a/chromium/components/update_client/update_client_internal.h +++ b/chromium/components/update_client/update_client_internal.h @@ -39,9 +39,11 @@ class UpdateClientImpl : public UpdateClient { void RemoveObserver(Observer* observer) override; void Install(const std::string& id, CrxDataCallback crx_data_callback, + CrxStateChangeCallback crx_state_change_callback, Callback callback) override; void Update(const std::vector<std::string>& ids, CrxDataCallback crx_data_callback, + CrxStateChangeCallback crx_state_change_callback, bool is_foreground, Callback callback) override; bool GetCrxUpdateState(const std::string& id, diff --git a/chromium/components/update_client/update_client_unittest.cc b/chromium/components/update_client/update_client_unittest.cc index c91cc18f741..aa487ebcd65 100644 --- a/chromium/components/update_client/update_client_unittest.cc +++ b/chromium/components/update_client/update_client_unittest.cc @@ -18,6 +18,7 @@ #include "base/stl_util.h" #include "base/task/post_task.h" #include "base/task/task_traits.h" +#include "base/task/thread_pool.h" #include "base/test/scoped_path_override.h" #include "base/test/task_environment.h" #include "base/threading/thread_task_runner_handle.h" @@ -84,15 +85,25 @@ class MockObserver : public UpdateClient::Observer { class MockActionHandler : public ActionHandler { public: MockActionHandler() = default; + MockActionHandler(const MockActionHandler&) = delete; + MockActionHandler& operator=(const MockActionHandler&) = delete; MOCK_METHOD3(Handle, void(const base::FilePath&, const std::string&, Callback)); private: ~MockActionHandler() override = default; +}; - MockActionHandler(const MockActionHandler&) = delete; - MockActionHandler& operator=(const MockActionHandler&) = delete; +class MockCrxStateChangeReceiver + : public base::RefCounted<MockCrxStateChangeReceiver> { + public: + MOCK_METHOD(void, Receive, (CrxUpdateItem)); + + private: + friend class base::RefCounted<MockCrxStateChangeReceiver>; + + ~MockCrxStateChangeReceiver() = default; }; } // namespace @@ -143,7 +154,7 @@ class MockPingManagerImpl : public PingManager { MockPingManagerImpl::MockPingManagerImpl(scoped_refptr<Configurator> config) : PingManager(config) {} -MockPingManagerImpl::~MockPingManagerImpl() {} +MockPingManagerImpl::~MockPingManagerImpl() = default; void MockPingManagerImpl::SendPing(const Component& component, Callback callback) { @@ -195,11 +206,12 @@ class UpdateClientTest : public testing::Test { base::test::TaskEnvironment task_environment_; base::RunLoop runloop_; - scoped_refptr<update_client::TestConfigurator> config_ = - base::MakeRefCounted<TestConfigurator>(); std::unique_ptr<TestingPrefServiceSimple> pref_ = std::make_unique<TestingPrefServiceSimple>(); - std::unique_ptr<update_client::PersistedData> metadata_; + scoped_refptr<update_client::TestConfigurator> config_ = + base::MakeRefCounted<TestConfigurator>(pref_.get()); + std::unique_ptr<update_client::PersistedData> metadata_ = + std::make_unique<PersistedData>(pref_.get(), nullptr); DISALLOW_COPY_AND_ASSIGN(UpdateClientTest); }; @@ -208,11 +220,9 @@ constexpr int UpdateClientTest::kNumWorkerThreads_; UpdateClientTest::UpdateClientTest() { PersistedData::RegisterPrefs(pref_->registry()); - metadata_ = std::make_unique<PersistedData>(pref_.get(), nullptr); } -UpdateClientTest::~UpdateClientTest() { -} +UpdateClientTest::~UpdateClientTest() = default; void UpdateClientTest::RunThreads() { runloop_.Run(); @@ -323,21 +333,36 @@ TEST_F(UpdateClientTest, OneCrxNoUpdate) { &MockUpdateChecker::Create, &MockCrxDownloader::Create); MockObserver observer; - InSequence seq; - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + { + InSequence seq; + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, + "jebgalgnebhfojomionfpkfelancnnkf")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "jebgalgnebhfojomionfpkfelancnnkf")) + .Times(1); + } - update_client->AddObserver(&observer); + std::vector<CrxUpdateItem> items; + auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>(); + EXPECT_CALL(*receiver, Receive(_)) + .WillRepeatedly( + [&items](const CrxUpdateItem& item) { items.push_back(item); }); + update_client->AddObserver(&observer); const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf"}; update_client->Update( - ids, base::BindOnce(&DataCallbackMock::Callback), true, + ids, base::BindOnce(&DataCallbackMock::Callback), + base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver), true, base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); - RunThreads(); + EXPECT_EQ(2u, items.size()); + EXPECT_EQ(ComponentState::kChecking, items[0].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[0].id.c_str()); + EXPECT_EQ(ComponentState::kUpToDate, items[1].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[1].id.c_str()); + update_client->RemoveObserver(&observer); } @@ -543,16 +568,39 @@ TEST_F(UpdateClientTest, TwoCrxUpdateNoUpdate) { "abagagagagagagagagagagagagagagag")).Times(1); } - update_client->AddObserver(&observer); + std::vector<CrxUpdateItem> items; + auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>(); + EXPECT_CALL(*receiver, Receive(_)) + .WillRepeatedly( + [&items](const CrxUpdateItem& item) { items.push_back(item); }); + update_client->AddObserver(&observer); const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf", "abagagagagagagagagagagagagagagag"}; update_client->Update( - ids, base::BindOnce(&DataCallbackMock::Callback), false, - base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); - + ids, base::BindOnce(&DataCallbackMock::Callback), + base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver), + false, base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); RunThreads(); + EXPECT_EQ(8u, items.size()); + EXPECT_EQ(ComponentState::kChecking, items[0].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[0].id.c_str()); + EXPECT_EQ(ComponentState::kChecking, items[1].state); + EXPECT_STREQ("abagagagagagagagagagagagagagagag", items[1].id.c_str()); + EXPECT_EQ(ComponentState::kCanUpdate, items[2].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[2].id.c_str()); + EXPECT_EQ(ComponentState::kDownloading, items[3].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[3].id.c_str()); + EXPECT_EQ(ComponentState::kDownloading, items[4].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[4].id.c_str()); + EXPECT_EQ(ComponentState::kUpdating, items[5].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[5].id.c_str()); + EXPECT_EQ(ComponentState::kUpdated, items[6].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[6].id.c_str()); + EXPECT_EQ(ComponentState::kUpToDate, items[7].state); + EXPECT_STREQ("abagagagagagagagagagagagagagagag", items[7].id.c_str()); + update_client->RemoveObserver(&observer); } @@ -758,16 +806,39 @@ TEST_F(UpdateClientTest, TwoCrxUpdateFirstServerIgnoresSecond) { })); } - update_client->AddObserver(&observer); + std::vector<CrxUpdateItem> items; + auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>(); + EXPECT_CALL(*receiver, Receive(_)) + .WillRepeatedly( + [&items](const CrxUpdateItem& item) { items.push_back(item); }); + update_client->AddObserver(&observer); const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf", "abagagagagagagagagagagagagagagag"}; update_client->Update( - ids, base::BindOnce(&DataCallbackMock::Callback), false, - base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); - + ids, base::BindOnce(&DataCallbackMock::Callback), + base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver), + false, base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); RunThreads(); + EXPECT_EQ(8u, items.size()); + EXPECT_EQ(ComponentState::kChecking, items[0].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[0].id.c_str()); + EXPECT_EQ(ComponentState::kChecking, items[1].state); + EXPECT_STREQ("abagagagagagagagagagagagagagagag", items[1].id.c_str()); + EXPECT_EQ(ComponentState::kCanUpdate, items[2].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[2].id.c_str()); + EXPECT_EQ(ComponentState::kDownloading, items[3].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[3].id.c_str()); + EXPECT_EQ(ComponentState::kDownloading, items[4].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[4].id.c_str()); + EXPECT_EQ(ComponentState::kUpdating, items[5].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[5].id.c_str()); + EXPECT_EQ(ComponentState::kUpdated, items[6].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[6].id.c_str()); + EXPECT_EQ(ComponentState::kUpdateError, items[7].state); + EXPECT_STREQ("abagagagagagagagagagagagagagagag", items[7].id.c_str()); + update_client->RemoveObserver(&observer); } @@ -955,16 +1026,37 @@ TEST_F(UpdateClientTest, TwoCrxUpdateNoCrxComponentData) { .Times(1); } - update_client->AddObserver(&observer); + std::vector<CrxUpdateItem> items; + auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>(); + EXPECT_CALL(*receiver, Receive(_)) + .WillRepeatedly( + [&items](const CrxUpdateItem& item) { items.push_back(item); }); + update_client->AddObserver(&observer); const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf", "ihfokbkgjpifnbbojhneepfflplebdkc"}; update_client->Update( - ids, base::BindOnce(&DataCallbackMock::Callback), false, - base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); - + ids, base::BindOnce(&DataCallbackMock::Callback), + base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver), + false, base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); RunThreads(); + EXPECT_EQ(7u, items.size()); + EXPECT_EQ(ComponentState::kChecking, items[0].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[0].id.c_str()); + EXPECT_EQ(ComponentState::kUpdateError, items[1].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[1].id.c_str()); + EXPECT_EQ(ComponentState::kCanUpdate, items[2].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[2].id.c_str()); + EXPECT_EQ(ComponentState::kDownloading, items[3].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[3].id.c_str()); + EXPECT_EQ(ComponentState::kDownloading, items[4].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[4].id.c_str()); + EXPECT_EQ(ComponentState::kUpdating, items[5].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[5].id.c_str()); + EXPECT_EQ(ComponentState::kUpdated, items[6].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[6].id.c_str()); + update_client->RemoveObserver(&observer); } @@ -1048,16 +1140,27 @@ TEST_F(UpdateClientTest, TwoCrxUpdateNoCrxComponentDataAtAll) { .Times(1); } - update_client->AddObserver(&observer); + std::vector<CrxUpdateItem> items; + auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>(); + EXPECT_CALL(*receiver, Receive(_)) + .WillRepeatedly( + [&items](const CrxUpdateItem& item) { items.push_back(item); }); + update_client->AddObserver(&observer); const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf", "ihfokbkgjpifnbbojhneepfflplebdkc"}; update_client->Update( - ids, base::BindOnce(&DataCallbackMock::Callback), false, - base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); - + ids, base::BindOnce(&DataCallbackMock::Callback), + base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver), + false, base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); RunThreads(); + EXPECT_EQ(2u, items.size()); + EXPECT_EQ(ComponentState::kUpdateError, items[0].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[0].id.c_str()); + EXPECT_EQ(ComponentState::kUpdateError, items[1].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[1].id.c_str()); + update_client->RemoveObserver(&observer); } @@ -1317,17 +1420,45 @@ TEST_F(UpdateClientTest, TwoCrxUpdateDownloadTimeout) { "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); } - update_client->AddObserver(&observer); + std::vector<CrxUpdateItem> items; + auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>(); + EXPECT_CALL(*receiver, Receive(_)) + .WillRepeatedly( + [&items](const CrxUpdateItem& item) { items.push_back(item); }); + update_client->AddObserver(&observer); const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf", "ihfokbkgjpifnbbojhneepfflplebdkc"}; - update_client->Update( - ids, base::BindOnce(&DataCallbackMock::Callback), false, - base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); - + ids, base::BindOnce(&DataCallbackMock::Callback), + base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver), + false, base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); RunThreads(); + EXPECT_EQ(11u, items.size()); + EXPECT_EQ(ComponentState::kChecking, items[0].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[0].id.c_str()); + EXPECT_EQ(ComponentState::kChecking, items[1].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[1].id.c_str()); + EXPECT_EQ(ComponentState::kCanUpdate, items[2].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[2].id.c_str()); + EXPECT_EQ(ComponentState::kDownloading, items[3].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[3].id.c_str()); + EXPECT_EQ(ComponentState::kDownloading, items[4].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[4].id.c_str()); + EXPECT_EQ(ComponentState::kUpdateError, items[5].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[5].id.c_str()); + EXPECT_EQ(ComponentState::kCanUpdate, items[6].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[6].id.c_str()); + EXPECT_EQ(ComponentState::kDownloading, items[7].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[7].id.c_str()); + EXPECT_EQ(ComponentState::kDownloading, items[8].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[8].id.c_str()); + EXPECT_EQ(ComponentState::kUpdating, items[9].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[9].id.c_str()); + EXPECT_EQ(ComponentState::kUpdated, items[10].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[10].id.c_str()); + update_client->RemoveObserver(&observer); } @@ -1603,24 +1734,67 @@ TEST_F(UpdateClientTest, OneCrxDiffUpdate) { } update_client->AddObserver(&observer); - const std::vector<std::string> ids = {"ihfokbkgjpifnbbojhneepfflplebdkc"}; { + std::vector<CrxUpdateItem> items; + auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>(); + EXPECT_CALL(*receiver, Receive(_)) + .WillRepeatedly( + [&items](const CrxUpdateItem& item) { items.push_back(item); }); + base::RunLoop runloop; - update_client->Update(ids, base::BindOnce(&DataCallbackMock::Callback), - false, - base::BindOnce(&CompletionCallbackMock::Callback, - runloop.QuitClosure())); + update_client->Update( + ids, base::BindOnce(&DataCallbackMock::Callback), + base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver), + false, + base::BindOnce(&CompletionCallbackMock::Callback, + runloop.QuitClosure())); runloop.Run(); + + EXPECT_EQ(6u, items.size()); + EXPECT_EQ(ComponentState::kChecking, items[0].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[0].id.c_str()); + EXPECT_EQ(ComponentState::kCanUpdate, items[1].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[1].id.c_str()); + EXPECT_EQ(ComponentState::kDownloading, items[2].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[2].id.c_str()); + EXPECT_EQ(ComponentState::kDownloading, items[3].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[3].id.c_str()); + EXPECT_EQ(ComponentState::kUpdating, items[4].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[4].id.c_str()); + EXPECT_EQ(ComponentState::kUpdated, items[5].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[5].id.c_str()); } { + std::vector<CrxUpdateItem> items; + auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>(); + EXPECT_CALL(*receiver, Receive(_)) + .WillRepeatedly( + [&items](const CrxUpdateItem& item) { items.push_back(item); }); + base::RunLoop runloop; - update_client->Update(ids, base::BindOnce(&DataCallbackMock::Callback), - false, - base::BindOnce(&CompletionCallbackMock::Callback, - runloop.QuitClosure())); + update_client->Update( + ids, base::BindOnce(&DataCallbackMock::Callback), + base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver), + false, + base::BindOnce(&CompletionCallbackMock::Callback, + runloop.QuitClosure())); runloop.Run(); + + EXPECT_EQ(6u, items.size()); + EXPECT_EQ(ComponentState::kChecking, items[0].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[0].id.c_str()); + EXPECT_EQ(ComponentState::kCanUpdate, items[1].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[1].id.c_str()); + EXPECT_EQ(ComponentState::kDownloadingDiff, items[2].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[2].id.c_str()); + EXPECT_EQ(ComponentState::kDownloadingDiff, items[3].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[3].id.c_str()); + EXPECT_EQ(ComponentState::kUpdatingDiff, items[4].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[4].id.c_str()); + EXPECT_EQ(ComponentState::kUpdated, items[5].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[5].id.c_str()); } update_client->RemoveObserver(&observer); @@ -1643,13 +1817,14 @@ TEST_F(UpdateClientTest, OneCrxInstallError) { void Install(const base::FilePath& unpack_path, const std::string& public_key, + std::unique_ptr<InstallParams> /*install_params*/, Callback callback) override { DoInstall(unpack_path, std::move(callback)); unpack_path_ = unpack_path; EXPECT_TRUE(base::DirectoryExists(unpack_path_)); - base::PostTask( - FROM_HERE, {base::ThreadPool(), base::MayBlock()}, + base::ThreadPool::PostTask( + FROM_HERE, {base::MayBlock()}, base::BindOnce(std::move(callback), CrxInstaller::Result(InstallError::GENERIC_ERROR))); } @@ -1840,15 +2015,34 @@ TEST_F(UpdateClientTest, OneCrxInstallError) { .Times(1); } - update_client->AddObserver(&observer); + std::vector<CrxUpdateItem> items; + auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>(); + EXPECT_CALL(*receiver, Receive(_)) + .WillRepeatedly( + [&items](const CrxUpdateItem& item) { items.push_back(item); }); + update_client->AddObserver(&observer); std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf"}; update_client->Update( - ids, base::BindOnce(&DataCallbackMock::Callback), false, - base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); - + ids, base::BindOnce(&DataCallbackMock::Callback), + base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver), + false, base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); RunThreads(); + EXPECT_EQ(6u, items.size()); + EXPECT_EQ(ComponentState::kChecking, items[0].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[0].id.c_str()); + EXPECT_EQ(ComponentState::kCanUpdate, items[1].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[1].id.c_str()); + EXPECT_EQ(ComponentState::kDownloading, items[2].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[2].id.c_str()); + EXPECT_EQ(ComponentState::kDownloading, items[3].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[3].id.c_str()); + EXPECT_EQ(ComponentState::kUpdating, items[4].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[4].id.c_str()); + EXPECT_EQ(ComponentState::kUpdateError, items[5].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[5].id.c_str()); + update_client->RemoveObserver(&observer); } @@ -2141,21 +2335,68 @@ TEST_F(UpdateClientTest, OneCrxDiffUpdateFailsFullUpdateSucceeds) { const std::vector<std::string> ids = {"ihfokbkgjpifnbbojhneepfflplebdkc"}; { + std::vector<CrxUpdateItem> items; + auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>(); + EXPECT_CALL(*receiver, Receive(_)) + .WillRepeatedly( + [&items](const CrxUpdateItem& item) { items.push_back(item); }); + base::RunLoop runloop; - update_client->Update(ids, base::BindOnce(&DataCallbackMock::Callback), - false, - base::BindOnce(&CompletionCallbackMock::Callback, - runloop.QuitClosure())); + update_client->Update( + ids, base::BindOnce(&DataCallbackMock::Callback), + base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver), + false, + base::BindOnce(&CompletionCallbackMock::Callback, + runloop.QuitClosure())); runloop.Run(); + EXPECT_EQ(6u, items.size()); + EXPECT_EQ(ComponentState::kChecking, items[0].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[0].id.c_str()); + EXPECT_EQ(ComponentState::kCanUpdate, items[1].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[1].id.c_str()); + EXPECT_EQ(ComponentState::kDownloading, items[2].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[2].id.c_str()); + EXPECT_EQ(ComponentState::kDownloading, items[3].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[3].id.c_str()); + EXPECT_EQ(ComponentState::kUpdating, items[4].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[4].id.c_str()); + EXPECT_EQ(ComponentState::kUpdated, items[5].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[5].id.c_str()); } { + std::vector<CrxUpdateItem> items; + auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>(); + EXPECT_CALL(*receiver, Receive(_)) + .WillRepeatedly( + [&items](const CrxUpdateItem& item) { items.push_back(item); }); + base::RunLoop runloop; - update_client->Update(ids, base::BindOnce(&DataCallbackMock::Callback), - false, - base::BindOnce(&CompletionCallbackMock::Callback, - runloop.QuitClosure())); + update_client->Update( + ids, base::BindOnce(&DataCallbackMock::Callback), + base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver), + false, + base::BindOnce(&CompletionCallbackMock::Callback, + runloop.QuitClosure())); runloop.Run(); + + EXPECT_EQ(8u, items.size()); + EXPECT_EQ(ComponentState::kChecking, items[0].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[0].id.c_str()); + EXPECT_EQ(ComponentState::kCanUpdate, items[1].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[1].id.c_str()); + EXPECT_EQ(ComponentState::kDownloadingDiff, items[2].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[2].id.c_str()); + EXPECT_EQ(ComponentState::kDownloadingDiff, items[3].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[3].id.c_str()); + EXPECT_EQ(ComponentState::kDownloading, items[4].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[4].id.c_str()); + EXPECT_EQ(ComponentState::kDownloading, items[5].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[5].id.c_str()); + EXPECT_EQ(ComponentState::kUpdating, items[6].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[6].id.c_str()); + EXPECT_EQ(ComponentState::kUpdated, items[7].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[7].id.c_str()); } update_client->RemoveObserver(&observer); @@ -2259,32 +2500,64 @@ TEST_F(UpdateClientTest, OneCrxNoUpdateQueuedCall) { &MockUpdateChecker::Create, &MockCrxDownloader::Create); MockObserver observer; - InSequence seq; - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + { + InSequence seq; + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, + "jebgalgnebhfojomionfpkfelancnnkf")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "jebgalgnebhfojomionfpkfelancnnkf")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, + "jebgalgnebhfojomionfpkfelancnnkf")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "jebgalgnebhfojomionfpkfelancnnkf")) + .Times(1); + } - update_client->AddObserver(&observer); + std::vector<CrxUpdateItem> items1; + auto receiver1 = base::MakeRefCounted<MockCrxStateChangeReceiver>(); + EXPECT_CALL(*receiver1, Receive(_)) + .WillRepeatedly( + [&items1](const CrxUpdateItem& item) { items1.push_back(item); }); + std::vector<CrxUpdateItem> items2; + auto receiver2 = base::MakeRefCounted<MockCrxStateChangeReceiver>(); + EXPECT_CALL(*receiver2, Receive(_)) + .WillRepeatedly( + [&items2](const CrxUpdateItem& item) { items2.push_back(item); }); + + update_client->AddObserver(&observer); const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf"}; update_client->Update( - ids, base::BindOnce(&DataCallbackMock::Callback), false, - base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); + ids, base::BindOnce(&DataCallbackMock::Callback), + base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver1), + false, base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); update_client->Update( - ids, base::BindOnce(&DataCallbackMock::Callback), false, - base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); - + ids, base::BindOnce(&DataCallbackMock::Callback), + base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver2), + false, base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); RunThreads(); + EXPECT_EQ(2u, items1.size()); + EXPECT_EQ(ComponentState::kChecking, items1[0].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items1[0].id.c_str()); + EXPECT_EQ(ComponentState::kUpToDate, items1[1].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items1[1].id.c_str()); + + EXPECT_EQ(2u, items2.size()); + EXPECT_EQ(ComponentState::kChecking, items2[0].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items2[0].id.c_str()); + EXPECT_EQ(ComponentState::kUpToDate, items2[1].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items2[1].id.c_str()); + update_client->RemoveObserver(&observer); } -// Tests the install of one CRX. +// Tests the install of one CRX. Tests the installer is invoked with the +// run and arguments values of the manifest object. Tests that "pv" and "fp" +// are persisted. TEST_F(UpdateClientTest, OneCrxInstall) { class DataCallbackMock { public: @@ -2333,7 +2606,8 @@ TEST_F(UpdateClientTest, OneCrxInstall) { <urls> <url codebase='http://localhost/download/'/> </urls> - <manifest version='1.0' prodversionmin='11.0.1.0'> + <manifest version='1.0' prodversionmin='11.0.1.0' + run='UpdaterSetup.exe' arguments='--arg1 --arg2'> <packages> <package name='jebgalgnebhfojomionfpkfelancnnkf.crx' hash_sha256='7ab32f071cd9b5ef8e0d7913be161f532d98b3e9f @@ -2356,6 +2630,7 @@ TEST_F(UpdateClientTest, OneCrxInstall) { package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx"; package.hash_sha256 = "7ab32f071cd9b5ef8e0d7913be161f532d98b3e9fa284a7cd8059c3409ce0498"; + package.fingerprint = "some-fingerprint"; ProtocolParser::Result result; result.extension_id = id; @@ -2363,6 +2638,8 @@ TEST_F(UpdateClientTest, OneCrxInstall) { result.crx_urls.push_back(GURL("http://localhost/download/")); result.manifest.version = "1.0"; result.manifest.browser_min_version = "11.0.1.0"; + result.manifest.run = "UpdaterSetup.exe"; + result.manifest.arguments = "--arg1 --arg2"; result.manifest.packages.push_back(package); ProtocolParser::Results results; @@ -2441,30 +2718,81 @@ TEST_F(UpdateClientTest, OneCrxInstall) { base::MakeRefCounted<UpdateClientImpl>( config(), base::MakeRefCounted<MockPingManager>(config()), &MockUpdateChecker::Create, &MockCrxDownloader::Create); + { + EXPECT_FALSE(config()->GetPrefService()->FindPreference( + "updateclientdata.apps.jebgalgnebhfojomionfpkfelancnnkf.pv")); + EXPECT_FALSE(config()->GetPrefService()->FindPreference( + "updateclientdata.apps.jebgalgnebhfojomionfpkfelancnnkf.fp")); + } MockObserver observer; - InSequence seq; - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, - "jebgalgnebhfojomionfpkfelancnnkf")) - .Times(AtLeast(1)); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + { + InSequence seq; + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, + "jebgalgnebhfojomionfpkfelancnnkf")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND, + "jebgalgnebhfojomionfpkfelancnnkf")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, + "jebgalgnebhfojomionfpkfelancnnkf")) + .Times(AtLeast(1)); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, + "jebgalgnebhfojomionfpkfelancnnkf")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED, + "jebgalgnebhfojomionfpkfelancnnkf")) + .Times(1) + .WillOnce(Invoke([update_client](Events event, const std::string& id) { + CrxUpdateItem update_item; + ASSERT_TRUE(update_client->GetCrxUpdateState(id, &update_item)); + ASSERT_TRUE(update_item.component); + const auto* test_installer = static_cast<TestInstaller*>( + update_item.component->installer.get()); + EXPECT_STREQ("UpdaterSetup.exe", + test_installer->install_params()->run.c_str()); + EXPECT_STREQ("--arg1 --arg2", + test_installer->install_params()->arguments.c_str()); + })); + } - update_client->AddObserver(&observer); + std::vector<CrxUpdateItem> items; + auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>(); + EXPECT_CALL(*receiver, Receive(_)) + .WillRepeatedly( + [&items](const CrxUpdateItem& item) { items.push_back(item); }); + update_client->AddObserver(&observer); update_client->Install( std::string("jebgalgnebhfojomionfpkfelancnnkf"), base::BindOnce(&DataCallbackMock::Callback), + base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver), base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); - RunThreads(); + EXPECT_EQ(6u, items.size()); + EXPECT_EQ(ComponentState::kChecking, items[0].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[0].id.c_str()); + EXPECT_EQ(ComponentState::kCanUpdate, items[1].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[1].id.c_str()); + EXPECT_EQ(ComponentState::kDownloading, items[2].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[2].id.c_str()); + EXPECT_EQ(ComponentState::kDownloading, items[3].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[3].id.c_str()); + EXPECT_EQ(ComponentState::kUpdating, items[4].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[4].id.c_str()); + EXPECT_EQ(ComponentState::kUpdated, items[5].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[5].id.c_str()); + + const base::DictionaryValue* dict = + config()->GetPrefService()->GetDictionary("updateclientdata"); + std::string pv; + dict->GetString("apps.jebgalgnebhfojomionfpkfelancnnkf.pv", &pv); + EXPECT_STREQ("1.0", pv.c_str()); + std::string fingerprint; + dict->GetString("apps.jebgalgnebhfojomionfpkfelancnnkf.fp", &fingerprint); + EXPECT_STREQ("some-fingerprint", fingerprint.c_str()); + update_client->RemoveObserver(&observer); } @@ -2537,33 +2865,44 @@ TEST_F(UpdateClientTest, OneCrxInstallNoCrxComponentData) { &MockUpdateChecker::Create, &MockCrxDownloader::Create); MockObserver observer; - InSequence seq; - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR, - "jebgalgnebhfojomionfpkfelancnnkf")) - .Times(1) - .WillOnce(Invoke([&update_client](Events event, const std::string& id) { - // Tests that the state of the component when the CrxComponent data - // is not provided. In this case, the optional |item.component| instance - // is not present. - CrxUpdateItem item; - EXPECT_TRUE(update_client->GetCrxUpdateState(id, &item)); - EXPECT_EQ(ComponentState::kUpdateError, item.state); - EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", item.id.c_str()); - EXPECT_FALSE(item.component); - EXPECT_EQ(ErrorCategory::kService, item.error_category); - EXPECT_EQ(static_cast<int>(Error::CRX_NOT_FOUND), item.error_code); - EXPECT_EQ(0, item.extra_code1); - })); + { + InSequence seq; + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR, + "jebgalgnebhfojomionfpkfelancnnkf")) + .Times(1) + .WillOnce(Invoke([&update_client](Events event, const std::string& id) { + // Tests that the state of the component when the CrxComponent data + // is not provided. In this case, the optional |item.component| + // instance is not present. + CrxUpdateItem item; + EXPECT_TRUE(update_client->GetCrxUpdateState(id, &item)); + EXPECT_EQ(ComponentState::kUpdateError, item.state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", item.id.c_str()); + EXPECT_FALSE(item.component); + EXPECT_EQ(ErrorCategory::kService, item.error_category); + EXPECT_EQ(static_cast<int>(Error::CRX_NOT_FOUND), item.error_code); + EXPECT_EQ(0, item.extra_code1); + })); + } - update_client->AddObserver(&observer); + std::vector<CrxUpdateItem> items; + auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>(); + EXPECT_CALL(*receiver, Receive(_)) + .WillRepeatedly( + [&items](const CrxUpdateItem& item) { items.push_back(item); }); + update_client->AddObserver(&observer); update_client->Install( std::string("jebgalgnebhfojomionfpkfelancnnkf"), base::BindOnce(&DataCallbackMock::Callback), + base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver), base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); - RunThreads(); + EXPECT_EQ(1u, items.size()); + EXPECT_EQ(ComponentState::kUpdateError, items[0].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[0].id.c_str()); + update_client->RemoveObserver(&observer); } @@ -2676,20 +3015,39 @@ TEST_F(UpdateClientTest, ConcurrentInstallSameCRX) { "jebgalgnebhfojomionfpkfelancnnkf")) .Times(1); - update_client->AddObserver(&observer); + std::vector<CrxUpdateItem> items1; + auto receiver1 = base::MakeRefCounted<MockCrxStateChangeReceiver>(); + EXPECT_CALL(*receiver1, Receive(_)) + .WillRepeatedly( + [&items1](const CrxUpdateItem& item) { items1.push_back(item); }); + + std::vector<CrxUpdateItem> items2; + auto receiver2 = base::MakeRefCounted<MockCrxStateChangeReceiver>(); + EXPECT_CALL(*receiver2, Receive(_)) + .WillRepeatedly( + [&items2](const CrxUpdateItem& item) { items2.push_back(item); }); + update_client->AddObserver(&observer); update_client->Install( std::string("jebgalgnebhfojomionfpkfelancnnkf"), base::BindOnce(&DataCallbackMock::Callback), + base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver1), base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); - update_client->Install( std::string("jebgalgnebhfojomionfpkfelancnnkf"), base::BindOnce(&DataCallbackMock::Callback), + base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver2), base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); - RunThreads(); + EXPECT_EQ(2u, items1.size()); + EXPECT_EQ(ComponentState::kChecking, items1[0].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items1[0].id.c_str()); + EXPECT_EQ(ComponentState::kUpToDate, items1[1].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items1[1].id.c_str()); + + EXPECT_TRUE(items2.empty()); + update_client->RemoveObserver(&observer); } @@ -2707,7 +3065,7 @@ TEST_F(UpdateClientTest, EmptyIdList) { class CompletionCallbackMock { public: static void Callback(base::OnceClosure quit_closure, Error error) { - DCHECK_EQ(Error::INVALID_ARGUMENT, error); + EXPECT_EQ(Error::INVALID_ARGUMENT, error); std::move(quit_closure).Run(); } }; @@ -2761,7 +3119,7 @@ TEST_F(UpdateClientTest, EmptyIdList) { const std::vector<std::string> empty_id_list; update_client->Update( - empty_id_list, base::BindOnce(&DataCallbackMock::Callback), false, + empty_id_list, base::BindOnce(&DataCallbackMock::Callback), {}, false, base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); RunThreads(); } @@ -2803,7 +3161,7 @@ TEST_F(UpdateClientTest, SendUninstallPing) { private: MockCrxDownloader() : CrxDownloader(nullptr) {} - ~MockCrxDownloader() override {} + ~MockCrxDownloader() override = default; void DoStartDownload(const GURL& url) override {} }; @@ -2982,7 +3340,7 @@ TEST_F(UpdateClientTest, RetryAfter) { // The engine handles this Update call but responds with a valid // |retry_after_sec|, which causes subsequent calls to fail. base::RunLoop runloop; - update_client->Update(ids, base::BindOnce(&DataCallbackMock::Callback), + update_client->Update(ids, base::BindOnce(&DataCallbackMock::Callback), {}, false, base::BindOnce(&CompletionCallbackMock::Callback, runloop.QuitClosure())); @@ -2993,7 +3351,7 @@ TEST_F(UpdateClientTest, RetryAfter) { // This call will result in a completion callback invoked with // Error::ERROR_UPDATE_RETRY_LATER. base::RunLoop runloop; - update_client->Update(ids, base::BindOnce(&DataCallbackMock::Callback), + update_client->Update(ids, base::BindOnce(&DataCallbackMock::Callback), {}, false, base::BindOnce(&CompletionCallbackMock::Callback, runloop.QuitClosure())); @@ -3005,7 +3363,7 @@ TEST_F(UpdateClientTest, RetryAfter) { // the value of |retry_after_sec| in the completion callback. base::RunLoop runloop; update_client->Install(std::string("jebgalgnebhfojomionfpkfelancnnkf"), - base::BindOnce(&DataCallbackMock::Callback), + base::BindOnce(&DataCallbackMock::Callback), {}, base::BindOnce(&CompletionCallbackMock::Callback, runloop.QuitClosure())); runloop.Run(); @@ -3014,7 +3372,7 @@ TEST_F(UpdateClientTest, RetryAfter) { { // This call succeeds. base::RunLoop runloop; - update_client->Update(ids, base::BindOnce(&DataCallbackMock::Callback), + update_client->Update(ids, base::BindOnce(&DataCallbackMock::Callback), {}, false, base::BindOnce(&CompletionCallbackMock::Callback, runloop.QuitClosure())); @@ -3272,16 +3630,41 @@ TEST_F(UpdateClientTest, TwoCrxUpdateOneUpdateDisabled) { .Times(1); } - update_client->AddObserver(&observer); + std::vector<CrxUpdateItem> items; + auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>(); + EXPECT_CALL(*receiver, Receive(_)) + .WillRepeatedly( + [&items](const CrxUpdateItem& item) { items.push_back(item); }); + update_client->AddObserver(&observer); const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf", "ihfokbkgjpifnbbojhneepfflplebdkc"}; update_client->Update( - ids, base::BindOnce(&DataCallbackMock::Callback), false, - base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); - + ids, base::BindOnce(&DataCallbackMock::Callback), + base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver), + false, base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); RunThreads(); + EXPECT_EQ(9u, items.size()); + EXPECT_EQ(ComponentState::kChecking, items[0].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[0].id.c_str()); + EXPECT_EQ(ComponentState::kChecking, items[1].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[1].id.c_str()); + EXPECT_EQ(ComponentState::kCanUpdate, items[2].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[2].id.c_str()); + EXPECT_EQ(ComponentState::kUpdateError, items[3].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[3].id.c_str()); + EXPECT_EQ(ComponentState::kCanUpdate, items[4].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[4].id.c_str()); + EXPECT_EQ(ComponentState::kDownloading, items[5].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[5].id.c_str()); + EXPECT_EQ(ComponentState::kDownloading, items[6].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[6].id.c_str()); + EXPECT_EQ(ComponentState::kUpdating, items[7].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[7].id.c_str()); + EXPECT_EQ(ComponentState::kUpdated, items[8].state); + EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[8].id.c_str()); + update_client->RemoveObserver(&observer); } @@ -3366,31 +3749,44 @@ TEST_F(UpdateClientTest, OneCrxUpdateCheckFails) { &MockUpdateChecker::Create, &MockCrxDownloader::Create); MockObserver observer; - InSequence seq; - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, - "jebgalgnebhfojomionfpkfelancnnkf")) - .Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR, - "jebgalgnebhfojomionfpkfelancnnkf")) - .Times(1) - .WillOnce(Invoke([&update_client](Events event, const std::string& id) { - CrxUpdateItem item; - EXPECT_TRUE(update_client->GetCrxUpdateState(id, &item)); - EXPECT_EQ(ComponentState::kUpdateError, item.state); - EXPECT_EQ(5, static_cast<int>(item.error_category)); - EXPECT_EQ(-1, item.error_code); - EXPECT_EQ(0, item.extra_code1); - })); + { + InSequence seq; + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, + "jebgalgnebhfojomionfpkfelancnnkf")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR, + "jebgalgnebhfojomionfpkfelancnnkf")) + .Times(1) + .WillOnce(Invoke([&update_client](Events event, const std::string& id) { + CrxUpdateItem item; + EXPECT_TRUE(update_client->GetCrxUpdateState(id, &item)); + EXPECT_EQ(ComponentState::kUpdateError, item.state); + EXPECT_EQ(5, static_cast<int>(item.error_category)); + EXPECT_EQ(-1, item.error_code); + EXPECT_EQ(0, item.extra_code1); + })); + } - update_client->AddObserver(&observer); + std::vector<CrxUpdateItem> items; + auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>(); + EXPECT_CALL(*receiver, Receive(_)) + .WillRepeatedly( + [&items](const CrxUpdateItem& item) { items.push_back(item); }); + update_client->AddObserver(&observer); const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf"}; update_client->Update( - ids, base::BindOnce(&DataCallbackMock::Callback), false, - base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); - + ids, base::BindOnce(&DataCallbackMock::Callback), + base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver), + false, base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); RunThreads(); + EXPECT_EQ(2u, items.size()); + EXPECT_EQ(ComponentState::kChecking, items[0].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[0].id.c_str()); + EXPECT_EQ(ComponentState::kUpdateError, items[1].state); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[1].id.c_str()); + update_client->RemoveObserver(&observer); } @@ -3598,7 +3994,7 @@ TEST_F(UpdateClientTest, OneCrxErrorUnknownApp) { "jebgalgnebhfojomionfpkfelancnnkf", "abagagagagagagagagagagagagagagag", "ihfokbkgjpifnbbojhneepfflplebdkc", "gjpmebpgbhcamgdgjcmnjfhggjpgcimm"}; update_client->Update( - ids, base::BindOnce(&DataCallbackMock::Callback), true, + ids, base::BindOnce(&DataCallbackMock::Callback), {}, true, base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); RunThreads(); @@ -3788,6 +4184,7 @@ TEST_F(UpdateClientTest, ActionRun_Install) { crx.crx_format_requirement = crx_file::VerifierFormat::CRX3; return std::vector<base::Optional<CrxComponent>>{crx}; }), + {}, base::BindOnce( [](base::OnceClosure quit_closure, Error error) { EXPECT_EQ(Error::NONE, error); @@ -3951,7 +4348,7 @@ TEST_F(UpdateClientTest, ActionRun_NoUpdate) { return std::vector<base::Optional<CrxComponent>>{crx}; }, unpack_path), - false, + {}, false, base::BindOnce( [](base::OnceClosure quit_closure, Error error) { EXPECT_EQ(Error::NONE, error); @@ -3962,4 +4359,132 @@ TEST_F(UpdateClientTest, ActionRun_NoUpdate) { RunThreads(); } +// Tests that custom response attributes are visible to observers. +TEST_F(UpdateClientTest, CustomAttributeNoUpdate) { + class DataCallbackMock { + public: + static std::vector<base::Optional<CrxComponent>> Callback( + const std::vector<std::string>& ids) { + CrxComponent crx; + crx.name = "test_jebg"; + crx.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash)); + crx.version = base::Version("0.9"); + crx.installer = base::MakeRefCounted<TestInstaller>(); + crx.crx_format_requirement = crx_file::VerifierFormat::CRX3; + std::vector<base::Optional<CrxComponent>> component = {crx}; + return component; + } + }; + + class CompletionCallbackMock { + public: + static void Callback(base::OnceClosure quit_closure, Error error) { + EXPECT_EQ(Error::NONE, error); + std::move(quit_closure).Run(); + } + }; + + class MockUpdateChecker : public UpdateChecker { + public: + static std::unique_ptr<UpdateChecker> Create( + scoped_refptr<Configurator> config, + PersistedData* metadata) { + return std::make_unique<MockUpdateChecker>(); + } + + void CheckForUpdates( + const std::string& session_id, + const std::vector<std::string>& ids_to_check, + const IdToComponentPtrMap& components, + const base::flat_map<std::string, std::string>& additional_attributes, + bool enabled_component_updates, + UpdateCheckCallback update_check_callback) override { + EXPECT_FALSE(session_id.empty()); + EXPECT_TRUE(enabled_component_updates); + EXPECT_EQ(1u, ids_to_check.size()); + const std::string id = "jebgalgnebhfojomionfpkfelancnnkf"; + EXPECT_EQ(id, ids_to_check.front()); + EXPECT_EQ(1u, components.count(id)); + + auto& component = components.at(id); + + EXPECT_TRUE(component->is_foreground()); + + ProtocolParser::Result result; + result.extension_id = id; + result.status = "noupdate"; + result.custom_attributes["_example"] = "example_value"; + + ProtocolParser::Results results; + results.list.push_back(result); + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(update_check_callback), results, + ErrorCategory::kNone, 0, 0)); + } + }; + + class MockCrxDownloader : public CrxDownloader { + public: + static std::unique_ptr<CrxDownloader> Create( + bool is_background_download, + scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) { + return std::make_unique<MockCrxDownloader>(); + } + + MockCrxDownloader() : CrxDownloader(nullptr) {} + + private: + void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); } + }; + + class MockPingManager : public MockPingManagerImpl { + public: + explicit MockPingManager(scoped_refptr<Configurator> config) + : MockPingManagerImpl(config) {} + + protected: + ~MockPingManager() override { EXPECT_TRUE(ping_data().empty()); } + }; + + scoped_refptr<UpdateClient> update_client = + base::MakeRefCounted<UpdateClientImpl>( + config(), base::MakeRefCounted<MockPingManager>(config()), + &MockUpdateChecker::Create, &MockCrxDownloader::Create); + + class Observer : public UpdateClient::Observer { + public: + explicit Observer(scoped_refptr<UpdateClient> update_client) + : update_client_(update_client) {} + + void OnEvent(Events event, const std::string& id) override { + if (event != Events::COMPONENT_NOT_UPDATED) + return; + ++calls; + CrxUpdateItem item; + EXPECT_TRUE(update_client_->GetCrxUpdateState( + "jebgalgnebhfojomionfpkfelancnnkf", &item)); + EXPECT_EQ("example_value", item.custom_updatecheck_data["_example"]); + } + + int calls = 0; + + private: + scoped_refptr<UpdateClient> update_client_; + }; + + Observer observer(update_client); + update_client->AddObserver(&observer); + + const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf"}; + update_client->Update( + ids, base::BindOnce(&DataCallbackMock::Callback), {}, true, + base::BindOnce(&CompletionCallbackMock::Callback, quit_closure())); + + RunThreads(); + + update_client->RemoveObserver(&observer); + + EXPECT_EQ(1, observer.calls); +} } // namespace update_client diff --git a/chromium/components/update_client/update_engine.cc b/chromium/components/update_client/update_engine.cc index a6d69208e44..7cb2e47942a 100644 --- a/chromium/components/update_client/update_engine.cc +++ b/chromium/components/update_client/update_engine.cc @@ -33,25 +33,29 @@ UpdateContext::UpdateContext( bool is_foreground, const std::vector<std::string>& ids, UpdateClient::CrxDataCallback crx_data_callback, + UpdateClient::CrxStateChangeCallback crx_state_change_callback, const UpdateEngine::NotifyObserversCallback& notify_observers_callback, UpdateEngine::Callback callback, - CrxDownloader::Factory crx_downloader_factory) + CrxDownloader::Factory crx_downloader_factory, + PersistedData* persisted_data) : config(config), is_foreground(is_foreground), enabled_component_updates(config->EnabledComponentUpdates()), ids(ids), crx_data_callback(std::move(crx_data_callback)), + crx_state_change_callback(crx_state_change_callback), notify_observers_callback(notify_observers_callback), callback(std::move(callback)), crx_downloader_factory(crx_downloader_factory), - session_id(base::StrCat({"{", base::GenerateGUID(), "}"})) { + session_id(base::StrCat({"{", base::GenerateGUID(), "}"})), + persisted_data(persisted_data) { for (const auto& id : ids) { components.insert( std::make_pair(id, std::make_unique<Component>(*this, id))); } } -UpdateContext::~UpdateContext() {} +UpdateContext::~UpdateContext() = default; UpdateEngine::UpdateEngine( scoped_refptr<Configurator> config, @@ -72,10 +76,12 @@ UpdateEngine::~UpdateEngine() { DCHECK(thread_checker_.CalledOnValidThread()); } -void UpdateEngine::Update(bool is_foreground, - const std::vector<std::string>& ids, - UpdateClient::CrxDataCallback crx_data_callback, - Callback callback) { +void UpdateEngine::Update( + bool is_foreground, + const std::vector<std::string>& ids, + UpdateClient::CrxDataCallback crx_data_callback, + UpdateClient::CrxStateChangeCallback crx_state_change_callback, + Callback callback) { DCHECK(thread_checker_.CalledOnValidThread()); if (ids.empty()) { @@ -86,11 +92,6 @@ void UpdateEngine::Update(bool is_foreground, } if (IsThrottled(is_foreground)) { - // TODO(xiaochu): remove this log after https://crbug.com/851151 is fixed. - VLOG(1) << "Background update is throttled for following components:"; - for (const auto& id : ids) { - VLOG(1) << "id:" << id; - } base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(std::move(callback), Error::RETRY_LATER)); return; @@ -98,7 +99,8 @@ void UpdateEngine::Update(bool is_foreground, const auto update_context = base::MakeRefCounted<UpdateContext>( config_, is_foreground, ids, std::move(crx_data_callback), - notify_observers_callback_, std::move(callback), crx_downloader_factory_); + crx_state_change_callback, notify_observers_callback_, + std::move(callback), crx_downloader_factory_, metadata_.get()); DCHECK(!update_context->session_id.empty()); const auto result = update_contexts_.insert( @@ -136,15 +138,15 @@ void UpdateEngine::Update(bool is_foreground, if (update_context->components_to_check_for_updates.empty()) { base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&UpdateEngine::HandleComponent, - base::Unretained(this), update_context)); + FROM_HERE, + base::BindOnce(&UpdateEngine::HandleComponent, this, update_context)); return; } for (const auto& id : update_context->components_to_check_for_updates) update_context->components[id]->Handle( - base::BindOnce(&UpdateEngine::ComponentCheckingForUpdatesStart, - base::Unretained(this), update_context, id)); + base::BindOnce(&UpdateEngine::ComponentCheckingForUpdatesStart, this, + update_context, id)); } void UpdateEngine::ComponentCheckingForUpdatesStart( @@ -159,8 +161,8 @@ void UpdateEngine::ComponentCheckingForUpdatesStart( // Handle |kChecking| state. auto& component = *update_context->components.at(id); component.Handle( - base::BindOnce(&UpdateEngine::ComponentCheckingForUpdatesComplete, - base::Unretained(this), update_context)); + base::BindOnce(&UpdateEngine::ComponentCheckingForUpdatesComplete, this, + update_context)); ++update_context->num_components_ready_to_check; if (update_context->num_components_ready_to_check < @@ -169,8 +171,8 @@ void UpdateEngine::ComponentCheckingForUpdatesStart( } base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&UpdateEngine::DoUpdateCheck, - base::Unretained(this), update_context)); + FROM_HERE, + base::BindOnce(&UpdateEngine::DoUpdateCheck, this, update_context)); } void UpdateEngine::DoUpdateCheck(scoped_refptr<UpdateContext> update_context) { @@ -185,8 +187,8 @@ void UpdateEngine::DoUpdateCheck(scoped_refptr<UpdateContext> update_context) { update_context->components_to_check_for_updates, update_context->components, config_->ExtraRequestParams(), update_context->enabled_component_updates, - base::BindOnce(&UpdateEngine::UpdateCheckResultsAvailable, - base::Unretained(this), update_context)); + base::BindOnce(&UpdateEngine::UpdateCheckResultsAvailable, this, + update_context)); } void UpdateEngine::UpdateCheckResultsAvailable( @@ -277,8 +279,8 @@ void UpdateEngine::ComponentCheckingForUpdatesComplete( } base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&UpdateEngine::UpdateCheckComplete, - base::Unretained(this), update_context)); + FROM_HERE, + base::BindOnce(&UpdateEngine::UpdateCheckComplete, this, update_context)); } void UpdateEngine::UpdateCheckComplete( @@ -290,8 +292,8 @@ void UpdateEngine::UpdateCheckComplete( update_context->component_queue.push(id); base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&UpdateEngine::HandleComponent, - base::Unretained(this), update_context)); + FROM_HERE, + base::BindOnce(&UpdateEngine::HandleComponent, this, update_context)); } void UpdateEngine::HandleComponent( @@ -307,9 +309,8 @@ void UpdateEngine::HandleComponent( : Error::NONE; base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce(&UpdateEngine::UpdateComplete, base::Unretained(this), - update_context, error)); + FROM_HERE, base::BindOnce(&UpdateEngine::UpdateComplete, this, + update_context, error)); return; } @@ -322,18 +323,15 @@ void UpdateEngine::HandleComponent( if (!next_update_delay.is_zero() && component->IsUpdateAvailable()) { base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, - base::BindOnce(&UpdateEngine::HandleComponent, base::Unretained(this), - update_context), + base::BindOnce(&UpdateEngine::HandleComponent, this, update_context), next_update_delay); next_update_delay = base::TimeDelta(); - - notify_observers_callback_.Run( - UpdateClient::Observer::Events::COMPONENT_WAIT, id); + component->NotifyWait(); return; } - component->Handle(base::BindOnce(&UpdateEngine::HandleComponentComplete, - base::Unretained(this), update_context)); + component->Handle(base::BindOnce(&UpdateEngine::HandleComponentComplete, this, + update_context)); } void UpdateEngine::HandleComponentComplete( @@ -361,8 +359,8 @@ void UpdateEngine::HandleComponentComplete( } base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&UpdateEngine::HandleComponent, - base::Unretained(this), update_context)); + FROM_HERE, + base::BindOnce(&UpdateEngine::HandleComponent, this, update_context)); } void UpdateEngine::UpdateComplete(scoped_refptr<UpdateContext> update_context, @@ -413,8 +411,9 @@ void UpdateEngine::SendUninstallPing(const std::string& id, const auto update_context = base::MakeRefCounted<UpdateContext>( config_, false, std::vector<std::string>{id}, - UpdateClient::CrxDataCallback(), UpdateEngine::NotifyObserversCallback(), - std::move(callback), nullptr); + UpdateClient::CrxDataCallback(), UpdateClient::CrxStateChangeCallback(), + UpdateEngine::NotifyObserversCallback(), std::move(callback), nullptr, + metadata_.get()); DCHECK(!update_context->session_id.empty()); const auto result = update_contexts_.insert( @@ -431,8 +430,8 @@ void UpdateEngine::SendUninstallPing(const std::string& id, update_context->component_queue.push(id); base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&UpdateEngine::HandleComponent, - base::Unretained(this), update_context)); + FROM_HERE, + base::BindOnce(&UpdateEngine::HandleComponent, this, update_context)); } } // namespace update_client diff --git a/chromium/components/update_client/update_engine.h b/chromium/components/update_client/update_engine.h index 96018736a9e..cdbfcb85e1c 100644 --- a/chromium/components/update_client/update_engine.h +++ b/chromium/components/update_client/update_engine.h @@ -13,7 +13,6 @@ #include "base/callback.h" #include "base/containers/queue.h" -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/optional.h" #include "base/threading/thread_checker.h" @@ -32,6 +31,7 @@ class TimeTicks; namespace update_client { class Configurator; +class PersistedData; struct UpdateContext; // Handles updates for a group of components. Updates for different groups @@ -41,8 +41,8 @@ class UpdateEngine : public base::RefCounted<UpdateEngine> { public: using Callback = base::OnceCallback<void(Error error)>; using NotifyObserversCallback = - base::Callback<void(UpdateClient::Observer::Events event, - const std::string& id)>; + base::RepeatingCallback<void(UpdateClient::Observer::Events event, + const std::string& id)>; using CrxDataCallback = UpdateClient::CrxDataCallback; UpdateEngine(scoped_refptr<Configurator> config, @@ -50,6 +50,8 @@ class UpdateEngine : public base::RefCounted<UpdateEngine> { CrxDownloader::Factory crx_downloader_factory, scoped_refptr<PingManager> ping_manager, const NotifyObserversCallback& notify_observers_callback); + UpdateEngine(const UpdateEngine&) = delete; + UpdateEngine& operator=(const UpdateEngine&) = delete; // Returns true and the state of the component identified by |id|, if the // component is found in any update context. Returns false if the component @@ -59,6 +61,7 @@ class UpdateEngine : public base::RefCounted<UpdateEngine> { void Update(bool is_foreground, const std::vector<std::string>& ids, UpdateClient::CrxDataCallback crx_data_callback, + UpdateClient::CrxStateChangeCallback crx_state_change_callback, Callback update_callback); void SendUninstallPing(const std::string& id, @@ -114,8 +117,6 @@ class UpdateEngine : public base::RefCounted<UpdateEngine> { // a certain time, which is negotiated with the server as part of the // update protocol. See the comments for X-Retry-After header. base::TimeTicks throttle_updates_until_; - - DISALLOW_COPY_AND_ASSIGN(UpdateEngine); }; // Describes a group of components which are installed or updated together. @@ -125,9 +126,13 @@ struct UpdateContext : public base::RefCounted<UpdateContext> { bool is_foreground, const std::vector<std::string>& ids, UpdateClient::CrxDataCallback crx_data_callback, + UpdateClient::CrxStateChangeCallback crx_state_change_callback, const UpdateEngine::NotifyObserversCallback& notify_observers_callback, UpdateEngine::Callback callback, - CrxDownloader::Factory crx_downloader_factory); + CrxDownloader::Factory crx_downloader_factory, + PersistedData* persisted_data); + UpdateContext(const UpdateContext&) = delete; + UpdateContext& operator=(const UpdateContext&) = delete; scoped_refptr<Configurator> config; @@ -147,6 +152,9 @@ struct UpdateContext : public base::RefCounted<UpdateContext> { // Called before an update check, when update metadata is needed. UpdateEngine::CrxDataCallback crx_data_callback; + // Called when the observable state of the CRX component has changed. + UpdateClient::CrxStateChangeCallback crx_state_change_callback; + // Called when there is a state change for any update in this context. const UpdateEngine::NotifyObserversCallback notify_observers_callback; @@ -189,11 +197,12 @@ struct UpdateContext : public base::RefCounted<UpdateContext> { // to uniquely identify an update context. const std::string session_id; + // Persists data using the prefs service. Not owned by this class. + PersistedData* persisted_data = nullptr; + private: friend class base::RefCounted<UpdateContext>; ~UpdateContext(); - - DISALLOW_COPY_AND_ASSIGN(UpdateContext); }; } // namespace update_client diff --git a/chromium/components/update_client/update_query_params_delegate.cc b/chromium/components/update_client/update_query_params_delegate.cc index e14665adac3..684713f2ebd 100644 --- a/chromium/components/update_client/update_query_params_delegate.cc +++ b/chromium/components/update_client/update_query_params_delegate.cc @@ -6,10 +6,8 @@ namespace update_client { -UpdateQueryParamsDelegate::UpdateQueryParamsDelegate() { -} +UpdateQueryParamsDelegate::UpdateQueryParamsDelegate() = default; -UpdateQueryParamsDelegate::~UpdateQueryParamsDelegate() { -} +UpdateQueryParamsDelegate::~UpdateQueryParamsDelegate() = default; } // namespace update_client diff --git a/chromium/components/update_client/updater_state.cc b/chromium/components/update_client/updater_state.cc index 5d05c8663aa..c3581e41568 100644 --- a/chromium/components/update_client/updater_state.cc +++ b/chromium/components/update_client/updater_state.cc @@ -24,7 +24,7 @@ const char UpdaterState::kIsEnterpriseManaged[] = "domainjoined"; UpdaterState::UpdaterState(bool is_machine) : is_machine_(is_machine) {} -UpdaterState::~UpdaterState() {} +UpdaterState::~UpdaterState() = default; std::unique_ptr<UpdaterState::Attributes> UpdaterState::GetState( bool is_machine) { @@ -84,13 +84,13 @@ UpdaterState::Attributes UpdaterState::BuildAttributes() const { std::string UpdaterState::NormalizeTimeDelta(const base::TimeDelta& delta) { const base::TimeDelta two_weeks = base::TimeDelta::FromDays(14); - const base::TimeDelta two_months = base::TimeDelta::FromDays(60); + const base::TimeDelta two_months = base::TimeDelta::FromDays(56); std::string val; // Contains the value to return in hours. if (delta <= two_weeks) { val = "0"; } else if (two_weeks < delta && delta <= two_months) { - val = "408"; // 2 weeks in hours. + val = "336"; // 2 weeks in hours. } else { val = "1344"; // 2*28 days in hours. } diff --git a/chromium/components/update_client/updater_state_unittest.cc b/chromium/components/update_client/updater_state_unittest.cc index e916adfe352..d8d96b37105 100644 --- a/chromium/components/update_client/updater_state_unittest.cc +++ b/chromium/components/update_client/updater_state_unittest.cc @@ -15,8 +15,8 @@ namespace update_client { class UpdaterStateTest : public testing::Test { public: - UpdaterStateTest() {} - ~UpdaterStateTest() override {} + UpdaterStateTest() = default; + ~UpdaterStateTest() override = default; private: DISALLOW_COPY_AND_ASSIGN(UpdaterStateTest); @@ -75,7 +75,12 @@ TEST_F(UpdaterStateTest, Serialize) { updater_state.last_autoupdate_started_ = base::Time::NowFromSystemTime() - base::TimeDelta::FromDays(15); attributes = updater_state.BuildAttributes(); - EXPECT_STREQ("408", attributes.at("laststarted").c_str()); + EXPECT_STREQ("336", attributes.at("laststarted").c_str()); + + updater_state.last_autoupdate_started_ = + base::Time::NowFromSystemTime() - base::TimeDelta::FromDays(58); + attributes = updater_state.BuildAttributes(); + EXPECT_STREQ("1344", attributes.at("laststarted").c_str()); updater_state.last_autoupdate_started_ = base::Time::NowFromSystemTime() - base::TimeDelta::FromDays(90); @@ -90,7 +95,7 @@ TEST_F(UpdaterStateTest, Serialize) { updater_state.last_checked_ = base::Time::NowFromSystemTime() - base::TimeDelta::FromDays(15); attributes = updater_state.BuildAttributes(); - EXPECT_STREQ("408", attributes.at("lastchecked").c_str()); + EXPECT_STREQ("336", attributes.at("lastchecked").c_str()); updater_state.last_checked_ = base::Time::NowFromSystemTime() - base::TimeDelta::FromDays(90); diff --git a/chromium/components/update_client/url_fetcher_downloader.cc b/chromium/components/update_client/url_fetcher_downloader.cc index ad808ce9f28..8b33cf81a44 100644 --- a/chromium/components/update_client/url_fetcher_downloader.cc +++ b/chromium/components/update_client/url_fetcher_downloader.cc @@ -12,20 +12,12 @@ #include "base/location.h" #include "base/logging.h" #include "base/sequenced_task_runner.h" -#include "base/task/post_task.h" -#include "base/task/task_traits.h" +#include "base/task/thread_pool.h" #include "components/update_client/network.h" +#include "components/update_client/task_traits.h" #include "components/update_client/utils.h" #include "url/gurl.h" -namespace { - -constexpr base::TaskTraits kTaskTraits = { - base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT, - base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}; - -} // namespace - namespace update_client { UrlFetcherDownloader::UrlFetcherDownloader( @@ -40,7 +32,7 @@ UrlFetcherDownloader::~UrlFetcherDownloader() { void UrlFetcherDownloader::DoStartDownload(const GURL& url) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - base::PostTaskAndReply( + base::ThreadPool::PostTaskAndReply( FROM_HERE, kTaskTraits, base::BindOnce(&UrlFetcherDownloader::CreateDownloadDir, base::Unretained(this)), @@ -132,9 +124,10 @@ void UrlFetcherDownloader::OnNetworkFetcherComplete(int net_error, // Delete the download directory in the error cases. if (error && !download_dir_.empty()) { - base::PostTask(FROM_HERE, kTaskTraits, - base::BindOnce(IgnoreResult(&base::DeleteFileRecursively), - download_dir_)); + base::ThreadPool::PostTask( + FROM_HERE, kTaskTraits, + base::BindOnce(IgnoreResult(&base::DeleteFileRecursively), + download_dir_)); } main_task_runner()->PostTask( |