OLD | NEW |
---|---|
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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
42 DCHECK(thread_checker_.CalledOnValidThread()); | 42 DCHECK(thread_checker_.CalledOnValidThread()); |
43 base::PostTaskAndReplyWithResult( | 43 base::PostTaskAndReplyWithResult( |
44 content::BrowserThread::GetBlockingPool(), | 44 content::BrowserThread::GetBlockingPool(), |
45 FROM_HERE, | 45 FROM_HERE, |
46 base::Bind(&ContentHashReader::Init, hash_reader_), | 46 base::Bind(&ContentHashReader::Init, hash_reader_), |
47 base::Bind(&ContentVerifyJob::OnHashesReady, this)); | 47 base::Bind(&ContentVerifyJob::OnHashesReady, this)); |
48 } | 48 } |
49 | 49 |
50 void ContentVerifyJob::BytesRead(int count, const char* data) { | 50 void ContentVerifyJob::BytesRead(int count, const char* data) { |
51 DCHECK(thread_checker_.CalledOnValidThread()); | 51 DCHECK(thread_checker_.CalledOnValidThread()); |
52 if (failure_callback_.is_null()) | |
Ken Rockot(use gerrit already)
2014/06/17 16:43:43
I think it would be easier to understand if you ju
asargent_no_longer_on_chrome
2014/06/18 00:13:51
Good suggestion. Done.
| |
53 return; | |
52 if (g_test_delegate) { | 54 if (g_test_delegate) { |
53 FailureReason reason = | 55 FailureReason reason = |
54 g_test_delegate->BytesRead(hash_reader_->extension_id(), count, data); | 56 g_test_delegate->BytesRead(hash_reader_->extension_id(), count, data); |
55 if (reason != NONE) | 57 if (reason != NONE) |
56 return DispatchFailureCallback(reason); | 58 return DispatchFailureCallback(reason); |
57 } | 59 } |
58 if (!hashes_ready_) { | 60 if (!hashes_ready_) { |
59 queue_.append(data, count); | 61 queue_.append(data, count); |
60 return; | 62 return; |
61 } | 63 } |
62 DCHECK_GE(count, 0); | 64 DCHECK_GE(count, 0); |
63 int bytes_added = 0; | 65 int bytes_added = 0; |
64 | 66 |
65 while (bytes_added < count) { | 67 while (bytes_added < count) { |
68 if (failure_callback_.is_null()) | |
Ken Rockot(use gerrit already)
2014/06/17 16:43:43
In this specific case, if FinishBlock() is the onl
| |
69 return; | |
70 | |
66 if (current_block_ >= hash_reader_->block_count()) | 71 if (current_block_ >= hash_reader_->block_count()) |
67 return DispatchFailureCallback(HASH_MISMATCH); | 72 return DispatchFailureCallback(HASH_MISMATCH); |
68 | 73 |
69 if (!current_hash_.get()) { | 74 if (!current_hash_.get()) { |
70 current_hash_byte_count_ = 0; | 75 current_hash_byte_count_ = 0; |
71 current_hash_.reset( | 76 current_hash_.reset( |
72 crypto::SecureHash::Create(crypto::SecureHash::SHA256)); | 77 crypto::SecureHash::Create(crypto::SecureHash::SHA256)); |
73 } | 78 } |
74 // Compute how many bytes we should hash, and add them to the current hash. | 79 // Compute how many bytes we should hash, and add them to the current hash. |
75 int bytes_to_hash = | 80 int bytes_to_hash = |
76 std::min(hash_reader_->block_size() - current_hash_byte_count_, | 81 std::min(hash_reader_->block_size() - current_hash_byte_count_, |
77 count - bytes_added); | 82 count - bytes_added); |
83 DCHECK(bytes_to_hash > 0); | |
78 current_hash_->Update(data + bytes_added, bytes_to_hash); | 84 current_hash_->Update(data + bytes_added, bytes_to_hash); |
79 bytes_added += bytes_to_hash; | 85 bytes_added += bytes_to_hash; |
80 current_hash_byte_count_ += bytes_to_hash; | 86 current_hash_byte_count_ += bytes_to_hash; |
81 total_bytes_read_ += bytes_to_hash; | 87 total_bytes_read_ += bytes_to_hash; |
82 | 88 |
83 // If we finished reading a block worth of data, finish computing the hash | 89 // If we finished reading a block worth of data, finish computing the hash |
84 // for it and make sure the expected hash matches. | 90 // for it and make sure the expected hash matches. |
85 if (current_hash_byte_count_ == hash_reader_->block_size()) | 91 if (current_hash_byte_count_ == hash_reader_->block_size()) |
86 FinishBlock(); | 92 FinishBlock(); |
87 } | 93 } |
88 } | 94 } |
89 | 95 |
90 void ContentVerifyJob::DoneReading() { | 96 void ContentVerifyJob::DoneReading() { |
91 DCHECK(thread_checker_.CalledOnValidThread()); | 97 DCHECK(thread_checker_.CalledOnValidThread()); |
98 if (failure_callback_.is_null()) | |
99 return; | |
92 if (g_test_delegate) { | 100 if (g_test_delegate) { |
93 FailureReason reason = | 101 FailureReason reason = |
94 g_test_delegate->DoneReading(hash_reader_->extension_id()); | 102 g_test_delegate->DoneReading(hash_reader_->extension_id()); |
95 if (reason != NONE) { | 103 if (reason != NONE) { |
96 DispatchFailureCallback(reason); | 104 DispatchFailureCallback(reason); |
97 return; | 105 return; |
98 } | 106 } |
99 } | 107 } |
100 done_reading_ = true; | 108 done_reading_ = true; |
101 if (hashes_ready_) | 109 if (hashes_ready_) |
102 FinishBlock(); | 110 FinishBlock(); |
103 } | 111 } |
104 | 112 |
105 void ContentVerifyJob::FinishBlock() { | 113 void ContentVerifyJob::FinishBlock() { |
106 if (current_hash_byte_count_ <= 0) | 114 if (current_hash_byte_count_ <= 0) |
107 return; | 115 return; |
108 std::string final(crypto::kSHA256Length, 0); | 116 std::string final(crypto::kSHA256Length, 0); |
109 current_hash_->Finish(string_as_array(&final), final.size()); | 117 current_hash_->Finish(string_as_array(&final), final.size()); |
110 | 118 |
111 const std::string* expected_hash = NULL; | 119 const std::string* expected_hash = NULL; |
112 if (!hash_reader_->GetHashForBlock(current_block_, &expected_hash)) | 120 if (!hash_reader_->GetHashForBlock(current_block_, &expected_hash) || |
113 return DispatchFailureCallback(HASH_MISMATCH); | 121 *expected_hash != final) |
114 | 122 DispatchFailureCallback(HASH_MISMATCH); |
115 if (*expected_hash != final) | |
116 return DispatchFailureCallback(HASH_MISMATCH); | |
117 | 123 |
118 current_hash_.reset(); | 124 current_hash_.reset(); |
119 current_hash_byte_count_ = 0; | 125 current_hash_byte_count_ = 0; |
120 current_block_++; | 126 current_block_++; |
121 } | 127 } |
122 | 128 |
123 void ContentVerifyJob::OnHashesReady(bool success) { | 129 void ContentVerifyJob::OnHashesReady(bool success) { |
124 if (!success && !g_test_delegate) | 130 if (!success && !g_test_delegate) { |
125 return DispatchFailureCallback(NO_HASHES); | 131 if (hash_reader_->have_verified_contents() && |
132 hash_reader_->have_computed_hashes()) | |
133 DispatchFailureCallback(NO_HASHES_FOR_FILE); | |
134 else | |
135 DispatchFailureCallback(MISSING_ALL_HASHES); | |
136 return; | |
137 } | |
126 | 138 |
127 hashes_ready_ = true; | 139 hashes_ready_ = true; |
128 if (!queue_.empty()) { | 140 if (!queue_.empty()) { |
129 std::string tmp; | 141 std::string tmp; |
130 queue_.swap(tmp); | 142 queue_.swap(tmp); |
131 BytesRead(tmp.size(), string_as_array(&tmp)); | 143 BytesRead(tmp.size(), string_as_array(&tmp)); |
132 } | 144 } |
133 if (done_reading_) | 145 if (done_reading_) |
134 FinishBlock(); | 146 FinishBlock(); |
135 } | 147 } |
136 | 148 |
137 // static | 149 // static |
138 void ContentVerifyJob::SetDelegateForTests(TestDelegate* delegate) { | 150 void ContentVerifyJob::SetDelegateForTests(TestDelegate* delegate) { |
139 g_test_delegate = delegate; | 151 g_test_delegate = delegate; |
140 } | 152 } |
141 | 153 |
142 void ContentVerifyJob::DispatchFailureCallback(FailureReason reason) { | 154 void ContentVerifyJob::DispatchFailureCallback(FailureReason reason) { |
143 if (!failure_callback_.is_null()) { | 155 if (!failure_callback_.is_null()) { |
156 VLOG(1) << "job failed for " << hash_reader_->extension_id() << " " | |
157 << hash_reader_->relative_path().MaybeAsASCII() | |
158 << " reason:" << reason; | |
144 failure_callback_.Run(reason); | 159 failure_callback_.Run(reason); |
145 failure_callback_.Reset(); | 160 failure_callback_.Reset(); |
146 } | 161 } |
147 } | 162 } |
148 | 163 |
149 } // namespace extensions | 164 } // namespace extensions |
OLD | NEW |