Index: content/browser/android/download_controller_android_impl.cc |
diff --git a/content/browser/android/download_controller_android_impl.cc b/content/browser/android/download_controller_android_impl.cc |
index 68675b56d9ae2b83e5d64265b806d136f2be4740..7cca4a8563256ef091e3e48e134bd5fcea4dcf13 100644 |
--- a/content/browser/android/download_controller_android_impl.cc |
+++ b/content/browser/android/download_controller_android_impl.cc |
@@ -7,8 +7,10 @@ |
#include "base/android/jni_android.h" |
#include "base/android/jni_string.h" |
#include "base/bind.h" |
+#include "base/lazy_instance.h" |
#include "base/logging.h" |
#include "base/memory/scoped_ptr.h" |
+#include "base/synchronization/lock.h" |
#include "base/time/time.h" |
#include "content/browser/android/content_view_core_impl.h" |
#include "content/browser/android/deferred_download_observer.h" |
@@ -38,6 +40,11 @@ |
using base::android::ConvertUTF8ToJavaString; |
using base::android::ScopedJavaLocalRef; |
+namespace { |
+// Guards download_controller_ |
+base::LazyInstance<base::Lock> g_download_controller_lock_; |
+} |
+ |
namespace content { |
// JNI methods |
@@ -45,6 +52,19 @@ static void Init(JNIEnv* env, jobject obj) { |
DownloadControllerAndroidImpl::GetInstance()->Init(env, obj); |
} |
+static void OnRequestFileAccessResult( |
+ JNIEnv* env, jobject obj, jlong callback_id, jboolean granted) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::UI); |
+ DCHECK(callback_id); |
+ |
+ // Convert java long long int to c++ pointer, take ownership. |
+ scoped_ptr<DownloadControllerAndroid::AcquireFileAccessPermissionCallback> cb( |
+ reinterpret_cast< |
+ DownloadControllerAndroid::AcquireFileAccessPermissionCallback*>( |
+ callback_id)); |
+ cb->Run(granted); |
+} |
+ |
struct DownloadControllerAndroidImpl::JavaObject { |
ScopedJavaLocalRef<jobject> Controller(JNIEnv* env) { |
return GetRealObject(env, obj); |
@@ -59,7 +79,17 @@ bool DownloadControllerAndroidImpl::RegisterDownloadController(JNIEnv* env) { |
// static |
DownloadControllerAndroid* DownloadControllerAndroid::Get() { |
- return DownloadControllerAndroidImpl::GetInstance(); |
+ base::AutoLock lock(g_download_controller_lock_.Get()); |
+ if (!DownloadControllerAndroid::download_controller_) |
+ download_controller_ = DownloadControllerAndroidImpl::GetInstance(); |
+ return DownloadControllerAndroid::download_controller_; |
+} |
+ |
+//static |
+void DownloadControllerAndroid::SetDownloadControllerAndroid( |
+ DownloadControllerAndroid* download_controller) { |
+ base::AutoLock lock(g_download_controller_lock_.Get()); |
+ DownloadControllerAndroid::download_controller_ = download_controller; |
} |
// static |
@@ -97,6 +127,48 @@ void DownloadControllerAndroidImpl::CancelDeferredDownload( |
} |
} |
+void DownloadControllerAndroidImpl::AcquireFileAccessPermission( |
+ WebContents* web_contents, |
+ const DownloadControllerAndroid::AcquireFileAccessPermissionCallback& cb) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::UI); |
+ if (!web_contents) { |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, base::Bind(cb, false)); |
+ return; |
+ } |
+ |
+ ScopedJavaLocalRef<jobject> view = |
+ GetContentViewCoreFromWebContents(web_contents); |
+ if (view.is_null()) { |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, base::Bind(cb, false)); |
+ return; |
+ } |
+ |
+ if (HasFileAccessPermission(view)) { |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, base::Bind(cb, true)); |
+ return; |
+ } |
+ |
+ JNIEnv* env = base::android::AttachCurrentThread(); |
+ // Make copy on the heap so we can pass the pointer through JNI. |
+ intptr_t callback_id = reinterpret_cast<intptr_t>( |
+ new DownloadControllerAndroid::AcquireFileAccessPermissionCallback(cb)); |
+ Java_DownloadController_requestFileAccess( |
+ env, GetJavaObject()->Controller(env).obj(), view.obj(), callback_id); |
+} |
+ |
+bool DownloadControllerAndroidImpl::HasFileAccessPermission( |
+ ScopedJavaLocalRef<jobject> j_content_view_core) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::UI); |
+ DCHECK(!j_content_view_core.is_null()); |
+ |
+ JNIEnv* env = base::android::AttachCurrentThread(); |
+ return Java_DownloadController_hasFileAccess( |
+ env, GetJavaObject()->Controller(env).obj(), j_content_view_core.obj()); |
+} |
+ |
void DownloadControllerAndroidImpl::CreateGETDownload( |
int render_process_id, int render_view_id, int request_id) { |
DCHECK_CURRENTLY_ON(BrowserThread::IO); |
@@ -211,9 +283,7 @@ void DownloadControllerAndroidImpl::StartAndroidDownload( |
int render_process_id, int render_view_id, |
const DownloadInfoAndroid& info) { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
- JNIEnv* env = base::android::AttachCurrentThread(); |
- // Call newHttpGetDownload |
WebContents* web_contents = GetWebContents(render_process_id, render_view_id); |
if (!web_contents) { |
// The view went away. Can't proceed. |
@@ -233,6 +303,32 @@ void DownloadControllerAndroidImpl::StartAndroidDownload( |
info))); |
return; |
} |
+ |
+ AcquireFileAccessPermission( |
+ web_contents, |
+ base::Bind(&DownloadControllerAndroidImpl::StartAndroidDownloadInternal, |
+ base::Unretained(this), render_process_id, render_view_id, |
+ info)); |
+} |
+ |
+void DownloadControllerAndroidImpl::StartAndroidDownloadInternal( |
+ int render_process_id, int render_view_id, |
+ const DownloadInfoAndroid& info, bool allowed) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::UI); |
+ if (!allowed) |
+ return; |
+ |
+ // Call newHttpGetDownload |
+ WebContents* web_contents = GetWebContents(render_process_id, render_view_id); |
+ // The view went away. Can't proceed. |
+ if (!web_contents) |
+ return; |
+ ScopedJavaLocalRef<jobject> view = |
+ GetContentViewCoreFromWebContents(web_contents); |
+ if (view.is_null()) |
+ return; |
+ |
+ JNIEnv* env = base::android::AttachCurrentThread(); |
ScopedJavaLocalRef<jstring> jurl = |
ConvertUTF8ToJavaString(env, info.url.spec()); |
ScopedJavaLocalRef<jstring> juser_agent = |