Chromium Code Reviews| 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_hash_fetcher.h" | 5 #include "extensions/browser/content_hash_fetcher.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <memory> | 10 #include <memory> |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 67 // Cancels this job, which will attempt to stop I/O operations sooner than | 67 // Cancels this job, which will attempt to stop I/O operations sooner than |
| 68 // just waiting for the entire job to complete. Safe to call from any thread. | 68 // just waiting for the entire job to complete. Safe to call from any thread. |
| 69 void Cancel(); | 69 void Cancel(); |
| 70 | 70 |
| 71 // Checks whether this job has been cancelled. Safe to call from any thread. | 71 // Checks whether this job has been cancelled. Safe to call from any thread. |
| 72 bool IsCancelled(); | 72 bool IsCancelled(); |
| 73 | 73 |
| 74 // Returns whether this job was successful (we have both verified contents | 74 // Returns whether this job was successful (we have both verified contents |
| 75 // and computed hashes). Even if the job was a success, there might have been | 75 // and computed hashes). Even if the job was a success, there might have been |
| 76 // files that were found to have contents not matching expectations; these | 76 // files that were found to have contents not matching expectations; these |
| 77 // are available by calling hash_mismatch_paths(). | 77 // are available by calling hash_mismatch_unix_paths(). |
| 78 bool success() { return success_; } | 78 bool success() { return success_; } |
| 79 | 79 |
| 80 bool force() { return force_; } | 80 bool force() { return force_; } |
| 81 | 81 |
| 82 const std::string& extension_id() { return extension_id_; } | 82 const std::string& extension_id() { return extension_id_; } |
| 83 | 83 |
| 84 // Returns the set of paths that had a hash mismatch. | 84 // Returns the set of paths (with unix style / separators) that had a hash |
|
Devlin
2017/04/24 15:06:56
I read this as "unix style/separators" rather than
lazyboy
2017/04/24 18:29:58
Done.
| |
| 85 const std::set<base::FilePath>& hash_mismatch_paths() { | 85 // mismatch. |
| 86 return hash_mismatch_paths_; | 86 const std::set<base::FilePath>& hash_mismatch_unix_paths() { |
| 87 return hash_mismatch_unix_paths_; | |
| 87 } | 88 } |
| 88 | 89 |
| 89 private: | 90 private: |
| 90 friend class base::RefCountedThreadSafe<ContentHashFetcherJob>; | 91 friend class base::RefCountedThreadSafe<ContentHashFetcherJob>; |
| 91 ~ContentHashFetcherJob() override; | 92 ~ContentHashFetcherJob() override; |
| 92 | 93 |
| 93 // Tries to load a verified_contents.json file at |path|. On successfully | 94 // Tries to load a verified_contents.json file at |path|. On successfully |
| 94 // reading and validing the file, the verified_contents_ member variable will | 95 // reading and validing the file, the verified_contents_ member variable will |
| 95 // be set and this function will return true. If the file does not exist, or | 96 // be set and this function will return true. If the file does not exist, or |
| 96 // exists but is invalid, it will return false. Also, any invalid | 97 // exists but is invalid, it will return false. Also, any invalid |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 148 ContentVerifierKey key_; | 149 ContentVerifierKey key_; |
| 149 | 150 |
| 150 // The parsed contents of the verified_contents.json file, either read from | 151 // The parsed contents of the verified_contents.json file, either read from |
| 151 // disk or fetched from the network and then written to disk. | 152 // disk or fetched from the network and then written to disk. |
| 152 std::unique_ptr<VerifiedContents> verified_contents_; | 153 std::unique_ptr<VerifiedContents> verified_contents_; |
| 153 | 154 |
| 154 // Whether this job succeeded. | 155 // Whether this job succeeded. |
| 155 bool success_; | 156 bool success_; |
| 156 | 157 |
| 157 // Paths that were found to have a mismatching hash. | 158 // Paths that were found to have a mismatching hash. |
| 158 std::set<base::FilePath> hash_mismatch_paths_; | 159 std::set<base::FilePath> hash_mismatch_unix_paths_; |
| 159 | 160 |
| 160 // The block size to use for hashing. | 161 // The block size to use for hashing. |
| 161 int block_size_; | 162 int block_size_; |
| 162 | 163 |
| 163 // Note: this may be accessed from multiple threads, so all access should | 164 // Note: this may be accessed from multiple threads, so all access should |
| 164 // be protected by |cancelled_lock_|. | 165 // be protected by |cancelled_lock_|. |
| 165 bool cancelled_; | 166 bool cancelled_; |
| 166 | 167 |
| 167 // A lock for synchronizing access to |cancelled_|. | 168 // A lock for synchronizing access to |cancelled_|. |
| 168 base::Lock cancelled_lock_; | 169 base::Lock cancelled_lock_; |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 410 paths.insert(full_path); | 411 paths.insert(full_path); |
| 411 } | 412 } |
| 412 | 413 |
| 413 // Now iterate over all the paths in sorted order and compute the block hashes | 414 // Now iterate over all the paths in sorted order and compute the block hashes |
| 414 // for each one. | 415 // for each one. |
| 415 ComputedHashes::Writer writer; | 416 ComputedHashes::Writer writer; |
| 416 for (SortedFilePathSet::iterator i = paths.begin(); i != paths.end(); ++i) { | 417 for (SortedFilePathSet::iterator i = paths.begin(); i != paths.end(); ++i) { |
| 417 if (IsCancelled()) | 418 if (IsCancelled()) |
| 418 return false; | 419 return false; |
| 419 const base::FilePath& full_path = *i; | 420 const base::FilePath& full_path = *i; |
| 420 base::FilePath relative_path; | 421 base::FilePath relative_unix_path; |
| 421 extension_path_.AppendRelativePath(full_path, &relative_path); | 422 extension_path_.AppendRelativePath(full_path, &relative_unix_path); |
| 422 relative_path = relative_path.NormalizePathSeparatorsTo('/'); | 423 relative_unix_path = relative_unix_path.NormalizePathSeparatorsTo('/'); |
| 423 | 424 |
| 424 if (!verified_contents_->HasTreeHashRoot(relative_path)) | 425 if (!verified_contents_->HasTreeHashRoot(relative_unix_path)) |
| 425 continue; | 426 continue; |
| 426 | 427 |
| 427 std::string contents; | 428 std::string contents; |
| 428 if (!base::ReadFileToString(full_path, &contents)) { | 429 if (!base::ReadFileToString(full_path, &contents)) { |
| 429 LOG(ERROR) << "Could not read " << full_path.MaybeAsASCII(); | 430 LOG(ERROR) << "Could not read " << full_path.MaybeAsASCII(); |
| 430 continue; | 431 continue; |
| 431 } | 432 } |
| 432 | 433 |
| 433 // Iterate through taking the hash of each block of size (block_size_) of | 434 // Iterate through taking the hash of each block of size (block_size_) of |
| 434 // the file. | 435 // the file. |
| 435 std::vector<std::string> hashes; | 436 std::vector<std::string> hashes; |
| 436 ComputedHashes::ComputeHashesForContent(contents, block_size_, &hashes); | 437 ComputedHashes::ComputeHashesForContent(contents, block_size_, &hashes); |
| 437 std::string root = | 438 std::string root = |
| 438 ComputeTreeHashRoot(hashes, block_size_ / crypto::kSHA256Length); | 439 ComputeTreeHashRoot(hashes, block_size_ / crypto::kSHA256Length); |
| 439 if (!verified_contents_->TreeHashRootEquals(relative_path, root)) { | 440 if (!verified_contents_->TreeHashRootEquals(relative_unix_path, root)) { |
| 440 VLOG(1) << "content mismatch for " << relative_path.AsUTF8Unsafe(); | 441 VLOG(1) << "content mismatch for " << relative_unix_path.AsUTF8Unsafe(); |
| 441 hash_mismatch_paths_.insert(relative_path); | 442 hash_mismatch_unix_paths_.insert(relative_unix_path); |
| 442 continue; | 443 continue; |
| 443 } | 444 } |
| 444 | 445 |
| 445 writer.AddHashes(relative_path, block_size_, hashes); | 446 writer.AddHashes(relative_unix_path, block_size_, hashes); |
| 446 } | 447 } |
| 447 bool result = writer.WriteToFile(hashes_file); | 448 bool result = writer.WriteToFile(hashes_file); |
| 448 UMA_HISTOGRAM_TIMES("ExtensionContentHashFetcher.CreateHashesTime", | 449 UMA_HISTOGRAM_TIMES("ExtensionContentHashFetcher.CreateHashesTime", |
| 449 timer.Elapsed()); | 450 timer.Elapsed()); |
| 450 return result; | 451 return result; |
| 451 } | 452 } |
| 452 | 453 |
| 453 void ContentHashFetcherJob::DispatchCallback() { | 454 void ContentHashFetcherJob::DispatchCallback() { |
| 454 { | 455 { |
| 455 base::AutoLock autolock(cancelled_lock_); | 456 base::AutoLock autolock(cancelled_lock_); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 524 } | 525 } |
| 525 } | 526 } |
| 526 | 527 |
| 527 void ContentHashFetcher::JobFinished(scoped_refptr<ContentHashFetcherJob> job) { | 528 void ContentHashFetcher::JobFinished(scoped_refptr<ContentHashFetcherJob> job) { |
| 528 if (!job->IsCancelled()) { | 529 if (!job->IsCancelled()) { |
| 529 // Note: Run can result in ContentHashFetcher::ExtensionUnloaded. | 530 // Note: Run can result in ContentHashFetcher::ExtensionUnloaded. |
| 530 // | 531 // |
| 531 // TODO(lazyboy): Add a unit test to cover the case where Run can result in | 532 // TODO(lazyboy): Add a unit test to cover the case where Run can result in |
| 532 // ContentHashFetcher::ExtensionUnloaded, once https://crbug.com/702300 is | 533 // ContentHashFetcher::ExtensionUnloaded, once https://crbug.com/702300 is |
| 533 // fixed. | 534 // fixed. |
| 534 fetch_callback_.Run(job->extension_id(), | 535 fetch_callback_.Run(job->extension_id(), job->success(), job->force(), |
| 535 job->success(), | 536 job->hash_mismatch_unix_paths()); |
| 536 job->force(), | |
| 537 job->hash_mismatch_paths()); | |
| 538 } | 537 } |
| 539 | 538 |
| 540 for (JobMap::iterator i = jobs_.begin(); i != jobs_.end(); ++i) { | 539 for (JobMap::iterator i = jobs_.begin(); i != jobs_.end(); ++i) { |
| 541 if (i->second.get() == job.get()) { | 540 if (i->second.get() == job.get()) { |
| 542 jobs_.erase(i); | 541 jobs_.erase(i); |
| 543 break; | 542 break; |
| 544 } | 543 } |
| 545 } | 544 } |
| 546 } | 545 } |
| 547 | 546 |
| 548 } // namespace extensions | 547 } // namespace extensions |
| OLD | NEW |