Home | History | Annotate | Download | only in plugins
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/plugins/plugin_installer.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/bind_helpers.h"
      9 #include "base/process/process.h"
     10 #include "base/strings/stringprintf.h"
     11 #include "chrome/browser/download/download_stats.h"
     12 #include "chrome/browser/platform_util.h"
     13 #include "chrome/browser/plugins/plugin_installer_observer.h"
     14 #include "content/public/browser/browser_context.h"
     15 #include "content/public/browser/download_item.h"
     16 #include "content/public/browser/download_manager.h"
     17 #include "content/public/browser/download_url_parameters.h"
     18 #include "content/public/browser/web_contents.h"
     19 
     20 using content::DownloadItem;
     21 
     22 PluginInstaller::PluginInstaller()
     23     : state_(INSTALLER_STATE_IDLE),
     24       strong_observer_count_(0) {
     25 }
     26 
     27 PluginInstaller::~PluginInstaller() {
     28 }
     29 
     30 void PluginInstaller::OnDownloadUpdated(DownloadItem* download) {
     31   DownloadItem::DownloadState state = download->GetState();
     32   switch (state) {
     33     case DownloadItem::IN_PROGRESS:
     34       return;
     35     case DownloadItem::COMPLETE: {
     36       DCHECK_EQ(INSTALLER_STATE_DOWNLOADING, state_);
     37       state_ = INSTALLER_STATE_IDLE;
     38       FOR_EACH_OBSERVER(PluginInstallerObserver, observers_,
     39                         DownloadFinished());
     40       break;
     41     }
     42     case DownloadItem::CANCELLED: {
     43       DownloadCancelled();
     44       break;
     45     }
     46     case DownloadItem::INTERRUPTED: {
     47       content::DownloadInterruptReason reason = download->GetLastReason();
     48       DownloadError(content::DownloadInterruptReasonToString(reason));
     49       break;
     50     }
     51     case DownloadItem::MAX_DOWNLOAD_STATE: {
     52       NOTREACHED();
     53       return;
     54     }
     55   }
     56   download->RemoveObserver(this);
     57 }
     58 
     59 void PluginInstaller::OnDownloadDestroyed(DownloadItem* download) {
     60   DCHECK_EQ(INSTALLER_STATE_DOWNLOADING, state_);
     61   state_ = INSTALLER_STATE_IDLE;
     62   download->RemoveObserver(this);
     63 }
     64 
     65 void PluginInstaller::AddObserver(PluginInstallerObserver* observer) {
     66   strong_observer_count_++;
     67   observers_.AddObserver(observer);
     68 }
     69 
     70 void PluginInstaller::RemoveObserver(PluginInstallerObserver* observer) {
     71   strong_observer_count_--;
     72   observers_.RemoveObserver(observer);
     73   if (strong_observer_count_ == 0) {
     74     FOR_EACH_OBSERVER(WeakPluginInstallerObserver, weak_observers_,
     75                       OnlyWeakObserversLeft());
     76   }
     77 }
     78 
     79 void PluginInstaller::AddWeakObserver(WeakPluginInstallerObserver* observer) {
     80   weak_observers_.AddObserver(observer);
     81 }
     82 
     83 void PluginInstaller::RemoveWeakObserver(
     84     WeakPluginInstallerObserver* observer) {
     85   weak_observers_.RemoveObserver(observer);
     86 }
     87 
     88 void PluginInstaller::StartInstalling(const GURL& plugin_url,
     89                                       content::WebContents* web_contents) {
     90   content::DownloadManager* download_manager =
     91       content::BrowserContext::GetDownloadManager(
     92           web_contents->GetBrowserContext());
     93   StartInstallingWithDownloadManager(
     94       plugin_url, web_contents, download_manager);
     95 }
     96 
     97 void PluginInstaller::StartInstallingWithDownloadManager(
     98     const GURL& plugin_url,
     99     content::WebContents* web_contents,
    100     content::DownloadManager* download_manager) {
    101   DCHECK_EQ(INSTALLER_STATE_IDLE, state_);
    102   state_ = INSTALLER_STATE_DOWNLOADING;
    103   FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadStarted());
    104   scoped_ptr<content::DownloadUrlParameters> download_parameters(
    105       content::DownloadUrlParameters::FromWebContents(web_contents,
    106                                                       plugin_url));
    107   download_parameters->set_callback(
    108       base::Bind(&PluginInstaller::DownloadStarted, base::Unretained(this)));
    109   RecordDownloadSource(DOWNLOAD_INITIATED_BY_PLUGIN_INSTALLER);
    110   download_manager->DownloadUrl(download_parameters.Pass());
    111 }
    112 
    113 void PluginInstaller::DownloadStarted(
    114     content::DownloadItem* item,
    115     content::DownloadInterruptReason interrupt_reason) {
    116   if (interrupt_reason != content::DOWNLOAD_INTERRUPT_REASON_NONE) {
    117     std::string msg = base::StringPrintf(
    118         "Error %d: %s",
    119         interrupt_reason,
    120         content::DownloadInterruptReasonToString(interrupt_reason).c_str());
    121     DownloadError(msg);
    122     return;
    123   }
    124   item->SetOpenWhenComplete(true);
    125   item->AddObserver(this);
    126 }
    127 
    128 void PluginInstaller::OpenDownloadURL(const GURL& plugin_url,
    129                                       content::WebContents* web_contents) {
    130   DCHECK_EQ(INSTALLER_STATE_IDLE, state_);
    131   web_contents->OpenURL(content::OpenURLParams(
    132       plugin_url,
    133       content::Referrer(web_contents->GetURL(),
    134                         blink::WebReferrerPolicyDefault),
    135       NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_TYPED, false));
    136   FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadFinished());
    137 }
    138 
    139 void PluginInstaller::DownloadError(const std::string& msg) {
    140   DCHECK_EQ(INSTALLER_STATE_DOWNLOADING, state_);
    141   state_ = INSTALLER_STATE_IDLE;
    142   FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadError(msg));
    143 }
    144 
    145 void PluginInstaller::DownloadCancelled() {
    146   DCHECK_EQ(INSTALLER_STATE_DOWNLOADING, state_);
    147   state_ = INSTALLER_STATE_IDLE;
    148   FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadCancelled());
    149 }
    150