OLD | NEW |
| (Empty) |
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/plugin_installer.h" | |
6 | |
7 #include "base/bind.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/plugin_installer_observer.h" | |
16 #include "chrome/browser/profiles/profile.h" | |
17 #include "chrome/browser/ui/tab_contents/tab_contents.h" | |
18 #include "content/public/browser/browser_context.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" | |
30 #include "webkit/plugins/npapi/plugin_group.h" | |
31 #include "webkit/plugins/npapi/plugin_utils.h" | |
32 #include "webkit/plugins/webplugininfo.h" | |
33 | |
34 using content::BrowserContext; | |
35 using content::BrowserThread; | |
36 using content::DownloadItem; | |
37 using content::DownloadManager; | |
38 using content::ResourceDispatcherHost; | |
39 | |
40 namespace { | |
41 | |
42 void BeginDownload( | |
43 const GURL& url, | |
44 content::ResourceContext* resource_context, | |
45 int render_process_host_id, | |
46 int render_view_host_routing_id, | |
47 const ResourceDispatcherHost::DownloadStartedCallback& callback) { | |
48 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
49 | |
50 ResourceDispatcherHost* rdh = ResourceDispatcherHost::Get(); | |
51 scoped_ptr<net::URLRequest> request( | |
52 resource_context->GetRequestContext()->CreateRequest(url, NULL)); | |
53 net::Error error = rdh->BeginDownload( | |
54 request.Pass(), | |
55 false, // is_content_initiated | |
56 resource_context, | |
57 render_process_host_id, | |
58 render_view_host_routing_id, | |
59 true, // prefer_cache | |
60 content::DownloadSaveInfo(), | |
61 callback); | |
62 | |
63 if (error != net::OK) { | |
64 BrowserThread::PostTask( | |
65 BrowserThread::UI, FROM_HERE, | |
66 base::Bind(callback, content::DownloadId::Invalid(), error)); | |
67 } | |
68 } | |
69 | |
70 } // namespace | |
71 | |
72 PluginInstaller::PluginInstaller(const std::string& identifier, | |
73 const string16& name, | |
74 bool url_for_display, | |
75 const GURL& plugin_url, | |
76 const GURL& help_url, | |
77 const string16& group_name_matcher) | |
78 : identifier_(identifier), | |
79 name_(name), | |
80 group_name_matcher_(group_name_matcher), | |
81 url_for_display_(url_for_display), | |
82 plugin_url_(plugin_url), | |
83 help_url_(help_url), | |
84 state_(INSTALLER_STATE_IDLE) { | |
85 } | |
86 | |
87 PluginInstaller::~PluginInstaller() { | |
88 } | |
89 | |
90 void PluginInstaller::AddVersion(const Version& version, | |
91 SecurityStatus status) { | |
92 DCHECK(versions_.find(version) == versions_.end()); | |
93 versions_[version] = status; | |
94 } | |
95 | |
96 PluginInstaller::SecurityStatus PluginInstaller::GetSecurityStatus( | |
97 const webkit::WebPluginInfo& plugin) const { | |
98 if (versions_.empty()) { | |
99 #if defined(OS_LINUX) | |
100 // On Linux, unknown plugins require authorization. | |
101 return SECURITY_STATUS_REQUIRES_AUTHORIZATION; | |
102 #else | |
103 return SECURITY_STATUS_UP_TO_DATE; | |
104 #endif | |
105 } | |
106 | |
107 Version version; | |
108 webkit::npapi::CreateVersionFromString(plugin.version, &version); | |
109 if (!version.IsValid()) | |
110 version = Version("0"); | |
111 | |
112 // |lower_bound| returns the latest version that is not newer than |version|. | |
113 std::map<Version, SecurityStatus, VersionComparator>::const_iterator it = | |
114 versions_.lower_bound(version); | |
115 // If there is at least one version defined, everything older than the oldest | |
116 // defined version is considered out-of-date. | |
117 if (it == versions_.end()) | |
118 return SECURITY_STATUS_OUT_OF_DATE; | |
119 | |
120 return it->second; | |
121 } | |
122 | |
123 bool PluginInstaller::VersionComparator::operator() (const Version& lhs, | |
124 const Version& rhs) const { | |
125 // Keep versions ordered by newest (biggest) first. | |
126 return lhs.CompareTo(rhs) > 0; | |
127 } | |
128 | |
129 // static | |
130 bool PluginInstaller::ParseSecurityStatus( | |
131 const std::string& status_str, | |
132 PluginInstaller::SecurityStatus* status) { | |
133 if (status_str == "up_to_date") | |
134 *status = SECURITY_STATUS_UP_TO_DATE; | |
135 else if (status_str == "out_of_date") | |
136 *status = SECURITY_STATUS_OUT_OF_DATE; | |
137 else if (status_str == "requires_authorization") | |
138 *status = SECURITY_STATUS_REQUIRES_AUTHORIZATION; | |
139 else | |
140 return false; | |
141 | |
142 return true; | |
143 } | |
144 | |
145 void PluginInstaller::OnDownloadUpdated(DownloadItem* download) { | |
146 DownloadItem::DownloadState state = download->GetState(); | |
147 switch (state) { | |
148 case DownloadItem::IN_PROGRESS: | |
149 return; | |
150 case DownloadItem::COMPLETE: { | |
151 DCHECK_EQ(INSTALLER_STATE_DOWNLOADING, state_); | |
152 state_ = INSTALLER_STATE_IDLE; | |
153 FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, | |
154 DownloadFinished()); | |
155 break; | |
156 } | |
157 case DownloadItem::CANCELLED: { | |
158 DownloadCancelled(); | |
159 break; | |
160 } | |
161 case DownloadItem::INTERRUPTED: { | |
162 content::DownloadInterruptReason reason = download->GetLastReason(); | |
163 DownloadError(content::InterruptReasonDebugString(reason)); | |
164 break; | |
165 } | |
166 case DownloadItem::MAX_DOWNLOAD_STATE: { | |
167 NOTREACHED(); | |
168 return; | |
169 } | |
170 } | |
171 download->RemoveObserver(this); | |
172 } | |
173 | |
174 void PluginInstaller::OnDownloadDestroyed(DownloadItem* download) { | |
175 DCHECK_EQ(INSTALLER_STATE_DOWNLOADING, state_); | |
176 state_ = INSTALLER_STATE_IDLE; | |
177 download->RemoveObserver(this); | |
178 } | |
179 | |
180 void PluginInstaller::AddObserver(PluginInstallerObserver* observer) { | |
181 observers_.AddObserver(observer); | |
182 } | |
183 | |
184 void PluginInstaller::RemoveObserver(PluginInstallerObserver* observer) { | |
185 observers_.RemoveObserver(observer); | |
186 if (observers_.size() == weak_observers_.size()) { | |
187 FOR_EACH_OBSERVER(WeakPluginInstallerObserver, weak_observers_, | |
188 OnlyWeakObserversLeft()); | |
189 } | |
190 } | |
191 | |
192 void PluginInstaller::AddWeakObserver(WeakPluginInstallerObserver* observer) { | |
193 weak_observers_.AddObserver(observer); | |
194 } | |
195 | |
196 void PluginInstaller::RemoveWeakObserver( | |
197 WeakPluginInstallerObserver* observer) { | |
198 weak_observers_.RemoveObserver(observer); | |
199 } | |
200 | |
201 void PluginInstaller::StartInstalling(TabContents* tab_contents) { | |
202 DCHECK_EQ(INSTALLER_STATE_IDLE, state_); | |
203 DCHECK(!url_for_display_); | |
204 state_ = INSTALLER_STATE_DOWNLOADING; | |
205 FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadStarted()); | |
206 content::WebContents* web_contents = tab_contents->web_contents(); | |
207 DownloadManager* download_manager = | |
208 BrowserContext::GetDownloadManager(tab_contents->profile()); | |
209 download_util::RecordDownloadSource( | |
210 download_util::INITIATED_BY_PLUGIN_INSTALLER); | |
211 BrowserThread::PostTask( | |
212 BrowserThread::IO, FROM_HERE, | |
213 base::Bind(&BeginDownload, | |
214 plugin_url_, | |
215 tab_contents->profile()->GetResourceContext(), | |
216 web_contents->GetRenderProcessHost()->GetID(), | |
217 web_contents->GetRenderViewHost()->GetRoutingID(), | |
218 base::Bind(&PluginInstaller::DownloadStarted, | |
219 base::Unretained(this), | |
220 make_scoped_refptr(download_manager)))); | |
221 } | |
222 | |
223 void PluginInstaller::DownloadStarted( | |
224 scoped_refptr<content::DownloadManager> dlm, | |
225 content::DownloadId download_id, | |
226 net::Error error) { | |
227 if (error != net::OK) { | |
228 std::string msg = | |
229 base::StringPrintf("Error %d: %s", error, net::ErrorToString(error)); | |
230 DownloadError(msg); | |
231 return; | |
232 } | |
233 DownloadItem* download_item = | |
234 dlm->GetActiveDownloadItem(download_id.local()); | |
235 download_item->SetOpenWhenComplete(true); | |
236 download_item->AddObserver(this); | |
237 } | |
238 | |
239 void PluginInstaller::OpenDownloadURL(content::WebContents* web_contents) { | |
240 DCHECK_EQ(INSTALLER_STATE_IDLE, state_); | |
241 DCHECK(url_for_display_); | |
242 web_contents->OpenURL(content::OpenURLParams( | |
243 plugin_url_, | |
244 content::Referrer(web_contents->GetURL(), | |
245 WebKit::WebReferrerPolicyDefault), | |
246 NEW_FOREGROUND_TAB, content::PAGE_TRANSITION_TYPED, false)); | |
247 FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadFinished()); | |
248 } | |
249 | |
250 void PluginInstaller::DownloadError(const std::string& msg) { | |
251 DCHECK_EQ(INSTALLER_STATE_DOWNLOADING, state_); | |
252 state_ = INSTALLER_STATE_IDLE; | |
253 FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadError(msg)); | |
254 } | |
255 | |
256 void PluginInstaller::DownloadCancelled() { | |
257 DCHECK_EQ(INSTALLER_STATE_DOWNLOADING, state_); | |
258 state_ = INSTALLER_STATE_IDLE; | |
259 FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadCancelled()); | |
260 } | |
261 | |
262 bool PluginInstaller::MatchesPlugin(const webkit::WebPluginInfo& plugin) { | |
263 return plugin.name.find(group_name_matcher_) != string16::npos; | |
264 } | |
OLD | NEW |