| Index: extensions/browser/content_verify_job.cc
|
| diff --git a/extensions/browser/content_verify_job.cc b/extensions/browser/content_verify_job.cc
|
| index 5eec659d331fc24881aeedfe8dc2b5101f96cd0b..e3e35506718441ec9f815f1269efe4b4043d4a27 100644
|
| --- a/extensions/browser/content_verify_job.cc
|
| +++ b/extensions/browser/content_verify_job.cc
|
| @@ -29,7 +29,8 @@ ContentVerifyJob::ContentVerifyJob(ContentHashReader* hash_reader,
|
| current_block_(0),
|
| current_hash_byte_count_(0),
|
| hash_reader_(hash_reader),
|
| - failure_callback_(failure_callback) {
|
| + failure_callback_(failure_callback),
|
| + failed_(false) {
|
| // It's ok for this object to be constructed on a different thread from where
|
| // it's used.
|
| thread_checker_.DetachFromThread();
|
| @@ -49,6 +50,8 @@ void ContentVerifyJob::Start() {
|
|
|
| void ContentVerifyJob::BytesRead(int count, const char* data) {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| + if (failed_)
|
| + return;
|
| if (g_test_delegate) {
|
| FailureReason reason =
|
| g_test_delegate->BytesRead(hash_reader_->extension_id(), count, data);
|
| @@ -75,6 +78,7 @@ void ContentVerifyJob::BytesRead(int count, const char* data) {
|
| int bytes_to_hash =
|
| std::min(hash_reader_->block_size() - current_hash_byte_count_,
|
| count - bytes_added);
|
| + DCHECK(bytes_to_hash > 0);
|
| current_hash_->Update(data + bytes_added, bytes_to_hash);
|
| bytes_added += bytes_to_hash;
|
| current_hash_byte_count_ += bytes_to_hash;
|
| @@ -82,13 +86,18 @@ void ContentVerifyJob::BytesRead(int count, const char* data) {
|
|
|
| // If we finished reading a block worth of data, finish computing the hash
|
| // for it and make sure the expected hash matches.
|
| - if (current_hash_byte_count_ == hash_reader_->block_size())
|
| - FinishBlock();
|
| + if (current_hash_byte_count_ == hash_reader_->block_size() &&
|
| + !FinishBlock()) {
|
| + DispatchFailureCallback(HASH_MISMATCH);
|
| + return;
|
| + }
|
| }
|
| }
|
|
|
| void ContentVerifyJob::DoneReading() {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| + if (failed_)
|
| + return;
|
| if (g_test_delegate) {
|
| FailureReason reason =
|
| g_test_delegate->DoneReading(hash_reader_->extension_id());
|
| @@ -98,31 +107,36 @@ void ContentVerifyJob::DoneReading() {
|
| }
|
| }
|
| done_reading_ = true;
|
| - if (hashes_ready_)
|
| - FinishBlock();
|
| + if (hashes_ready_ && !FinishBlock())
|
| + DispatchFailureCallback(HASH_MISMATCH);
|
| }
|
|
|
| -void ContentVerifyJob::FinishBlock() {
|
| +bool ContentVerifyJob::FinishBlock() {
|
| if (current_hash_byte_count_ <= 0)
|
| - return;
|
| + return true;
|
| std::string final(crypto::kSHA256Length, 0);
|
| current_hash_->Finish(string_as_array(&final), final.size());
|
|
|
| const std::string* expected_hash = NULL;
|
| - if (!hash_reader_->GetHashForBlock(current_block_, &expected_hash))
|
| - return DispatchFailureCallback(HASH_MISMATCH);
|
| -
|
| - if (*expected_hash != final)
|
| - return DispatchFailureCallback(HASH_MISMATCH);
|
| + if (!hash_reader_->GetHashForBlock(current_block_, &expected_hash) ||
|
| + *expected_hash != final)
|
| + return false;
|
|
|
| current_hash_.reset();
|
| current_hash_byte_count_ = 0;
|
| current_block_++;
|
| + return true;
|
| }
|
|
|
| void ContentVerifyJob::OnHashesReady(bool success) {
|
| - if (!success && !g_test_delegate)
|
| - return DispatchFailureCallback(NO_HASHES);
|
| + if (!success && !g_test_delegate) {
|
| + if (hash_reader_->have_verified_contents() &&
|
| + hash_reader_->have_computed_hashes())
|
| + DispatchFailureCallback(NO_HASHES_FOR_FILE);
|
| + else
|
| + DispatchFailureCallback(MISSING_ALL_HASHES);
|
| + return;
|
| + }
|
|
|
| hashes_ready_ = true;
|
| if (!queue_.empty()) {
|
| @@ -130,8 +144,8 @@ void ContentVerifyJob::OnHashesReady(bool success) {
|
| queue_.swap(tmp);
|
| BytesRead(tmp.size(), string_as_array(&tmp));
|
| }
|
| - if (done_reading_)
|
| - FinishBlock();
|
| + if (done_reading_ && !FinishBlock())
|
| + DispatchFailureCallback(HASH_MISMATCH);
|
| }
|
|
|
| // static
|
| @@ -140,7 +154,12 @@ void ContentVerifyJob::SetDelegateForTests(TestDelegate* delegate) {
|
| }
|
|
|
| void ContentVerifyJob::DispatchFailureCallback(FailureReason reason) {
|
| + DCHECK(!failed_);
|
| + failed_ = true;
|
| if (!failure_callback_.is_null()) {
|
| + VLOG(1) << "job failed for " << hash_reader_->extension_id() << " "
|
| + << hash_reader_->relative_path().MaybeAsASCII()
|
| + << " reason:" << reason;
|
| failure_callback_.Run(reason);
|
| failure_callback_.Reset();
|
| }
|
|
|