content_verify_job.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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. #ifndef EXTENSIONS_BROWSER_CONTENT_VERIFY_JOB_H_
  5. #define EXTENSIONS_BROWSER_CONTENT_VERIFY_JOB_H_
  6. #include <stdint.h>
  7. #include <memory>
  8. #include <string>
  9. #include "base/callback.h"
  10. #include "base/files/file_path.h"
  11. #include "base/memory/ref_counted.h"
  12. #include "base/synchronization/lock.h"
  13. #include "base/time/time.h"
  14. #include "base/version.h"
  15. #include "extensions/browser/content_verifier/content_verifier_key.h"
  16. #include "extensions/common/extension_id.h"
  17. #include "mojo/public/c/system/types.h"
  18. namespace base {
  19. class FilePath;
  20. }
  21. namespace crypto {
  22. class SecureHash;
  23. }
  24. namespace extensions {
  25. class ContentHash;
  26. class ContentHashReader;
  27. class ContentVerifier;
  28. // Objects of this class are responsible for verifying that the actual content
  29. // read from an extension file matches an expected set of hashes. This class
  30. // can be created and used on any thread.
  31. class ContentVerifyJob : public base::RefCountedThreadSafe<ContentVerifyJob> {
  32. public:
  33. enum FailureReason {
  34. // No failure.
  35. NONE,
  36. // Failed because there were no expected hashes at all (eg they haven't
  37. // been fetched yet).
  38. MISSING_ALL_HASHES,
  39. // Failed because hashes files exist, but are unreadabale or damaged, and
  40. // content verifier was not able to compute new hashes.
  41. CORRUPTED_HASHES,
  42. // Failed because this file wasn't found in the list of expected hashes.
  43. NO_HASHES_FOR_FILE,
  44. // Some of the content read did not match the expected hash.
  45. HASH_MISMATCH,
  46. FAILURE_REASON_MAX
  47. };
  48. using FailureCallback = base::OnceCallback<void(FailureReason)>;
  49. // The |failure_callback| will be called at most once if there was a failure.
  50. ContentVerifyJob(const ExtensionId& extension_id,
  51. const base::Version& extension_version,
  52. const base::FilePath& extension_root,
  53. const base::FilePath& relative_path,
  54. FailureCallback failure_callback);
  55. ContentVerifyJob(const ContentVerifyJob&) = delete;
  56. ContentVerifyJob& operator=(const ContentVerifyJob&) = delete;
  57. // This begins the process of getting expected hashes, so it should be called
  58. // as early as possible.
  59. void Start(ContentVerifier* verifier);
  60. // Call this to add more bytes to verify. If at any point the read bytes
  61. // don't match the expected hashes, this will dispatch the failure callback.
  62. // The failure callback will only be run once even if more bytes are read.
  63. // Make sure to call Done so that any final bytes that were read that didn't
  64. // align exactly on a block size boundary get their hash checked as well.
  65. void Read(const char* data, int count, MojoResult read_result);
  66. // Call once when finished adding bytes via OnDone.
  67. // TODO(lazyboy): A more descriptive name of this method is warranted, "Done"
  68. // is not so appropriate.
  69. void Done();
  70. class TestObserver : public base::RefCountedThreadSafe<TestObserver> {
  71. public:
  72. virtual void JobStarted(const ExtensionId& extension_id,
  73. const base::FilePath& relative_path) = 0;
  74. virtual void JobFinished(const ExtensionId& extension_id,
  75. const base::FilePath& relative_path,
  76. FailureReason failure_reason) = 0;
  77. virtual void OnHashesReady(const ExtensionId& extension_id,
  78. const base::FilePath& relative_path,
  79. const ContentHashReader& hash_reader) = 0;
  80. protected:
  81. virtual ~TestObserver() = default;
  82. friend class base::RefCountedThreadSafe<TestObserver>;
  83. };
  84. static void SetIgnoreVerificationForTests(bool value);
  85. // Note: having interleaved observer is not supported.
  86. static void SetObserverForTests(scoped_refptr<TestObserver> observer);
  87. private:
  88. virtual ~ContentVerifyJob();
  89. friend class base::RefCountedThreadSafe<ContentVerifyJob>;
  90. void DidGetContentHashOnIO(scoped_refptr<const ContentHash> hash);
  91. // Same as Read, but is run without acquiring lock.
  92. void ReadImpl(const char* data, int count, MojoResult read_result);
  93. // Called each time we're done adding bytes for the current block, and are
  94. // ready to finish the hash operation for those bytes and make sure it
  95. // matches what was expected for that block. Returns true if everything is
  96. // still ok so far, or false if a mismatch was detected.
  97. bool FinishBlock();
  98. // Dispatches the failure callback with the given reason.
  99. void DispatchFailureCallback(FailureReason reason);
  100. // Called when our ContentHashReader has finished initializing.
  101. void OnHashesReady(std::unique_ptr<const ContentHashReader> hash_reader);
  102. // True if BytesRead has seen some errors that can be ignored from content
  103. // verification's perspective.
  104. bool has_ignorable_read_error_ = false;
  105. // Indicates whether the caller has told us they are done calling BytesRead.
  106. bool done_reading_;
  107. // Set to true once hash_reader_ has read its expected hashes.
  108. bool hashes_ready_;
  109. // While we're waiting for the callback from the ContentHashReader, we need
  110. // to queue up bytes any bytes that are read.
  111. std::string queue_;
  112. // The total bytes we've read.
  113. int64_t total_bytes_read_;
  114. // The index of the block we're currently on.
  115. int current_block_;
  116. // The hash we're building up for the bytes of |current_block_|.
  117. std::unique_ptr<crypto::SecureHash> current_hash_;
  118. // The number of bytes we've already input into |current_hash_|.
  119. int current_hash_byte_count_;
  120. // Valid and set after |hashes_ready_| is set to true.
  121. std::unique_ptr<const ContentHashReader> hash_reader_;
  122. // Resource info for this verify job.
  123. const ExtensionId extension_id_;
  124. const base::Version extension_version_;
  125. const base::FilePath extension_root_;
  126. const base::FilePath relative_path_;
  127. base::TimeDelta time_spent_;
  128. // Called once if verification fails.
  129. FailureCallback failure_callback_;
  130. // Set to true if we detected a mismatch and called the failure callback.
  131. bool failed_;
  132. // Used to synchronize all public methods.
  133. base::Lock lock_;
  134. };
  135. } // namespace extensions
  136. #endif // EXTENSIONS_BROWSER_CONTENT_VERIFY_JOB_H_