root/chrome/browser/chromeos/extensions/install_limiter.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. GetFileSizeOnBlockingPool
  2. path
  3. Get
  4. DisableForTest
  5. Add
  6. AddWithSize
  7. CheckAndRunDeferrredInstalls
  8. RunInstall
  9. Observe

// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/extensions/install_limiter.h"

#include <string>

#include "base/bind.h"
#include "base/file_util.h"
#include "base/threading/sequenced_worker_pool.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/extensions/install_limiter_factory.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"

using content::BrowserThread;

namespace {

int64 GetFileSizeOnBlockingPool(const base::FilePath& file) {
  DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());

  // Get file size. In case of error, sets 0 as file size to let the installer
  // run and fail.
  int64 size;
  return base::GetFileSize(file, &size) ? size : 0;
}

}  // namespace

namespace extensions {

////////////////////////////////////////////////////////////////////////////////
// InstallLimiter::DeferredInstall

InstallLimiter::DeferredInstall::DeferredInstall(
    const scoped_refptr<CrxInstaller>& installer,
    const base::FilePath& path)
    : installer(installer),
      path(path) {
}

InstallLimiter::DeferredInstall::~DeferredInstall() {
}

////////////////////////////////////////////////////////////////////////////////
// InstallLimiter

InstallLimiter* InstallLimiter::Get(Profile* profile) {
  return InstallLimiterFactory::GetForProfile(profile);
}

InstallLimiter::InstallLimiter() : disabled_for_test_(false) {
}

InstallLimiter::~InstallLimiter() {
}

void InstallLimiter::DisableForTest() {
  disabled_for_test_ = true;
}

void InstallLimiter::Add(const scoped_refptr<CrxInstaller>& installer,
                         const base::FilePath& path) {
  // No deferred installs when disabled for test.
  if (disabled_for_test_) {
    installer->InstallCrx(path);
    return;
  }

  base::PostTaskAndReplyWithResult(
      BrowserThread::GetBlockingPool(),
      FROM_HERE,
      base::Bind(&GetFileSizeOnBlockingPool, path),
      base::Bind(&InstallLimiter::AddWithSize, AsWeakPtr(), installer, path));
}

void InstallLimiter::AddWithSize(
    const scoped_refptr<CrxInstaller>& installer,
    const base::FilePath& path,
    int64 size) {
  const int64 kBigAppSizeThreshold = 1048576;  // 1MB

  if (size <= kBigAppSizeThreshold) {
    RunInstall(installer, path);

    // Stop wait timer and let install notification drive deferred installs.
    wait_timer_.Stop();
    return;
  }

  deferred_installs_.push(DeferredInstall(installer, path));

  // When there are no running installs, wait a bit before running deferred
  // installs to allow small app install to take precedence, especially when a
  // big app is the first one in the list.
  if (running_installers_.empty() && !wait_timer_.IsRunning()) {
    const int kMaxWaitTimeInMs = 5000;  // 5 seconds.
    wait_timer_.Start(
        FROM_HERE,
        base::TimeDelta::FromMilliseconds(kMaxWaitTimeInMs),
        this, &InstallLimiter::CheckAndRunDeferrredInstalls);
  }
}

void InstallLimiter::CheckAndRunDeferrredInstalls() {
  if (deferred_installs_.empty() || !running_installers_.empty())
    return;

  const DeferredInstall& deferred = deferred_installs_.front();
  RunInstall(deferred.installer, deferred.path);
  deferred_installs_.pop();
}

void InstallLimiter::RunInstall(const scoped_refptr<CrxInstaller>& installer,
                                const base::FilePath& path) {
  registrar_.Add(this,
                 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
                 content::Source<CrxInstaller>(installer.get()));

  installer->InstallCrx(path);
  running_installers_.insert(installer);
}

void InstallLimiter::Observe(int type,
                             const content::NotificationSource& source,
                             const content::NotificationDetails& details) {
  DCHECK_EQ(chrome::NOTIFICATION_CRX_INSTALLER_DONE, type);

  registrar_.Remove(this,
                    chrome::NOTIFICATION_CRX_INSTALLER_DONE,
                    source);

  const scoped_refptr<CrxInstaller> installer =
      content::Source<extensions::CrxInstaller>(source).ptr();
  running_installers_.erase(installer);
  CheckAndRunDeferrredInstalls();
}

}  // namespace extensions

/* [<][>][^][v][top][bottom][index][help] */