// 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_registry.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"

#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/drive/file_system_util.h"
#endif

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");

  int uniquifier =
      base::GetUniquePathNumber(file, base::FilePath::StringType());
  if (uniquifier > 0) {
    file = file.InsertBeforeExtensionASCII(
        base::StringPrintf(" (%d)", uniquifier));
  }

  return 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),
      extension_registry_observer_(this),
      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_ = NULL;

  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);

#if defined(OS_CHROMEOS)
  // Do not use drive for extension downloads.
  if (drive::util::IsUnderDriveMountPoint(download_directory)) {
    download_directory = DownloadPrefs::FromBrowserContext(
        profile_)->GetDefaultDownloadDirectoryForProfile();
  }
#endif

  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::Bind(&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());

  // The clock may be backward, e.g. daylight savings time just happenned.
  if (download.GetEndTime() >= download.GetStartTime()) {
    UMA_HISTOGRAM_TIMES("Extensions.WebstoreDownload.FileDownload",
                        download.GetEndTime() - download.GetStartTime());
  }
  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
