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 |
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 |