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.
5 #include "chrome/browser/plugins/plugin_installer.h"
8 #include "base/bind_helpers.h"
9 #include "base/file_util.h"
10 #include "base/process.h"
11 #include "chrome/browser/download/download_service.h"
12 #include "chrome/browser/download/download_service_factory.h"
13 #include "chrome/browser/download/download_util.h"
14 #include "chrome/browser/platform_util.h"
15 #include "chrome/browser/plugins/plugin_installer_observer.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "content/public/browser/browser_context.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/download_id.h"
20 #include "content/public/browser/download_item.h"
21 #include "content/public/browser/download_manager.h"
22 #include "content/public/browser/download_save_info.h"
23 #include "content/public/browser/render_process_host.h"
24 #include "content/public/browser/render_view_host.h"
25 #include "content/public/browser/resource_context.h"
26 #include "content/public/browser/resource_dispatcher_host.h"
27 #include "content/public/browser/web_contents.h"
28 #include "net/url_request/url_request.h"
29 #include "net/url_request/url_request_context.h"
31 using content::BrowserContext
;
32 using content::BrowserThread
;
33 using content::DownloadItem
;
34 using content::DownloadManager
;
35 using content::ResourceDispatcherHost
;
41 content::ResourceContext
* resource_context
,
42 int render_process_host_id
,
43 int render_view_host_routing_id
,
44 const ResourceDispatcherHost::DownloadStartedCallback
& callback
) {
45 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
47 ResourceDispatcherHost
* rdh
= ResourceDispatcherHost::Get();
48 scoped_ptr
<net::URLRequest
> request(
49 resource_context
->GetRequestContext()->CreateRequest(url
, NULL
));
50 net::Error error
= rdh
->BeginDownload(
52 false, // is_content_initiated
54 render_process_host_id
,
55 render_view_host_routing_id
,
57 scoped_ptr
<content::DownloadSaveInfo
>(new content::DownloadSaveInfo()),
58 content::DownloadId::Invalid(),
61 if (error
!= net::OK
) {
62 BrowserThread::PostTask(
63 BrowserThread::UI
, FROM_HERE
,
64 base::Bind(callback
, static_cast<DownloadItem
*>(NULL
), error
));
70 PluginInstaller::PluginInstaller()
71 : state_(INSTALLER_STATE_IDLE
) {
74 PluginInstaller::~PluginInstaller() {
77 void PluginInstaller::OnDownloadUpdated(DownloadItem
* download
) {
78 DownloadItem::DownloadState state
= download
->GetState();
80 case DownloadItem::IN_PROGRESS
:
82 case DownloadItem::COMPLETE
: {
83 DCHECK_EQ(INSTALLER_STATE_DOWNLOADING
, state_
);
84 state_
= INSTALLER_STATE_IDLE
;
85 FOR_EACH_OBSERVER(PluginInstallerObserver
, observers_
,
89 case DownloadItem::CANCELLED
: {
93 case DownloadItem::INTERRUPTED
: {
94 content::DownloadInterruptReason reason
= download
->GetLastReason();
95 DownloadError(content::InterruptReasonDebugString(reason
));
98 case DownloadItem::MAX_DOWNLOAD_STATE
: {
103 download
->RemoveObserver(this);
106 void PluginInstaller::OnDownloadDestroyed(DownloadItem
* download
) {
107 DCHECK_EQ(INSTALLER_STATE_DOWNLOADING
, state_
);
108 state_
= INSTALLER_STATE_IDLE
;
109 download
->RemoveObserver(this);
112 void PluginInstaller::AddObserver(PluginInstallerObserver
* observer
) {
113 observers_
.AddObserver(observer
);
116 void PluginInstaller::RemoveObserver(PluginInstallerObserver
* observer
) {
117 observers_
.RemoveObserver(observer
);
118 if (observers_
.size() == weak_observers_
.size()) {
119 FOR_EACH_OBSERVER(WeakPluginInstallerObserver
, weak_observers_
,
120 OnlyWeakObserversLeft());
124 void PluginInstaller::AddWeakObserver(WeakPluginInstallerObserver
* observer
) {
125 weak_observers_
.AddObserver(observer
);
128 void PluginInstaller::RemoveWeakObserver(
129 WeakPluginInstallerObserver
* observer
) {
130 weak_observers_
.RemoveObserver(observer
);
133 void PluginInstaller::StartInstalling(const GURL
& plugin_url
,
134 content::WebContents
* web_contents
) {
135 DCHECK_EQ(INSTALLER_STATE_IDLE
, state_
);
136 state_
= INSTALLER_STATE_DOWNLOADING
;
137 FOR_EACH_OBSERVER(PluginInstallerObserver
, observers_
, DownloadStarted());
139 Profile::FromBrowserContext(web_contents
->GetBrowserContext());
140 DownloadManager
* download_manager
=
141 BrowserContext::GetDownloadManager(profile
);
142 download_util::RecordDownloadSource(
143 download_util::INITIATED_BY_PLUGIN_INSTALLER
);
144 BrowserThread::PostTask(
145 BrowserThread::IO
, FROM_HERE
,
146 base::Bind(&BeginDownload
,
148 profile
->GetResourceContext(),
149 web_contents
->GetRenderProcessHost()->GetID(),
150 web_contents
->GetRenderViewHost()->GetRoutingID(),
151 base::Bind(&PluginInstaller::DownloadStarted
,
152 base::Unretained(this),
153 make_scoped_refptr(download_manager
))));
156 void PluginInstaller::DownloadStarted(
157 scoped_refptr
<content::DownloadManager
> dlm
,
158 content::DownloadItem
* item
,
161 DCHECK_NE(net::OK
, error
);
163 base::StringPrintf("Error %d: %s", error
, net::ErrorToString(error
));
167 DCHECK_EQ(net::OK
, error
);
168 item
->SetOpenWhenComplete(true);
169 item
->AddObserver(this);
172 void PluginInstaller::OpenDownloadURL(const GURL
& plugin_url
,
173 content::WebContents
* web_contents
) {
174 DCHECK_EQ(INSTALLER_STATE_IDLE
, state_
);
175 web_contents
->OpenURL(content::OpenURLParams(
177 content::Referrer(web_contents
->GetURL(),
178 WebKit::WebReferrerPolicyDefault
),
179 NEW_FOREGROUND_TAB
, content::PAGE_TRANSITION_TYPED
, false));
180 FOR_EACH_OBSERVER(PluginInstallerObserver
, observers_
, DownloadFinished());
183 void PluginInstaller::DownloadError(const std::string
& msg
) {
184 DCHECK_EQ(INSTALLER_STATE_DOWNLOADING
, state_
);
185 state_
= INSTALLER_STATE_IDLE
;
186 FOR_EACH_OBSERVER(PluginInstallerObserver
, observers_
, DownloadError(msg
));
189 void PluginInstaller::DownloadCancelled() {
190 DCHECK_EQ(INSTALLER_STATE_DOWNLOADING
, state_
);
191 state_
= INSTALLER_STATE_IDLE
;
192 FOR_EACH_OBSERVER(PluginInstallerObserver
, observers_
, DownloadCancelled());