Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(235)

Side by Side Diff: extensions/browser/content_verify_job.cc

Issue 329303007: Fix several problems with the content verification code (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: responded to review comments Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « extensions/browser/content_verify_job.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "extensions/browser/content_verify_job.h" 5 #include "extensions/browser/content_verify_job.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/stl_util.h" 9 #include "base/stl_util.h"
10 #include "base/task_runner_util.h" 10 #include "base/task_runner_util.h"
(...skipping 11 matching lines...) Expand all
22 } // namespace 22 } // namespace
23 23
24 ContentVerifyJob::ContentVerifyJob(ContentHashReader* hash_reader, 24 ContentVerifyJob::ContentVerifyJob(ContentHashReader* hash_reader,
25 const FailureCallback& failure_callback) 25 const FailureCallback& failure_callback)
26 : done_reading_(false), 26 : done_reading_(false),
27 hashes_ready_(false), 27 hashes_ready_(false),
28 total_bytes_read_(0), 28 total_bytes_read_(0),
29 current_block_(0), 29 current_block_(0),
30 current_hash_byte_count_(0), 30 current_hash_byte_count_(0),
31 hash_reader_(hash_reader), 31 hash_reader_(hash_reader),
32 failure_callback_(failure_callback) { 32 failure_callback_(failure_callback),
33 failed_(false) {
33 // It's ok for this object to be constructed on a different thread from where 34 // It's ok for this object to be constructed on a different thread from where
34 // it's used. 35 // it's used.
35 thread_checker_.DetachFromThread(); 36 thread_checker_.DetachFromThread();
36 } 37 }
37 38
38 ContentVerifyJob::~ContentVerifyJob() { 39 ContentVerifyJob::~ContentVerifyJob() {
39 } 40 }
40 41
41 void ContentVerifyJob::Start() { 42 void ContentVerifyJob::Start() {
42 DCHECK(thread_checker_.CalledOnValidThread()); 43 DCHECK(thread_checker_.CalledOnValidThread());
43 base::PostTaskAndReplyWithResult( 44 base::PostTaskAndReplyWithResult(
44 content::BrowserThread::GetBlockingPool(), 45 content::BrowserThread::GetBlockingPool(),
45 FROM_HERE, 46 FROM_HERE,
46 base::Bind(&ContentHashReader::Init, hash_reader_), 47 base::Bind(&ContentHashReader::Init, hash_reader_),
47 base::Bind(&ContentVerifyJob::OnHashesReady, this)); 48 base::Bind(&ContentVerifyJob::OnHashesReady, this));
48 } 49 }
49 50
50 void ContentVerifyJob::BytesRead(int count, const char* data) { 51 void ContentVerifyJob::BytesRead(int count, const char* data) {
51 DCHECK(thread_checker_.CalledOnValidThread()); 52 DCHECK(thread_checker_.CalledOnValidThread());
53 if (failed_)
54 return;
52 if (g_test_delegate) { 55 if (g_test_delegate) {
53 FailureReason reason = 56 FailureReason reason =
54 g_test_delegate->BytesRead(hash_reader_->extension_id(), count, data); 57 g_test_delegate->BytesRead(hash_reader_->extension_id(), count, data);
55 if (reason != NONE) 58 if (reason != NONE)
56 return DispatchFailureCallback(reason); 59 return DispatchFailureCallback(reason);
57 } 60 }
58 if (!hashes_ready_) { 61 if (!hashes_ready_) {
59 queue_.append(data, count); 62 queue_.append(data, count);
60 return; 63 return;
61 } 64 }
62 DCHECK_GE(count, 0); 65 DCHECK_GE(count, 0);
63 int bytes_added = 0; 66 int bytes_added = 0;
64 67
65 while (bytes_added < count) { 68 while (bytes_added < count) {
66 if (current_block_ >= hash_reader_->block_count()) 69 if (current_block_ >= hash_reader_->block_count())
67 return DispatchFailureCallback(HASH_MISMATCH); 70 return DispatchFailureCallback(HASH_MISMATCH);
68 71
69 if (!current_hash_.get()) { 72 if (!current_hash_.get()) {
70 current_hash_byte_count_ = 0; 73 current_hash_byte_count_ = 0;
71 current_hash_.reset( 74 current_hash_.reset(
72 crypto::SecureHash::Create(crypto::SecureHash::SHA256)); 75 crypto::SecureHash::Create(crypto::SecureHash::SHA256));
73 } 76 }
74 // Compute how many bytes we should hash, and add them to the current hash. 77 // Compute how many bytes we should hash, and add them to the current hash.
75 int bytes_to_hash = 78 int bytes_to_hash =
76 std::min(hash_reader_->block_size() - current_hash_byte_count_, 79 std::min(hash_reader_->block_size() - current_hash_byte_count_,
77 count - bytes_added); 80 count - bytes_added);
81 DCHECK(bytes_to_hash > 0);
78 current_hash_->Update(data + bytes_added, bytes_to_hash); 82 current_hash_->Update(data + bytes_added, bytes_to_hash);
79 bytes_added += bytes_to_hash; 83 bytes_added += bytes_to_hash;
80 current_hash_byte_count_ += bytes_to_hash; 84 current_hash_byte_count_ += bytes_to_hash;
81 total_bytes_read_ += bytes_to_hash; 85 total_bytes_read_ += bytes_to_hash;
82 86
83 // If we finished reading a block worth of data, finish computing the hash 87 // If we finished reading a block worth of data, finish computing the hash
84 // for it and make sure the expected hash matches. 88 // for it and make sure the expected hash matches.
85 if (current_hash_byte_count_ == hash_reader_->block_size()) 89 if (current_hash_byte_count_ == hash_reader_->block_size() &&
86 FinishBlock(); 90 !FinishBlock()) {
91 DispatchFailureCallback(HASH_MISMATCH);
92 return;
93 }
87 } 94 }
88 } 95 }
89 96
90 void ContentVerifyJob::DoneReading() { 97 void ContentVerifyJob::DoneReading() {
91 DCHECK(thread_checker_.CalledOnValidThread()); 98 DCHECK(thread_checker_.CalledOnValidThread());
99 if (failed_)
100 return;
92 if (g_test_delegate) { 101 if (g_test_delegate) {
93 FailureReason reason = 102 FailureReason reason =
94 g_test_delegate->DoneReading(hash_reader_->extension_id()); 103 g_test_delegate->DoneReading(hash_reader_->extension_id());
95 if (reason != NONE) { 104 if (reason != NONE) {
96 DispatchFailureCallback(reason); 105 DispatchFailureCallback(reason);
97 return; 106 return;
98 } 107 }
99 } 108 }
100 done_reading_ = true; 109 done_reading_ = true;
101 if (hashes_ready_) 110 if (hashes_ready_ && !FinishBlock())
102 FinishBlock(); 111 DispatchFailureCallback(HASH_MISMATCH);
103 } 112 }
104 113
105 void ContentVerifyJob::FinishBlock() { 114 bool ContentVerifyJob::FinishBlock() {
106 if (current_hash_byte_count_ <= 0) 115 if (current_hash_byte_count_ <= 0)
107 return; 116 return true;
108 std::string final(crypto::kSHA256Length, 0); 117 std::string final(crypto::kSHA256Length, 0);
109 current_hash_->Finish(string_as_array(&final), final.size()); 118 current_hash_->Finish(string_as_array(&final), final.size());
110 119
111 const std::string* expected_hash = NULL; 120 const std::string* expected_hash = NULL;
112 if (!hash_reader_->GetHashForBlock(current_block_, &expected_hash)) 121 if (!hash_reader_->GetHashForBlock(current_block_, &expected_hash) ||
113 return DispatchFailureCallback(HASH_MISMATCH); 122 *expected_hash != final)
114 123 return false;
115 if (*expected_hash != final)
116 return DispatchFailureCallback(HASH_MISMATCH);
117 124
118 current_hash_.reset(); 125 current_hash_.reset();
119 current_hash_byte_count_ = 0; 126 current_hash_byte_count_ = 0;
120 current_block_++; 127 current_block_++;
128 return true;
121 } 129 }
122 130
123 void ContentVerifyJob::OnHashesReady(bool success) { 131 void ContentVerifyJob::OnHashesReady(bool success) {
124 if (!success && !g_test_delegate) 132 if (!success && !g_test_delegate) {
125 return DispatchFailureCallback(NO_HASHES); 133 if (hash_reader_->have_verified_contents() &&
134 hash_reader_->have_computed_hashes())
135 DispatchFailureCallback(NO_HASHES_FOR_FILE);
136 else
137 DispatchFailureCallback(MISSING_ALL_HASHES);
138 return;
139 }
126 140
127 hashes_ready_ = true; 141 hashes_ready_ = true;
128 if (!queue_.empty()) { 142 if (!queue_.empty()) {
129 std::string tmp; 143 std::string tmp;
130 queue_.swap(tmp); 144 queue_.swap(tmp);
131 BytesRead(tmp.size(), string_as_array(&tmp)); 145 BytesRead(tmp.size(), string_as_array(&tmp));
132 } 146 }
133 if (done_reading_) 147 if (done_reading_ && !FinishBlock())
134 FinishBlock(); 148 DispatchFailureCallback(HASH_MISMATCH);
135 } 149 }
136 150
137 // static 151 // static
138 void ContentVerifyJob::SetDelegateForTests(TestDelegate* delegate) { 152 void ContentVerifyJob::SetDelegateForTests(TestDelegate* delegate) {
139 g_test_delegate = delegate; 153 g_test_delegate = delegate;
140 } 154 }
141 155
142 void ContentVerifyJob::DispatchFailureCallback(FailureReason reason) { 156 void ContentVerifyJob::DispatchFailureCallback(FailureReason reason) {
157 DCHECK(!failed_);
158 failed_ = true;
143 if (!failure_callback_.is_null()) { 159 if (!failure_callback_.is_null()) {
160 VLOG(1) << "job failed for " << hash_reader_->extension_id() << " "
161 << hash_reader_->relative_path().MaybeAsASCII()
162 << " reason:" << reason;
144 failure_callback_.Run(reason); 163 failure_callback_.Run(reason);
145 failure_callback_.Reset(); 164 failure_callback_.Reset();
146 } 165 }
147 } 166 }
148 167
149 } // namespace extensions 168 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/browser/content_verify_job.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698