| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "chrome/browser/android/download/download_controller.h" | 5 #include "chrome/browser/android/download/download_controller.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/android/jni_android.h" | 10 #include "base/android/jni_android.h" |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 DCHECK_NE(interrupt_reason, content::DOWNLOAD_INTERRUPT_REASON_NONE); | 101 DCHECK_NE(interrupt_reason, content::DOWNLOAD_INTERRUPT_REASON_NONE); |
| 102 return | 102 return |
| 103 interrupt_reason == content::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT || | 103 interrupt_reason == content::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT || |
| 104 interrupt_reason == content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED || | 104 interrupt_reason == content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED || |
| 105 interrupt_reason == | 105 interrupt_reason == |
| 106 content::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED; | 106 content::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED; |
| 107 } | 107 } |
| 108 | 108 |
| 109 } // namespace | 109 } // namespace |
| 110 | 110 |
| 111 // JNI methods | |
| 112 static void Init(JNIEnv* env, const JavaParamRef<jobject>& obj) { | |
| 113 DownloadController::GetInstance()->Init(env, obj); | |
| 114 } | |
| 115 | |
| 116 static void OnAcquirePermissionResult( | 111 static void OnAcquirePermissionResult( |
| 117 JNIEnv* env, | 112 JNIEnv* env, |
| 118 const JavaParamRef<jobject>& obj, | 113 const JavaParamRef<jclass>& clazz, |
| 119 jlong callback_id, | 114 jlong callback_id, |
| 120 jboolean granted, | 115 jboolean granted, |
| 121 const JavaParamRef<jstring>& jpermission_to_update) { | 116 const JavaParamRef<jstring>& jpermission_to_update) { |
| 122 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 117 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 123 DCHECK(callback_id); | 118 DCHECK(callback_id); |
| 124 | 119 |
| 125 std::string permission_to_update = | 120 std::string permission_to_update = |
| 126 base::android::ConvertJavaStringToUTF8(env, jpermission_to_update); | 121 base::android::ConvertJavaStringToUTF8(env, jpermission_to_update); |
| 127 // Convert java long long int to c++ pointer, take ownership. | 122 // Convert java long long int to c++ pointer, take ownership. |
| 128 std::unique_ptr<DownloadController::AcquirePermissionCallback> cb( | 123 std::unique_ptr<DownloadController::AcquirePermissionCallback> cb( |
| (...skipping 20 matching lines...) Expand all Loading... |
| 149 return; | 144 return; |
| 150 } | 145 } |
| 151 | 146 |
| 152 if (!granted) { | 147 if (!granted) { |
| 153 DownloadController::RecordDownloadCancelReason( | 148 DownloadController::RecordDownloadCancelReason( |
| 154 DownloadController::CANCEL_REASON_NO_STORAGE_PERMISSION); | 149 DownloadController::CANCEL_REASON_NO_STORAGE_PERMISSION); |
| 155 } | 150 } |
| 156 cb.Run(granted); | 151 cb.Run(granted); |
| 157 } | 152 } |
| 158 | 153 |
| 159 struct DownloadController::JavaObject { | |
| 160 ScopedJavaLocalRef<jobject> Controller(JNIEnv* env) { | |
| 161 return GetRealObject(env, obj_); | |
| 162 } | |
| 163 jweak obj_; | |
| 164 }; | |
| 165 | |
| 166 // static | 154 // static |
| 167 bool DownloadController::RegisterDownloadController(JNIEnv* env) { | 155 bool DownloadController::RegisterDownloadController(JNIEnv* env) { |
| 168 return RegisterNativesImpl(env); | 156 return RegisterNativesImpl(env); |
| 169 } | 157 } |
| 170 | 158 |
| 171 // static | 159 // static |
| 172 DownloadControllerBase* DownloadControllerBase::Get() { | 160 DownloadControllerBase* DownloadControllerBase::Get() { |
| 173 base::AutoLock lock(g_download_controller_lock_.Get()); | 161 base::AutoLock lock(g_download_controller_lock_.Get()); |
| 174 if (!DownloadControllerBase::download_controller_) | 162 if (!DownloadControllerBase::download_controller_) |
| 175 download_controller_ = DownloadController::GetInstance(); | 163 download_controller_ = DownloadController::GetInstance(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 188 DownloadCancelReason reason) { | 176 DownloadCancelReason reason) { |
| 189 UMA_HISTOGRAM_ENUMERATION( | 177 UMA_HISTOGRAM_ENUMERATION( |
| 190 "MobileDownload.CancelReason", reason, CANCEL_REASON_MAX); | 178 "MobileDownload.CancelReason", reason, CANCEL_REASON_MAX); |
| 191 } | 179 } |
| 192 | 180 |
| 193 // static | 181 // static |
| 194 DownloadController* DownloadController::GetInstance() { | 182 DownloadController* DownloadController::GetInstance() { |
| 195 return base::Singleton<DownloadController>::get(); | 183 return base::Singleton<DownloadController>::get(); |
| 196 } | 184 } |
| 197 | 185 |
| 198 DownloadController::DownloadController() | 186 DownloadController::DownloadController() = default; |
| 199 : java_object_(NULL) { | |
| 200 } | |
| 201 | 187 |
| 202 DownloadController::~DownloadController() { | 188 DownloadController::~DownloadController() = default; |
| 203 if (java_object_) { | |
| 204 JNIEnv* env = base::android::AttachCurrentThread(); | |
| 205 env->DeleteWeakGlobalRef(java_object_->obj_); | |
| 206 delete java_object_; | |
| 207 base::android::CheckException(env); | |
| 208 } | |
| 209 } | |
| 210 | |
| 211 // Initialize references to Java object. | |
| 212 void DownloadController::Init(JNIEnv* env, jobject obj) { | |
| 213 java_object_ = new JavaObject; | |
| 214 java_object_->obj_ = env->NewWeakGlobalRef(obj); | |
| 215 } | |
| 216 | 189 |
| 217 void DownloadController::AcquireFileAccessPermission( | 190 void DownloadController::AcquireFileAccessPermission( |
| 218 const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter, | 191 const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter, |
| 219 const DownloadControllerBase::AcquireFileAccessPermissionCallback& cb) { | 192 const DownloadControllerBase::AcquireFileAccessPermissionCallback& cb) { |
| 220 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 193 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 221 | 194 |
| 222 if (HasFileAccessPermission()) { | 195 if (HasFileAccessPermission()) { |
| 223 BrowserThread::PostTask( | 196 BrowserThread::PostTask( |
| 224 BrowserThread::UI, FROM_HERE, base::Bind(cb, true)); | 197 BrowserThread::UI, FROM_HERE, base::Bind(cb, true)); |
| 225 return; | 198 return; |
| 226 } | 199 } |
| 227 | 200 |
| 228 AcquirePermissionCallback callback( | 201 AcquirePermissionCallback callback( |
| 229 base::Bind(&OnRequestFileAccessResult, web_contents_getter, cb)); | 202 base::Bind(&OnRequestFileAccessResult, web_contents_getter, cb)); |
| 230 // Make copy on the heap so we can pass the pointer through JNI. | 203 // Make copy on the heap so we can pass the pointer through JNI. |
| 231 intptr_t callback_id = | 204 intptr_t callback_id = |
| 232 reinterpret_cast<intptr_t>(new AcquirePermissionCallback(callback)); | 205 reinterpret_cast<intptr_t>(new AcquirePermissionCallback(callback)); |
| 233 JNIEnv* env = base::android::AttachCurrentThread(); | 206 JNIEnv* env = base::android::AttachCurrentThread(); |
| 234 Java_DownloadController_requestFileAccess( | 207 Java_DownloadController_requestFileAccess(env, callback_id); |
| 235 env, GetJavaObject()->Controller(env), callback_id); | |
| 236 } | 208 } |
| 237 | 209 |
| 238 void DownloadController::CreateAndroidDownload( | 210 void DownloadController::CreateAndroidDownload( |
| 239 const content::ResourceRequestInfo::WebContentsGetter& wc_getter, | 211 const content::ResourceRequestInfo::WebContentsGetter& wc_getter, |
| 240 const DownloadInfo& info) { | 212 const DownloadInfo& info) { |
| 241 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 213 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 242 | 214 |
| 243 BrowserThread::PostTask( | 215 BrowserThread::PostTask( |
| 244 BrowserThread::UI, FROM_HERE, | 216 BrowserThread::UI, FROM_HERE, |
| 245 base::Bind(&DownloadController::StartAndroidDownload, | 217 base::Bind(&DownloadController::StartAndroidDownload, |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 281 ScopedJavaLocalRef<jstring> jreferer = | 253 ScopedJavaLocalRef<jstring> jreferer = |
| 282 ConvertUTF8ToJavaString(env, info.referer); | 254 ConvertUTF8ToJavaString(env, info.referer); |
| 283 ScopedJavaLocalRef<jstring> jfile_name = | 255 ScopedJavaLocalRef<jstring> jfile_name = |
| 284 base::android::ConvertUTF16ToJavaString(env, file_name); | 256 base::android::ConvertUTF16ToJavaString(env, file_name); |
| 285 Java_DownloadController_enqueueAndroidDownloadManagerRequest( | 257 Java_DownloadController_enqueueAndroidDownloadManagerRequest( |
| 286 env, jurl, juser_agent, jfile_name, jmime_type, jcookie, jreferer); | 258 env, jurl, juser_agent, jfile_name, jmime_type, jcookie, jreferer); |
| 287 | 259 |
| 288 WebContents* web_contents = wc_getter.Run(); | 260 WebContents* web_contents = wc_getter.Run(); |
| 289 if (web_contents) { | 261 if (web_contents) { |
| 290 TabAndroid* tab = TabAndroid::FromWebContents(web_contents); | 262 TabAndroid* tab = TabAndroid::FromWebContents(web_contents); |
| 291 if (tab && !tab->GetJavaObject().is_null()) { | 263 if (tab && !tab->GetJavaObject().is_null()) |
| 292 Java_DownloadController_closeTabIfBlank(env, tab->GetJavaObject()); | 264 Java_DownloadController_closeTabIfBlank(env, tab->GetJavaObject()); |
| 293 } | |
| 294 } | 265 } |
| 295 } | 266 } |
| 296 | 267 |
| 297 bool DownloadController::HasFileAccessPermission() { | 268 bool DownloadController::HasFileAccessPermission() { |
| 298 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 269 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 299 | 270 |
| 300 JNIEnv* env = base::android::AttachCurrentThread(); | 271 JNIEnv* env = base::android::AttachCurrentThread(); |
| 301 return Java_DownloadController_hasFileAccess( | 272 return Java_DownloadController_hasFileAccess(env); |
| 302 env, GetJavaObject()->Controller(env)); | |
| 303 } | 273 } |
| 304 | 274 |
| 305 void DownloadController::OnDownloadStarted( | 275 void DownloadController::OnDownloadStarted( |
| 306 DownloadItem* download_item) { | 276 DownloadItem* download_item) { |
| 307 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 277 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 308 | 278 |
| 309 // For dangerous item, we need to show the dangerous infobar before the | 279 // For dangerous item, we need to show the dangerous infobar before the |
| 310 // download can start. | 280 // download can start. |
| 311 JNIEnv* env = base::android::AttachCurrentThread(); | 281 JNIEnv* env = base::android::AttachCurrentThread(); |
| 312 if (!download_item->IsDangerous()) { | 282 if (!download_item->IsDangerous()) |
| 313 Java_DownloadController_onDownloadStarted( | 283 Java_DownloadController_onDownloadStarted(env); |
| 314 env, GetJavaObject()->Controller(env)); | |
| 315 } | |
| 316 | 284 |
| 317 WebContents* web_contents = download_item->GetWebContents(); | 285 WebContents* web_contents = download_item->GetWebContents(); |
| 318 if (web_contents) { | 286 if (web_contents) { |
| 319 TabAndroid* tab = TabAndroid::FromWebContents(web_contents); | 287 TabAndroid* tab = TabAndroid::FromWebContents(web_contents); |
| 320 if (tab && !tab->GetJavaObject().is_null()) { | 288 if (tab && !tab->GetJavaObject().is_null()) { |
| 321 Java_DownloadController_closeTabIfBlank(env, tab->GetJavaObject()); | 289 Java_DownloadController_closeTabIfBlank(env, tab->GetJavaObject()); |
| 322 } | 290 } |
| 323 } | 291 } |
| 324 | 292 |
| 325 // Register for updates to the DownloadItem. | 293 // Register for updates to the DownloadItem. |
| 326 download_item->AddObserver(this); | 294 download_item->AddObserver(this); |
| 327 | 295 |
| 328 OnDownloadUpdated(download_item); | 296 OnDownloadUpdated(download_item); |
| 329 } | 297 } |
| 330 | 298 |
| 331 void DownloadController::OnDownloadUpdated(DownloadItem* item) { | 299 void DownloadController::OnDownloadUpdated(DownloadItem* item) { |
| 332 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 300 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 333 if (item->IsDangerous() && (item->GetState() != DownloadItem::CANCELLED)) { | 301 if (item->IsDangerous() && (item->GetState() != DownloadItem::CANCELLED)) { |
| 334 // Dont't show notification for a dangerous download, as user can resume | 302 // Dont't show notification for a dangerous download, as user can resume |
| 335 // the download after browser crash through notification. | 303 // the download after browser crash through notification. |
| 336 OnDangerousDownload(item); | 304 OnDangerousDownload(item); |
| 337 return; | 305 return; |
| 338 } | 306 } |
| 339 | 307 |
| 340 JNIEnv* env = base::android::AttachCurrentThread(); | 308 JNIEnv* env = base::android::AttachCurrentThread(); |
| 341 ScopedJavaLocalRef<jobject> j_item = | 309 ScopedJavaLocalRef<jobject> j_item = |
| 342 DownloadManagerService::CreateJavaDownloadInfo(env, item); | 310 DownloadManagerService::CreateJavaDownloadInfo(env, item); |
| 343 switch (item->GetState()) { | 311 switch (item->GetState()) { |
| 344 case DownloadItem::IN_PROGRESS: { | 312 case DownloadItem::IN_PROGRESS: { |
| 345 Java_DownloadController_onDownloadUpdated( | 313 Java_DownloadController_onDownloadUpdated(env, j_item); |
| 346 env, GetJavaObject()->Controller(env), j_item); | |
| 347 break; | 314 break; |
| 348 } | 315 } |
| 349 case DownloadItem::COMPLETE: | 316 case DownloadItem::COMPLETE: |
| 350 // Multiple OnDownloadUpdated() notifications may be issued while the | 317 // Multiple OnDownloadUpdated() notifications may be issued while the |
| 351 // download is in the COMPLETE state. Only handle one. | 318 // download is in the COMPLETE state. Only handle one. |
| 352 item->RemoveObserver(this); | 319 item->RemoveObserver(this); |
| 353 | 320 |
| 354 // Call onDownloadCompleted | 321 // Call onDownloadCompleted |
| 355 Java_DownloadController_onDownloadCompleted( | 322 Java_DownloadController_onDownloadCompleted(env, j_item); |
| 356 env, GetJavaObject()->Controller(env), j_item); | |
| 357 DownloadController::RecordDownloadCancelReason( | 323 DownloadController::RecordDownloadCancelReason( |
| 358 DownloadController::CANCEL_REASON_NOT_CANCELED); | 324 DownloadController::CANCEL_REASON_NOT_CANCELED); |
| 359 break; | 325 break; |
| 360 case DownloadItem::CANCELLED: | 326 case DownloadItem::CANCELLED: |
| 361 Java_DownloadController_onDownloadCancelled( | 327 Java_DownloadController_onDownloadCancelled(env, j_item); |
| 362 env, GetJavaObject()->Controller(env), j_item); | |
| 363 DownloadController::RecordDownloadCancelReason( | 328 DownloadController::RecordDownloadCancelReason( |
| 364 DownloadController::CANCEL_REASON_OTHER_NATIVE_RESONS); | 329 DownloadController::CANCEL_REASON_OTHER_NATIVE_RESONS); |
| 365 break; | 330 break; |
| 366 case DownloadItem::INTERRUPTED: | 331 case DownloadItem::INTERRUPTED: |
| 367 // When device loses/changes network, we get a NETWORK_TIMEOUT, | 332 // When device loses/changes network, we get a NETWORK_TIMEOUT, |
| 368 // NETWORK_FAILED or NETWORK_DISCONNECTED error. Download should auto | 333 // NETWORK_FAILED or NETWORK_DISCONNECTED error. Download should auto |
| 369 // resume in this case. | 334 // resume in this case. |
| 370 Java_DownloadController_onDownloadInterrupted( | 335 Java_DownloadController_onDownloadInterrupted(env, j_item, |
| 371 env, GetJavaObject()->Controller(env), j_item, | |
| 372 IsInterruptedDownloadAutoResumable(item)); | 336 IsInterruptedDownloadAutoResumable(item)); |
| 373 item->RemoveObserver(this); | 337 item->RemoveObserver(this); |
| 374 break; | 338 break; |
| 375 case DownloadItem::MAX_DOWNLOAD_STATE: | 339 case DownloadItem::MAX_DOWNLOAD_STATE: |
| 376 NOTREACHED(); | 340 NOTREACHED(); |
| 377 } | 341 } |
| 378 } | 342 } |
| 379 | 343 |
| 380 void DownloadController::OnDangerousDownload(DownloadItem* item) { | 344 void DownloadController::OnDangerousDownload(DownloadItem* item) { |
| 381 WebContents* web_contents = item->GetWebContents(); | 345 WebContents* web_contents = item->GetWebContents(); |
| 382 if (!web_contents) { | 346 if (!web_contents) { |
| 383 item->Remove(); | 347 item->Remove(); |
| 384 return; | 348 return; |
| 385 } | 349 } |
| 386 | 350 |
| 387 DangerousDownloadInfoBarDelegate::Create( | 351 DangerousDownloadInfoBarDelegate::Create( |
| 388 InfoBarService::FromWebContents(web_contents), item); | 352 InfoBarService::FromWebContents(web_contents), item); |
| 389 } | 353 } |
| 390 | 354 |
| 391 DownloadController::JavaObject* | |
| 392 DownloadController::GetJavaObject() { | |
| 393 if (!java_object_) { | |
| 394 // Initialize Java DownloadController by calling | |
| 395 // DownloadController.getInstance(), which will call Init() | |
| 396 // if Java DownloadController is not instantiated already. | |
| 397 JNIEnv* env = base::android::AttachCurrentThread(); | |
| 398 Java_DownloadController_getInstance(env); | |
| 399 } | |
| 400 | |
| 401 DCHECK(java_object_); | |
| 402 return java_object_; | |
| 403 } | |
| 404 | |
| 405 void DownloadController::StartContextMenuDownload( | 355 void DownloadController::StartContextMenuDownload( |
| 406 const ContextMenuParams& params, WebContents* web_contents, bool is_link, | 356 const ContextMenuParams& params, WebContents* web_contents, bool is_link, |
| 407 const std::string& extra_headers) { | 357 const std::string& extra_headers) { |
| 408 int process_id = web_contents->GetRenderProcessHost()->GetID(); | 358 int process_id = web_contents->GetRenderProcessHost()->GetID(); |
| 409 int routing_id = web_contents->GetRenderViewHost()->GetRoutingID(); | 359 int routing_id = web_contents->GetRenderViewHost()->GetRoutingID(); |
| 410 | 360 |
| 411 const content::ResourceRequestInfo::WebContentsGetter& wc_getter( | 361 const content::ResourceRequestInfo::WebContentsGetter& wc_getter( |
| 412 base::Bind(&GetWebContents, process_id, routing_id)); | 362 base::Bind(&GetWebContents, process_id, routing_id)); |
| 413 | 363 |
| 414 AcquireFileAccessPermission( | 364 AcquireFileAccessPermission( |
| 415 wc_getter, base::Bind(&CreateContextMenuDownload, wc_getter, params, | 365 wc_getter, base::Bind(&CreateContextMenuDownload, wc_getter, params, |
| 416 is_link, extra_headers)); | 366 is_link, extra_headers)); |
| 417 } | 367 } |
| 418 | 368 |
| OLD | NEW |