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/process/process.h"
10 #include "base/strings/stringprintf.h"
11 #include "chrome/browser/download/download_service.h"
12 #include "chrome/browser/download/download_service_factory.h"
13 #include "chrome/browser/download/download_stats.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_item.h"
20 #include "content/public/browser/download_save_info.h"
21 #include "content/public/browser/download_url_parameters.h"
22 #include "content/public/browser/render_process_host.h"
23 #include "content/public/browser/render_view_host.h"
24 #include "content/public/browser/resource_context.h"
25 #include "content/public/browser/resource_dispatcher_host.h"
26 #include "content/public/browser/web_contents.h"
27 #include "content/public/common/referrer.h"
28 #include "net/base/request_priority.h"
29 #include "net/url_request/url_request.h"
30 #include "net/url_request/url_request_context.h"
32 using content::BrowserContext
;
33 using content::BrowserThread
;
34 using content::DownloadItem
;
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(
50 url
, net::DEFAULT_PRIORITY
, NULL
));
51 content::DownloadInterruptReason error
= rdh
->BeginDownload(
54 false, // is_content_initiated
56 render_process_host_id
,
57 render_view_host_routing_id
,
59 scoped_ptr
<content::DownloadSaveInfo
>(new content::DownloadSaveInfo()),
60 content::DownloadItem::kInvalidId
,
63 if (error
!= content::DOWNLOAD_INTERRUPT_REASON_NONE
) {
64 BrowserThread::PostTask(
65 BrowserThread::UI
, FROM_HERE
,
66 base::Bind(callback
, static_cast<DownloadItem
*>(NULL
), error
));
72 PluginInstaller::PluginInstaller()
73 : state_(INSTALLER_STATE_IDLE
),
74 strong_observer_count_(0) {
77 PluginInstaller::~PluginInstaller() {
80 void PluginInstaller::OnDownloadUpdated(DownloadItem
* download
) {
81 DownloadItem::DownloadState state
= download
->GetState();
83 case DownloadItem::IN_PROGRESS
:
85 case DownloadItem::COMPLETE
: {
86 DCHECK_EQ(INSTALLER_STATE_DOWNLOADING
, state_
);
87 state_
= INSTALLER_STATE_IDLE
;
88 FOR_EACH_OBSERVER(PluginInstallerObserver
, observers_
,
92 case DownloadItem::CANCELLED
: {
96 case DownloadItem::INTERRUPTED
: {
97 content::DownloadInterruptReason reason
= download
->GetLastReason();
98 DownloadError(content::DownloadInterruptReasonToString(reason
));
101 case DownloadItem::MAX_DOWNLOAD_STATE
: {
106 download
->RemoveObserver(this);
109 void PluginInstaller::OnDownloadDestroyed(DownloadItem
* download
) {
110 DCHECK_EQ(INSTALLER_STATE_DOWNLOADING
, state_
);
111 state_
= INSTALLER_STATE_IDLE
;
112 download
->RemoveObserver(this);
115 void PluginInstaller::AddObserver(PluginInstallerObserver
* observer
) {
116 strong_observer_count_
++;
117 observers_
.AddObserver(observer
);
120 void PluginInstaller::RemoveObserver(PluginInstallerObserver
* observer
) {
121 strong_observer_count_
--;
122 observers_
.RemoveObserver(observer
);
123 if (strong_observer_count_
== 0) {
124 FOR_EACH_OBSERVER(WeakPluginInstallerObserver
, weak_observers_
,
125 OnlyWeakObserversLeft());
129 void PluginInstaller::AddWeakObserver(WeakPluginInstallerObserver
* observer
) {
130 weak_observers_
.AddObserver(observer
);
133 void PluginInstaller::RemoveWeakObserver(
134 WeakPluginInstallerObserver
* observer
) {
135 weak_observers_
.RemoveObserver(observer
);
138 void PluginInstaller::StartInstalling(const GURL
& plugin_url
,
139 content::WebContents
* web_contents
) {
140 DCHECK_EQ(INSTALLER_STATE_IDLE
, state_
);
141 state_
= INSTALLER_STATE_DOWNLOADING
;
142 FOR_EACH_OBSERVER(PluginInstallerObserver
, observers_
, DownloadStarted());
144 Profile::FromBrowserContext(web_contents
->GetBrowserContext());
145 RecordDownloadSource(DOWNLOAD_INITIATED_BY_PLUGIN_INSTALLER
);
146 BrowserThread::PostTask(
147 BrowserThread::IO
, FROM_HERE
,
148 base::Bind(&BeginDownload
,
150 profile
->GetResourceContext(),
151 web_contents
->GetRenderProcessHost()->GetID(),
152 web_contents
->GetRenderViewHost()->GetRoutingID(),
153 base::Bind(&PluginInstaller::DownloadStarted
,
154 base::Unretained(this))));
157 void PluginInstaller::DownloadStarted(
158 content::DownloadItem
* item
,
159 content::DownloadInterruptReason interrupt_reason
) {
161 DCHECK_NE(content::DOWNLOAD_INTERRUPT_REASON_NONE
, interrupt_reason
);
162 std::string msg
= base::StringPrintf(
165 content::DownloadInterruptReasonToString(interrupt_reason
).c_str());
169 DCHECK_EQ(content::DOWNLOAD_INTERRUPT_REASON_NONE
, interrupt_reason
);
170 item
->SetOpenWhenComplete(true);
171 item
->AddObserver(this);
174 void PluginInstaller::OpenDownloadURL(const GURL
& plugin_url
,
175 content::WebContents
* web_contents
) {
176 DCHECK_EQ(INSTALLER_STATE_IDLE
, state_
);
177 web_contents
->OpenURL(content::OpenURLParams(
179 content::Referrer(web_contents
->GetURL(),
180 blink::WebReferrerPolicyDefault
),
181 NEW_FOREGROUND_TAB
, content::PAGE_TRANSITION_TYPED
, false));
182 FOR_EACH_OBSERVER(PluginInstallerObserver
, observers_
, DownloadFinished());
185 void PluginInstaller::DownloadError(const std::string
& msg
) {
186 DCHECK_EQ(INSTALLER_STATE_DOWNLOADING
, state_
);
187 state_
= INSTALLER_STATE_IDLE
;
188 FOR_EACH_OBSERVER(PluginInstallerObserver
, observers_
, DownloadError(msg
));
191 void PluginInstaller::DownloadCancelled() {
192 DCHECK_EQ(INSTALLER_STATE_DOWNLOADING
, state_
);
193 state_
= INSTALLER_STATE_IDLE
;
194 FOR_EACH_OBSERVER(PluginInstallerObserver
, observers_
, DownloadCancelled());