component.cc 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174
  1. // 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. #include "components/update_client/component.h"
  5. #include <algorithm>
  6. #include <tuple>
  7. #include <utility>
  8. #include <vector>
  9. #include "base/bind.h"
  10. #include "base/callback.h"
  11. #include "base/callback_helpers.h"
  12. #include "base/check_op.h"
  13. #include "base/files/file_util.h"
  14. #include "base/files/scoped_temp_dir.h"
  15. #include "base/location.h"
  16. #include "base/logging.h"
  17. #include "base/notreached.h"
  18. #include "base/strings/string_number_conversions.h"
  19. #include "base/task/thread_pool.h"
  20. #include "base/threading/sequenced_task_runner_handle.h"
  21. #include "base/values.h"
  22. #include "components/update_client/action_runner.h"
  23. #include "components/update_client/component_unpacker.h"
  24. #include "components/update_client/configurator.h"
  25. #include "components/update_client/crx_downloader_factory.h"
  26. #include "components/update_client/network.h"
  27. #include "components/update_client/patcher.h"
  28. #include "components/update_client/persisted_data.h"
  29. #include "components/update_client/protocol_definition.h"
  30. #include "components/update_client/protocol_serializer.h"
  31. #include "components/update_client/task_traits.h"
  32. #include "components/update_client/unzipper.h"
  33. #include "components/update_client/update_client.h"
  34. #include "components/update_client/update_client_errors.h"
  35. #include "components/update_client/update_engine.h"
  36. #include "components/update_client/utils.h"
  37. // The state machine representing how a CRX component changes during an update.
  38. //
  39. // +------------------------- kNew
  40. // | |
  41. // | V
  42. // | kChecking
  43. // | |
  44. // V error V no no
  45. // kUpdateError <------------- [update?] -> [action?] -> kUpToDate kUpdated
  46. // ^ | | ^ ^
  47. // | yes | | yes | |
  48. // | update disabled V | | |
  49. // +-<--------------------- kCanUpdate +--------> kRun |
  50. // | | |
  51. // | no V |
  52. // | +-<- [differential update?] |
  53. // | | | |
  54. // | | yes | |
  55. // | | error V |
  56. // | +-<----- kDownloadingDiff kRun---->-+
  57. // | | | ^ |
  58. // | | | yes | |
  59. // | | error V | |
  60. // | +-<----- kUpdatingDiff ---------> [action?] ->-+
  61. // | | ^ no
  62. // | error V |
  63. // +-<-------- kDownloading |
  64. // | | |
  65. // | | |
  66. // | error V |
  67. // +-<-------- kUpdating --------------------------------+
  68. namespace update_client {
  69. namespace {
  70. using InstallOnBlockingTaskRunnerCompleteCallback = base::OnceCallback<
  71. void(ErrorCategory error_category, int error_code, int extra_code1)>;
  72. void InstallComplete(scoped_refptr<base::SequencedTaskRunner> main_task_runner,
  73. InstallOnBlockingTaskRunnerCompleteCallback callback,
  74. const base::FilePath& unpack_path,
  75. const CrxInstaller::Result& result) {
  76. base::ThreadPool::PostTask(
  77. FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
  78. base::BindOnce(
  79. [](scoped_refptr<base::SequencedTaskRunner> main_task_runner,
  80. InstallOnBlockingTaskRunnerCompleteCallback callback,
  81. const base::FilePath& unpack_path,
  82. const CrxInstaller::Result& result) {
  83. base::DeletePathRecursively(unpack_path);
  84. const ErrorCategory error_category =
  85. result.error ? ErrorCategory::kInstall : ErrorCategory::kNone;
  86. main_task_runner->PostTask(
  87. FROM_HERE, base::BindOnce(std::move(callback), error_category,
  88. static_cast<int>(result.error),
  89. result.extended_error));
  90. },
  91. main_task_runner, std::move(callback), unpack_path, result));
  92. }
  93. void InstallOnBlockingTaskRunner(
  94. scoped_refptr<base::SequencedTaskRunner> main_task_runner,
  95. const base::FilePath& unpack_path,
  96. const std::string& public_key,
  97. const std::string& fingerprint,
  98. std::unique_ptr<CrxInstaller::InstallParams> install_params,
  99. scoped_refptr<CrxInstaller> installer,
  100. CrxInstaller::ProgressCallback progress_callback,
  101. InstallOnBlockingTaskRunnerCompleteCallback callback) {
  102. DCHECK(base::DirectoryExists(unpack_path));
  103. // Acquire the ownership of the |unpack_path|.
  104. base::ScopedTempDir unpack_path_owner;
  105. std::ignore = unpack_path_owner.Set(unpack_path);
  106. if (static_cast<int>(fingerprint.size()) !=
  107. base::WriteFile(
  108. unpack_path.Append(FILE_PATH_LITERAL("manifest.fingerprint")),
  109. fingerprint.c_str(), base::checked_cast<int>(fingerprint.size()))) {
  110. const CrxInstaller::Result result(InstallError::FINGERPRINT_WRITE_FAILED);
  111. main_task_runner->PostTask(
  112. FROM_HERE,
  113. base::BindOnce(std::move(callback), ErrorCategory::kInstall,
  114. static_cast<int>(result.error), result.extended_error));
  115. return;
  116. }
  117. // Ensures that progress callback is not posted after the completion
  118. // callback. There is a current design limitation in the update client where a
  119. // poorly implemented installer could post progress after the completion, and
  120. // thus, break some update client invariants.
  121. // Both callbacks maintain a reference to an instance of this class.
  122. // The state of the boolean atomic member is tested on the main sequence, and
  123. // the progress callback is posted to the sequence only if the completion
  124. // callback has not occurred yet.
  125. class CallbackChecker : public base::RefCountedThreadSafe<CallbackChecker> {
  126. public:
  127. bool is_safe() const { return is_safe_; }
  128. void set_unsafe() { is_safe_ = false; }
  129. private:
  130. friend class base::RefCountedThreadSafe<CallbackChecker>;
  131. ~CallbackChecker() = default;
  132. std::atomic<bool> is_safe_ = {true};
  133. };
  134. // Adapts the progress and completion callbacks such that the callback checker
  135. // is marked as unsafe before invoking the completion callback. On the
  136. // progress side, it allows reposting of the progress callback only when the
  137. // checker is in a safe state, as seen from the main sequence.
  138. auto callback_checker = base::MakeRefCounted<CallbackChecker>();
  139. installer->Install(
  140. unpack_path, public_key, std::move(install_params),
  141. base::BindRepeating(
  142. [](scoped_refptr<base::SequencedTaskRunner> main_task_runner,
  143. scoped_refptr<CallbackChecker> callback_checker,
  144. CrxInstaller::ProgressCallback progress_callback, int progress) {
  145. main_task_runner->PostTask(
  146. FROM_HERE,
  147. base::BindRepeating(
  148. [](scoped_refptr<CallbackChecker> callback_checker,
  149. CrxInstaller::ProgressCallback progress_callback,
  150. int progress) {
  151. if (callback_checker->is_safe()) {
  152. progress_callback.Run(progress);
  153. } else {
  154. DVLOG(2) << "Progress callback was skipped.";
  155. }
  156. },
  157. callback_checker, progress_callback, progress));
  158. },
  159. main_task_runner, callback_checker, progress_callback),
  160. base::BindOnce(
  161. [](scoped_refptr<CallbackChecker> callback_checker,
  162. CrxInstaller::Callback callback,
  163. const CrxInstaller::Result& result) {
  164. callback_checker->set_unsafe();
  165. std::move(callback).Run(result);
  166. },
  167. callback_checker,
  168. base::BindOnce(&InstallComplete, main_task_runner,
  169. std::move(callback), unpack_path_owner.Take())));
  170. }
  171. void UnpackCompleteOnBlockingTaskRunner(
  172. scoped_refptr<base::SequencedTaskRunner> main_task_runner,
  173. const base::FilePath& crx_path,
  174. const std::string& fingerprint,
  175. std::unique_ptr<CrxInstaller::InstallParams> install_params,
  176. scoped_refptr<CrxInstaller> installer,
  177. CrxInstaller::ProgressCallback progress_callback,
  178. InstallOnBlockingTaskRunnerCompleteCallback callback,
  179. const ComponentUnpacker::Result& result) {
  180. update_client::DeleteFileAndEmptyParentDirectory(crx_path);
  181. if (result.error != UnpackerError::kNone) {
  182. main_task_runner->PostTask(
  183. FROM_HERE,
  184. base::BindOnce(std::move(callback), ErrorCategory::kUnpack,
  185. static_cast<int>(result.error), result.extended_error));
  186. return;
  187. }
  188. base::ThreadPool::PostTask(
  189. FROM_HERE, kTaskTraits,
  190. base::BindOnce(&InstallOnBlockingTaskRunner, main_task_runner,
  191. result.unpack_path, result.public_key, fingerprint,
  192. std::move(install_params), installer,
  193. std::move(progress_callback), std::move(callback)));
  194. }
  195. void StartInstallOnBlockingTaskRunner(
  196. scoped_refptr<base::SequencedTaskRunner> main_task_runner,
  197. const std::vector<uint8_t>& pk_hash,
  198. const base::FilePath& crx_path,
  199. const std::string& fingerprint,
  200. std::unique_ptr<CrxInstaller::InstallParams> install_params,
  201. scoped_refptr<CrxInstaller> installer,
  202. std::unique_ptr<Unzipper> unzipper_,
  203. scoped_refptr<Patcher> patcher_,
  204. crx_file::VerifierFormat crx_format,
  205. CrxInstaller::ProgressCallback progress_callback,
  206. InstallOnBlockingTaskRunnerCompleteCallback callback) {
  207. auto unpacker = base::MakeRefCounted<ComponentUnpacker>(
  208. pk_hash, crx_path, installer, std::move(unzipper_), std::move(patcher_),
  209. crx_format);
  210. unpacker->Unpack(base::BindOnce(
  211. &UnpackCompleteOnBlockingTaskRunner, main_task_runner, crx_path,
  212. fingerprint, std::move(install_params), installer,
  213. std::move(progress_callback), std::move(callback)));
  214. }
  215. // Returns a string literal corresponding to the value of the downloader |d|.
  216. const char* DownloaderToString(CrxDownloader::DownloadMetrics::Downloader d) {
  217. switch (d) {
  218. case CrxDownloader::DownloadMetrics::kUrlFetcher:
  219. return "direct";
  220. case CrxDownloader::DownloadMetrics::kBits:
  221. return "bits";
  222. default:
  223. return "unknown";
  224. }
  225. }
  226. } // namespace
  227. Component::Component(const UpdateContext& update_context, const std::string& id)
  228. : id_(id),
  229. state_(std::make_unique<StateNew>(this)),
  230. update_context_(update_context) {}
  231. Component::~Component() = default;
  232. scoped_refptr<Configurator> Component::config() const {
  233. return update_context_.config;
  234. }
  235. std::string Component::session_id() const {
  236. return update_context_.session_id;
  237. }
  238. bool Component::is_foreground() const {
  239. return update_context_.is_foreground;
  240. }
  241. void Component::Handle(CallbackHandleComplete callback_handle_complete) {
  242. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  243. DCHECK(state_);
  244. callback_handle_complete_ = std::move(callback_handle_complete);
  245. state_->Handle(
  246. base::BindOnce(&Component::ChangeState, base::Unretained(this)));
  247. }
  248. void Component::ChangeState(std::unique_ptr<State> next_state) {
  249. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  250. previous_state_ = state();
  251. if (next_state)
  252. state_ = std::move(next_state);
  253. else
  254. is_handled_ = true;
  255. base::SequencedTaskRunnerHandle::Get()->PostTask(
  256. FROM_HERE, std::move(callback_handle_complete_));
  257. }
  258. CrxUpdateItem Component::GetCrxUpdateItem() const {
  259. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  260. CrxUpdateItem crx_update_item;
  261. crx_update_item.state = state_->state();
  262. crx_update_item.id = id_;
  263. if (crx_component_)
  264. crx_update_item.component = *crx_component_;
  265. crx_update_item.last_check = last_check_;
  266. crx_update_item.next_version = next_version_;
  267. crx_update_item.next_fp = next_fp_;
  268. crx_update_item.downloaded_bytes = downloaded_bytes_;
  269. crx_update_item.install_progress = install_progress_;
  270. crx_update_item.total_bytes = total_bytes_;
  271. crx_update_item.error_category = error_category_;
  272. crx_update_item.error_code = error_code_;
  273. crx_update_item.extra_code1 = extra_code1_;
  274. crx_update_item.custom_updatecheck_data = custom_attrs_;
  275. return crx_update_item;
  276. }
  277. void Component::SetParseResult(const ProtocolParser::Result& result) {
  278. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  279. DCHECK_EQ(0, update_check_error_);
  280. status_ = result.status;
  281. action_run_ = result.action_run;
  282. custom_attrs_ = result.custom_attributes;
  283. if (result.manifest.packages.empty())
  284. return;
  285. next_version_ = base::Version(result.manifest.version);
  286. const auto& package = result.manifest.packages.front();
  287. next_fp_ = package.fingerprint;
  288. // Resolve the urls by combining the base urls with the package names.
  289. for (const auto& crx_url : result.crx_urls) {
  290. const GURL url = crx_url.Resolve(package.name);
  291. if (url.is_valid())
  292. crx_urls_.push_back(url);
  293. }
  294. for (const auto& crx_diffurl : result.crx_diffurls) {
  295. const GURL url = crx_diffurl.Resolve(package.namediff);
  296. if (url.is_valid())
  297. crx_diffurls_.push_back(url);
  298. }
  299. hash_sha256_ = package.hash_sha256;
  300. hashdiff_sha256_ = package.hashdiff_sha256;
  301. if (!result.manifest.run.empty()) {
  302. install_params_ = absl::make_optional(CrxInstaller::InstallParams(
  303. result.manifest.run, result.manifest.arguments,
  304. [&result](const std::string& expected) -> std::string {
  305. if (expected.empty() || result.data.empty()) {
  306. return "";
  307. }
  308. auto it =
  309. std::find_if(std::begin(result.data), std::end(result.data),
  310. [&expected](const ProtocolParser::Result::Data& d) {
  311. return d.install_data_index == expected;
  312. });
  313. const bool matched = it != std::end(result.data);
  314. DVLOG(2) << "Expected install_data_index: " << expected
  315. << ", matched: " << matched;
  316. return matched ? it->text : "";
  317. }(crx_component_ ? crx_component_->install_data_index : "")));
  318. }
  319. }
  320. void Component::Uninstall(const CrxComponent& crx_component, int reason) {
  321. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  322. DCHECK_EQ(ComponentState::kNew, state());
  323. crx_component_ = crx_component;
  324. previous_version_ = crx_component_->version;
  325. next_version_ = base::Version("0");
  326. extra_code1_ = reason;
  327. state_ = std::make_unique<StateUninstalled>(this);
  328. }
  329. void Component::Registration(const CrxComponent& crx_component) {
  330. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  331. DCHECK_EQ(ComponentState::kNew, state());
  332. crx_component_ = crx_component;
  333. next_version_ = crx_component_->version;
  334. state_ = std::make_unique<StateRegistration>(this);
  335. }
  336. void Component::SetUpdateCheckResult(
  337. const absl::optional<ProtocolParser::Result>& result,
  338. ErrorCategory error_category,
  339. int error) {
  340. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  341. DCHECK_EQ(ComponentState::kChecking, state());
  342. error_category_ = error_category;
  343. error_code_ = error;
  344. if (result)
  345. SetParseResult(result.value());
  346. }
  347. void Component::NotifyWait() {
  348. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  349. NotifyObservers(Events::COMPONENT_WAIT);
  350. }
  351. bool Component::CanDoBackgroundDownload() const {
  352. // Foreground component updates are always downloaded in foreground.
  353. return !is_foreground() &&
  354. (crx_component() && crx_component()->allows_background_download) &&
  355. update_context_.config->EnabledBackgroundDownloader();
  356. }
  357. void Component::AppendEvent(base::Value event) {
  358. events_.push_back(std::move(event));
  359. }
  360. void Component::NotifyObservers(UpdateClient::Observer::Events event) const {
  361. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  362. // There is no corresponding component state for the COMPONENT_WAIT event.
  363. if (update_context_.crx_state_change_callback &&
  364. event != UpdateClient::Observer::Events::COMPONENT_WAIT) {
  365. base::SequencedTaskRunnerHandle::Get()->PostTask(
  366. FROM_HERE,
  367. base::BindRepeating(update_context_.crx_state_change_callback,
  368. GetCrxUpdateItem()));
  369. }
  370. update_context_.notify_observers_callback.Run(event, id_);
  371. }
  372. base::TimeDelta Component::GetUpdateDuration() const {
  373. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  374. if (update_begin_.is_null())
  375. return base::TimeDelta();
  376. const base::TimeDelta update_cost(base::TimeTicks::Now() - update_begin_);
  377. DCHECK_GE(update_cost, base::TimeDelta());
  378. const base::TimeDelta max_update_delay =
  379. base::Seconds(update_context_.config->UpdateDelay());
  380. return std::min(update_cost, max_update_delay);
  381. }
  382. base::Value Component::MakeEventUpdateComplete() const {
  383. base::Value event(base::Value::Type::DICTIONARY);
  384. event.SetKey("eventtype", base::Value(update_context_.is_install ? 2 : 3));
  385. event.SetKey(
  386. "eventresult",
  387. base::Value(static_cast<int>(state() == ComponentState::kUpdated)));
  388. if (error_category() != ErrorCategory::kNone)
  389. event.SetKey("errorcat", base::Value(static_cast<int>(error_category())));
  390. if (error_code())
  391. event.SetKey("errorcode", base::Value(error_code()));
  392. if (extra_code1())
  393. event.SetKey("extracode1", base::Value(extra_code1()));
  394. if (HasDiffUpdate(*this)) {
  395. const int diffresult = static_cast<int>(!diff_update_failed());
  396. event.SetKey("diffresult", base::Value(diffresult));
  397. }
  398. if (diff_error_category() != ErrorCategory::kNone) {
  399. const int differrorcat = static_cast<int>(diff_error_category());
  400. event.SetKey("differrorcat", base::Value(differrorcat));
  401. }
  402. if (diff_error_code())
  403. event.SetKey("differrorcode", base::Value(diff_error_code()));
  404. if (diff_extra_code1())
  405. event.SetKey("diffextracode1", base::Value(diff_extra_code1()));
  406. if (!previous_fp().empty())
  407. event.SetKey("previousfp", base::Value(previous_fp()));
  408. if (!next_fp().empty())
  409. event.SetKey("nextfp", base::Value(next_fp()));
  410. DCHECK(previous_version().IsValid());
  411. event.SetKey("previousversion", base::Value(previous_version().GetString()));
  412. if (next_version().IsValid())
  413. event.SetKey("nextversion", base::Value(next_version().GetString()));
  414. return event;
  415. }
  416. base::Value Component::MakeEventDownloadMetrics(
  417. const CrxDownloader::DownloadMetrics& dm) const {
  418. base::Value event(base::Value::Type::DICTIONARY);
  419. event.SetKey("eventtype", base::Value(14));
  420. event.SetKey("eventresult", base::Value(static_cast<int>(dm.error == 0)));
  421. event.SetKey("downloader", base::Value(DownloaderToString(dm.downloader)));
  422. if (dm.error)
  423. event.SetKey("errorcode", base::Value(dm.error));
  424. event.SetKey("url", base::Value(dm.url.spec()));
  425. // -1 means that the byte counts are not known.
  426. if (dm.total_bytes != -1 && dm.total_bytes < kProtocolMaxInt)
  427. event.SetKey("total", base::Value(static_cast<double>(dm.total_bytes)));
  428. if (dm.downloaded_bytes != -1 && dm.total_bytes < kProtocolMaxInt) {
  429. event.SetKey("downloaded",
  430. base::Value(static_cast<double>(dm.downloaded_bytes)));
  431. }
  432. if (dm.download_time_ms && dm.total_bytes < kProtocolMaxInt) {
  433. event.SetKey("download_time_ms",
  434. base::Value(static_cast<double>(dm.download_time_ms)));
  435. }
  436. DCHECK(previous_version().IsValid());
  437. event.SetKey("previousversion", base::Value(previous_version().GetString()));
  438. if (next_version().IsValid())
  439. event.SetKey("nextversion", base::Value(next_version().GetString()));
  440. return event;
  441. }
  442. base::Value Component::MakeEventUninstalled() const {
  443. DCHECK(state() == ComponentState::kUninstalled);
  444. base::Value event(base::Value::Type::DICTIONARY);
  445. event.SetKey("eventtype", base::Value(4));
  446. event.SetKey("eventresult", base::Value(1));
  447. if (extra_code1())
  448. event.SetKey("extracode1", base::Value(extra_code1()));
  449. DCHECK(previous_version().IsValid());
  450. event.SetKey("previousversion", base::Value(previous_version().GetString()));
  451. DCHECK(next_version().IsValid());
  452. event.SetKey("nextversion", base::Value(next_version().GetString()));
  453. return event;
  454. }
  455. base::Value Component::MakeEventRegistration() const {
  456. DCHECK(state() == ComponentState::kRegistration);
  457. base::Value event(base::Value::Type::DICTIONARY);
  458. event.SetKey("eventtype", base::Value(2));
  459. event.SetKey("eventresult", base::Value(1));
  460. if (error_code())
  461. event.SetKey("errorcode", base::Value(error_code()));
  462. if (extra_code1())
  463. event.SetKey("extracode1", base::Value(extra_code1()));
  464. DCHECK(next_version().IsValid());
  465. event.SetKey("nextversion", base::Value(next_version().GetString()));
  466. return event;
  467. }
  468. base::Value Component::MakeEventActionRun(bool succeeded,
  469. int error_code,
  470. int extra_code1) const {
  471. base::Value event(base::Value::Type::DICTIONARY);
  472. event.SetKey("eventtype", base::Value(42));
  473. event.SetKey("eventresult", base::Value(static_cast<int>(succeeded)));
  474. if (error_code)
  475. event.SetKey("errorcode", base::Value(error_code));
  476. if (extra_code1)
  477. event.SetKey("extracode1", base::Value(extra_code1));
  478. return event;
  479. }
  480. std::vector<base::Value> Component::GetEvents() const {
  481. std::vector<base::Value> events;
  482. for (const auto& event : events_)
  483. events.push_back(event.Clone());
  484. return events;
  485. }
  486. std::unique_ptr<CrxInstaller::InstallParams> Component::install_params() const {
  487. return install_params_
  488. ? std::make_unique<CrxInstaller::InstallParams>(*install_params_)
  489. : nullptr;
  490. }
  491. Component::State::State(Component* component, ComponentState state)
  492. : state_(state), component_(*component) {}
  493. Component::State::~State() = default;
  494. void Component::State::Handle(CallbackNextState callback_next_state) {
  495. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  496. callback_next_state_ = std::move(callback_next_state);
  497. DoHandle();
  498. }
  499. void Component::State::TransitionState(std::unique_ptr<State> next_state) {
  500. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  501. DCHECK(next_state);
  502. base::SequencedTaskRunnerHandle::Get()->PostTask(
  503. FROM_HERE,
  504. base::BindOnce(std::move(callback_next_state_), std::move(next_state)));
  505. }
  506. void Component::State::EndState() {
  507. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  508. base::SequencedTaskRunnerHandle::Get()->PostTask(
  509. FROM_HERE, base::BindOnce(std::move(callback_next_state_), nullptr));
  510. }
  511. Component::StateNew::StateNew(Component* component)
  512. : State(component, ComponentState::kNew) {}
  513. Component::StateNew::~StateNew() {
  514. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  515. }
  516. void Component::StateNew::DoHandle() {
  517. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  518. auto& component = State::component();
  519. if (component.crx_component()) {
  520. TransitionState(std::make_unique<StateChecking>(&component));
  521. // Notify that the component is being checked for updates after the
  522. // transition to `StateChecking` occurs. This event indicates the start
  523. // of the update check. The component receives the update check results when
  524. // the update checks completes, and after that, `UpdateEngine` invokes the
  525. // function `StateChecking::DoHandle` to transition the component out of
  526. // the `StateChecking`. The current design allows for notifying observers
  527. // on state transitions but it does not allow such notifications when a
  528. // new state is entered. Hence, posting the task below is a workaround for
  529. // this design oversight.
  530. base::SequencedTaskRunnerHandle::Get()->PostTask(
  531. FROM_HERE,
  532. base::BindOnce(
  533. [](Component& component) {
  534. component.NotifyObservers(Events::COMPONENT_CHECKING_FOR_UPDATES);
  535. },
  536. std::ref(component)));
  537. } else {
  538. component.error_code_ = static_cast<int>(Error::CRX_NOT_FOUND);
  539. component.error_category_ = ErrorCategory::kService;
  540. TransitionState(std::make_unique<StateUpdateError>(&component));
  541. }
  542. }
  543. Component::StateChecking::StateChecking(Component* component)
  544. : State(component, ComponentState::kChecking) {
  545. component->last_check_ = base::TimeTicks::Now();
  546. }
  547. Component::StateChecking::~StateChecking() {
  548. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  549. }
  550. void Component::StateChecking::DoHandle() {
  551. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  552. auto& component = State::component();
  553. DCHECK(component.crx_component());
  554. if (component.error_code_) {
  555. TransitionState(std::make_unique<StateUpdateError>(&component));
  556. return;
  557. }
  558. if (component.update_context_.is_cancelled) {
  559. TransitionState(std::make_unique<StateUpdateError>(&component));
  560. component.error_category_ = ErrorCategory::kService;
  561. component.error_code_ = static_cast<int>(ServiceError::CANCELLED);
  562. return;
  563. }
  564. if (component.status_ == "ok") {
  565. TransitionState(std::make_unique<StateCanUpdate>(&component));
  566. return;
  567. }
  568. if (component.status_ == "noupdate") {
  569. if (component.action_run_.empty()) {
  570. TransitionState(std::make_unique<StateUpToDate>(&component));
  571. } else {
  572. TransitionState(std::make_unique<StateRun>(&component));
  573. }
  574. return;
  575. }
  576. TransitionState(std::make_unique<StateUpdateError>(&component));
  577. }
  578. Component::StateUpdateError::StateUpdateError(Component* component)
  579. : State(component, ComponentState::kUpdateError) {}
  580. Component::StateUpdateError::~StateUpdateError() {
  581. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  582. }
  583. void Component::StateUpdateError::DoHandle() {
  584. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  585. auto& component = State::component();
  586. DCHECK_NE(ErrorCategory::kNone, component.error_category_);
  587. DCHECK_NE(0, component.error_code_);
  588. // Create an event only when the server response included an update.
  589. if (component.IsUpdateAvailable())
  590. component.AppendEvent(component.MakeEventUpdateComplete());
  591. EndState();
  592. component.NotifyObservers(Events::COMPONENT_UPDATE_ERROR);
  593. }
  594. Component::StateCanUpdate::StateCanUpdate(Component* component)
  595. : State(component, ComponentState::kCanUpdate) {}
  596. Component::StateCanUpdate::~StateCanUpdate() {
  597. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  598. }
  599. void Component::StateCanUpdate::DoHandle() {
  600. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  601. auto& component = State::component();
  602. DCHECK(component.crx_component());
  603. component.is_update_available_ = true;
  604. component.NotifyObservers(Events::COMPONENT_UPDATE_FOUND);
  605. if (!component.crx_component()->updates_enabled) {
  606. component.error_category_ = ErrorCategory::kService;
  607. component.error_code_ = static_cast<int>(ServiceError::UPDATE_DISABLED);
  608. component.extra_code1_ = 0;
  609. TransitionState(std::make_unique<StateUpdateError>(&component));
  610. return;
  611. }
  612. if (component.update_context_.is_cancelled) {
  613. TransitionState(std::make_unique<StateUpdateError>(&component));
  614. component.error_category_ = ErrorCategory::kService;
  615. component.error_code_ = static_cast<int>(ServiceError::CANCELLED);
  616. return;
  617. }
  618. // Start computing the cost of the this update from here on.
  619. component.update_begin_ = base::TimeTicks::Now();
  620. if (CanTryDiffUpdate())
  621. TransitionState(std::make_unique<StateDownloadingDiff>(&component));
  622. else
  623. TransitionState(std::make_unique<StateDownloading>(&component));
  624. }
  625. // Returns true if a differential update is available, it has not failed yet,
  626. // and the configuration allows this update.
  627. bool Component::StateCanUpdate::CanTryDiffUpdate() const {
  628. const auto& component = Component::State::component();
  629. return HasDiffUpdate(component) && !component.diff_error_code_ &&
  630. component.update_context_.config->EnabledDeltas();
  631. }
  632. Component::StateUpToDate::StateUpToDate(Component* component)
  633. : State(component, ComponentState::kUpToDate) {}
  634. Component::StateUpToDate::~StateUpToDate() {
  635. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  636. }
  637. void Component::StateUpToDate::DoHandle() {
  638. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  639. auto& component = State::component();
  640. DCHECK(component.crx_component());
  641. component.NotifyObservers(Events::COMPONENT_ALREADY_UP_TO_DATE);
  642. EndState();
  643. }
  644. Component::StateDownloadingDiff::StateDownloadingDiff(Component* component)
  645. : State(component, ComponentState::kDownloadingDiff) {}
  646. Component::StateDownloadingDiff::~StateDownloadingDiff() {
  647. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  648. }
  649. void Component::StateDownloadingDiff::DoHandle() {
  650. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  651. auto& component = Component::State::component();
  652. DCHECK(component.crx_component());
  653. component.downloaded_bytes_ = -1;
  654. component.total_bytes_ = -1;
  655. crx_downloader_ =
  656. component.config()->GetCrxDownloaderFactory()->MakeCrxDownloader(
  657. component.CanDoBackgroundDownload());
  658. crx_downloader_->set_progress_callback(
  659. base::BindRepeating(&Component::StateDownloadingDiff::DownloadProgress,
  660. base::Unretained(this)));
  661. crx_downloader_->StartDownload(
  662. component.crx_diffurls_, component.hashdiff_sha256_,
  663. base::BindOnce(&Component::StateDownloadingDiff::DownloadComplete,
  664. base::Unretained(this)));
  665. component.NotifyObservers(Events::COMPONENT_UPDATE_DOWNLOADING);
  666. }
  667. // Called when progress is being made downloading a CRX. Can be called multiple
  668. // times due to how the CRX downloader switches between different downloaders
  669. // and fallback urls.
  670. void Component::StateDownloadingDiff::DownloadProgress(int64_t downloaded_bytes,
  671. int64_t total_bytes) {
  672. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  673. if (downloaded_bytes != -1 && total_bytes != -1)
  674. DCHECK_LE(downloaded_bytes, total_bytes);
  675. auto& component = Component::State::component();
  676. component.downloaded_bytes_ = downloaded_bytes;
  677. component.total_bytes_ = total_bytes;
  678. component.NotifyObservers(Events::COMPONENT_UPDATE_DOWNLOADING);
  679. }
  680. void Component::StateDownloadingDiff::DownloadComplete(
  681. const CrxDownloader::Result& download_result) {
  682. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  683. auto& component = Component::State::component();
  684. for (const auto& download_metrics : crx_downloader_->download_metrics())
  685. component.AppendEvent(component.MakeEventDownloadMetrics(download_metrics));
  686. crx_downloader_ = nullptr;
  687. if (component.update_context_.is_cancelled) {
  688. TransitionState(std::make_unique<StateUpdateError>(&component));
  689. component.error_category_ = ErrorCategory::kService;
  690. component.error_code_ = static_cast<int>(ServiceError::CANCELLED);
  691. return;
  692. }
  693. if (download_result.error) {
  694. DCHECK(download_result.response.empty());
  695. component.diff_error_category_ = ErrorCategory::kDownload;
  696. component.diff_error_code_ = download_result.error;
  697. TransitionState(std::make_unique<StateDownloading>(&component));
  698. return;
  699. }
  700. component.crx_path_ = download_result.response;
  701. TransitionState(std::make_unique<StateUpdatingDiff>(&component));
  702. }
  703. Component::StateDownloading::StateDownloading(Component* component)
  704. : State(component, ComponentState::kDownloading) {}
  705. Component::StateDownloading::~StateDownloading() {
  706. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  707. }
  708. void Component::StateDownloading::DoHandle() {
  709. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  710. auto& component = Component::State::component();
  711. DCHECK(component.crx_component());
  712. component.downloaded_bytes_ = -1;
  713. component.total_bytes_ = -1;
  714. crx_downloader_ =
  715. component.config()->GetCrxDownloaderFactory()->MakeCrxDownloader(
  716. component.CanDoBackgroundDownload());
  717. crx_downloader_->set_progress_callback(base::BindRepeating(
  718. &Component::StateDownloading::DownloadProgress, base::Unretained(this)));
  719. crx_downloader_->StartDownload(
  720. component.crx_urls_, component.hash_sha256_,
  721. base::BindOnce(&Component::StateDownloading::DownloadComplete,
  722. base::Unretained(this)));
  723. component.NotifyObservers(Events::COMPONENT_UPDATE_DOWNLOADING);
  724. }
  725. // Called when progress is being made downloading a CRX. Can be called multiple
  726. // times due to how the CRX downloader switches between different downloaders
  727. // and fallback urls.
  728. void Component::StateDownloading::DownloadProgress(int64_t downloaded_bytes,
  729. int64_t total_bytes) {
  730. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  731. if (downloaded_bytes != -1 && total_bytes != -1)
  732. DCHECK_LE(downloaded_bytes, total_bytes);
  733. auto& component = Component::State::component();
  734. component.downloaded_bytes_ = downloaded_bytes;
  735. component.total_bytes_ = total_bytes;
  736. component.NotifyObservers(Events::COMPONENT_UPDATE_DOWNLOADING);
  737. }
  738. void Component::StateDownloading::DownloadComplete(
  739. const CrxDownloader::Result& download_result) {
  740. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  741. auto& component = Component::State::component();
  742. for (const auto& download_metrics : crx_downloader_->download_metrics())
  743. component.AppendEvent(component.MakeEventDownloadMetrics(download_metrics));
  744. crx_downloader_ = nullptr;
  745. if (component.update_context_.is_cancelled) {
  746. TransitionState(std::make_unique<StateUpdateError>(&component));
  747. component.error_category_ = ErrorCategory::kService;
  748. component.error_code_ = static_cast<int>(ServiceError::CANCELLED);
  749. return;
  750. }
  751. if (download_result.error) {
  752. DCHECK(download_result.response.empty());
  753. component.error_category_ = ErrorCategory::kDownload;
  754. component.error_code_ = download_result.error;
  755. TransitionState(std::make_unique<StateUpdateError>(&component));
  756. return;
  757. }
  758. component.crx_path_ = download_result.response;
  759. TransitionState(std::make_unique<StateUpdating>(&component));
  760. }
  761. Component::StateUpdatingDiff::StateUpdatingDiff(Component* component)
  762. : State(component, ComponentState::kUpdatingDiff) {}
  763. Component::StateUpdatingDiff::~StateUpdatingDiff() {
  764. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  765. }
  766. void Component::StateUpdatingDiff::DoHandle() {
  767. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  768. auto& component = Component::State::component();
  769. const auto& update_context = component.update_context_;
  770. DCHECK(component.crx_component());
  771. component.install_progress_ = -1;
  772. component.NotifyObservers(Events::COMPONENT_UPDATE_READY);
  773. // Adapts the repeating progress callback invoked by the installer so that
  774. // the callback can be posted to the main sequence instead of running
  775. // the callback on the sequence the installer is running on.
  776. auto main_task_runner = base::SequencedTaskRunnerHandle::Get();
  777. base::ThreadPool::CreateSequencedTaskRunner(kTaskTraits)
  778. ->PostTask(
  779. FROM_HERE,
  780. base::BindOnce(
  781. &update_client::StartInstallOnBlockingTaskRunner,
  782. base::SequencedTaskRunnerHandle::Get(),
  783. component.crx_component()->pk_hash, component.crx_path_,
  784. component.next_fp_, component.install_params(),
  785. component.crx_component()->installer,
  786. update_context.config->GetUnzipperFactory()->Create(),
  787. update_context.config->GetPatcherFactory()->Create(),
  788. component.crx_component()->crx_format_requirement,
  789. base::BindRepeating(
  790. &Component::StateUpdatingDiff::InstallProgress,
  791. base::Unretained(this)),
  792. base::BindOnce(&Component::StateUpdatingDiff::InstallComplete,
  793. base::Unretained(this))));
  794. }
  795. void Component::StateUpdatingDiff::InstallProgress(int install_progress) {
  796. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  797. auto& component = Component::State::component();
  798. if (install_progress >= 0 && install_progress <= 100)
  799. component.install_progress_ = install_progress;
  800. component.NotifyObservers(Events::COMPONENT_UPDATE_UPDATING);
  801. }
  802. void Component::StateUpdatingDiff::InstallComplete(ErrorCategory error_category,
  803. int error_code,
  804. int extra_code1) {
  805. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  806. auto& component = Component::State::component();
  807. component.diff_error_category_ = error_category;
  808. component.diff_error_code_ = error_code;
  809. component.diff_extra_code1_ = extra_code1;
  810. if (component.diff_error_code_ != 0) {
  811. TransitionState(std::make_unique<StateDownloading>(&component));
  812. return;
  813. }
  814. DCHECK_EQ(ErrorCategory::kNone, component.diff_error_category_);
  815. DCHECK_EQ(0, component.diff_error_code_);
  816. DCHECK_EQ(0, component.diff_extra_code1_);
  817. DCHECK_EQ(ErrorCategory::kNone, component.error_category_);
  818. DCHECK_EQ(0, component.error_code_);
  819. DCHECK_EQ(0, component.extra_code1_);
  820. if (component.action_run_.empty())
  821. TransitionState(std::make_unique<StateUpdated>(&component));
  822. else
  823. TransitionState(std::make_unique<StateRun>(&component));
  824. }
  825. Component::StateUpdating::StateUpdating(Component* component)
  826. : State(component, ComponentState::kUpdating) {}
  827. Component::StateUpdating::~StateUpdating() {
  828. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  829. }
  830. void Component::StateUpdating::DoHandle() {
  831. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  832. auto& component = Component::State::component();
  833. const auto& update_context = component.update_context_;
  834. DCHECK(component.crx_component());
  835. component.install_progress_ = -1;
  836. component.NotifyObservers(Events::COMPONENT_UPDATE_READY);
  837. // Adapts the repeating progress callback invoked by the installer so that
  838. // the callback can be posted to the main sequence instead of running
  839. // the callback on the sequence the installer is running on.
  840. auto main_task_runner = base::SequencedTaskRunnerHandle::Get();
  841. base::ThreadPool::CreateSequencedTaskRunner(kTaskTraits)
  842. ->PostTask(
  843. FROM_HERE,
  844. base::BindOnce(
  845. &update_client::StartInstallOnBlockingTaskRunner,
  846. main_task_runner, component.crx_component()->pk_hash,
  847. component.crx_path_, component.next_fp_,
  848. component.install_params(), component.crx_component()->installer,
  849. update_context.config->GetUnzipperFactory()->Create(),
  850. update_context.config->GetPatcherFactory()->Create(),
  851. component.crx_component()->crx_format_requirement,
  852. base::BindRepeating(&Component::StateUpdating::InstallProgress,
  853. base::Unretained(this)),
  854. base::BindOnce(&Component::StateUpdating::InstallComplete,
  855. base::Unretained(this))));
  856. }
  857. void Component::StateUpdating::InstallProgress(int install_progress) {
  858. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  859. auto& component = Component::State::component();
  860. if (install_progress >= 0 && install_progress <= 100)
  861. component.install_progress_ = install_progress;
  862. component.NotifyObservers(Events::COMPONENT_UPDATE_UPDATING);
  863. }
  864. void Component::StateUpdating::InstallComplete(ErrorCategory error_category,
  865. int error_code,
  866. int extra_code1) {
  867. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  868. auto& component = Component::State::component();
  869. component.error_category_ = error_category;
  870. component.error_code_ = error_code;
  871. component.extra_code1_ = extra_code1;
  872. if (component.error_code_ != 0) {
  873. TransitionState(std::make_unique<StateUpdateError>(&component));
  874. return;
  875. }
  876. DCHECK_EQ(ErrorCategory::kNone, component.error_category_);
  877. DCHECK_EQ(0, component.error_code_);
  878. DCHECK_EQ(0, component.extra_code1_);
  879. if (component.action_run_.empty())
  880. TransitionState(std::make_unique<StateUpdated>(&component));
  881. else
  882. TransitionState(std::make_unique<StateRun>(&component));
  883. }
  884. Component::StateUpdated::StateUpdated(Component* component)
  885. : State(component, ComponentState::kUpdated) {
  886. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  887. }
  888. Component::StateUpdated::~StateUpdated() {
  889. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  890. }
  891. void Component::StateUpdated::DoHandle() {
  892. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  893. auto& component = State::component();
  894. DCHECK(component.crx_component());
  895. component.crx_component_->version = component.next_version_;
  896. component.crx_component_->fingerprint = component.next_fp_;
  897. component.update_context_.persisted_data->SetProductVersion(
  898. component.id(), component.crx_component_->version);
  899. component.update_context_.persisted_data->SetFingerprint(
  900. component.id(), component.crx_component_->fingerprint);
  901. component.AppendEvent(component.MakeEventUpdateComplete());
  902. component.NotifyObservers(Events::COMPONENT_UPDATED);
  903. EndState();
  904. }
  905. Component::StateUninstalled::StateUninstalled(Component* component)
  906. : State(component, ComponentState::kUninstalled) {
  907. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  908. }
  909. Component::StateUninstalled::~StateUninstalled() {
  910. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  911. }
  912. void Component::StateUninstalled::DoHandle() {
  913. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  914. auto& component = State::component();
  915. DCHECK(component.crx_component());
  916. component.AppendEvent(component.MakeEventUninstalled());
  917. EndState();
  918. }
  919. Component::StateRegistration::StateRegistration(Component* component)
  920. : State(component, ComponentState::kRegistration) {
  921. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  922. }
  923. Component::StateRegistration::~StateRegistration() {
  924. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  925. }
  926. void Component::StateRegistration::DoHandle() {
  927. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  928. auto& component = State::component();
  929. DCHECK(component.crx_component());
  930. component.AppendEvent(component.MakeEventRegistration());
  931. EndState();
  932. }
  933. Component::StateRun::StateRun(Component* component)
  934. : State(component, ComponentState::kRun) {}
  935. Component::StateRun::~StateRun() {
  936. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  937. }
  938. void Component::StateRun::DoHandle() {
  939. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  940. const auto& component = State::component();
  941. DCHECK(component.crx_component());
  942. action_runner_ = std::make_unique<ActionRunner>(component);
  943. action_runner_->Run(
  944. base::BindOnce(&StateRun::ActionRunComplete, base::Unretained(this)));
  945. }
  946. void Component::StateRun::ActionRunComplete(bool succeeded,
  947. int error_code,
  948. int extra_code1) {
  949. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  950. auto& component = State::component();
  951. component.AppendEvent(
  952. component.MakeEventActionRun(succeeded, error_code, extra_code1));
  953. switch (component.previous_state_) {
  954. case ComponentState::kChecking:
  955. TransitionState(std::make_unique<StateUpToDate>(&component));
  956. return;
  957. case ComponentState::kUpdating:
  958. case ComponentState::kUpdatingDiff:
  959. TransitionState(std::make_unique<StateUpdated>(&component));
  960. return;
  961. default:
  962. break;
  963. }
  964. NOTREACHED();
  965. }
  966. } // namespace update_client