blob: bef3f4d7fa9e8d4a4a39531f39a3639fe924500f [file] [log] [blame]
// 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/plugins/plugin_installer.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/process/process.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/download/download_stats.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/plugins/plugin_installer_observer.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/download_item.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/download_url_parameters.h"
#include "content/public/browser/web_contents.h"
using content::DownloadItem;
PluginInstaller::PluginInstaller()
: state_(INSTALLER_STATE_IDLE),
strong_observer_count_(0) {
}
PluginInstaller::~PluginInstaller() {
}
void PluginInstaller::OnDownloadUpdated(DownloadItem* download) {
DownloadItem::DownloadState state = download->GetState();
switch (state) {
case DownloadItem::IN_PROGRESS:
return;
case DownloadItem::COMPLETE: {
DCHECK_EQ(INSTALLER_STATE_DOWNLOADING, state_);
state_ = INSTALLER_STATE_IDLE;
FOR_EACH_OBSERVER(PluginInstallerObserver, observers_,
DownloadFinished());
break;
}
case DownloadItem::CANCELLED: {
DownloadCancelled();
break;
}
case DownloadItem::INTERRUPTED: {
content::DownloadInterruptReason reason = download->GetLastReason();
DownloadError(content::DownloadInterruptReasonToString(reason));
break;
}
case DownloadItem::MAX_DOWNLOAD_STATE: {
NOTREACHED();
return;
}
}
download->RemoveObserver(this);
}
void PluginInstaller::OnDownloadDestroyed(DownloadItem* download) {
DCHECK_EQ(INSTALLER_STATE_DOWNLOADING, state_);
state_ = INSTALLER_STATE_IDLE;
download->RemoveObserver(this);
}
void PluginInstaller::AddObserver(PluginInstallerObserver* observer) {
strong_observer_count_++;
observers_.AddObserver(observer);
}
void PluginInstaller::RemoveObserver(PluginInstallerObserver* observer) {
strong_observer_count_--;
observers_.RemoveObserver(observer);
if (strong_observer_count_ == 0) {
FOR_EACH_OBSERVER(WeakPluginInstallerObserver, weak_observers_,
OnlyWeakObserversLeft());
}
}
void PluginInstaller::AddWeakObserver(WeakPluginInstallerObserver* observer) {
weak_observers_.AddObserver(observer);
}
void PluginInstaller::RemoveWeakObserver(
WeakPluginInstallerObserver* observer) {
weak_observers_.RemoveObserver(observer);
}
void PluginInstaller::StartInstalling(const GURL& plugin_url,
content::WebContents* web_contents) {
content::DownloadManager* download_manager =
content::BrowserContext::GetDownloadManager(
web_contents->GetBrowserContext());
StartInstallingWithDownloadManager(
plugin_url, web_contents, download_manager);
}
void PluginInstaller::StartInstallingWithDownloadManager(
const GURL& plugin_url,
content::WebContents* web_contents,
content::DownloadManager* download_manager) {
DCHECK_EQ(INSTALLER_STATE_IDLE, state_);
state_ = INSTALLER_STATE_DOWNLOADING;
FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadStarted());
scoped_ptr<content::DownloadUrlParameters> download_parameters(
content::DownloadUrlParameters::FromWebContents(web_contents,
plugin_url));
download_parameters->set_callback(
base::Bind(&PluginInstaller::DownloadStarted, base::Unretained(this)));
RecordDownloadSource(DOWNLOAD_INITIATED_BY_PLUGIN_INSTALLER);
download_manager->DownloadUrl(download_parameters.Pass());
}
void PluginInstaller::DownloadStarted(
content::DownloadItem* item,
content::DownloadInterruptReason interrupt_reason) {
if (interrupt_reason != content::DOWNLOAD_INTERRUPT_REASON_NONE) {
std::string msg = base::StringPrintf(
"Error %d: %s",
interrupt_reason,
content::DownloadInterruptReasonToString(interrupt_reason).c_str());
DownloadError(msg);
return;
}
item->SetOpenWhenComplete(true);
item->AddObserver(this);
}
void PluginInstaller::OpenDownloadURL(const GURL& plugin_url,
content::WebContents* web_contents) {
DCHECK_EQ(INSTALLER_STATE_IDLE, state_);
web_contents->OpenURL(content::OpenURLParams(
plugin_url,
content::Referrer(web_contents->GetURL(),
blink::WebReferrerPolicyDefault),
NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_TYPED, false));
FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadFinished());
}
void PluginInstaller::DownloadError(const std::string& msg) {
DCHECK_EQ(INSTALLER_STATE_DOWNLOADING, state_);
state_ = INSTALLER_STATE_IDLE;
FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadError(msg));
}
void PluginInstaller::DownloadCancelled() {
DCHECK_EQ(INSTALLER_STATE_DOWNLOADING, state_);
state_ = INSTALLER_STATE_IDLE;
FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadCancelled());
}