plugin_installer.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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.h" 10#include "chrome/browser/download/download_service.h" 11#include "chrome/browser/download/download_service_factory.h" 12#include "chrome/browser/download/download_util.h" 13#include "chrome/browser/platform_util.h" 14#include "chrome/browser/plugins/plugin_installer_observer.h" 15#include "chrome/browser/profiles/profile.h" 16#include "content/public/browser/browser_context.h" 17#include "content/public/browser/browser_thread.h" 18#include "content/public/browser/download_id.h" 19#include "content/public/browser/download_item.h" 20#include "content/public/browser/download_save_info.h" 21#include "content/public/browser/render_process_host.h" 22#include "content/public/browser/render_view_host.h" 23#include "content/public/browser/resource_context.h" 24#include "content/public/browser/resource_dispatcher_host.h" 25#include "content/public/browser/web_contents.h" 26#include "content/public/common/referrer.h" 27#include "net/url_request/url_request.h" 28#include "net/url_request/url_request_context.h" 29 30using content::BrowserContext; 31using content::BrowserThread; 32using content::DownloadItem; 33using content::ResourceDispatcherHost; 34 35namespace { 36 37void BeginDownload( 38 const GURL& url, 39 content::ResourceContext* resource_context, 40 int render_process_host_id, 41 int render_view_host_routing_id, 42 const ResourceDispatcherHost::DownloadStartedCallback& callback) { 43 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 44 45 ResourceDispatcherHost* rdh = ResourceDispatcherHost::Get(); 46 scoped_ptr<net::URLRequest> request( 47 resource_context->GetRequestContext()->CreateRequest(url, NULL)); 48 net::Error error = rdh->BeginDownload( 49 request.Pass(), 50 content::Referrer(), 51 false, // is_content_initiated 52 resource_context, 53 render_process_host_id, 54 render_view_host_routing_id, 55 true, // prefer_cache 56 scoped_ptr<content::DownloadSaveInfo>(new content::DownloadSaveInfo()), 57 content::DownloadId::Invalid(), 58 callback); 59 60 if (error != net::OK) { 61 BrowserThread::PostTask( 62 BrowserThread::UI, FROM_HERE, 63 base::Bind(callback, static_cast<DownloadItem*>(NULL), error)); 64 } 65} 66 67} // namespace 68 69PluginInstaller::PluginInstaller() 70 : state_(INSTALLER_STATE_IDLE) { 71} 72 73PluginInstaller::~PluginInstaller() { 74} 75 76void PluginInstaller::OnDownloadUpdated(DownloadItem* download) { 77 DownloadItem::DownloadState state = download->GetState(); 78 switch (state) { 79 case DownloadItem::IN_PROGRESS: 80 return; 81 case DownloadItem::COMPLETE: { 82 DCHECK_EQ(INSTALLER_STATE_DOWNLOADING, state_); 83 state_ = INSTALLER_STATE_IDLE; 84 FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, 85 DownloadFinished()); 86 break; 87 } 88 case DownloadItem::CANCELLED: { 89 DownloadCancelled(); 90 break; 91 } 92 case DownloadItem::INTERRUPTED: { 93 content::DownloadInterruptReason reason = download->GetLastReason(); 94 DownloadError(content::InterruptReasonDebugString(reason)); 95 break; 96 } 97 case DownloadItem::MAX_DOWNLOAD_STATE: { 98 NOTREACHED(); 99 return; 100 } 101 } 102 download->RemoveObserver(this); 103} 104 105void PluginInstaller::OnDownloadDestroyed(DownloadItem* download) { 106 DCHECK_EQ(INSTALLER_STATE_DOWNLOADING, state_); 107 state_ = INSTALLER_STATE_IDLE; 108 download->RemoveObserver(this); 109} 110 111void PluginInstaller::AddObserver(PluginInstallerObserver* observer) { 112 observers_.AddObserver(observer); 113} 114 115void PluginInstaller::RemoveObserver(PluginInstallerObserver* observer) { 116 observers_.RemoveObserver(observer); 117 if (observers_.size() == weak_observers_.size()) { 118 FOR_EACH_OBSERVER(WeakPluginInstallerObserver, weak_observers_, 119 OnlyWeakObserversLeft()); 120 } 121} 122 123void PluginInstaller::AddWeakObserver(WeakPluginInstallerObserver* observer) { 124 weak_observers_.AddObserver(observer); 125} 126 127void PluginInstaller::RemoveWeakObserver( 128 WeakPluginInstallerObserver* observer) { 129 weak_observers_.RemoveObserver(observer); 130} 131 132void PluginInstaller::StartInstalling(const GURL& plugin_url, 133 content::WebContents* web_contents) { 134 DCHECK_EQ(INSTALLER_STATE_IDLE, state_); 135 state_ = INSTALLER_STATE_DOWNLOADING; 136 FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadStarted()); 137 Profile* profile = 138 Profile::FromBrowserContext(web_contents->GetBrowserContext()); 139 download_util::RecordDownloadSource( 140 download_util::INITIATED_BY_PLUGIN_INSTALLER); 141 BrowserThread::PostTask( 142 BrowserThread::IO, FROM_HERE, 143 base::Bind(&BeginDownload, 144 plugin_url, 145 profile->GetResourceContext(), 146 web_contents->GetRenderProcessHost()->GetID(), 147 web_contents->GetRenderViewHost()->GetRoutingID(), 148 base::Bind(&PluginInstaller::DownloadStarted, 149 base::Unretained(this)))); 150} 151 152void PluginInstaller::DownloadStarted(content::DownloadItem* item, 153 net::Error error) { 154 if (!item) { 155 DCHECK_NE(net::OK, error); 156 std::string msg = 157 base::StringPrintf("Error %d: %s", error, net::ErrorToString(error)); 158 DownloadError(msg); 159 return; 160 } 161 DCHECK_EQ(net::OK, error); 162 item->SetOpenWhenComplete(true); 163 item->AddObserver(this); 164} 165 166void PluginInstaller::OpenDownloadURL(const GURL& plugin_url, 167 content::WebContents* web_contents) { 168 DCHECK_EQ(INSTALLER_STATE_IDLE, state_); 169 web_contents->OpenURL(content::OpenURLParams( 170 plugin_url, 171 content::Referrer(web_contents->GetURL(), 172 WebKit::WebReferrerPolicyDefault), 173 NEW_FOREGROUND_TAB, content::PAGE_TRANSITION_TYPED, false)); 174 FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadFinished()); 175} 176 177void PluginInstaller::DownloadError(const std::string& msg) { 178 DCHECK_EQ(INSTALLER_STATE_DOWNLOADING, state_); 179 state_ = INSTALLER_STATE_IDLE; 180 FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadError(msg)); 181} 182 183void PluginInstaller::DownloadCancelled() { 184 DCHECK_EQ(INSTALLER_STATE_DOWNLOADING, state_); 185 state_ = INSTALLER_STATE_IDLE; 186 FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadCancelled()); 187} 188