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