1 // Copyright (c) 2013 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.
5 #include "chrome/browser/chromeos/extensions/install_limiter.h"
10 #include "base/file_util.h"
11 #include "base/threading/sequenced_worker_pool.h"
12 #include "chrome/browser/chrome_notification_types.h"
13 #include "chrome/browser/chromeos/extensions/install_limiter_factory.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "content/public/browser/notification_details.h"
16 #include "content/public/browser/notification_source.h"
18 using content::BrowserThread;
22 // Gets the file size of |file| and stores it in |size| on the blocking pool.
23 void GetFileSizeOnBlockingPool(const base::FilePath& file, int64* size) {
24 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
26 // Get file size. In case of error, sets 0 as file size to let the installer
28 if (!file_util::GetFileSize(file, size))
34 namespace extensions {
36 ////////////////////////////////////////////////////////////////////////////////
37 // InstallLimiter::DeferredInstall
39 InstallLimiter::DeferredInstall::DeferredInstall(
40 const scoped_refptr<CrxInstaller>& installer,
41 const base::FilePath& path)
42 : installer(installer),
46 InstallLimiter::DeferredInstall::~DeferredInstall() {
49 ////////////////////////////////////////////////////////////////////////////////
52 InstallLimiter* InstallLimiter::Get(Profile* profile) {
53 return InstallLimiterFactory::GetForProfile(profile);
56 InstallLimiter::InstallLimiter() : disabled_for_test_(false) {
59 InstallLimiter::~InstallLimiter() {
62 void InstallLimiter::DisableForTest() {
63 disabled_for_test_ = true;
66 void InstallLimiter::Add(const scoped_refptr<CrxInstaller>& installer,
67 const base::FilePath& path) {
68 // No deferred installs when disabled for test.
69 if (disabled_for_test_) {
70 installer->InstallCrx(path);
74 int64* size = new int64(0); // Owned by reply callback below.
75 BrowserThread::PostBlockingPoolTaskAndReply(
77 base::Bind(&GetFileSizeOnBlockingPool, path, size),
78 base::Bind(&InstallLimiter::AddWithSize, AsWeakPtr(),
79 installer, path, base::Owned(size)));
82 void InstallLimiter::AddWithSize(
83 const scoped_refptr<CrxInstaller>& installer,
84 const base::FilePath& path,
86 const int64 kBigAppSizeThreshold = 1048576; // 1MB
88 if (*size <= kBigAppSizeThreshold) {
89 RunInstall(installer, path);
91 // Stop wait timer and let install notification drive deferred installs.
96 deferred_installs_.push(DeferredInstall(installer, path));
98 // When there are no running installs, wait a bit before running deferred
99 // installs to allow small app install to take precedence, especially when a
100 // big app is the first one in the list.
101 if (running_installers_.empty() && !wait_timer_.IsRunning()) {
102 const int kMaxWaitTimeInMs = 5000; // 5 seconds.
105 base::TimeDelta::FromMilliseconds(kMaxWaitTimeInMs),
106 this, &InstallLimiter::CheckAndRunDeferrredInstalls);
110 void InstallLimiter::CheckAndRunDeferrredInstalls() {
111 if (deferred_installs_.empty() || !running_installers_.empty())
114 const DeferredInstall& deferred = deferred_installs_.front();
115 RunInstall(deferred.installer, deferred.path);
116 deferred_installs_.pop();
119 void InstallLimiter::RunInstall(const scoped_refptr<CrxInstaller>& installer,
120 const base::FilePath& path) {
122 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
123 content::Source<CrxInstaller>(installer.get()));
125 installer->InstallCrx(path);
126 running_installers_.insert(installer);
129 void InstallLimiter::Observe(int type,
130 const content::NotificationSource& source,
131 const content::NotificationDetails& details) {
132 DCHECK_EQ(chrome::NOTIFICATION_CRX_INSTALLER_DONE, type);
134 registrar_.Remove(this,
135 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
138 const scoped_refptr<CrxInstaller> installer =
139 content::Source<extensions::CrxInstaller>(source).ptr();
140 running_installers_.erase(installer);
141 CheckAndRunDeferrredInstalls();
144 } // namespace extensions