OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/extensions/webstore_installer.h" | 5 #include "chrome/browser/extensions/webstore_installer.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
12 #include "base/file_util.h" | 12 #include "base/file_util.h" |
13 #include "base/metrics/field_trial.h" | 13 #include "base/metrics/field_trial.h" |
14 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
15 #include "base/metrics/sparse_histogram.h" | 15 #include "base/metrics/sparse_histogram.h" |
16 #include "base/path_service.h" | 16 #include "base/path_service.h" |
17 #include "base/rand_util.h" | 17 #include "base/rand_util.h" |
18 #include "base/strings/string_number_conversions.h" | 18 #include "base/strings/string_number_conversions.h" |
19 #include "base/strings/string_util.h" | 19 #include "base/strings/string_util.h" |
20 #include "base/strings/stringprintf.h" | 20 #include "base/strings/stringprintf.h" |
21 #include "base/strings/utf_string_conversions.h" | 21 #include "base/strings/utf_string_conversions.h" |
22 #include "base/time/time.h" | |
22 #include "chrome/browser/chrome_notification_types.h" | 23 #include "chrome/browser/chrome_notification_types.h" |
23 #include "chrome/browser/download/download_crx_util.h" | 24 #include "chrome/browser/download/download_crx_util.h" |
24 #include "chrome/browser/download/download_prefs.h" | 25 #include "chrome/browser/download/download_prefs.h" |
25 #include "chrome/browser/download/download_stats.h" | 26 #include "chrome/browser/download/download_stats.h" |
26 #include "chrome/browser/extensions/crx_installer.h" | 27 #include "chrome/browser/extensions/crx_installer.h" |
27 #include "chrome/browser/extensions/install_tracker.h" | 28 #include "chrome/browser/extensions/install_tracker.h" |
28 #include "chrome/browser/extensions/install_tracker_factory.h" | 29 #include "chrome/browser/extensions/install_tracker_factory.h" |
29 #include "chrome/browser/extensions/install_verifier.h" | 30 #include "chrome/browser/extensions/install_verifier.h" |
30 #include "chrome/browser/omaha_query_params/omaha_query_params.h" | 31 #include "chrome/browser/omaha_query_params/omaha_query_params.h" |
31 #include "chrome/browser/profiles/profile.h" | 32 #include "chrome/browser/profiles/profile.h" |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
77 const char kDownloadInterruptedError[] = "Download interrupted"; | 78 const char kDownloadInterruptedError[] = "Download interrupted"; |
78 const char kInvalidDownloadError[] = | 79 const char kInvalidDownloadError[] = |
79 "Download was not a valid extension or user script"; | 80 "Download was not a valid extension or user script"; |
80 const char kDependencyNotFoundError[] = "Dependency not found"; | 81 const char kDependencyNotFoundError[] = "Dependency not found"; |
81 const char kDependencyNotSharedModuleError[] = | 82 const char kDependencyNotSharedModuleError[] = |
82 "Dependency is not shared module"; | 83 "Dependency is not shared module"; |
83 const char kInlineInstallSource[] = "inline"; | 84 const char kInlineInstallSource[] = "inline"; |
84 const char kDefaultInstallSource[] = "ondemand"; | 85 const char kDefaultInstallSource[] = "ondemand"; |
85 const char kAppLauncherInstallSource[] = "applauncher"; | 86 const char kAppLauncherInstallSource[] = "applauncher"; |
86 | 87 |
88 const size_t kTimeRemainingMinutesThreshold = 1u; | |
89 | |
87 // Folder for downloading crx files from the webstore. This is used so that the | 90 // Folder for downloading crx files from the webstore. This is used so that the |
88 // crx files don't go via the usual downloads folder. | 91 // crx files don't go via the usual downloads folder. |
89 const base::FilePath::CharType kWebstoreDownloadFolder[] = | 92 const base::FilePath::CharType kWebstoreDownloadFolder[] = |
90 FILE_PATH_LITERAL("Webstore Downloads"); | 93 FILE_PATH_LITERAL("Webstore Downloads"); |
91 | 94 |
92 base::FilePath* g_download_directory_for_tests = NULL; | 95 base::FilePath* g_download_directory_for_tests = NULL; |
93 | 96 |
94 // Must be executed on the FILE thread. | 97 // Must be executed on the FILE thread. |
95 void GetDownloadFilePath( | 98 void GetDownloadFilePath( |
96 const base::FilePath& download_directory, | 99 const base::FilePath& download_directory, |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
296 | 299 |
297 total_modules_ = pending_modules_.size(); | 300 total_modules_ = pending_modules_.size(); |
298 | 301 |
299 std::set<std::string> ids; | 302 std::set<std::string> ids; |
300 std::list<SharedModuleInfo::ImportInfo>::const_iterator i; | 303 std::list<SharedModuleInfo::ImportInfo>::const_iterator i; |
301 for (i = pending_modules_.begin(); i != pending_modules_.end(); ++i) { | 304 for (i = pending_modules_.begin(); i != pending_modules_.end(); ++i) { |
302 ids.insert(i->extension_id); | 305 ids.insert(i->extension_id); |
303 } | 306 } |
304 ExtensionSystem::Get(profile_)->install_verifier()->AddProvisional(ids); | 307 ExtensionSystem::Get(profile_)->install_verifier()->AddProvisional(ids); |
305 | 308 |
306 // TODO(crbug.com/305343): Query manifest of dependencises before | |
307 // downloading & installing those dependencies. | |
308 DownloadNextPendingModule(); | |
309 | |
310 std::string name; | 309 std::string name; |
311 if (!approval_->manifest->value()->GetString(manifest_keys::kName, &name)) { | 310 if (!approval_->manifest->value()->GetString(manifest_keys::kName, &name)) { |
312 NOTREACHED(); | 311 NOTREACHED(); |
313 } | 312 } |
314 extensions::InstallTracker* tracker = | 313 extensions::InstallTracker* tracker = |
315 extensions::InstallTrackerFactory::GetForProfile(profile_); | 314 extensions::InstallTrackerFactory::GetForProfile(profile_); |
316 extensions::InstallObserver::ExtensionInstallParams params( | 315 extensions::InstallObserver::ExtensionInstallParams params( |
317 id_, | 316 id_, |
318 name, | 317 name, |
319 approval_->installing_icon, | 318 approval_->installing_icon, |
320 approval_->manifest->is_app(), | 319 approval_->manifest->is_app(), |
321 approval_->manifest->is_platform_app()); | 320 approval_->manifest->is_platform_app()); |
322 params.is_ephemeral = approval_->is_ephemeral; | 321 params.is_ephemeral = approval_->is_ephemeral; |
323 tracker->OnBeginExtensionInstall(params); | 322 tracker->OnBeginExtensionInstall(params); |
323 | |
324 tracker->OnBeginExtensionDownload(id_); | |
325 | |
326 // TODO(crbug.com/305343): Query manifest of dependencies before | |
327 // downloading & installing those dependencies. | |
328 DownloadNextPendingModule(); | |
324 } | 329 } |
325 | 330 |
326 void WebstoreInstaller::Observe(int type, | 331 void WebstoreInstaller::Observe(int type, |
327 const content::NotificationSource& source, | 332 const content::NotificationSource& source, |
328 const content::NotificationDetails& details) { | 333 const content::NotificationDetails& details) { |
329 switch (type) { | 334 switch (type) { |
330 case chrome::NOTIFICATION_CRX_INSTALLER_DONE: { | 335 case chrome::NOTIFICATION_CRX_INSTALLER_DONE: { |
331 const Extension* extension = | 336 const Extension* extension = |
332 content::Details<const Extension>(details).ptr(); | 337 content::Details<const Extension>(details).ptr(); |
333 CrxInstaller* installer = content::Source<CrxInstaller>(source).ptr(); | 338 CrxInstaller* installer = content::Source<CrxInstaller>(source).ptr(); |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
466 if (!download_crx_util::IsExtensionDownload(*download)) { | 471 if (!download_crx_util::IsExtensionDownload(*download)) { |
467 ReportFailure(kInvalidDownloadError, FAILURE_REASON_OTHER); | 472 ReportFailure(kInvalidDownloadError, FAILURE_REASON_OTHER); |
468 } else if (pending_modules_.empty()) { | 473 } else if (pending_modules_.empty()) { |
469 // The download is the last module - the extension main module. | 474 // The download is the last module - the extension main module. |
470 if (delegate_) | 475 if (delegate_) |
471 delegate_->OnExtensionDownloadProgress(id_, download); | 476 delegate_->OnExtensionDownloadProgress(id_, download); |
472 extensions::InstallTracker* tracker = | 477 extensions::InstallTracker* tracker = |
473 extensions::InstallTrackerFactory::GetForProfile(profile_); | 478 extensions::InstallTrackerFactory::GetForProfile(profile_); |
474 tracker->OnDownloadProgress(id_, 100); | 479 tracker->OnDownloadProgress(id_, 100); |
475 } | 480 } |
481 // Stop the progress timer if it's running. | |
482 download_progress_timer_.Stop(); | |
476 break; | 483 break; |
477 case DownloadItem::IN_PROGRESS: { | 484 case DownloadItem::IN_PROGRESS: { |
478 if (delegate_ && pending_modules_.size() == 1) { | 485 if (delegate_ && pending_modules_.size() == 1) { |
479 // Only report download progress for the main module to |delegrate_|. | 486 // Only report download progress for the main module to |delegrate_|. |
480 delegate_->OnExtensionDownloadProgress(id_, download); | 487 delegate_->OnExtensionDownloadProgress(id_, download); |
481 } | 488 } |
482 int percent = download->PercentComplete(); | 489 UpdateDownloadProgress(); |
483 // Only report progress if precent is more than 0 | |
484 if (percent >= 0) { | |
485 int finished_modules = total_modules_ - pending_modules_.size(); | |
486 percent = (percent + finished_modules * 100) / total_modules_; | |
487 extensions::InstallTracker* tracker = | |
488 extensions::InstallTrackerFactory::GetForProfile(profile_); | |
489 tracker->OnDownloadProgress(id_, percent); | |
490 } | |
491 break; | 490 break; |
492 } | 491 } |
493 default: | 492 default: |
494 // Continue listening if the download is not in one of the above states. | 493 // Continue listening if the download is not in one of the above states. |
495 break; | 494 break; |
496 } | 495 } |
497 } | 496 } |
498 | 497 |
499 void WebstoreInstaller::OnDownloadDestroyed(DownloadItem* download) { | 498 void WebstoreInstaller::OnDownloadDestroyed(DownloadItem* download) { |
500 CHECK_EQ(download_item_, download); | 499 CHECK_EQ(download_item_, download); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
607 resource_context)); | 606 resource_context)); |
608 params->set_file_path(file); | 607 params->set_file_path(file); |
609 if (controller.GetVisibleEntry()) | 608 if (controller.GetVisibleEntry()) |
610 params->set_referrer( | 609 params->set_referrer( |
611 content::Referrer(controller.GetVisibleEntry()->GetURL(), | 610 content::Referrer(controller.GetVisibleEntry()->GetURL(), |
612 blink::WebReferrerPolicyDefault)); | 611 blink::WebReferrerPolicyDefault)); |
613 params->set_callback(base::Bind(&WebstoreInstaller::OnDownloadStarted, this)); | 612 params->set_callback(base::Bind(&WebstoreInstaller::OnDownloadStarted, this)); |
614 download_manager->DownloadUrl(params.Pass()); | 613 download_manager->DownloadUrl(params.Pass()); |
615 } | 614 } |
616 | 615 |
616 void WebstoreInstaller::UpdateDownloadProgress() { | |
617 // If the download has gone away, or isn't in progress (in which case we can't | |
618 // give a good progress estimate), stop any running timers and return. | |
619 if (!download_item_ || | |
620 download_item_->GetState() != DownloadItem::IN_PROGRESS) { | |
621 download_progress_timer_.Stop(); | |
622 return; | |
623 } | |
624 | |
625 int percent = download_item_->PercentComplete(); | |
626 // Only report progress if precent is more than 0 | |
627 if (percent >= 0) { | |
628 int finished_modules = total_modules_ - pending_modules_.size(); | |
629 percent = (percent + finished_modules * 100) / total_modules_; | |
asargent_no_longer_on_chrome
2014/03/03 18:49:08
nit: add extra () to make intended order of arithm
Devlin
2014/03/03 21:15:13
Done.
| |
630 extensions::InstallTracker* tracker = | |
631 extensions::InstallTrackerFactory::GetForProfile(profile_); | |
632 tracker->OnDownloadProgress(id_, percent); | |
633 } | |
634 | |
635 // If there's enough time remaining on the download to warrant an update, | |
636 // set the timer (overwriting any current timers). Otherwise, stop the | |
637 // timer. | |
638 base::TimeDelta time_remaining; | |
639 if (download_item_->TimeRemaining(&time_remaining) && | |
640 time_remaining > | |
641 base::TimeDelta::FromSeconds(kTimeRemainingMinutesThreshold)) { | |
642 download_progress_timer_.Start( | |
643 FROM_HERE, | |
644 base::TimeDelta::FromSeconds(kTimeRemainingMinutesThreshold), | |
645 this, | |
646 &WebstoreInstaller::UpdateDownloadProgress); | |
647 } else { | |
648 download_progress_timer_.Stop(); | |
649 } | |
650 } | |
651 | |
617 void WebstoreInstaller::ReportFailure(const std::string& error, | 652 void WebstoreInstaller::ReportFailure(const std::string& error, |
618 FailureReason reason) { | 653 FailureReason reason) { |
619 if (delegate_) { | 654 if (delegate_) { |
620 delegate_->OnExtensionInstallFailure(id_, error, reason); | 655 delegate_->OnExtensionInstallFailure(id_, error, reason); |
621 delegate_ = NULL; | 656 delegate_ = NULL; |
622 } | 657 } |
623 | 658 |
624 extensions::InstallTracker* tracker = | 659 extensions::InstallTracker* tracker = |
625 extensions::InstallTrackerFactory::GetForProfile(profile_); | 660 extensions::InstallTrackerFactory::GetForProfile(profile_); |
626 tracker->OnInstallFailure(id_); | 661 tracker->OnInstallFailure(id_); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
658 1, | 693 1, |
659 kMaxSizeKb, | 694 kMaxSizeKb, |
660 kNumBuckets); | 695 kNumBuckets); |
661 } | 696 } |
662 UMA_HISTOGRAM_BOOLEAN( | 697 UMA_HISTOGRAM_BOOLEAN( |
663 "Extensions.WebstoreDownload.InterruptTotalSizeUnknown", | 698 "Extensions.WebstoreDownload.InterruptTotalSizeUnknown", |
664 total_bytes <= 0); | 699 total_bytes <= 0); |
665 } | 700 } |
666 | 701 |
667 } // namespace extensions | 702 } // namespace extensions |
OLD | NEW |