// 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 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()); }