summaryrefslogtreecommitdiff
path: root/chromium/components/update_client/crx_cache.cc
blob: af0ce697be31ab3b99ce701c1a4fb668b1e0af60 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/update_client/crx_cache.h"

#include <cstdint>
#include <string>
#include <utility>

#include "base/bind.h"
#include "base/callback.h"
#include "base/check.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/notreached.h"
#include "base/path_service.h"
#include "base/sequence_checker.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/task/task_runner.h"
#include "base/task/thread_pool.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "third_party/abseil-cpp/absl/types/optional.h"

namespace update_client {

CrxCache::CrxCache(const CrxCache::Options& options)
    : crx_cache_root_path_(options.crx_cache_root_path) {}

CrxCache::~CrxCache() = default;

base::FilePath CrxCache::BuildCrxFilePath(const std::string& id,
                                          const std::string& fp) {
  return crx_cache_root_path_.AppendASCII(base::JoinString({id, fp}, "_"));
}

void CrxCache::Get(const std::string& id,
                   const std::string& fp,
                   base::OnceCallback<void(const Result& result)> callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(main_sequence_checker_);
  task_runner_->PostTaskAndReplyWithResult(
      FROM_HERE, base::BindOnce(&CrxCache::ProcessGet, this, id, fp),
      base::BindOnce(&CrxCache::EndRequest, this, std::move(callback)));
}

CrxCache::Result CrxCache::ProcessGet(const std::string& id,
                                      const std::string& fp) {
  CrxCache::Result result;
  absl::optional<base::FilePath> opt_file_path;
  base::FilePath file_path = BuildCrxFilePath(id, fp);
  if (!base::PathExists(file_path)) {
    result.error = UnpackerError::kPuffinMissingPreviousCrx;
  } else {
    result.error = UnpackerError::kNone;
    result.crx_cache_path = BuildCrxFilePath(id, fp);
  }
  return result;
}

void CrxCache::Put(const base::FilePath& crx_path,
                   const std::string& id,
                   const std::string& fp,
                   base::OnceCallback<void(const Result& result)> callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(main_sequence_checker_);
  task_runner_->PostTaskAndReplyWithResult(
      FROM_HERE, base::BindOnce(&CrxCache::ProcessPut, this, crx_path, id, fp),
      base::BindOnce(&CrxCache::EndRequest, this, std::move(callback)));
}

CrxCache::Result CrxCache::ProcessPut(const base::FilePath& crx_path,
                                      const std::string& id,
                                      const std::string& fp) {
  CrxCache::Result result;
  base::FilePath dest_path = BuildCrxFilePath(id, fp);
  RemoveAll(id);
  result.error = MoveFileToCache(crx_path, dest_path);
  if (result.error == UnpackerError::kNone) {
    result.crx_cache_path = dest_path;
  }
  return result;
}

void CrxCache::RemoveAll(const std::string& id) {
  if (base::PathExists(crx_cache_root_path_)) {
    base::FileEnumerator file_enum(crx_cache_root_path_, false,
                                   base::FileEnumerator::FILES,
                                   FILE_PATH_LITERAL(base::StrCat({id, "*"})));
    for (base::FilePath file_path = file_enum.Next(); !file_path.empty();
         file_path = file_enum.Next()) {
      base::DeleteFile(file_path);
    }
  }
}

UnpackerError CrxCache::MoveFileToCache(const base::FilePath& src_path,
                                        const base::FilePath& dest_path) {
  if (!base::CreateDirectory(crx_cache_root_path_)) {
    return update_client::UnpackerError::kFailedToCreateCacheDir;
  }
  if (!base::Move(src_path, dest_path)) {
    return update_client::UnpackerError::kFailedToAddToCache;
  }
  return update_client::UnpackerError::kNone;
}

void CrxCache::EndRequest(
    base::OnceCallback<void(const Result& result)> callback,
    CrxCache::Result result) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(main_sequence_checker_);
  base::SequencedTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::BindOnce(std::move(callback), result));
}

}  // namespace update_client