Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/android/download_controller_android_impl.h" | 5 #include "content/browser/android/download_controller_android_impl.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/android/context_utils.h" | 10 #include "base/android/context_utils.h" |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 33 #include "content/public/common/referrer.h" | 33 #include "content/public/common/referrer.h" |
| 34 #include "jni/DownloadController_jni.h" | 34 #include "jni/DownloadController_jni.h" |
| 35 #include "net/base/filename_util.h" | 35 #include "net/base/filename_util.h" |
| 36 #include "net/cookies/cookie_options.h" | 36 #include "net/cookies/cookie_options.h" |
| 37 #include "net/cookies/cookie_store.h" | 37 #include "net/cookies/cookie_store.h" |
| 38 #include "net/http/http_content_disposition.h" | 38 #include "net/http/http_content_disposition.h" |
| 39 #include "net/http/http_request_headers.h" | 39 #include "net/http/http_request_headers.h" |
| 40 #include "net/http/http_response_headers.h" | 40 #include "net/http/http_response_headers.h" |
| 41 #include "net/url_request/url_request.h" | 41 #include "net/url_request/url_request.h" |
| 42 #include "net/url_request/url_request_context.h" | 42 #include "net/url_request/url_request_context.h" |
| 43 #include "ui/android/window_android.h" | |
| 43 | 44 |
| 44 using base::android::ConvertUTF8ToJavaString; | 45 using base::android::ConvertUTF8ToJavaString; |
| 45 using base::android::ScopedJavaLocalRef; | 46 using base::android::ScopedJavaLocalRef; |
| 46 | 47 |
| 47 namespace { | 48 namespace { |
| 48 // Guards download_controller_ | 49 // Guards download_controller_ |
| 49 base::LazyInstance<base::Lock> g_download_controller_lock_; | 50 base::LazyInstance<base::Lock> g_download_controller_lock_; |
| 50 | 51 |
| 51 content::WebContents* GetWebContents(int render_process_id, | 52 content::WebContents* GetWebContents(int render_process_id, |
| 52 int render_view_id) { | 53 int render_view_id) { |
| 53 content::RenderViewHost* render_view_host = | 54 content::RenderViewHost* render_view_host = |
| 54 content::RenderViewHost::FromID(render_process_id, render_view_id); | 55 content::RenderViewHost::FromID(render_process_id, render_view_id); |
| 55 | 56 |
| 56 if (!render_view_host) | 57 if (!render_view_host) |
| 57 return nullptr; | 58 return nullptr; |
| 58 | 59 |
| 59 return content::WebContents::FromRenderViewHost(render_view_host); | 60 return content::WebContents::FromRenderViewHost(render_view_host); |
| 60 } | 61 } |
| 61 | 62 |
| 63 ScopedJavaLocalRef<jobject> | |
| 64 GetJavaWebContents(content::WebContents* web_contents) { | |
| 65 return (static_cast<content::WebContentsImpl*>(web_contents)) | |
| 66 ->GetJavaWebContents(); | |
| 67 } | |
| 68 | |
| 62 void CreateContextMenuDownload(int render_process_id, | 69 void CreateContextMenuDownload(int render_process_id, |
| 63 int render_view_id, | 70 int render_view_id, |
| 64 const content::ContextMenuParams& params, | 71 const content::ContextMenuParams& params, |
| 65 bool is_link, | 72 bool is_link, |
| 66 const std::string& extra_headers, | 73 const std::string& extra_headers, |
| 67 bool granted) { | 74 bool granted) { |
| 68 if (!granted) | 75 if (!granted) |
| 69 return; | 76 return; |
| 70 | 77 |
| 71 content::WebContents* web_contents = | 78 content::WebContents* web_contents = |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 196 } | 203 } |
| 197 } | 204 } |
| 198 } | 205 } |
| 199 | 206 |
| 200 void DownloadControllerAndroidImpl::AcquireFileAccessPermission( | 207 void DownloadControllerAndroidImpl::AcquireFileAccessPermission( |
| 201 WebContents* web_contents, | 208 WebContents* web_contents, |
| 202 const DownloadControllerAndroid::AcquireFileAccessPermissionCallback& cb) { | 209 const DownloadControllerAndroid::AcquireFileAccessPermissionCallback& cb) { |
| 203 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 210 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 204 DCHECK(web_contents); | 211 DCHECK(web_contents); |
| 205 | 212 |
| 206 ScopedJavaLocalRef<jobject> view = | 213 ContentViewCore* view_core = ContentViewCore::FromWebContents(web_contents); |
| 207 GetContentViewCoreFromWebContents(web_contents); | 214 if (!view_core) { |
| 208 if (view.is_null()) { | |
| 209 BrowserThread::PostTask( | 215 BrowserThread::PostTask( |
| 210 BrowserThread::UI, FROM_HERE, base::Bind(cb, false)); | 216 BrowserThread::UI, FROM_HERE, base::Bind(cb, false)); |
| 211 return; | 217 return; |
| 212 } | 218 } |
| 213 | 219 |
| 214 if (HasFileAccessPermission(view)) { | 220 ScopedJavaLocalRef<jobject> jweb_contents = |
| 221 GetJavaWebContents(web_contents); | |
| 222 ScopedJavaLocalRef<jobject> jwindow_android = | |
| 223 view_core->GetWindowAndroid()->GetJavaObject(); | |
| 224 if (HasFileAccessPermission(jwindow_android)) { | |
| 215 BrowserThread::PostTask( | 225 BrowserThread::PostTask( |
| 216 BrowserThread::UI, FROM_HERE, base::Bind(cb, true)); | 226 BrowserThread::UI, FROM_HERE, base::Bind(cb, true)); |
| 217 return; | 227 return; |
| 218 } | 228 } |
| 219 | 229 |
| 220 JNIEnv* env = base::android::AttachCurrentThread(); | 230 JNIEnv* env = base::android::AttachCurrentThread(); |
| 221 // Make copy on the heap so we can pass the pointer through JNI. | 231 // Make copy on the heap so we can pass the pointer through JNI. |
| 222 intptr_t callback_id = reinterpret_cast<intptr_t>( | 232 intptr_t callback_id = reinterpret_cast<intptr_t>( |
| 223 new DownloadControllerAndroid::AcquireFileAccessPermissionCallback(cb)); | 233 new DownloadControllerAndroid::AcquireFileAccessPermissionCallback(cb)); |
| 224 Java_DownloadController_requestFileAccess( | 234 Java_DownloadController_requestFileAccess( |
| 225 env, GetJavaObject()->Controller(env).obj(), view.obj(), callback_id); | 235 env, GetJavaObject()->Controller(env).obj(), jweb_contents.obj(), |
| 236 jwindow_android.obj(), callback_id); | |
| 226 } | 237 } |
| 227 | 238 |
| 228 void DownloadControllerAndroidImpl::SetDefaultDownloadFileName( | 239 void DownloadControllerAndroidImpl::SetDefaultDownloadFileName( |
| 229 const std::string& file_name) { | 240 const std::string& file_name) { |
| 230 default_file_name_ = file_name; | 241 default_file_name_ = file_name; |
| 231 } | 242 } |
| 232 | 243 |
| 233 bool DownloadControllerAndroidImpl::HasFileAccessPermission( | 244 bool DownloadControllerAndroidImpl::HasFileAccessPermission( |
| 234 ScopedJavaLocalRef<jobject> j_content_view_core) { | 245 ScopedJavaLocalRef<jobject> jwindow_android) { |
| 235 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 246 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 236 DCHECK(!j_content_view_core.is_null()); | 247 DCHECK(!jwindow_android.is_null()); |
| 237 | 248 |
| 238 JNIEnv* env = base::android::AttachCurrentThread(); | 249 JNIEnv* env = base::android::AttachCurrentThread(); |
| 239 return Java_DownloadController_hasFileAccess( | 250 return Java_DownloadController_hasFileAccess( |
| 240 env, GetJavaObject()->Controller(env).obj(), j_content_view_core.obj()); | 251 env, GetJavaObject()->Controller(env).obj(), jwindow_android.obj()); |
| 241 } | 252 } |
| 242 | 253 |
| 243 void DownloadControllerAndroidImpl::CreateGETDownload( | 254 void DownloadControllerAndroidImpl::CreateGETDownload( |
| 244 int render_process_id, int render_view_id, int request_id, | 255 int render_process_id, int render_view_id, int request_id, |
| 245 bool must_download) { | 256 bool must_download) { |
| 246 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 257 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 247 GlobalRequestID global_id(render_process_id, request_id); | 258 GlobalRequestID global_id(render_process_id, request_id); |
| 248 | 259 |
| 249 // We are yielding the UI thread and render_view_host may go away by | 260 // We are yielding the UI thread and render_view_host may go away by |
| 250 // the time we come back. Pass along render_process_id and render_view_id | 261 // the time we come back. Pass along render_process_id and render_view_id |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 349 int render_process_id, int render_view_id, bool must_download, | 360 int render_process_id, int render_view_id, bool must_download, |
| 350 const DownloadInfoAndroid& info) { | 361 const DownloadInfoAndroid& info) { |
| 351 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 362 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 352 | 363 |
| 353 WebContents* web_contents = GetWebContents(render_process_id, render_view_id); | 364 WebContents* web_contents = GetWebContents(render_process_id, render_view_id); |
| 354 if (!web_contents) { | 365 if (!web_contents) { |
| 355 // The view went away. Can't proceed. | 366 // The view went away. Can't proceed. |
| 356 LOG(ERROR) << "Download failed on URL:" << info.url.spec(); | 367 LOG(ERROR) << "Download failed on URL:" << info.url.spec(); |
| 357 return; | 368 return; |
| 358 } | 369 } |
| 359 ScopedJavaLocalRef<jobject> view = | |
| 360 GetContentViewCoreFromWebContents(web_contents); | |
| 361 if (view.is_null()) { | |
| 362 // ContentViewCore might not have been created yet, pass a callback to | |
| 363 // DeferredDownloadTaskManager so that the download can restart when | |
| 364 // ContentViewCore is created. | |
|
no sievers
2016/05/27 19:09:25
That would be really neat if we can get rid of thi
Jinsuk Kim
2016/05/30 01:20:57
I don't think we need it any more once the depende
| |
| 365 deferred_downloads_.push_back(new DeferredDownloadObserver( | |
| 366 web_contents, | |
| 367 base::Bind(&DownloadControllerAndroidImpl::StartAndroidDownload, | |
| 368 base::Unretained(this), render_process_id, render_view_id, | |
| 369 must_download, info))); | |
| 370 return; | |
| 371 } | |
| 372 | 370 |
| 373 AcquireFileAccessPermission( | 371 AcquireFileAccessPermission( |
| 374 web_contents, | 372 web_contents, |
| 375 base::Bind(&DownloadControllerAndroidImpl::StartAndroidDownloadInternal, | 373 base::Bind(&DownloadControllerAndroidImpl::StartAndroidDownloadInternal, |
| 376 base::Unretained(this), render_process_id, render_view_id, | 374 base::Unretained(this), render_process_id, render_view_id, |
| 377 must_download, info)); | 375 must_download, info)); |
| 378 } | 376 } |
| 379 | 377 |
| 380 void DownloadControllerAndroidImpl::StartAndroidDownloadInternal( | 378 void DownloadControllerAndroidImpl::StartAndroidDownloadInternal( |
| 381 int render_process_id, int render_view_id, bool must_download, | 379 int render_process_id, int render_view_id, bool must_download, |
| 382 const DownloadInfoAndroid& info, bool allowed) { | 380 const DownloadInfoAndroid& info, bool allowed) { |
| 383 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 381 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 384 if (!allowed) | 382 if (!allowed) |
| 385 return; | 383 return; |
| 386 | 384 |
| 387 // Call newHttpGetDownload | 385 // Call newHttpGetDownload |
| 388 WebContents* web_contents = GetWebContents(render_process_id, render_view_id); | 386 WebContents* web_contents = GetWebContents(render_process_id, render_view_id); |
| 389 // The view went away. Can't proceed. | 387 // The view went away. Can't proceed. |
| 390 if (!web_contents) | 388 if (!web_contents) |
| 391 return; | 389 return; |
| 392 ScopedJavaLocalRef<jobject> view = | 390 ScopedJavaLocalRef<jobject> jweb_contents = GetJavaWebContents(web_contents); |
| 393 GetContentViewCoreFromWebContents(web_contents); | |
| 394 if (view.is_null()) | |
| 395 return; | |
| 396 | 391 |
| 397 JNIEnv* env = base::android::AttachCurrentThread(); | 392 JNIEnv* env = base::android::AttachCurrentThread(); |
| 398 ScopedJavaLocalRef<jstring> jurl = | 393 ScopedJavaLocalRef<jstring> jurl = |
| 399 ConvertUTF8ToJavaString(env, info.url.spec()); | 394 ConvertUTF8ToJavaString(env, info.url.spec()); |
| 400 ScopedJavaLocalRef<jstring> juser_agent = | 395 ScopedJavaLocalRef<jstring> juser_agent = |
| 401 ConvertUTF8ToJavaString(env, info.user_agent); | 396 ConvertUTF8ToJavaString(env, info.user_agent); |
| 402 ScopedJavaLocalRef<jstring> jcontent_disposition = | 397 ScopedJavaLocalRef<jstring> jcontent_disposition = |
| 403 ConvertUTF8ToJavaString(env, info.content_disposition); | 398 ConvertUTF8ToJavaString(env, info.content_disposition); |
| 404 ScopedJavaLocalRef<jstring> jmime_type = | 399 ScopedJavaLocalRef<jstring> jmime_type = |
| 405 ConvertUTF8ToJavaString(env, info.original_mime_type); | 400 ConvertUTF8ToJavaString(env, info.original_mime_type); |
| 406 ScopedJavaLocalRef<jstring> jcookie = | 401 ScopedJavaLocalRef<jstring> jcookie = |
| 407 ConvertUTF8ToJavaString(env, info.cookie); | 402 ConvertUTF8ToJavaString(env, info.cookie); |
| 408 ScopedJavaLocalRef<jstring> jreferer = | 403 ScopedJavaLocalRef<jstring> jreferer = |
| 409 ConvertUTF8ToJavaString(env, info.referer); | 404 ConvertUTF8ToJavaString(env, info.referer); |
| 410 | 405 |
| 411 // net::GetSuggestedFilename will fallback to "download" as filename. | 406 // net::GetSuggestedFilename will fallback to "download" as filename. |
| 412 ScopedJavaLocalRef<jstring> jfilename = | 407 ScopedJavaLocalRef<jstring> jfilename = |
| 413 base::android::ConvertUTF16ToJavaString( | 408 base::android::ConvertUTF16ToJavaString( |
| 414 env, net::GetSuggestedFilename(info.url, info.content_disposition, | 409 env, net::GetSuggestedFilename(info.url, info.content_disposition, |
| 415 std::string(), // referrer_charset | 410 std::string(), // referrer_charset |
| 416 std::string(), // suggested_name | 411 std::string(), // suggested_name |
| 417 info.original_mime_type, | 412 info.original_mime_type, |
| 418 default_file_name_)); | 413 default_file_name_)); |
| 419 | 414 |
| 420 Java_DownloadController_newHttpGetDownload( | 415 Java_DownloadController_newHttpGetDownload( |
| 421 env, GetJavaObject()->Controller(env).obj(), view.obj(), jurl.obj(), | 416 env, GetJavaObject()->Controller(env).obj(), jweb_contents.obj(), |
| 422 juser_agent.obj(), jcontent_disposition.obj(), jmime_type.obj(), | 417 jurl.obj(), juser_agent.obj(), jcontent_disposition.obj(), |
| 423 jcookie.obj(), jreferer.obj(), info.has_user_gesture, jfilename.obj(), | 418 jmime_type.obj(), jcookie.obj(), jreferer.obj(), info.has_user_gesture, |
| 424 info.total_bytes, must_download); | 419 jfilename.obj(), info.total_bytes, must_download); |
| 425 } | 420 } |
| 426 | 421 |
| 427 void DownloadControllerAndroidImpl::OnDownloadStarted( | 422 void DownloadControllerAndroidImpl::OnDownloadStarted( |
| 428 DownloadItem* download_item) { | 423 DownloadItem* download_item) { |
| 429 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 424 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 430 if (!download_item->GetWebContents()) | 425 if (!download_item->GetWebContents()) |
| 431 return; | 426 return; |
| 432 | 427 |
| 433 JNIEnv* env = base::android::AttachCurrentThread(); | 428 JNIEnv* env = base::android::AttachCurrentThread(); |
| 434 | 429 |
| 435 // Register for updates to the DownloadItem. | 430 // Register for updates to the DownloadItem. |
| 436 download_item->AddObserver(this); | 431 download_item->AddObserver(this); |
| 437 | 432 |
| 438 ScopedJavaLocalRef<jobject> view = | 433 ScopedJavaLocalRef<jobject> jweb_contents = |
| 439 GetContentViewCoreFromWebContents(download_item->GetWebContents()); | 434 GetJavaWebContents(download_item->GetWebContents()); |
| 440 // The view went away. Can't proceed. | |
| 441 if (view.is_null()) | |
| 442 return; | |
| 443 | 435 |
| 444 ScopedJavaLocalRef<jstring> jmime_type = | 436 ScopedJavaLocalRef<jstring> jmime_type = |
| 445 ConvertUTF8ToJavaString(env, download_item->GetMimeType()); | 437 ConvertUTF8ToJavaString(env, download_item->GetMimeType()); |
| 446 ScopedJavaLocalRef<jstring> jfilename = ConvertUTF8ToJavaString( | 438 ScopedJavaLocalRef<jstring> jfilename = ConvertUTF8ToJavaString( |
| 447 env, download_item->GetTargetFilePath().BaseName().value()); | 439 env, download_item->GetTargetFilePath().BaseName().value()); |
| 448 Java_DownloadController_onDownloadStarted( | 440 Java_DownloadController_onDownloadStarted( |
| 449 env, GetJavaObject()->Controller(env).obj(), view.obj(), jfilename.obj(), | 441 env, GetJavaObject()->Controller(env).obj(), jweb_contents.obj(), |
| 450 jmime_type.obj()); | 442 jfilename.obj(), jmime_type.obj()); |
| 451 } | 443 } |
| 452 | 444 |
| 453 void DownloadControllerAndroidImpl::OnDownloadUpdated(DownloadItem* item) { | 445 void DownloadControllerAndroidImpl::OnDownloadUpdated(DownloadItem* item) { |
| 454 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 446 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 455 if (item->IsDangerous() && (item->GetState() != DownloadItem::CANCELLED)) | 447 if (item->IsDangerous() && (item->GetState() != DownloadItem::CANCELLED)) |
| 456 OnDangerousDownload(item); | 448 OnDangerousDownload(item); |
| 457 | 449 |
| 458 JNIEnv* env = base::android::AttachCurrentThread(); | 450 JNIEnv* env = base::android::AttachCurrentThread(); |
| 459 ScopedJavaLocalRef<jstring> jguid = | 451 ScopedJavaLocalRef<jstring> jguid = |
| 460 ConvertUTF8ToJavaString(env, item->GetGuid()); | 452 ConvertUTF8ToJavaString(env, item->GetGuid()); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 516 NOTREACHED(); | 508 NOTREACHED(); |
| 517 } | 509 } |
| 518 } | 510 } |
| 519 | 511 |
| 520 void DownloadControllerAndroidImpl::OnDangerousDownload(DownloadItem* item) { | 512 void DownloadControllerAndroidImpl::OnDangerousDownload(DownloadItem* item) { |
| 521 JNIEnv* env = base::android::AttachCurrentThread(); | 513 JNIEnv* env = base::android::AttachCurrentThread(); |
| 522 ScopedJavaLocalRef<jstring> jfilename = ConvertUTF8ToJavaString( | 514 ScopedJavaLocalRef<jstring> jfilename = ConvertUTF8ToJavaString( |
| 523 env, item->GetTargetFilePath().BaseName().value()); | 515 env, item->GetTargetFilePath().BaseName().value()); |
| 524 ScopedJavaLocalRef<jstring> jguid = | 516 ScopedJavaLocalRef<jstring> jguid = |
| 525 ConvertUTF8ToJavaString(env, item->GetGuid()); | 517 ConvertUTF8ToJavaString(env, item->GetGuid()); |
| 526 ScopedJavaLocalRef<jobject> view_core = GetContentViewCoreFromWebContents( | 518 ScopedJavaLocalRef<jobject> jweb_contents = GetJavaWebContents( |
| 527 item->GetWebContents()); | 519 item->GetWebContents()); |
| 528 if (!view_core.is_null()) { | 520 if (!jweb_contents.is_null()) { |
| 529 Java_DownloadController_onDangerousDownload( | 521 Java_DownloadController_onDangerousDownload( |
| 530 env, GetJavaObject()->Controller(env).obj(), view_core.obj(), | 522 env, GetJavaObject()->Controller(env).obj(), jweb_contents.obj(), |
| 531 jfilename.obj(), jguid.obj()); | 523 jfilename.obj(), jguid.obj()); |
| 532 } | 524 } |
| 533 } | 525 } |
| 534 | 526 |
| 535 ScopedJavaLocalRef<jobject> | 527 ScopedJavaLocalRef<jobject> |
| 536 DownloadControllerAndroidImpl::GetContentViewCoreFromWebContents( | 528 DownloadControllerAndroidImpl::GetContentViewCoreFromWebContents( |
| 537 WebContents* web_contents) { | 529 WebContents* web_contents) { |
| 538 if (!web_contents) | 530 if (!web_contents) |
| 539 return ScopedJavaLocalRef<jobject>(); | 531 return ScopedJavaLocalRef<jobject>(); |
| 540 | 532 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 608 if (info) | 600 if (info) |
| 609 has_user_gesture = info->HasUserGesture(); | 601 has_user_gesture = info->HasUserGesture(); |
| 610 } | 602 } |
| 611 | 603 |
| 612 DownloadControllerAndroidImpl::DownloadInfoAndroid::DownloadInfoAndroid( | 604 DownloadControllerAndroidImpl::DownloadInfoAndroid::DownloadInfoAndroid( |
| 613 const DownloadInfoAndroid& other) = default; | 605 const DownloadInfoAndroid& other) = default; |
| 614 | 606 |
| 615 DownloadControllerAndroidImpl::DownloadInfoAndroid::~DownloadInfoAndroid() {} | 607 DownloadControllerAndroidImpl::DownloadInfoAndroid::~DownloadInfoAndroid() {} |
| 616 | 608 |
| 617 } // namespace content | 609 } // namespace content |
| OLD | NEW |