1010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// found in the LICENSE file. 4010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 5010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#ifndef EXTENSIONS_BROWSER_CONTENT_VERIFY_JOB_H_ 6010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#define EXTENSIONS_BROWSER_CONTENT_VERIFY_JOB_H_ 7010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 8010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include <string> 9010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 10010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/callback.h" 11010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/memory/ref_counted.h" 12010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 13010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/threading/thread_checker.h" 14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 15010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace base { 16010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)class FilePath; 17010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 18010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace crypto { 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class SecureHash; 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 23010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace extensions { 24010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 25010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)class ContentHashReader; 26010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 27010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Objects of this class are responsible for verifying that the actual content 28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// read from an extension file matches an expected set of hashes. This class 29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// can be created on any thread but the rest of the methods should be called 30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// from only one thread. 31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)class ContentVerifyJob : public base::RefCountedThreadSafe<ContentVerifyJob> { 32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) public: 33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) enum FailureReason { 34010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // No failure. 35010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) NONE, 36010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Failed because there were no expected hashes at all (eg they haven't 38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // been fetched yet). 39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MISSING_ALL_HASHES, 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Failed because this file wasn't found in the list of expected hashes. 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NO_HASHES_FOR_FILE, 43010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 44010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Some of the content read did not match the expected hash. 4534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) HASH_MISMATCH, 4634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 4734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) FAILURE_REASON_MAX 48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) }; 49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) typedef base::Callback<void(FailureReason)> FailureCallback; 50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 51010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // The |failure_callback| will be called at most once if there was a failure. 52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ContentVerifyJob(ContentHashReader* hash_reader, 53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const FailureCallback& failure_callback); 54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // This begins the process of getting expected hashes, so it should be called 56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // as early as possible. 57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) void Start(); 58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Call this to add more bytes to verify. If at any point the read bytes 60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // don't match the expected hashes, this will dispatch the failure 61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // callback. The failure callback will only be run once even if more bytes 62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // are read. Make sure to call DoneReading so that any final bytes that were 63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // read that didn't align exactly on a block size boundary get their hash 64010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // checked as well. 65010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) void BytesRead(int count, const char* data); 66010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Call once when finished adding bytes via BytesRead. 68010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) void DoneReading(); 69010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 70010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) class TestDelegate { 71010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) public: 72010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // These methods will be called inside BytesRead/DoneReading respectively. 73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // If either return something other than NONE, then the failure callback 74010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // will be dispatched with that reason. 75010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) virtual FailureReason BytesRead(const std::string& extension_id, 76010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int count, 77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const char* data) = 0; 78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) virtual FailureReason DoneReading(const std::string& extension_id) = 0; 79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) }; 80010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 811675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch class TestObserver { 821675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch public: 831675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch virtual void JobStarted(const std::string& extension_id, 841675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch const base::FilePath& relative_path) = 0; 851675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch 861675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch virtual void JobFinished(const std::string& extension_id, 871675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch const base::FilePath& relative_path, 881675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch bool failed) = 0; 891675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch }; 901675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch 91010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) static void SetDelegateForTests(TestDelegate* delegate); 921675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch static void SetObserverForTests(TestObserver* observer); 93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) private: 95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ContentVerifyJob); 96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) virtual ~ContentVerifyJob(); 98010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) friend class base::RefCountedThreadSafe<ContentVerifyJob>; 99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Called each time we're done adding bytes for the current block, and are 101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // ready to finish the hash operation for those bytes and make sure it 102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // matches what was expected for that block. Returns true if everything is 103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // still ok so far, or false if a mismatch was detected. 104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool FinishBlock(); 105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Dispatches the failure callback with the given reason. 107010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) void DispatchFailureCallback(FailureReason reason); 108010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Called when our ContentHashReader has finished initializing. 110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void OnHashesReady(bool success); 111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Indicates whether the caller has told us they are done calling BytesRead. 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool done_reading_; 114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Set to true once hash_reader_ has read its expected hashes. 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool hashes_ready_; 117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // While we're waiting for the callback from the ContentHashReader, we need 119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // to queue up bytes any bytes that are read. 120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string queue_; 121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // The total bytes we've read. 123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int64 total_bytes_read_; 124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // The index of the block we're currently on. 126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int current_block_; 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // The hash we're building up for the bytes of |current_block_|. 129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<crypto::SecureHash> current_hash_; 130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // The number of bytes we've already input into |current_hash_|. 132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int current_hash_byte_count_; 133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_refptr<ContentHashReader> hash_reader_; 135010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::TimeDelta time_spent_; 137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 138010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Called once if verification fails. 139010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) FailureCallback failure_callback_; 140010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Set to true if we detected a mismatch and called the failure callback. 142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool failed_; 143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 144010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // For ensuring methods on called on the right thread. 145010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::ThreadChecker thread_checker_; 146010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}; 147010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 148010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} // namespace extensions 149010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 150010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif // EXTENSIONS_BROWSER_CONTENT_VERIFY_JOB_H_ 151