// Copyright (c) 2012 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/extensions/webstore_installer.h"

#include <stddef.h>
#include <stdint.h>
#include <limits>
#include <set>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/path_service.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/download/download_crx_util.h"
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/download/download_stats.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/install_tracker.h"
#include "chrome/browser/extensions/install_tracker_factory.h"
#include "chrome/browser/extensions/install_verifier.h"
#include "chrome/browser/extensions/shared_module_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/grit/generated_resources.h"
#include "components/crx_file/id_util.h"
#include "components/download/public/common/download_url_parameters.h"
#include "components/update_client/update_query_params.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/extension_file_task_runner.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/install/crx_install_error.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_urls.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/manifest_handlers/shared_module_info.h"
#include "net/base/escape.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"

using content::BrowserContext;
using content::BrowserThread;
using content::DownloadManager;
using content::NavigationController;
using download::DownloadItem;
using download::DownloadUrlParameters;

namespace {

// Key used to attach the Approval to the DownloadItem.
const char kApprovalKey[] = "extensions.webstore_installer";

const char kInvalidIdError[] = "Invalid id";
const char kDownloadDirectoryError[] = "Could not create download directory";
const char kDownloadCanceledError[] = "Download canceled";
const char kDownloadInterruptedError[] = "Download interrupted";
const char kInvalidDownloadError[] =
    "Download was not a valid extension or user script";
const char kDependencyNotFoundError[] = "Dependency not found";
const char kDependencyNotSharedModuleError[] =
    "Dependency is not shared module";
const char kInlineInstallSource[] = "inline";
const char kDefaultInstallSource[] = "ondemand";
const char kAppLauncherInstallSource[] = "applauncher";

// TODO(rockot): Share this duplicated constant with the extension updater.
// See http://crbug.com/371398.
const char kAuthUserQueryKey[] = "authuser";

constexpr base::TimeDelta kTimeRemainingThreshold =
    base::TimeDelta::FromSeconds(1);

// Folder for downloading crx files from the webstore. This is used so that the
// crx files don't go via the usual downloads folder.
const base::FilePath::CharType kWebstoreDownloadFolder[] =
    FILE_PATH_LITERAL("Webstore Downloads");

base::FilePath* g_download_directory_for_tests = NULL;

base::FilePath GetDownloadFilePath(const base::FilePath& download_directory,
                                   const std::string& id) {
  // Ensure the download directory exists. TODO(asargent) - make this use
  // common code from the downloads system.
  if (!base::DirectoryExists(download_directory) &&
      !base::CreateDirectory(download_directory)) {
    return base::FilePath();
  }

  // This is to help avoid a race condition between when we generate this
  // filename and when the download starts writing to it (think concurrently
  // running sharded browser tests installing the same test file, for
  // instance).
  std::string random_number = base::NumberToString(
      base::RandGenerator(std::numeric_limits<uint16_t>::max()));

  base::FilePath file =
      download_directory.AppendASCII(id + "_" + random_number + ".crx");

  return base::GetUniquePath(file);
}

void MaybeAppendAuthUserParameter(const std::string& authuser, GURL* url) {
  if (authuser.empty())
    return;
  std::string old_query = url->query();
  url::Component query(0, old_query.length());
  url::Component key, value;
  // Ensure that the URL doesn't already specify an authuser parameter.
  while (url::ExtractQueryKeyValue(
             old_query.c_str(), &query, &key, &value)) {
    std::string key_string = old_query.substr(key.begin, key.len);
    if (key_string == kAuthUserQueryKey) {
      return;
    }
  }
  if (!old_query.empty()) {
    old_query += "&";
  }
  std::string authuser_param = base::StringPrintf(
      "%s=%s",
      kAuthUserQueryKey,
      authuser.c_str());

  // TODO(rockot): Share this duplicated code with the extension updater.
  // See http://crbug.com/371398.
  std::string new_query_string = old_query + authuser_param;
  url::Component new_query(0, new_query_string.length());
  url::Replacements<char> replacements;
  replacements.SetQuery(new_query_string.c_str(), new_query);
  *url = url->ReplaceComponents(replacements);
}

std::string GetErrorMessageForDownloadInterrupt(
    download::DownloadInterruptReason reason) {
  switch (reason) {
    case download::DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED:
    case download::DOWNLOAD_INTERRUPT_REASON_SERVER_FORBIDDEN:
      return l10n_util::GetStringUTF8(IDS_WEBSTORE_DOWNLOAD_ACCESS_DENIED);
    default:
      break;
  }
  return kDownloadInterruptedError;
}

}  // namespace

namespace extensions {

// static
GURL WebstoreInstaller::GetWebstoreInstallURL(
    const std::string& extension_id,
    InstallSource source) {
  std::string install_source;
  switch (source) {
    case INSTALL_SOURCE_INLINE:
      install_source = kInlineInstallSource;
      break;
    case INSTALL_SOURCE_APP_LAUNCHER:
      install_source = kAppLauncherInstallSource;
      break;
    case INSTALL_SOURCE_OTHER:
      install_source = kDefaultInstallSource;
  }

  base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
  if (cmd_line->HasSwitch(::switches::kAppsGalleryDownloadURL)) {
    std::string download_url =
        cmd_line->GetSwitchValueASCII(::switches::kAppsGalleryDownloadURL);
    return GURL(base::StringPrintf(download_url.c_str(),
                                   extension_id.c_str()));
  }
  std::vector<base::StringPiece> params;
  std::string extension_param = "id=" + extension_id;
  std::string installsource_param = "installsource=" + install_source;
  params.push_back(extension_param);
  if (!install_source.empty())
    params.push_back(installsource_param);
  params.push_back("uc");
  std::string url_string = extension_urls::GetWebstoreUpdateUrl().spec();

  GURL url(url_string + "?response=redirect&" +
           update_client::UpdateQueryParams::Get(
               update_client::UpdateQueryParams::CRX) +
           "&x=" + net::EscapeQueryParamValue(base::JoinString(params, "&"),
                                              true));
  DCHECK(url.is_valid());

  return url;
}

void WebstoreInstaller::Delegate::OnExtensionDownloadStarted(
    const std::string& id,
    download::DownloadItem* item) {}

void WebstoreInstaller::Delegate::OnExtensionDownloadProgress(
    const std::string& id,
    download::DownloadItem* item) {}

WebstoreInstaller::Approval::Approval()
    : profile(NULL),
      use_app_installed_bubble(false),
      skip_post_install_ui(false),
      skip_install_dialog(false),
      manifest_check_level(MANIFEST_CHECK_LEVEL_STRICT) {
}

std::unique_ptr<WebstoreInstaller::Approval>
WebstoreInstaller::Approval::CreateWithInstallPrompt(Profile* profile) {
  std::unique_ptr<Approval> result(new Approval());
  result->profile = profile;
  return result;
}

std::unique_ptr<WebstoreInstaller::Approval>
WebstoreInstaller::Approval::CreateForSharedModule(Profile* profile) {
  std::unique_ptr<Approval> result(new Approval());
  result->profile = profile;
  result->skip_install_dialog = true;
  result->skip_post_install_ui = true;
  result->manifest_check_level = MANIFEST_CHECK_LEVEL_NONE;
  return result;
}

std::unique_ptr<WebstoreInstaller::Approval>
WebstoreInstaller::Approval::CreateWithNoInstallPrompt(
    Profile* profile,
    const std::string& extension_id,
    std::unique_ptr<base::DictionaryValue> parsed_manifest,
    bool strict_manifest_check) {
  std::unique_ptr<Approval> result(new Approval());
  result->extension_id = extension_id;
  result->profile = profile;
  result->manifest = std::unique_ptr<Manifest>(new Manifest(
      Manifest::INVALID_LOCATION,
      std::unique_ptr<base::DictionaryValue>(parsed_manifest->DeepCopy())));
  result->skip_install_dialog = true;
  result->manifest_check_level = strict_manifest_check ?
    MANIFEST_CHECK_LEVEL_STRICT : MANIFEST_CHECK_LEVEL_LOOSE;
  return result;
}

WebstoreInstaller::Approval::~Approval() {}

const WebstoreInstaller::Approval* WebstoreInstaller::GetAssociatedApproval(
    const DownloadItem& download) {
  return static_cast<const Approval*>(download.GetUserData(kApprovalKey));
}

WebstoreInstaller::WebstoreInstaller(Profile* profile,
                                     Delegate* delegate,
                                     content::WebContents* web_contents,
                                     const std::string& id,
                                     std::unique_ptr<Approval> approval,
                                     InstallSource source)
    : content::WebContentsObserver(web_contents),
      profile_(profile),
      delegate_(delegate),
      id_(id),
      install_source_(source),
      download_item_(NULL),
      approval_(approval.release()),
      total_modules_(0),
      download_started_(false) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(web_contents);

  registrar_.Add(this,
                 extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR,
                 content::Source<CrxInstaller>(NULL));
  extension_registry_observer_.Add(ExtensionRegistry::Get(profile));
}

void WebstoreInstaller::Start() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  AddRef();  // Balanced in ReportSuccess and ReportFailure.

  if (!crx_file::id_util::IdIsValid(id_)) {
    ReportFailure(kInvalidIdError, FAILURE_REASON_OTHER);
    return;
  }

  ExtensionService* extension_service =
    ExtensionSystem::Get(profile_)->extension_service();
  if (approval_.get() && approval_->dummy_extension.get()) {
    extension_service->shared_module_service()->CheckImports(
        approval_->dummy_extension.get(), &pending_modules_, &pending_modules_);
    // Do not check the return value of CheckImports, the CRX installer
    // will report appropriate error messages and fail to install if there
    // is an import error.
  }

  // Add the extension main module into the list.
  SharedModuleInfo::ImportInfo info;
  info.extension_id = id_;
  pending_modules_.push_back(info);

  total_modules_ = pending_modules_.size();

  std::set<std::string> ids;
  std::list<SharedModuleInfo::ImportInfo>::const_iterator i;
  for (i = pending_modules_.begin(); i != pending_modules_.end(); ++i) {
    ids.insert(i->extension_id);
  }
  InstallVerifier::Get(profile_)->AddProvisional(ids);

  std::string name;
  if (!approval_->manifest->value()->GetString(manifest_keys::kName, &name)) {
    NOTREACHED();
  }
  extensions::InstallTracker* tracker =
      extensions::InstallTrackerFactory::GetForBrowserContext(profile_);
  extensions::InstallObserver::ExtensionInstallParams params(
      id_,
      name,
      approval_->installing_icon,
      approval_->manifest->is_app(),
      approval_->manifest->is_platform_app());
  tracker->OnBeginExtensionInstall(params);

  tracker->OnBeginExtensionDownload(id_);

  // TODO(crbug.com/305343): Query manifest of dependencies before
  // downloading & installing those dependencies.
  DownloadNextPendingModule();
}

void WebstoreInstaller::Observe(int type,
                                const content::NotificationSource& source,
                                const content::NotificationDetails& details) {
  DCHECK_EQ(extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR, type);

  CrxInstaller* crx_installer = content::Source<CrxInstaller>(source).ptr();
  CHECK(crx_installer);
  if (crx_installer != crx_installer_.get())
    return;

  // TODO(rdevlin.cronin): Continue removing std::string errors and
  // replacing with base::string16. See crbug.com/71980.
  const extensions::CrxInstallError* error =
      content::Details<const extensions::CrxInstallError>(details).ptr();
  const std::string utf8_error = base::UTF16ToUTF8(error->message());
  crx_installer_ = nullptr;
  // ReportFailure releases a reference to this object so it must be the
  // last operation in this method.
  ReportFailure(utf8_error, FAILURE_REASON_OTHER);
}

void WebstoreInstaller::OnExtensionInstalled(
    content::BrowserContext* browser_context,
    const Extension* extension,
    bool is_update) {
  CHECK(profile_->IsSameProfile(Profile::FromBrowserContext(browser_context)));
  if (pending_modules_.empty())
    return;
  SharedModuleInfo::ImportInfo info = pending_modules_.front();
  if (extension->id() != info.extension_id)
    return;
  pending_modules_.pop_front();

  // Clean up local state from the current download.
  if (download_item_) {
    download_item_->RemoveObserver(this);
    download_item_->Remove();
    download_item_ = NULL;
  }
  crx_installer_.reset();

  if (pending_modules_.empty()) {
    CHECK_EQ(extension->id(), id_);
    ReportSuccess();
  } else {
    const base::Version version_required(info.minimum_version);
    if (version_required.IsValid() &&
        extension->version().CompareTo(version_required) < 0) {
      // It should not happen, CrxInstaller will make sure the version is
      // equal or newer than version_required.
      ReportFailure(kDependencyNotFoundError,
                    FAILURE_REASON_DEPENDENCY_NOT_FOUND);
    } else if (!SharedModuleInfo::IsSharedModule(extension)) {
      // It should not happen, CrxInstaller will make sure it is a shared
      // module.
      ReportFailure(kDependencyNotSharedModuleError,
                    FAILURE_REASON_DEPENDENCY_NOT_SHARED_MODULE);
    } else {
      DownloadNextPendingModule();
    }
  }
}

void WebstoreInstaller::InvalidateDelegate() {
  delegate_ = NULL;
}

void WebstoreInstaller::SetDownloadDirectoryForTests(
    base::FilePath* directory) {
  g_download_directory_for_tests = directory;
}

WebstoreInstaller::~WebstoreInstaller() {
  if (download_item_) {
    download_item_->RemoveObserver(this);
    download_item_ = NULL;
  }
}

void WebstoreInstaller::OnDownloadStarted(
    const std::string& extension_id,
    DownloadItem* item,
    download::DownloadInterruptReason interrupt_reason) {
  if (!item || interrupt_reason != download::DOWNLOAD_INTERRUPT_REASON_NONE) {
    if (item)
      item->Remove();
    ReportFailure(download::DownloadInterruptReasonToString(interrupt_reason),
                  FAILURE_REASON_OTHER);
    return;
  }

  bool found = false;
  for (const auto& module : pending_modules_) {
    if (extension_id == module.extension_id) {
      found = true;
      break;
    }
  }
  if (!found) {
    // If this extension is not pending, it means another installer has
    // installed this extension and triggered OnExtensionInstalled(). In this
    // case, either it was the main module and success has already been
    // reported, or it was a dependency and either failed (ie. wrong version) or
    // the next download was triggered. In any case, the only thing that needs
    // to be done is to stop this download.
    item->Remove();
    return;
  }

  DCHECK_EQ(download::DOWNLOAD_INTERRUPT_REASON_NONE, interrupt_reason);
  DCHECK(!pending_modules_.empty());
  download_item_ = item;
  download_item_->AddObserver(this);
  if (pending_modules_.size() > 1) {
    // We are downloading a shared module. We need create an approval for it.
    std::unique_ptr<Approval> approval =
        Approval::CreateForSharedModule(profile_);
    const SharedModuleInfo::ImportInfo& info = pending_modules_.front();
    approval->extension_id = info.extension_id;
    const base::Version version_required(info.minimum_version);

    if (version_required.IsValid()) {
      approval->minimum_version.reset(new base::Version(version_required));
    }
    download_item_->SetUserData(kApprovalKey, std::move(approval));
  } else {
    // It is for the main module of the extension. We should use the provided
    // |approval_|.
    if (approval_)
      download_item_->SetUserData(kApprovalKey, std::move(approval_));
  }

  if (!download_started_) {
    if (delegate_)
      delegate_->OnExtensionDownloadStarted(id_, download_item_);
    download_started_ = true;
  }
}

void WebstoreInstaller::OnDownloadUpdated(DownloadItem* download) {
  CHECK_EQ(download_item_, download);

  switch (download->GetState()) {
    case DownloadItem::CANCELLED:
      ReportFailure(kDownloadCanceledError, FAILURE_REASON_CANCELLED);
      break;
    case DownloadItem::INTERRUPTED:
      RecordInterrupt(download);
      ReportFailure(
          GetErrorMessageForDownloadInterrupt(download->GetLastReason()),
          FAILURE_REASON_OTHER);
      break;
    case DownloadItem::COMPLETE:
      // Stop the progress timer if it's running.
      download_progress_timer_.Stop();

      // Only wait for other notifications if the download is really
      // an extension.
      if (!download_crx_util::IsExtensionDownload(*download)) {
        ReportFailure(kInvalidDownloadError, FAILURE_REASON_OTHER);
        return;
      }

      if (crx_installer_.get())
        return;  // DownloadItemImpl calls the observer twice, ignore it.

      StartCrxInstaller(*download);

      if (pending_modules_.size() == 1) {
        // The download is the last module - the extension main module.
        if (delegate_)
          delegate_->OnExtensionDownloadProgress(id_, download);
        extensions::InstallTracker* tracker =
            extensions::InstallTrackerFactory::GetForBrowserContext(profile_);
        tracker->OnDownloadProgress(id_, 100);
      }
      break;
    case DownloadItem::IN_PROGRESS: {
      if (delegate_ && pending_modules_.size() == 1) {
        // Only report download progress for the main module to |delegrate_|.
        delegate_->OnExtensionDownloadProgress(id_, download);
      }
      UpdateDownloadProgress();
      break;
    }
    default:
      // Continue listening if the download is not in one of the above states.
      break;
  }
}

void WebstoreInstaller::OnDownloadDestroyed(DownloadItem* download) {
  CHECK_EQ(download_item_, download);
  download_item_->RemoveObserver(this);
  download_item_ = NULL;
}

void WebstoreInstaller::DownloadNextPendingModule() {
  CHECK(!pending_modules_.empty());
  if (pending_modules_.size() == 1) {
    DCHECK_EQ(id_, pending_modules_.front().extension_id);
    DownloadCrx(id_, install_source_);
  } else {
    DownloadCrx(pending_modules_.front().extension_id, INSTALL_SOURCE_OTHER);
  }
}

void WebstoreInstaller::DownloadCrx(
    const std::string& extension_id,
    InstallSource source) {
  download_url_ = GetWebstoreInstallURL(extension_id, source);
  MaybeAppendAuthUserParameter(approval_->authuser, &download_url_);

  base::FilePath user_data_dir;
  base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
  base::FilePath download_path = user_data_dir.Append(kWebstoreDownloadFolder);

  base::FilePath download_directory(g_download_directory_for_tests ?
      *g_download_directory_for_tests : download_path);

  base::PostTaskAndReplyWithResult(
      GetExtensionFileTaskRunner().get(), FROM_HERE,
      base::BindOnce(&GetDownloadFilePath, download_directory, extension_id),
      base::BindOnce(&WebstoreInstaller::StartDownload, this, extension_id));
}

// http://crbug.com/165634
// http://crbug.com/126013
// The current working theory is that one of the many pointers dereferenced in
// here is occasionally deleted before all of its referers are nullified,
// probably in a callback race. After this comment is released, the crash
// reports should narrow down exactly which pointer it is.  Collapsing all the
// early-returns into a single branch makes it hard to see exactly which pointer
// it is.
void WebstoreInstaller::StartDownload(const std::string& extension_id,
                                      const base::FilePath& file) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (file.empty()) {
    ReportFailure(kDownloadDirectoryError, FAILURE_REASON_OTHER);
    return;
  }

  DownloadManager* download_manager =
      BrowserContext::GetDownloadManager(profile_);
  if (!download_manager) {
    ReportFailure(kDownloadDirectoryError, FAILURE_REASON_OTHER);
    return;
  }

  content::WebContents* contents = web_contents();
  if (!contents) {
    ReportFailure(kDownloadDirectoryError, FAILURE_REASON_OTHER);
    return;
  }
  if (!contents->GetRenderViewHost()) {
    ReportFailure(kDownloadDirectoryError, FAILURE_REASON_OTHER);
    return;
  }
  if (!contents->GetRenderViewHost()->GetProcess()) {
    ReportFailure(kDownloadDirectoryError, FAILURE_REASON_OTHER);
    return;
  }

  content::NavigationController& controller = contents->GetController();
  if (!controller.GetBrowserContext()) {
    ReportFailure(kDownloadDirectoryError, FAILURE_REASON_OTHER);
    return;
  }
  if (!controller.GetBrowserContext()->GetResourceContext()) {
    ReportFailure(kDownloadDirectoryError, FAILURE_REASON_OTHER);
    return;
  }

  // The download url for the given extension is contained in |download_url_|.
  // We will navigate the current tab to this url to start the download. The
  // download system will then pass the crx to the CrxInstaller.
  int render_process_host_id =
      contents->GetRenderViewHost()->GetProcess()->GetID();
  int render_view_host_routing_id =
      contents->GetRenderViewHost()->GetRoutingID();

  content::RenderFrameHost* render_frame_host = contents->GetMainFrame();
  net::NetworkTrafficAnnotationTag traffic_annotation =
      net::DefineNetworkTrafficAnnotation("webstore_installer", R"(
        semantics {
          sender: "Webstore Installer"
          description: "Downloads an extension for installation."
          trigger:
            "User initiates a webstore extension installation flow, including "
            "installing from the webstore, inline installation from a site, "
            "re-installing a corrupted extension, and others."
          data:
            "The id of the extension to be installed and information about the "
            "user's installation, including version, language, distribution "
            "(Chrome vs Chromium), NaCl architecture, installation source (as "
            "an enum), and accepted crx formats."
          destination: GOOGLE_OWNED_SERVICE
        }
        policy {
          cookies_allowed: YES
          cookies_store: "user"
          setting:
            "This feature cannot be disabled. It is only activated if the user "
            "triggers an extension installation."
          chrome_policy {
            ExtensionInstallBlacklist {
              ExtensionInstallBlacklist: {
                entries: '*'
              }
            }
          }
        })");
  std::unique_ptr<DownloadUrlParameters> params(new DownloadUrlParameters(
      download_url_, render_process_host_id, render_view_host_routing_id,
      render_frame_host->GetRoutingID(), traffic_annotation));
  params->set_file_path(file);
  if (controller.GetVisibleEntry()) {
    content::Referrer referrer = content::Referrer::SanitizeForRequest(
        download_url_,
        content::Referrer(controller.GetVisibleEntry()->GetURL(),
                          network::mojom::ReferrerPolicy::kDefault));
    params->set_referrer(referrer.url);
    params->set_referrer_policy(
        content::Referrer::ReferrerPolicyForUrlRequest(referrer.policy));
  }
  params->set_callback(base::BindOnce(&WebstoreInstaller::OnDownloadStarted,
                                      this, extension_id));
  params->set_download_source(download::DownloadSource::EXTENSION_INSTALLER);
  download_manager->DownloadUrl(std::move(params));
}

void WebstoreInstaller::UpdateDownloadProgress() {
  // If the download has gone away, or isn't in progress (in which case we can't
  // give a good progress estimate), stop any running timers and return.
  if (!download_item_ ||
      download_item_->GetState() != DownloadItem::IN_PROGRESS) {
    download_progress_timer_.Stop();
    return;
  }

  int percent = download_item_->PercentComplete();
  // Only report progress if percent is more than 0 or we have finished
  // downloading at least one of the pending modules.
  int finished_modules = total_modules_ - pending_modules_.size();
  if (finished_modules > 0 && percent < 0)
    percent = 0;
  if (percent >= 0) {
    percent = (percent + (finished_modules * 100)) / total_modules_;
    extensions::InstallTracker* tracker =
        extensions::InstallTrackerFactory::GetForBrowserContext(profile_);
    tracker->OnDownloadProgress(id_, percent);
  }

  // If there's enough time remaining on the download to warrant an update,
  // set the timer (overwriting any current timers). Otherwise, stop the
  // timer.
  base::TimeDelta time_remaining;
  if (download_item_->TimeRemaining(&time_remaining) &&
      time_remaining > kTimeRemainingThreshold) {
    download_progress_timer_.Start(FROM_HERE, kTimeRemainingThreshold, this,
                                   &WebstoreInstaller::UpdateDownloadProgress);
  } else {
    download_progress_timer_.Stop();
  }
}

void WebstoreInstaller::StartCrxInstaller(const DownloadItem& download) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(!crx_installer_.get());

  ExtensionService* service = ExtensionSystem::Get(profile_)->
      extension_service();
  CHECK(service);

  const Approval* approval = GetAssociatedApproval(download);
  DCHECK(approval);

  crx_installer_ = download_crx_util::CreateCrxInstaller(profile_, download);

  crx_installer_->set_expected_id(approval->extension_id);
  crx_installer_->set_is_gallery_install(true);
  crx_installer_->set_allow_silent_install(true);

  crx_installer_->InstallCrx(download.GetFullPath());
}

void WebstoreInstaller::ReportFailure(const std::string& error,
                                      FailureReason reason) {
  if (delegate_) {
    delegate_->OnExtensionInstallFailure(id_, error, reason);
    delegate_ = NULL;
  }

  extensions::InstallTracker* tracker =
      extensions::InstallTrackerFactory::GetForBrowserContext(profile_);
  tracker->OnInstallFailure(id_);

  Release();  // Balanced in Start().
}

void WebstoreInstaller::ReportSuccess() {
  if (delegate_) {
    delegate_->OnExtensionInstallSuccess(id_);
    delegate_ = NULL;
  }

  Release();  // Balanced in Start().
}

void WebstoreInstaller::RecordInterrupt(const DownloadItem* download) const {
  base::UmaHistogramSparse("Extensions.WebstoreDownload.InterruptReason",
                           download->GetLastReason());

  // Use logarithmic bin sizes up to 1 TB.
  const int kNumBuckets = 30;
  const int64_t kMaxSizeKb = 1 << kNumBuckets;
  UMA_HISTOGRAM_CUSTOM_COUNTS(
      "Extensions.WebstoreDownload.InterruptReceivedKBytes",
      download->GetReceivedBytes() / 1024,
      1,
      kMaxSizeKb,
      kNumBuckets);
  int64_t total_bytes = download->GetTotalBytes();
  if (total_bytes >= 0) {
    UMA_HISTOGRAM_CUSTOM_COUNTS(
        "Extensions.WebstoreDownload.InterruptTotalKBytes",
        total_bytes / 1024,
        1,
        kMaxSizeKb,
        kNumBuckets);
  }
  UMA_HISTOGRAM_BOOLEAN(
      "Extensions.WebstoreDownload.InterruptTotalSizeUnknown",
      total_bytes <= 0);
}

}  // namespace extensions
