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 |