blob: b456f138e6ce1e806cfb856188c1a6df66fe466f [file] [log] [blame]
Yavor Goulishev9c08e842020-04-29 14:03:33 -07001// Copyright 2017 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "components/update_client/action_runner.h"
6
7#include <iterator>
8#include <stack>
9#include <utility>
10
11#include "base/bind.h"
12#include "base/command_line.h"
13#include "base/files/file_enumerator.h"
14#include "base/files/file_util.h"
15#include "base/location.h"
16#include "base/logging.h"
Kaido Kert25902c62024-06-17 17:10:28 -070017#include "base/task/sequenced_task_runner.h"
18#include "base/task/thread_pool.h"
Yavor Goulishev9c08e842020-04-29 14:03:33 -070019#include "base/threading/thread_task_runner_handle.h"
20#include "build/build_config.h"
21#include "components/crx_file/crx_verifier.h"
22#include "components/update_client/component.h"
23#include "components/update_client/configurator.h"
24#include "components/update_client/patcher.h"
25#include "components/update_client/task_traits.h"
26#include "components/update_client/unzipper.h"
27#include "components/update_client/update_client.h"
28#include "components/update_client/update_engine.h"
29
30namespace {
31
Kaido Kert72bde072021-03-12 15:55:15 -080032#if defined(STARBOARD)
Yavor Goulishev9c08e842020-04-29 14:03:33 -070033void CleanupDirectory(base::FilePath& dir) {
34 std::stack<std::string> directories;
35 base::FileEnumerator file_enumerator(
36 dir, true,
37 base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
38 for (auto path = file_enumerator.Next(); !path.value().empty();
39 path = file_enumerator.Next()) {
40 base::FileEnumerator::FileInfo info(file_enumerator.GetInfo());
41
42 if (info.IsDirectory()) {
43 directories.push(path.value());
44 } else {
45 SbFileDelete(path.value().c_str());
46 }
47 }
48 while (!directories.empty()) {
49 SbFileDelete(directories.top().c_str());
50 directories.pop();
51 }
52}
53#endif
54
55} // namespace
56
57namespace update_client {
58
59ActionRunner::ActionRunner(const Component& component)
60 : is_per_user_install_(component.config()->IsPerUserInstall()),
61 component_(component),
Kaido Kert25902c62024-06-17 17:10:28 -070062 main_task_runner_(base::SequencedTaskRunner::GetCurrentDefault()) {}
Yavor Goulishev9c08e842020-04-29 14:03:33 -070063
64ActionRunner::~ActionRunner() {
Kaido Kert25902c62024-06-17 17:10:28 -070065 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Yavor Goulishev9c08e842020-04-29 14:03:33 -070066}
67
68void ActionRunner::Run(Callback run_complete) {
Kaido Kert25902c62024-06-17 17:10:28 -070069 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Yavor Goulishev9c08e842020-04-29 14:03:33 -070070
71 run_complete_ = std::move(run_complete);
72
Kaido Kert25902c62024-06-17 17:10:28 -070073 base::ThreadPool::CreateSequencedTaskRunner(kTaskTraits)
Yavor Goulishev9c08e842020-04-29 14:03:33 -070074 ->PostTask(
75 FROM_HERE,
76 base::BindOnce(&ActionRunner::RunOnTaskRunner, base::Unretained(this),
77 component_.config()->GetUnzipperFactory()->Create(),
78 component_.config()->GetPatcherFactory()->Create()));
79}
80
81void ActionRunner::RunOnTaskRunner(std::unique_ptr<Unzipper> unzip,
82 scoped_refptr<Patcher> patch) {
83 const auto installer = component_.crx_component()->installer;
84
85 base::FilePath crx_path;
86 installer->GetInstalledFile(component_.action_run(), &crx_path);
87
88 if (!is_per_user_install_) {
89 RunRecoveryCRXElevated(std::move(crx_path));
90 return;
91 }
92
93 const auto config = component_.config();
Kaido Kerte51ce0a2023-08-12 21:43:21 -070094
95#if defined(IN_MEMORY_UPDATES)
96 // TODO(hwarriner): see if we need to support this code path in Cobalt.
97 CHECK(false);
98#else
Yavor Goulishev9c08e842020-04-29 14:03:33 -070099 auto unpacker = base::MakeRefCounted<ComponentUnpacker>(
100 config->GetRunActionKeyHash(), crx_path, installer, std::move(unzip),
101 std::move(patch), component_.crx_component()->crx_format_requirement);
102 unpacker->Unpack(
103 base::BindOnce(&ActionRunner::UnpackComplete, base::Unretained(this)));
Kaido Kerte51ce0a2023-08-12 21:43:21 -0700104#endif
Yavor Goulishev9c08e842020-04-29 14:03:33 -0700105}
106
107void ActionRunner::UnpackComplete(const ComponentUnpacker::Result& result) {
108 if (result.error != UnpackerError::kNone) {
109 DCHECK(!base::DirectoryExists(result.unpack_path));
110
111 main_task_runner_->PostTask(
112 FROM_HERE,
113 base::BindOnce(std::move(run_complete_), false,
114 static_cast<int>(result.error), result.extended_error));
115 return;
116 }
117
118 unpack_path_ = result.unpack_path;
Kaido Kert25902c62024-06-17 17:10:28 -0700119 base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
Yavor Goulishev9c08e842020-04-29 14:03:33 -0700120 FROM_HERE,
121 base::BindOnce(&ActionRunner::RunCommand, base::Unretained(this),
122 MakeCommandLine(result.unpack_path)));
123}
124
125#if !defined(OS_WIN)
126
127void ActionRunner::RunRecoveryCRXElevated(const base::FilePath& crx_path) {
128 NOTREACHED();
129}
130
131void ActionRunner::RunCommand(const base::CommandLine& cmdline) {
Kaido Kert72bde072021-03-12 15:55:15 -0800132#if defined(STARBOARD)
Yavor Goulishev9c08e842020-04-29 14:03:33 -0700133 CleanupDirectory(unpack_path_);
134#else
135 base::DeleteFile(unpack_path_, true);
136#endif
137 main_task_runner_->PostTask(
138 FROM_HERE, base::BindOnce(std::move(run_complete_), false, -1, 0));
139}
140
141base::CommandLine ActionRunner::MakeCommandLine(
142 const base::FilePath& unpack_path) const {
143 return base::CommandLine(base::CommandLine::NO_PROGRAM);
144}
145
146#endif // OS_WIN
147
148} // namespace update_client