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
PluginInstaller()22 PluginInstaller::PluginInstaller()
23 : state_(INSTALLER_STATE_IDLE),
24 strong_observer_count_(0) {
25 }
26
~PluginInstaller()27 PluginInstaller::~PluginInstaller() {
28 }
29
OnDownloadUpdated(DownloadItem * download)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
OnDownloadDestroyed(DownloadItem * download)59 void PluginInstaller::OnDownloadDestroyed(DownloadItem* download) {
60 DCHECK_EQ(INSTALLER_STATE_DOWNLOADING, state_);
61 state_ = INSTALLER_STATE_IDLE;
62 download->RemoveObserver(this);
63 }
64
AddObserver(PluginInstallerObserver * observer)65 void PluginInstaller::AddObserver(PluginInstallerObserver* observer) {
66 strong_observer_count_++;
67 observers_.AddObserver(observer);
68 }
69
RemoveObserver(PluginInstallerObserver * observer)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
AddWeakObserver(WeakPluginInstallerObserver * observer)79 void PluginInstaller::AddWeakObserver(WeakPluginInstallerObserver* observer) {
80 weak_observers_.AddObserver(observer);
81 }
82
RemoveWeakObserver(WeakPluginInstallerObserver * observer)83 void PluginInstaller::RemoveWeakObserver(
84 WeakPluginInstallerObserver* observer) {
85 weak_observers_.RemoveObserver(observer);
86 }
87
StartInstalling(const GURL & plugin_url,content::WebContents * web_contents)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
StartInstallingWithDownloadManager(const GURL & plugin_url,content::WebContents * web_contents,content::DownloadManager * download_manager)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
DownloadStarted(content::DownloadItem * item,content::DownloadInterruptReason interrupt_reason)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
OpenDownloadURL(const GURL & plugin_url,content::WebContents * web_contents)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, content::PAGE_TRANSITION_TYPED, false));
136 FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadFinished());
137 }
138
DownloadError(const std::string & msg)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
DownloadCancelled()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