| 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> |
| 11 #include <vector> |
| 10 | 12 |
| 11 #include "base/base64.h" | 13 #include "base/base64.h" |
| 12 #include "base/files/file_enumerator.h" | 14 #include "base/files/file_enumerator.h" |
| 13 #include "base/files/file_util.h" | 15 #include "base/files/file_util.h" |
| 14 #include "base/json/json_reader.h" | 16 #include "base/json/json_reader.h" |
| 15 #include "base/macros.h" | 17 #include "base/macros.h" |
| 16 #include "base/memory/ref_counted.h" | 18 #include "base/memory/ref_counted.h" |
| 17 #include "base/metrics/histogram.h" | 19 #include "base/metrics/histogram.h" |
| 18 #include "base/synchronization/lock.h" | 20 #include "base/synchronization/lock.h" |
| 19 #include "base/task_runner_util.h" | 21 #include "base/task_runner_util.h" |
| 20 #include "base/timer/elapsed_timer.h" | 22 #include "base/timer/elapsed_timer.h" |
| 21 #include "base/version.h" | 23 #include "base/version.h" |
| 22 #include "content/public/browser/browser_context.h" | |
| 23 #include "content/public/browser/browser_thread.h" | 24 #include "content/public/browser/browser_thread.h" |
| 24 #include "content/public/browser/storage_partition.h" | |
| 25 #include "crypto/sha2.h" | 25 #include "crypto/sha2.h" |
| 26 #include "extensions/browser/computed_hashes.h" | 26 #include "extensions/browser/computed_hashes.h" |
| 27 #include "extensions/browser/content_hash_tree.h" | 27 #include "extensions/browser/content_hash_tree.h" |
| 28 #include "extensions/browser/content_verifier_delegate.h" | 28 #include "extensions/browser/content_verifier_delegate.h" |
| 29 #include "extensions/browser/verified_contents.h" | 29 #include "extensions/browser/verified_contents.h" |
| 30 #include "extensions/common/constants.h" | 30 #include "extensions/common/constants.h" |
| 31 #include "extensions/common/extension.h" | 31 #include "extensions/common/extension.h" |
| 32 #include "extensions/common/file_util.h" | 32 #include "extensions/common/file_util.h" |
| 33 #include "net/base/load_flags.h" | 33 #include "net/base/load_flags.h" |
| 34 #include "net/url_request/url_fetcher.h" | 34 #include "net/url_request/url_fetcher.h" |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 url_fetcher_->Start(); | 251 url_fetcher_->Start(); |
| 252 } | 252 } |
| 253 } | 253 } |
| 254 | 254 |
| 255 // Helper function to let us pass ownership of a string via base::Bind with the | 255 // Helper function to let us pass ownership of a string via base::Bind with the |
| 256 // contents to be written into a file. Also ensures that the directory for | 256 // contents to be written into a file. Also ensures that the directory for |
| 257 // |path| exists, creating it if needed. | 257 // |path| exists, creating it if needed. |
| 258 static int WriteFileHelper(const base::FilePath& path, | 258 static int WriteFileHelper(const base::FilePath& path, |
| 259 std::unique_ptr<std::string> content) { | 259 std::unique_ptr<std::string> content) { |
| 260 base::FilePath dir = path.DirName(); | 260 base::FilePath dir = path.DirName(); |
| 261 return (base::CreateDirectoryAndGetError(dir, NULL) && | 261 if (!base::CreateDirectoryAndGetError(dir, nullptr)) |
| 262 base::WriteFile(path, content->data(), content->size())); | 262 return -1; |
| 263 return base::WriteFile(path, content->data(), content->size()); |
| 263 } | 264 } |
| 264 | 265 |
| 265 void ContentHashFetcherJob::OnURLFetchComplete(const net::URLFetcher* source) { | 266 void ContentHashFetcherJob::OnURLFetchComplete(const net::URLFetcher* source) { |
| 266 VLOG(1) << "URLFetchComplete for " << extension_id_ | 267 VLOG(1) << "URLFetchComplete for " << extension_id_ |
| 267 << " is_success:" << url_fetcher_->GetStatus().is_success() << " " | 268 << " is_success:" << url_fetcher_->GetStatus().is_success() << " " |
| 268 << fetch_url_.possibly_invalid_spec(); | 269 << fetch_url_.possibly_invalid_spec(); |
| 269 if (IsCancelled()) | 270 if (IsCancelled()) |
| 270 return; | 271 return; |
| 271 std::unique_ptr<std::string> response(new std::string); | 272 std::unique_ptr<std::string> response(new std::string); |
| 272 if (!url_fetcher_->GetStatus().is_success() || | 273 if (!url_fetcher_->GetStatus().is_success() || |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 if (IsCancelled()) | 346 if (IsCancelled()) |
| 346 return false; | 347 return false; |
| 347 // Make sure the directory exists. | 348 // Make sure the directory exists. |
| 348 if (!base::CreateDirectoryAndGetError(hashes_file.DirName(), NULL)) | 349 if (!base::CreateDirectoryAndGetError(hashes_file.DirName(), NULL)) |
| 349 return false; | 350 return false; |
| 350 | 351 |
| 351 if (!verified_contents_.get()) { | 352 if (!verified_contents_.get()) { |
| 352 base::FilePath verified_contents_path = | 353 base::FilePath verified_contents_path = |
| 353 file_util::GetVerifiedContentsPath(extension_path_); | 354 file_util::GetVerifiedContentsPath(extension_path_); |
| 354 verified_contents_.reset(new VerifiedContents(key_.data, key_.size)); | 355 verified_contents_.reset(new VerifiedContents(key_.data, key_.size)); |
| 355 if (!verified_contents_->InitFrom(verified_contents_path, false)) | 356 if (!verified_contents_->InitFrom(verified_contents_path, false)) { |
| 357 verified_contents_.reset(); |
| 356 return false; | 358 return false; |
| 357 verified_contents_.reset(); | 359 } |
| 358 } | 360 } |
| 359 | 361 |
| 360 base::FileEnumerator enumerator(extension_path_, | 362 base::FileEnumerator enumerator(extension_path_, |
| 361 true, /* recursive */ | 363 true, /* recursive */ |
| 362 base::FileEnumerator::FILES); | 364 base::FileEnumerator::FILES); |
| 363 // First discover all the file paths and put them in a sorted set. | 365 // First discover all the file paths and put them in a sorted set. |
| 364 SortedFilePathSet paths; | 366 SortedFilePathSet paths; |
| 365 for (;;) { | 367 for (;;) { |
| 366 if (IsCancelled()) | 368 if (IsCancelled()) |
| 367 return false; | 369 return false; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 { | 418 { |
| 417 base::AutoLock autolock(cancelled_lock_); | 419 base::AutoLock autolock(cancelled_lock_); |
| 418 if (cancelled_) | 420 if (cancelled_) |
| 419 return; | 421 return; |
| 420 } | 422 } |
| 421 callback_.Run(this); | 423 callback_.Run(this); |
| 422 } | 424 } |
| 423 | 425 |
| 424 // ---- | 426 // ---- |
| 425 | 427 |
| 426 ContentHashFetcher::ContentHashFetcher(content::BrowserContext* context, | 428 ContentHashFetcher::ContentHashFetcher( |
| 427 ContentVerifierDelegate* delegate, | 429 net::URLRequestContextGetter* context_getter, |
| 428 const FetchCallback& callback) | 430 ContentVerifierDelegate* delegate, |
| 429 : context_(context), | 431 const FetchCallback& callback) |
| 432 : context_getter_(context_getter), |
| 430 delegate_(delegate), | 433 delegate_(delegate), |
| 431 fetch_callback_(callback), | 434 fetch_callback_(callback), |
| 432 weak_ptr_factory_(this) { | 435 weak_ptr_factory_(this) {} |
| 433 } | |
| 434 | 436 |
| 435 ContentHashFetcher::~ContentHashFetcher() { | 437 ContentHashFetcher::~ContentHashFetcher() { |
| 436 for (JobMap::iterator i = jobs_.begin(); i != jobs_.end(); ++i) { | 438 for (JobMap::iterator i = jobs_.begin(); i != jobs_.end(); ++i) { |
| 437 i->second->Cancel(); | 439 i->second->Cancel(); |
| 438 } | 440 } |
| 439 } | 441 } |
| 440 | 442 |
| 441 void ContentHashFetcher::DoFetch(const Extension* extension, bool force) { | 443 void ContentHashFetcher::DoFetch(const Extension* extension, bool force) { |
| 442 DCHECK(extension); | 444 DCHECK(extension); |
| 443 | 445 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 455 } | 457 } |
| 456 | 458 |
| 457 // TODO(asargent) - we should do something here to remember recent attempts | 459 // TODO(asargent) - we should do something here to remember recent attempts |
| 458 // to fetch signatures by extension id, and use exponential backoff to avoid | 460 // to fetch signatures by extension id, and use exponential backoff to avoid |
| 459 // hammering the server when we aren't successful in getting them. | 461 // hammering the server when we aren't successful in getting them. |
| 460 // crbug.com/373397 | 462 // crbug.com/373397 |
| 461 | 463 |
| 462 DCHECK(extension->version()); | 464 DCHECK(extension->version()); |
| 463 GURL url = | 465 GURL url = |
| 464 delegate_->GetSignatureFetchUrl(extension->id(), *extension->version()); | 466 delegate_->GetSignatureFetchUrl(extension->id(), *extension->version()); |
| 465 ContentHashFetcherJob* job = new ContentHashFetcherJob( | 467 ContentHashFetcherJob* job = |
| 466 content::BrowserContext::GetDefaultStoragePartition(context_)-> | 468 new ContentHashFetcherJob(context_getter_, delegate_->GetPublicKey(), |
| 467 GetURLRequestContext(), | 469 extension->id(), extension->path(), url, force, |
| 468 delegate_->GetPublicKey(), extension->id(), | 470 base::Bind(&ContentHashFetcher::JobFinished, |
| 469 extension->path(), url, force, | 471 weak_ptr_factory_.GetWeakPtr())); |
| 470 base::Bind(&ContentHashFetcher::JobFinished, | |
| 471 weak_ptr_factory_.GetWeakPtr())); | |
| 472 jobs_.insert(std::make_pair(key, job)); | 472 jobs_.insert(std::make_pair(key, job)); |
| 473 job->Start(); | 473 job->Start(); |
| 474 } | 474 } |
| 475 | 475 |
| 476 void ContentHashFetcher::ExtensionLoaded(const Extension* extension) { | 476 void ContentHashFetcher::ExtensionLoaded(const Extension* extension) { |
| 477 CHECK(extension); | 477 CHECK(extension); |
| 478 DoFetch(extension, false); | 478 DoFetch(extension, false); |
| 479 } | 479 } |
| 480 | 480 |
| 481 void ContentHashFetcher::ExtensionUnloaded(const Extension* extension) { | 481 void ContentHashFetcher::ExtensionUnloaded(const Extension* extension) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 498 | 498 |
| 499 for (JobMap::iterator i = jobs_.begin(); i != jobs_.end(); ++i) { | 499 for (JobMap::iterator i = jobs_.begin(); i != jobs_.end(); ++i) { |
| 500 if (i->second.get() == job) { | 500 if (i->second.get() == job) { |
| 501 jobs_.erase(i); | 501 jobs_.erase(i); |
| 502 break; | 502 break; |
| 503 } | 503 } |
| 504 } | 504 } |
| 505 } | 505 } |
| 506 | 506 |
| 507 } // namespace extensions | 507 } // namespace extensions |
| OLD | NEW |