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 3// found in the LICENSE file. 4 5#ifndef EXTENSIONS_BROWSER_CONTENT_VERIFY_JOB_H_ 6#define EXTENSIONS_BROWSER_CONTENT_VERIFY_JOB_H_ 7 8#include <string> 9 10#include "base/callback.h" 11#include "base/memory/ref_counted.h" 12#include "base/memory/scoped_ptr.h" 13#include "base/threading/thread_checker.h" 14 15namespace base { 16class FilePath; 17} 18 19namespace crypto { 20class SecureHash; 21} 22 23namespace extensions { 24 25class ContentHashReader; 26 27// Objects of this class are responsible for verifying that the actual content 28// read from an extension file matches an expected set of hashes. This class 29// can be created on any thread but the rest of the methods should be called 30// from only one thread. 31class ContentVerifyJob : public base::RefCountedThreadSafe<ContentVerifyJob> { 32 public: 33 enum FailureReason { 34 // No failure. 35 NONE, 36 37 // Failed because there were no expected hashes at all (eg they haven't 38 // been fetched yet). 39 MISSING_ALL_HASHES, 40 41 // Failed because this file wasn't found in the list of expected hashes. 42 NO_HASHES_FOR_FILE, 43 44 // Some of the content read did not match the expected hash. 45 HASH_MISMATCH, 46 47 FAILURE_REASON_MAX 48 }; 49 typedef base::Callback<void(FailureReason)> FailureCallback; 50 51 // The |failure_callback| will be called at most once if there was a failure. 52 ContentVerifyJob(ContentHashReader* hash_reader, 53 const FailureCallback& failure_callback); 54 55 // This begins the process of getting expected hashes, so it should be called 56 // as early as possible. 57 void Start(); 58 59 // Call this to add more bytes to verify. If at any point the read bytes 60 // don't match the expected hashes, this will dispatch the failure 61 // callback. The failure callback will only be run once even if more bytes 62 // are read. Make sure to call DoneReading so that any final bytes that were 63 // read that didn't align exactly on a block size boundary get their hash 64 // checked as well. 65 void BytesRead(int count, const char* data); 66 67 // Call once when finished adding bytes via BytesRead. 68 void DoneReading(); 69 70 class TestDelegate { 71 public: 72 // These methods will be called inside BytesRead/DoneReading respectively. 73 // If either return something other than NONE, then the failure callback 74 // will be dispatched with that reason. 75 virtual FailureReason BytesRead(const std::string& extension_id, 76 int count, 77 const char* data) = 0; 78 virtual FailureReason DoneReading(const std::string& extension_id) = 0; 79 }; 80 81 class TestObserver { 82 public: 83 virtual void JobStarted(const std::string& extension_id, 84 const base::FilePath& relative_path) = 0; 85 86 virtual void JobFinished(const std::string& extension_id, 87 const base::FilePath& relative_path, 88 bool failed) = 0; 89 }; 90 91 static void SetDelegateForTests(TestDelegate* delegate); 92 static void SetObserverForTests(TestObserver* observer); 93 94 private: 95 DISALLOW_COPY_AND_ASSIGN(ContentVerifyJob); 96 97 virtual ~ContentVerifyJob(); 98 friend class base::RefCountedThreadSafe<ContentVerifyJob>; 99 100 // Called each time we're done adding bytes for the current block, and are 101 // ready to finish the hash operation for those bytes and make sure it 102 // matches what was expected for that block. Returns true if everything is 103 // still ok so far, or false if a mismatch was detected. 104 bool FinishBlock(); 105 106 // Dispatches the failure callback with the given reason. 107 void DispatchFailureCallback(FailureReason reason); 108 109 // Called when our ContentHashReader has finished initializing. 110 void OnHashesReady(bool success); 111 112 // Indicates whether the caller has told us they are done calling BytesRead. 113 bool done_reading_; 114 115 // Set to true once hash_reader_ has read its expected hashes. 116 bool hashes_ready_; 117 118 // While we're waiting for the callback from the ContentHashReader, we need 119 // to queue up bytes any bytes that are read. 120 std::string queue_; 121 122 // The total bytes we've read. 123 int64 total_bytes_read_; 124 125 // The index of the block we're currently on. 126 int current_block_; 127 128 // The hash we're building up for the bytes of |current_block_|. 129 scoped_ptr<crypto::SecureHash> current_hash_; 130 131 // The number of bytes we've already input into |current_hash_|. 132 int current_hash_byte_count_; 133 134 scoped_refptr<ContentHashReader> hash_reader_; 135 136 base::TimeDelta time_spent_; 137 138 // Called once if verification fails. 139 FailureCallback failure_callback_; 140 141 // Set to true if we detected a mismatch and called the failure callback. 142 bool failed_; 143 144 // For ensuring methods on called on the right thread. 145 base::ThreadChecker thread_checker_; 146}; 147 148} // namespace extensions 149 150#endif // EXTENSIONS_BROWSER_CONTENT_VERIFY_JOB_H_ 151