forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcontent_verify_job.h
182 lines (135 loc) · 6.08 KB
/
content_verify_job.h
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
// 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_CONTENT_VERIFY_JOB_H_
#define EXTENSIONS_BROWSER_CONTENT_VERIFY_JOB_H_
#include <stdint.h>
#include <memory>
#include <string>
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
#include "base/version.h"
#include "extensions/browser/content_verifier/content_verifier_key.h"
#include "extensions/common/extension_id.h"
#include "mojo/public/c/system/types.h"
namespace base {
class FilePath;
}
namespace crypto {
class SecureHash;
}
namespace extensions {
class ContentHash;
class ContentHashReader;
class ContentVerifier;
// Objects of this class are responsible for verifying that the actual content
// read from an extension file matches an expected set of hashes. This class
// can be created and used on any thread.
class ContentVerifyJob : public base::RefCountedThreadSafe<ContentVerifyJob> {
public:
enum FailureReason {
// No failure.
NONE,
// Failed because there were no expected hashes at all (eg they haven't
// been fetched yet).
MISSING_ALL_HASHES,
// Failed because hashes files exist, but are unreadabale or damaged, and
// content verifier was not able to compute new hashes.
CORRUPTED_HASHES,
// Failed because this file wasn't found in the list of expected hashes.
NO_HASHES_FOR_FILE,
// Some of the content read did not match the expected hash.
HASH_MISMATCH,
FAILURE_REASON_MAX
};
using FailureCallback = base::OnceCallback<void(FailureReason)>;
// The |failure_callback| will be called at most once if there was a failure.
ContentVerifyJob(const ExtensionId& extension_id,
const base::Version& extension_version,
const base::FilePath& extension_root,
const base::FilePath& relative_path,
FailureCallback failure_callback);
// This begins the process of getting expected hashes, so it should be called
// as early as possible.
void Start(ContentVerifier* verifier);
// Call this to add more bytes to verify. If at any point the read bytes
// don't match the expected hashes, this will dispatch the failure callback.
// The failure callback will only be run once even if more bytes are read.
// Make sure to call Done so that any final bytes that were read that didn't
// align exactly on a block size boundary get their hash checked as well.
void Read(const char* data, int count, MojoResult read_result);
// Call once when finished adding bytes via OnDone.
// TODO(lazyboy): A more descriptive name of this method is warranted, "Done"
// is not so appropriate.
void Done();
class TestObserver : public base::RefCountedThreadSafe<TestObserver> {
public:
virtual void JobStarted(const ExtensionId& extension_id,
const base::FilePath& relative_path) = 0;
virtual void JobFinished(const ExtensionId& extension_id,
const base::FilePath& relative_path,
FailureReason failure_reason) = 0;
virtual void OnHashesReady(const ExtensionId& extension_id,
const base::FilePath& relative_path,
const ContentHashReader& hash_reader) = 0;
protected:
virtual ~TestObserver() = default;
friend class base::RefCountedThreadSafe<TestObserver>;
};
static void SetIgnoreVerificationForTests(bool value);
// Note: having interleaved observer is not supported.
static void SetObserverForTests(scoped_refptr<TestObserver> observer);
private:
virtual ~ContentVerifyJob();
friend class base::RefCountedThreadSafe<ContentVerifyJob>;
void DidGetContentHashOnIO(scoped_refptr<const ContentHash> hash);
// Same as Read, but is run without acquiring lock.
void ReadImpl(const char* data, int count, MojoResult read_result);
// Called each time we're done adding bytes for the current block, and are
// ready to finish the hash operation for those bytes and make sure it
// matches what was expected for that block. Returns true if everything is
// still ok so far, or false if a mismatch was detected.
bool FinishBlock();
// Dispatches the failure callback with the given reason.
void DispatchFailureCallback(FailureReason reason);
// Called when our ContentHashReader has finished initializing.
void OnHashesReady(std::unique_ptr<const ContentHashReader> hash_reader);
// True if BytesRead has seen some errors that can be ignored from content
// verification's perspective.
bool has_ignorable_read_error_ = false;
// Indicates whether the caller has told us they are done calling BytesRead.
bool done_reading_;
// Set to true once hash_reader_ has read its expected hashes.
bool hashes_ready_;
// While we're waiting for the callback from the ContentHashReader, we need
// to queue up bytes any bytes that are read.
std::string queue_;
// The total bytes we've read.
int64_t total_bytes_read_;
// The index of the block we're currently on.
int current_block_;
// The hash we're building up for the bytes of |current_block_|.
std::unique_ptr<crypto::SecureHash> current_hash_;
// The number of bytes we've already input into |current_hash_|.
int current_hash_byte_count_;
// Valid and set after |hashes_ready_| is set to true.
std::unique_ptr<const ContentHashReader> hash_reader_;
// Resource info for this verify job.
const ExtensionId extension_id_;
const base::Version extension_version_;
const base::FilePath extension_root_;
const base::FilePath relative_path_;
base::TimeDelta time_spent_;
// Called once if verification fails.
FailureCallback failure_callback_;
// Set to true if we detected a mismatch and called the failure callback.
bool failed_;
// Used to synchronize all public methods.
base::Lock lock_;
DISALLOW_COPY_AND_ASSIGN(ContentVerifyJob);
};
} // namespace extensions
#endif // EXTENSIONS_BROWSER_CONTENT_VERIFY_JOB_H_