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
|