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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef EXTENSIONS_BROWSER_COMPUTED_HASHES_H_
#define EXTENSIONS_BROWSER_COMPUTED_HASHES_H_
#include <stddef.h>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/files/file_path.h"
#include "extensions/browser/content_verifier/content_verifier_utils.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace extensions {
using IsCancelledCallback = base::RepeatingCallback<bool(void)>;
using ShouldComputeHashesCallback =
base::RepeatingCallback<bool(const base::FilePath& relative_path)>;
using CanonicalRelativePath = content_verifier_utils::CanonicalRelativePath;
// A class for storage and serialization of a set of SHA256 block hashes
// computed over the files inside an extension.
class ComputedHashes {
public:
// Status of reading computed hashes from file: either success or error type.
enum class Status {
// Status is undefined.
UNKNOWN,
// Failed to read file.
READ_FAILED,
// File read successfully, but failed to parse the contents.
PARSE_FAILED,
// No error.
SUCCESS,
};
// Hashes data for relative paths.
// System specific path canonicalization is taken care of inside this class.
class Data {
public:
struct HashInfo {
int block_size;
std::vector<std::string> hashes;
// The relative unix style path.
// Note that we use canonicalized paths as keys to HashInfo's container
// |items_|.
//
// TODO(http://crbug.com/796395#c28): Consider removing this once
// ContentVerifier::ShouldVerifyAnyPaths works with canonicalized relative
// paths.
base::FilePath relative_unix_path;
HashInfo(int block_size,
std::vector<std::string> hashes,
base::FilePath relative_unix_path);
~HashInfo();
HashInfo(const HashInfo&) = delete;
HashInfo& operator=(const HashInfo&) = delete;
HashInfo(HashInfo&&);
HashInfo& operator=(HashInfo&&);
};
using Items = std::map<CanonicalRelativePath, HashInfo>;
Data();
~Data();
Data(const Data&) = delete;
Data& operator=(const Data&) = delete;
Data(Data&&);
Data& operator=(Data&&);
// For |relative_path|, adds hash information with |block_size| and
// |hashes|.
// Note that |relative_path| will be canonicalized.
void Add(const base::FilePath& relative_path,
int block_size,
std::vector<std::string> hashes);
// Removes the item that corresponds to |relative_path|.
void Remove(const base::FilePath& relative_path);
// Returns HashInfo* for |relative_path| or nullptr if not found.
const HashInfo* GetItem(const base::FilePath& relative_path) const;
const Items& items() const;
private:
// All items, stored by canonicalized FilePath::StringType key.
Items items_;
};
explicit ComputedHashes(Data&& data);
ComputedHashes(const ComputedHashes&) = delete;
ComputedHashes& operator=(const ComputedHashes&) = delete;
ComputedHashes(ComputedHashes&&);
ComputedHashes& operator=(ComputedHashes&&);
~ComputedHashes();
// Reads computed hashes from the computed_hashes.json file, stores read
// success/failure status to |status|. Returns nullopt upon any failure (i.e.
// |status| != Status::SUCCESS).
static absl::optional<ComputedHashes> CreateFromFile(
const base::FilePath& path,
Status* status);
// Computes hashes for files in |extension_root|. Returns nullopt upon any
// failure. Callback |should_compute_hashes_for| is used to determine whether
// we need hashes for a resource or not.
// TODO(https://crbug.com/796395#c24) To support per-file block size instead
// of passing |block_size| as an argument make callback
// |should_compute_hashes_for| return optional<int>: nullopt if hashes are not
// needed for this file, block size for this file otherwise.
static absl::optional<ComputedHashes::Data> Compute(
const base::FilePath& extension_root,
int block_size,
const IsCancelledCallback& is_cancelled,
const ShouldComputeHashesCallback& should_compute_hashes_for_resource);
// Saves computed hashes to given file, returns false upon any failure (and
// true on success).
bool WriteToFile(const base::FilePath& path) const;
// Gets hash info for |relative_path|. The block size and hashes for
// |relative_path| will be copied into the out parameters. Returns false if
// resource was not found (and true on success).
bool GetHashes(const base::FilePath& relative_path,
int* block_size,
std::vector<std::string>* hashes) const;
// Returns the SHA256 hash of each |block_size| chunk in |contents|.
static std::vector<std::string> GetHashesForContent(
const std::string& contents,
size_t block_size);
private:
// Builds hashes for one resource and checks them against
// verified_contents.json if needed. Returns nullopt if nothing should be
// added to computed_hashes.json for this resource.
static absl::optional<std::vector<std::string>> ComputeAndCheckResourceHash(
const base::FilePath& full_path,
int block_size);
Data data_;
};
} // namespace extensions
#endif // EXTENSIONS_BROWSER_COMPUTED_HASHES_H_
|