Remove implicit conversions from scoped_refptr to T* in content/browser/service_worker
[chromium-blink-merge.git] / content / browser / android / download_controller_android_impl.cc
blob08cea4be685598b5cbe345e07bf5ec67f7e0a299
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 "content/browser/android/download_controller_android_impl.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_string.h"
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/time/time.h"
13 #include "content/browser/android/content_view_core_impl.h"
14 #include "content/browser/download/download_item_impl.h"
15 #include "content/browser/download/download_manager_impl.h"
16 #include "content/browser/loader/resource_dispatcher_host_impl.h"
17 #include "content/browser/renderer_host/render_process_host_impl.h"
18 #include "content/browser/renderer_host/render_view_host_delegate.h"
19 #include "content/browser/renderer_host/render_view_host_impl.h"
20 #include "content/browser/web_contents/web_contents_impl.h"
21 #include "content/public/browser/browser_context.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "content/public/browser/download_url_parameters.h"
24 #include "content/public/browser/global_request_id.h"
25 #include "content/public/browser/resource_request_info.h"
26 #include "content/public/common/referrer.h"
27 #include "jni/DownloadController_jni.h"
28 #include "net/cookies/cookie_options.h"
29 #include "net/cookies/cookie_store.h"
30 #include "net/http/http_content_disposition.h"
31 #include "net/http/http_request_headers.h"
32 #include "net/http/http_response_headers.h"
33 #include "net/url_request/url_request.h"
34 #include "net/url_request/url_request_context.h"
36 using base::android::ConvertUTF8ToJavaString;
37 using base::android::ScopedJavaLocalRef;
39 namespace content {
41 // JNI methods
42 static void Init(JNIEnv* env, jobject obj) {
43 DownloadControllerAndroidImpl::GetInstance()->Init(env, obj);
46 struct DownloadControllerAndroidImpl::JavaObject {
47 ScopedJavaLocalRef<jobject> Controller(JNIEnv* env) {
48 return GetRealObject(env, obj);
50 jweak obj;
53 // static
54 bool DownloadControllerAndroidImpl::RegisterDownloadController(JNIEnv* env) {
55 return RegisterNativesImpl(env);
58 // static
59 DownloadControllerAndroid* DownloadControllerAndroid::Get() {
60 return DownloadControllerAndroidImpl::GetInstance();
63 // static
64 DownloadControllerAndroidImpl* DownloadControllerAndroidImpl::GetInstance() {
65 return Singleton<DownloadControllerAndroidImpl>::get();
68 DownloadControllerAndroidImpl::DownloadControllerAndroidImpl()
69 : java_object_(NULL) {
72 DownloadControllerAndroidImpl::~DownloadControllerAndroidImpl() {
73 if (java_object_) {
74 JNIEnv* env = base::android::AttachCurrentThread();
75 env->DeleteWeakGlobalRef(java_object_->obj);
76 delete java_object_;
77 base::android::CheckException(env);
81 // Initialize references to Java object.
82 void DownloadControllerAndroidImpl::Init(JNIEnv* env, jobject obj) {
83 java_object_ = new JavaObject;
84 java_object_->obj = env->NewWeakGlobalRef(obj);
87 void DownloadControllerAndroidImpl::CreateGETDownload(
88 int render_process_id, int render_view_id, int request_id) {
89 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
90 GlobalRequestID global_id(render_process_id, request_id);
92 // We are yielding the UI thread and render_view_host may go away by
93 // the time we come back. Pass along render_process_id and render_view_id
94 // to retrieve it later (if it still exists).
95 GetDownloadInfoCB cb = base::Bind(
96 &DownloadControllerAndroidImpl::StartAndroidDownload,
97 base::Unretained(this), render_process_id,
98 render_view_id);
100 PrepareDownloadInfo(
101 global_id,
102 base::Bind(&DownloadControllerAndroidImpl::StartDownloadOnUIThread,
103 base::Unretained(this), cb));
106 void DownloadControllerAndroidImpl::PrepareDownloadInfo(
107 const GlobalRequestID& global_id,
108 const GetDownloadInfoCB& callback) {
109 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
111 net::URLRequest* request =
112 ResourceDispatcherHostImpl::Get()->GetURLRequest(global_id);
113 if (!request) {
114 LOG(ERROR) << "Request to download not found.";
115 return;
118 DownloadInfoAndroid info_android(request);
120 net::CookieStore* cookie_store = request->context()->cookie_store();
121 if (cookie_store) {
122 net::CookieMonster* cookie_monster = cookie_store->GetCookieMonster();
123 if (cookie_monster) {
124 cookie_monster->GetAllCookiesForURLAsync(
125 request->url(),
126 base::Bind(&DownloadControllerAndroidImpl::CheckPolicyAndLoadCookies,
127 base::Unretained(this), info_android, callback,
128 global_id));
129 } else {
130 DoLoadCookies(info_android, callback, global_id);
132 } else {
133 // Can't get any cookies, start android download.
134 callback.Run(info_android);
138 void DownloadControllerAndroidImpl::CheckPolicyAndLoadCookies(
139 const DownloadInfoAndroid& info, const GetDownloadInfoCB& callback,
140 const GlobalRequestID& global_id, const net::CookieList& cookie_list) {
141 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
143 net::URLRequest* request =
144 ResourceDispatcherHostImpl::Get()->GetURLRequest(global_id);
145 if (!request) {
146 LOG(ERROR) << "Request to download not found.";
147 return;
150 if (request->context()->network_delegate()->CanGetCookies(
151 *request, cookie_list)) {
152 DoLoadCookies(info, callback, global_id);
153 } else {
154 callback.Run(info);
158 void DownloadControllerAndroidImpl::DoLoadCookies(
159 const DownloadInfoAndroid& info, const GetDownloadInfoCB& callback,
160 const GlobalRequestID& global_id) {
161 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
163 net::CookieOptions options;
164 options.set_include_httponly();
166 net::URLRequest* request =
167 ResourceDispatcherHostImpl::Get()->GetURLRequest(global_id);
168 if (!request) {
169 LOG(ERROR) << "Request to download not found.";
170 return;
173 request->context()->cookie_store()->GetCookiesWithOptionsAsync(
174 info.url, options,
175 base::Bind(&DownloadControllerAndroidImpl::OnCookieResponse,
176 base::Unretained(this), info, callback));
179 void DownloadControllerAndroidImpl::OnCookieResponse(
180 DownloadInfoAndroid download_info,
181 const GetDownloadInfoCB& callback,
182 const std::string& cookie) {
183 download_info.cookie = cookie;
185 // We have everything we need, start Android download.
186 callback.Run(download_info);
189 void DownloadControllerAndroidImpl::StartDownloadOnUIThread(
190 const GetDownloadInfoCB& callback,
191 const DownloadInfoAndroid& info) {
192 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
193 BrowserThread::PostTask(
194 BrowserThread::UI, FROM_HERE, base::Bind(callback, info));
197 void DownloadControllerAndroidImpl::StartAndroidDownload(
198 int render_process_id, int render_view_id,
199 const DownloadInfoAndroid& info) {
200 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
201 JNIEnv* env = base::android::AttachCurrentThread();
203 // Call newHttpGetDownload
204 ScopedJavaLocalRef<jobject> view = GetContentView(render_process_id,
205 render_view_id);
206 if (view.is_null()) {
207 // The view went away. Can't proceed.
208 LOG(ERROR) << "Download failed on URL:" << info.url.spec();
209 return;
212 ScopedJavaLocalRef<jstring> jurl =
213 ConvertUTF8ToJavaString(env, info.url.spec());
214 ScopedJavaLocalRef<jstring> juser_agent =
215 ConvertUTF8ToJavaString(env, info.user_agent);
216 ScopedJavaLocalRef<jstring> jcontent_disposition =
217 ConvertUTF8ToJavaString(env, info.content_disposition);
218 ScopedJavaLocalRef<jstring> jmime_type =
219 ConvertUTF8ToJavaString(env, info.original_mime_type);
220 ScopedJavaLocalRef<jstring> jcookie =
221 ConvertUTF8ToJavaString(env, info.cookie);
222 ScopedJavaLocalRef<jstring> jreferer =
223 ConvertUTF8ToJavaString(env, info.referer);
225 // Try parsing the content disposition header to get a
226 // explicitly specified filename if available.
227 net::HttpContentDisposition header(info.content_disposition, "");
228 ScopedJavaLocalRef<jstring> jfilename =
229 ConvertUTF8ToJavaString(env, header.filename());
231 Java_DownloadController_newHttpGetDownload(
232 env, GetJavaObject()->Controller(env).obj(), view.obj(), jurl.obj(),
233 juser_agent.obj(), jcontent_disposition.obj(), jmime_type.obj(),
234 jcookie.obj(), jreferer.obj(), info.has_user_gesture, jfilename.obj(),
235 info.total_bytes);
238 void DownloadControllerAndroidImpl::OnDownloadStarted(
239 DownloadItem* download_item) {
240 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
241 if (!download_item->GetWebContents())
242 return;
244 JNIEnv* env = base::android::AttachCurrentThread();
246 // Register for updates to the DownloadItem.
247 download_item->AddObserver(this);
249 ScopedJavaLocalRef<jobject> view =
250 GetContentViewCoreFromWebContents(download_item->GetWebContents());
251 // The view went away. Can't proceed.
252 if (view.is_null())
253 return;
255 ScopedJavaLocalRef<jstring> jmime_type =
256 ConvertUTF8ToJavaString(env, download_item->GetMimeType());
257 ScopedJavaLocalRef<jstring> jfilename = ConvertUTF8ToJavaString(
258 env, download_item->GetTargetFilePath().BaseName().value());
259 Java_DownloadController_onDownloadStarted(
260 env, GetJavaObject()->Controller(env).obj(), view.obj(), jfilename.obj(),
261 jmime_type.obj());
264 void DownloadControllerAndroidImpl::OnDownloadUpdated(DownloadItem* item) {
265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
266 if (item->IsDangerous() && (item->GetState() != DownloadItem::CANCELLED))
267 OnDangerousDownload(item);
269 JNIEnv* env = base::android::AttachCurrentThread();
270 ScopedJavaLocalRef<jstring> jurl =
271 ConvertUTF8ToJavaString(env, item->GetURL().spec());
272 ScopedJavaLocalRef<jstring> jmime_type =
273 ConvertUTF8ToJavaString(env, item->GetMimeType());
274 ScopedJavaLocalRef<jstring> jpath =
275 ConvertUTF8ToJavaString(env, item->GetTargetFilePath().value());
276 ScopedJavaLocalRef<jstring> jfilename = ConvertUTF8ToJavaString(
277 env, item->GetTargetFilePath().BaseName().value());
279 switch (item->GetState()) {
280 case DownloadItem::IN_PROGRESS: {
281 base::TimeDelta time_delta;
282 item->TimeRemaining(&time_delta);
283 Java_DownloadController_onDownloadUpdated(
284 env, GetJavaObject()->Controller(env).obj(),
285 base::android::GetApplicationContext(), jurl.obj(), jmime_type.obj(),
286 jfilename.obj(), jpath.obj(), item->GetReceivedBytes(), true,
287 item->GetId(), item->PercentComplete(), time_delta.InMilliseconds());
288 break;
290 case DownloadItem::COMPLETE:
291 // Multiple OnDownloadUpdated() notifications may be issued while the
292 // download is in the COMPLETE state. Only handle one.
293 item->RemoveObserver(this);
295 // Call onDownloadCompleted
296 Java_DownloadController_onDownloadCompleted(
297 env, GetJavaObject()->Controller(env).obj(),
298 base::android::GetApplicationContext(), jurl.obj(), jmime_type.obj(),
299 jfilename.obj(), jpath.obj(), item->GetReceivedBytes(), true,
300 item->GetId());
301 break;
302 case DownloadItem::CANCELLED:
303 // TODO(shashishekhar): An interrupted download can be resumed. Android
304 // currently does not support resumable downloads. Add handling for
305 // interrupted case based on item->CanResume().
306 case DownloadItem::INTERRUPTED:
307 // Call onDownloadCompleted with success = false.
308 Java_DownloadController_onDownloadCompleted(
309 env, GetJavaObject()->Controller(env).obj(),
310 base::android::GetApplicationContext(), jurl.obj(), jmime_type.obj(),
311 jfilename.obj(), jpath.obj(), item->GetReceivedBytes(), false,
312 item->GetId());
313 break;
314 case DownloadItem::MAX_DOWNLOAD_STATE:
315 NOTREACHED();
319 void DownloadControllerAndroidImpl::OnDangerousDownload(DownloadItem* item) {
320 JNIEnv* env = base::android::AttachCurrentThread();
321 ScopedJavaLocalRef<jstring> jfilename = ConvertUTF8ToJavaString(
322 env, item->GetTargetFilePath().BaseName().value());
323 ScopedJavaLocalRef<jobject> view_core = GetContentViewCoreFromWebContents(
324 item->GetWebContents());
325 if (!view_core.is_null()) {
326 Java_DownloadController_onDangerousDownload(
327 env, GetJavaObject()->Controller(env).obj(), view_core.obj(),
328 jfilename.obj(), item->GetId());
332 ScopedJavaLocalRef<jobject> DownloadControllerAndroidImpl::GetContentView(
333 int render_process_id, int render_view_id) {
334 RenderViewHost* render_view_host =
335 RenderViewHost::FromID(render_process_id, render_view_id);
337 if (!render_view_host)
338 return ScopedJavaLocalRef<jobject>();
340 WebContents* web_contents =
341 render_view_host->GetDelegate()->GetAsWebContents();
343 return GetContentViewCoreFromWebContents(web_contents);
346 ScopedJavaLocalRef<jobject>
347 DownloadControllerAndroidImpl::GetContentViewCoreFromWebContents(
348 WebContents* web_contents) {
349 if (!web_contents)
350 return ScopedJavaLocalRef<jobject>();
352 ContentViewCore* view_core = ContentViewCore::FromWebContents(web_contents);
353 return view_core ? view_core->GetJavaObject() :
354 ScopedJavaLocalRef<jobject>();
357 DownloadControllerAndroidImpl::JavaObject*
358 DownloadControllerAndroidImpl::GetJavaObject() {
359 if (!java_object_) {
360 // Initialize Java DownloadController by calling
361 // DownloadController.getInstance(), which will call Init()
362 // if Java DownloadController is not instantiated already.
363 JNIEnv* env = base::android::AttachCurrentThread();
364 Java_DownloadController_getInstance(env);
367 DCHECK(java_object_);
368 return java_object_;
371 void DownloadControllerAndroidImpl::StartContextMenuDownload(
372 const ContextMenuParams& params, WebContents* web_contents, bool is_link) {
373 const GURL& url = is_link ? params.link_url : params.src_url;
374 const GURL& referrer = params.frame_url.is_empty() ?
375 params.page_url : params.frame_url;
376 DownloadManagerImpl* dlm = static_cast<DownloadManagerImpl*>(
377 BrowserContext::GetDownloadManager(web_contents->GetBrowserContext()));
378 scoped_ptr<DownloadUrlParameters> dl_params(
379 DownloadUrlParameters::FromWebContents(web_contents, url));
380 dl_params->set_referrer(
381 Referrer(referrer, params.referrer_policy));
382 if (is_link)
383 dl_params->set_referrer_encoding(params.frame_charset);
384 else
385 dl_params->set_prefer_cache(true);
386 dl_params->set_prompt(false);
387 dlm->DownloadUrl(dl_params.Pass());
390 void DownloadControllerAndroidImpl::DangerousDownloadValidated(
391 WebContents* web_contents, int download_id, bool accept) {
392 if (!web_contents)
393 return;
394 DownloadManagerImpl* dlm = static_cast<DownloadManagerImpl*>(
395 BrowserContext::GetDownloadManager(web_contents->GetBrowserContext()));
396 DownloadItem* item = dlm->GetDownload(download_id);
397 if (!item)
398 return;
399 if (accept)
400 item->ValidateDangerousDownload();
401 else
402 item->Remove();
405 DownloadControllerAndroidImpl::DownloadInfoAndroid::DownloadInfoAndroid(
406 net::URLRequest* request)
407 : has_user_gesture(false) {
408 request->GetResponseHeaderByName("content-disposition", &content_disposition);
410 if (request->response_headers())
411 request->response_headers()->GetMimeType(&original_mime_type);
413 request->extra_request_headers().GetHeader(
414 net::HttpRequestHeaders::kUserAgent, &user_agent);
415 GURL referer_url(request->referrer());
416 if (referer_url.is_valid())
417 referer = referer_url.spec();
418 if (!request->url_chain().empty()) {
419 original_url = request->url_chain().front();
420 url = request->url_chain().back();
423 const content::ResourceRequestInfo* info =
424 content::ResourceRequestInfo::ForRequest(request);
425 if (info)
426 has_user_gesture = info->HasUserGesture();
429 DownloadControllerAndroidImpl::DownloadInfoAndroid::~DownloadInfoAndroid() {}
431 } // namespace content