| 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/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| 11 #include "base/task_runner_util.h" | 11 #include "base/task_runner_util.h" |
| 12 #include "base/timer/elapsed_timer.h" | 12 #include "base/timer/elapsed_timer.h" |
| 13 #include "content/public/browser/browser_thread.h" | 13 #include "content/public/browser/browser_thread.h" |
| 14 #include "crypto/secure_hash.h" | 14 #include "crypto/secure_hash.h" |
| 15 #include "crypto/sha2.h" | 15 #include "crypto/sha2.h" |
| 16 #include "extensions/browser/content_hash_reader.h" | 16 #include "extensions/browser/content_hash_reader.h" |
| 17 | 17 |
| 18 namespace extensions { | 18 namespace extensions { |
| 19 | 19 |
| 20 namespace { | 20 namespace { |
| 21 | 21 |
| 22 ContentVerifyJob::TestDelegate* g_test_delegate = NULL; | 22 ContentVerifyJob::TestDelegate* g_test_delegate = NULL; |
| 23 ContentVerifyJob::TestObserver* g_test_observer = NULL; | 23 ContentVerifyJob::TestObserver* g_test_observer = NULL; |
| 24 | 24 |
| 25 class ScopedElapsedTimer { | 25 class ScopedElapsedTimer { |
| 26 public: | 26 public: |
| 27 ScopedElapsedTimer(base::TimeDelta* total) : total_(total) { DCHECK(total_); } | 27 explicit ScopedElapsedTimer(base::TimeDelta* total) : total_(total) { |
| 28 DCHECK(total_); |
| 29 } |
| 28 | 30 |
| 29 ~ScopedElapsedTimer() { *total_ += timer.Elapsed(); } | 31 ~ScopedElapsedTimer() { *total_ += timer.Elapsed(); } |
| 30 | 32 |
| 31 private: | 33 private: |
| 32 // Some total amount of time we should add our elapsed time to at | 34 // Some total amount of time we should add our elapsed time to at |
| 33 // destruction. | 35 // destruction. |
| 34 base::TimeDelta* total_; | 36 base::TimeDelta* total_; |
| 35 | 37 |
| 36 // A timer for how long this object has been alive. | 38 // A timer for how long this object has been alive. |
| 37 base::ElapsedTimer timer; | 39 base::ElapsedTimer timer; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 | 75 |
| 74 void ContentVerifyJob::BytesRead(int count, const char* data) { | 76 void ContentVerifyJob::BytesRead(int count, const char* data) { |
| 75 ScopedElapsedTimer timer(&time_spent_); | 77 ScopedElapsedTimer timer(&time_spent_); |
| 76 DCHECK(thread_checker_.CalledOnValidThread()); | 78 DCHECK(thread_checker_.CalledOnValidThread()); |
| 77 if (failed_) | 79 if (failed_) |
| 78 return; | 80 return; |
| 79 if (g_test_delegate) { | 81 if (g_test_delegate) { |
| 80 FailureReason reason = | 82 FailureReason reason = |
| 81 g_test_delegate->BytesRead(hash_reader_->extension_id(), count, data); | 83 g_test_delegate->BytesRead(hash_reader_->extension_id(), count, data); |
| 82 if (reason != NONE) | 84 if (reason != NONE) |
| 83 return DispatchFailureCallback(reason); | 85 DispatchFailureCallback(reason); |
| 86 return; |
| 84 } | 87 } |
| 85 if (!hashes_ready_) { | 88 if (!hashes_ready_) { |
| 86 queue_.append(data, count); | 89 queue_.append(data, count); |
| 87 return; | 90 return; |
| 88 } | 91 } |
| 89 DCHECK_GE(count, 0); | 92 DCHECK_GE(count, 0); |
| 90 int bytes_added = 0; | 93 int bytes_added = 0; |
| 91 | 94 |
| 92 while (bytes_added < count) { | 95 while (bytes_added < count) { |
| 93 if (current_block_ >= hash_reader_->block_count()) | 96 if (current_block_ >= hash_reader_->block_count()) |
| 94 return DispatchFailureCallback(HASH_MISMATCH); | 97 return DispatchFailureCallback(HASH_MISMATCH); |
| 95 | 98 |
| 96 if (!current_hash_.get()) { | 99 if (!current_hash_.get()) { |
| 97 current_hash_byte_count_ = 0; | 100 current_hash_byte_count_ = 0; |
| 98 current_hash_.reset( | 101 current_hash_.reset( |
| 99 crypto::SecureHash::Create(crypto::SecureHash::SHA256)); | 102 crypto::SecureHash::Create(crypto::SecureHash::SHA256)); |
| 100 } | 103 } |
| 101 // Compute how many bytes we should hash, and add them to the current hash. | 104 // Compute how many bytes we should hash, and add them to the current hash. |
| 102 int bytes_to_hash = | 105 int bytes_to_hash = |
| 103 std::min(hash_reader_->block_size() - current_hash_byte_count_, | 106 std::min(hash_reader_->block_size() - current_hash_byte_count_, |
| 104 count - bytes_added); | 107 count - bytes_added); |
| 105 DCHECK(bytes_to_hash > 0); | 108 DCHECK_GT(bytes_to_hash, 0); |
| 106 current_hash_->Update(data + bytes_added, bytes_to_hash); | 109 current_hash_->Update(data + bytes_added, bytes_to_hash); |
| 107 bytes_added += bytes_to_hash; | 110 bytes_added += bytes_to_hash; |
| 108 current_hash_byte_count_ += bytes_to_hash; | 111 current_hash_byte_count_ += bytes_to_hash; |
| 109 total_bytes_read_ += bytes_to_hash; | 112 total_bytes_read_ += bytes_to_hash; |
| 110 | 113 |
| 111 // If we finished reading a block worth of data, finish computing the hash | 114 // If we finished reading a block worth of data, finish computing the hash |
| 112 // for it and make sure the expected hash matches. | 115 // for it and make sure the expected hash matches. |
| 113 if (current_hash_byte_count_ == hash_reader_->block_size() && | 116 if (current_hash_byte_count_ == hash_reader_->block_size() && |
| 114 !FinishBlock()) { | 117 !FinishBlock()) { |
| 115 DispatchFailureCallback(HASH_MISMATCH); | 118 DispatchFailureCallback(HASH_MISMATCH); |
| 116 return; | 119 return; |
| 117 } | 120 } |
| 118 } | 121 } |
| 119 } | 122 } |
| 120 | 123 |
| 121 void ContentVerifyJob::DoneReading() { | 124 void ContentVerifyJob::DoneReading() { |
| 122 ScopedElapsedTimer timer(&time_spent_); | 125 ScopedElapsedTimer timer(&time_spent_); |
| 123 DCHECK(thread_checker_.CalledOnValidThread()); | 126 DCHECK(thread_checker_.CalledOnValidThread()); |
| 124 if (failed_) | 127 if (failed_) |
| 125 return; | 128 return; |
| 126 if (g_test_delegate) { | 129 if (g_test_delegate) { |
| 127 FailureReason reason = | 130 FailureReason reason = |
| 128 g_test_delegate->DoneReading(hash_reader_->extension_id()); | 131 g_test_delegate->DoneReading(hash_reader_->extension_id()); |
| 129 if (reason != NONE) { | 132 if (reason != NONE) |
| 130 DispatchFailureCallback(reason); | 133 DispatchFailureCallback(reason); |
| 131 return; | 134 return; |
| 132 } | |
| 133 } | 135 } |
| 134 done_reading_ = true; | 136 done_reading_ = true; |
| 135 if (hashes_ready_) { | 137 if (hashes_ready_) { |
| 136 if (!FinishBlock()) | 138 if (!FinishBlock()) |
| 137 DispatchFailureCallback(HASH_MISMATCH); | 139 DispatchFailureCallback(HASH_MISMATCH); |
| 138 else if (g_test_observer) | 140 else if (g_test_observer) |
| 139 g_test_observer->JobFinished(hash_reader_->extension_id(), | 141 g_test_observer->JobFinished(hash_reader_->extension_id(), |
| 140 hash_reader_->relative_path(), failed_); | 142 hash_reader_->relative_path(), failed_); |
| 141 } | 143 } |
| 142 } | 144 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 174 } | 176 } |
| 175 | 177 |
| 176 hashes_ready_ = true; | 178 hashes_ready_ = true; |
| 177 if (!queue_.empty()) { | 179 if (!queue_.empty()) { |
| 178 std::string tmp; | 180 std::string tmp; |
| 179 queue_.swap(tmp); | 181 queue_.swap(tmp); |
| 180 BytesRead(tmp.size(), string_as_array(&tmp)); | 182 BytesRead(tmp.size(), string_as_array(&tmp)); |
| 181 } | 183 } |
| 182 if (done_reading_) { | 184 if (done_reading_) { |
| 183 ScopedElapsedTimer timer(&time_spent_); | 185 ScopedElapsedTimer timer(&time_spent_); |
| 184 if (!FinishBlock()) | 186 if (!FinishBlock()) { |
| 185 DispatchFailureCallback(HASH_MISMATCH); | 187 DispatchFailureCallback(HASH_MISMATCH); |
| 186 else if (g_test_observer) { | 188 } else if (g_test_observer) { |
| 187 g_test_observer->JobFinished(hash_reader_->extension_id(), | 189 g_test_observer->JobFinished(hash_reader_->extension_id(), |
| 188 hash_reader_->relative_path(), failed_); | 190 hash_reader_->relative_path(), failed_); |
| 189 } | 191 } |
| 190 } | 192 } |
| 191 } | 193 } |
| 192 | 194 |
| 193 // static | 195 // static |
| 194 void ContentVerifyJob::SetDelegateForTests(TestDelegate* delegate) { | 196 void ContentVerifyJob::SetDelegateForTests(TestDelegate* delegate) { |
| 195 g_test_delegate = delegate; | 197 g_test_delegate = delegate; |
| 196 } | 198 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 209 << " reason:" << reason; | 211 << " reason:" << reason; |
| 210 failure_callback_.Run(reason); | 212 failure_callback_.Run(reason); |
| 211 failure_callback_.Reset(); | 213 failure_callback_.Reset(); |
| 212 } | 214 } |
| 213 if (g_test_observer) | 215 if (g_test_observer) |
| 214 g_test_observer->JobFinished( | 216 g_test_observer->JobFinished( |
| 215 hash_reader_->extension_id(), hash_reader_->relative_path(), failed_); | 217 hash_reader_->extension_id(), hash_reader_->relative_path(), failed_); |
| 216 } | 218 } |
| 217 | 219 |
| 218 } // namespace extensions | 220 } // namespace extensions |
| OLD | NEW |