Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(146)

Side by Side Diff: chrome/browser/android/download/download_controller.cc

Issue 2850223002: remove reliance on webcontents when requesting storage permission (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/context_utils.h" 10 #include "base/android/context_utils.h"
11 #include "base/android/jni_android.h" 11 #include "base/android/jni_android.h"
12 #include "base/android/jni_string.h" 12 #include "base/android/jni_string.h"
13 #include "base/bind.h" 13 #include "base/bind.h"
14 #include "base/lazy_instance.h" 14 #include "base/lazy_instance.h"
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/metrics/histogram_macros.h" 16 #include "base/metrics/histogram_macros.h"
17 #include "base/synchronization/lock.h" 17 #include "base/synchronization/lock.h"
18 #include "chrome/browser/android/download/chrome_download_delegate.h" 18 #include "chrome/browser/android/download/chrome_download_delegate.h"
19 #include "chrome/browser/android/download/dangerous_download_infobar_delegate.h" 19 #include "chrome/browser/android/download/dangerous_download_infobar_delegate.h"
20 #include "chrome/browser/android/download/download_manager_service.h" 20 #include "chrome/browser/android/download/download_manager_service.h"
21 #include "chrome/browser/infobars/infobar_service.h" 21 #include "chrome/browser/infobars/infobar_service.h"
22 #include "chrome/browser/permissions/permission_update_infobar_delegate_android. h"
22 #include "chrome/browser/ui/android/view_android_helper.h" 23 #include "chrome/browser/ui/android/view_android_helper.h"
24 #include "chrome/grit/chromium_strings.h"
23 #include "content/public/browser/browser_context.h" 25 #include "content/public/browser/browser_context.h"
24 #include "content/public/browser/browser_thread.h" 26 #include "content/public/browser/browser_thread.h"
25 #include "content/public/browser/download_manager.h" 27 #include "content/public/browser/download_manager.h"
26 #include "content/public/browser/download_url_parameters.h" 28 #include "content/public/browser/download_url_parameters.h"
27 #include "content/public/browser/render_process_host.h" 29 #include "content/public/browser/render_process_host.h"
28 #include "content/public/browser/render_view_host.h" 30 #include "content/public/browser/render_view_host.h"
29 #include "content/public/common/referrer.h" 31 #include "content/public/common/referrer.h"
30 #include "jni/DownloadController_jni.h" 32 #include "jni/DownloadController_jni.h"
31 #include "net/base/filename_util.h" 33 #include "net/base/filename_util.h"
32 #include "ui/android/view_android.h" 34 #include "ui/android/view_android.h"
(...skipping 17 matching lines...) Expand all
50 WebContents* GetWebContents(int render_process_id, int render_view_id) { 52 WebContents* GetWebContents(int render_process_id, int render_view_id) {
51 content::RenderViewHost* render_view_host = 53 content::RenderViewHost* render_view_host =
52 content::RenderViewHost::FromID(render_process_id, render_view_id); 54 content::RenderViewHost::FromID(render_process_id, render_view_id);
53 55
54 if (!render_view_host) 56 if (!render_view_host)
55 return nullptr; 57 return nullptr;
56 58
57 return WebContents::FromRenderViewHost(render_view_host); 59 return WebContents::FromRenderViewHost(render_view_host);
58 } 60 }
59 61
60 void CreateContextMenuDownload(int render_process_id, 62 void CreateContextMenuDownload(
61 int render_view_id, 63 const content::ResourceRequestInfo::WebContentsGetter& wc_getter,
62 const content::ContextMenuParams& params, 64 const content::ContextMenuParams& params,
63 bool is_link, 65 bool is_link,
64 const std::string& extra_headers, 66 const std::string& extra_headers,
65 bool granted) { 67 bool granted) {
66 if (!granted) 68 content::WebContents* web_contents = wc_getter.Run();
67 return;
68 69
69 content::WebContents* web_contents =
70 GetWebContents(render_process_id, render_view_id);
71 if (!web_contents) 70 if (!web_contents)
72 return; 71 return;
73 72
74 const GURL& url = is_link ? params.link_url : params.src_url; 73 const GURL& url = is_link ? params.link_url : params.src_url;
75 const GURL& referring_url = 74 const GURL& referring_url =
76 params.frame_url.is_empty() ? params.page_url : params.frame_url; 75 params.frame_url.is_empty() ? params.page_url : params.frame_url;
77 content::DownloadManager* dlm = 76 content::DownloadManager* dlm =
78 content::BrowserContext::GetDownloadManager( 77 content::BrowserContext::GetDownloadManager(
79 web_contents->GetBrowserContext()); 78 web_contents->GetBrowserContext());
80 std::unique_ptr<content::DownloadUrlParameters> dl_params( 79 std::unique_ptr<content::DownloadUrlParameters> dl_params(
(...skipping 26 matching lines...) Expand all
107 content::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED; 106 content::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED;
108 } 107 }
109 108
110 } // namespace 109 } // namespace
111 110
112 // JNI methods 111 // JNI methods
113 static void Init(JNIEnv* env, const JavaParamRef<jobject>& obj) { 112 static void Init(JNIEnv* env, const JavaParamRef<jobject>& obj) {
114 DownloadController::GetInstance()->Init(env, obj); 113 DownloadController::GetInstance()->Init(env, obj);
115 } 114 }
116 115
117 static void OnRequestFileAccessResult(JNIEnv* env, 116 static void OnAcquirePermissionResult(
118 const JavaParamRef<jobject>& obj, 117 JNIEnv* env,
119 jlong callback_id, 118 const JavaParamRef<jobject>& obj,
120 jboolean granted) { 119 jlong callback_id,
120 jboolean granted,
121 const JavaParamRef<jstring>& jpermission_to_update) {
121 DCHECK_CURRENTLY_ON(BrowserThread::UI); 122 DCHECK_CURRENTLY_ON(BrowserThread::UI);
122 DCHECK(callback_id); 123 DCHECK(callback_id);
123 124
125 std::string permission_to_update =
126 base::android::ConvertJavaStringToUTF8(env, jpermission_to_update);
124 // Convert java long long int to c++ pointer, take ownership. 127 // Convert java long long int to c++ pointer, take ownership.
125 std::unique_ptr< 128 std::unique_ptr<DownloadController::AcquirePermissionCallback> cb(
126 DownloadControllerBase::AcquireFileAccessPermissionCallback> 129 reinterpret_cast<DownloadController::AcquirePermissionCallback*>(
127 cb(reinterpret_cast< 130 callback_id));
128 DownloadControllerBase::AcquireFileAccessPermissionCallback*>( 131 cb->Run(granted, permission_to_update);
129 callback_id)); 132 }
133
134 static void OnRequestFileAccessResult(
135 const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter,
136 const DownloadControllerBase::AcquireFileAccessPermissionCallback& cb,
137 bool granted,
138 const std::string& permission_to_update) {
139 DCHECK_CURRENTLY_ON(BrowserThread::UI);
140
141 if (!granted && !permission_to_update.empty() && web_contents_getter.Run()) {
David Trainor- moved to gerrit 2017/05/03 20:43:47 Will this show a dialog and then, if the user says
qinmin 2017/05/04 17:36:16 If we show the dialog, there will be no infobar. S
142 WebContents* web_contents = web_contents_getter.Run();
143 std::vector<std::string> permissions;
144 permissions.push_back(permission_to_update);
145
146 PermissionUpdateInfoBarDelegate::Create(
147 web_contents, permissions,
148 IDS_MISSING_STORAGE_PERMISSION_DOWNLOAD_EDUCATION_TEXT, cb);
149 return;
150 }
151
130 if (!granted) { 152 if (!granted) {
131 DownloadController::RecordDownloadCancelReason( 153 DownloadController::RecordDownloadCancelReason(
132 DownloadController::CANCEL_REASON_NO_STORAGE_PERMISSION); 154 DownloadController::CANCEL_REASON_NO_STORAGE_PERMISSION);
133 } 155 }
134 cb->Run(granted); 156 cb.Run(granted);
135 } 157 }
136 158
137 struct DownloadController::JavaObject { 159 struct DownloadController::JavaObject {
138 ScopedJavaLocalRef<jobject> Controller(JNIEnv* env) { 160 ScopedJavaLocalRef<jobject> Controller(JNIEnv* env) {
139 return GetRealObject(env, obj_); 161 return GetRealObject(env, obj_);
140 } 162 }
141 jweak obj_; 163 jweak obj_;
142 }; 164 };
143 165
144 // static 166 // static
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 } 208 }
187 } 209 }
188 210
189 // Initialize references to Java object. 211 // Initialize references to Java object.
190 void DownloadController::Init(JNIEnv* env, jobject obj) { 212 void DownloadController::Init(JNIEnv* env, jobject obj) {
191 java_object_ = new JavaObject; 213 java_object_ = new JavaObject;
192 java_object_->obj_ = env->NewWeakGlobalRef(obj); 214 java_object_->obj_ = env->NewWeakGlobalRef(obj);
193 } 215 }
194 216
195 void DownloadController::AcquireFileAccessPermission( 217 void DownloadController::AcquireFileAccessPermission(
196 WebContents* web_contents, 218 const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter,
197 const DownloadControllerBase::AcquireFileAccessPermissionCallback& cb) { 219 const DownloadControllerBase::AcquireFileAccessPermissionCallback& cb) {
198 DCHECK_CURRENTLY_ON(BrowserThread::UI); 220 DCHECK_CURRENTLY_ON(BrowserThread::UI);
199 DCHECK(web_contents);
200 221
201 ViewAndroidHelper* view_helper = 222 if (HasFileAccessPermission()) {
202 ViewAndroidHelper::FromWebContents(web_contents);
203 if (!view_helper)
204 return;
205
206 ui::ViewAndroid* view_android = view_helper->GetViewAndroid();
207 if (!view_android) {
208 // ViewAndroid may have been gone away.
209 BrowserThread::PostTask(
210 BrowserThread::UI, FROM_HERE, base::Bind(cb, false));
211 return;
212 }
213 ui::WindowAndroid* window_android = view_android->GetWindowAndroid();
214 if (window_android && HasFileAccessPermission(window_android)) {
215 BrowserThread::PostTask( 223 BrowserThread::PostTask(
216 BrowserThread::UI, FROM_HERE, base::Bind(cb, true)); 224 BrowserThread::UI, FROM_HERE, base::Bind(cb, true));
217 return; 225 return;
218 } 226 }
227
228 AcquirePermissionCallback callback(
229 base::Bind(&OnRequestFileAccessResult, web_contents_getter, cb));
219 // Make copy on the heap so we can pass the pointer through JNI. 230 // Make copy on the heap so we can pass the pointer through JNI.
220 intptr_t callback_id = reinterpret_cast<intptr_t>( 231 intptr_t callback_id =
221 new DownloadControllerBase::AcquireFileAccessPermissionCallback(cb)); 232 reinterpret_cast<intptr_t>(new AcquirePermissionCallback(callback));
222 ChromeDownloadDelegate::FromWebContents(web_contents)-> 233 JNIEnv* env = base::android::AttachCurrentThread();
223 RequestFileAccess(callback_id); 234 Java_DownloadController_requestFileAccess(
235 env, GetJavaObject()->Controller(env), callback_id);
224 } 236 }
225 237
226 void DownloadController::CreateAndroidDownload( 238 void DownloadController::CreateAndroidDownload(
227 const content::ResourceRequestInfo::WebContentsGetter& wc_getter, 239 const content::ResourceRequestInfo::WebContentsGetter& wc_getter,
228 const DownloadInfo& info) { 240 const DownloadInfo& info) {
229 DCHECK_CURRENTLY_ON(BrowserThread::IO); 241 DCHECK_CURRENTLY_ON(BrowserThread::IO);
230 242
231 BrowserThread::PostTask( 243 BrowserThread::PostTask(
232 BrowserThread::UI, FROM_HERE, 244 BrowserThread::UI, FROM_HERE,
233 base::Bind(&DownloadController::StartAndroidDownload, 245 base::Bind(&DownloadController::StartAndroidDownload,
234 base::Unretained(this), 246 base::Unretained(this),
235 wc_getter, info)); 247 wc_getter, info));
236 } 248 }
237 249
238 void DownloadController::StartAndroidDownload( 250 void DownloadController::StartAndroidDownload(
239 const content::ResourceRequestInfo::WebContentsGetter& wc_getter, 251 const content::ResourceRequestInfo::WebContentsGetter& wc_getter,
240 const DownloadInfo& info) { 252 const DownloadInfo& info) {
241 DCHECK_CURRENTLY_ON(BrowserThread::UI); 253 DCHECK_CURRENTLY_ON(BrowserThread::UI);
242 254
243 WebContents* web_contents = wc_getter.Run();
244 if (!web_contents) {
245 // The view went away. Can't proceed.
246 LOG(ERROR) << "Tab closed, download failed on URL:" << info.url.spec();
247 return;
248 }
249
250 AcquireFileAccessPermission( 255 AcquireFileAccessPermission(
251 web_contents, 256 wc_getter, base::Bind(&DownloadController::StartAndroidDownloadInternal,
252 base::Bind(&DownloadController::StartAndroidDownloadInternal, 257 base::Unretained(this), wc_getter, info));
253 base::Unretained(this), wc_getter, info));
254 } 258 }
255 259
256 void DownloadController::StartAndroidDownloadInternal( 260 void DownloadController::StartAndroidDownloadInternal(
257 const content::ResourceRequestInfo::WebContentsGetter& wc_getter, 261 const content::ResourceRequestInfo::WebContentsGetter& wc_getter,
258 const DownloadInfo& info, bool allowed) { 262 const DownloadInfo& info, bool allowed) {
259 DCHECK_CURRENTLY_ON(BrowserThread::UI); 263 DCHECK_CURRENTLY_ON(BrowserThread::UI);
260 if (!allowed) 264 if (!allowed)
261 return; 265 return;
262 266
263 WebContents* web_contents = wc_getter.Run(); 267 WebContents* web_contents = wc_getter.Run();
264 if (!web_contents) { 268 if (!web_contents) {
265 // The view went away. Can't proceed. 269 // The view went away. Can't proceed.
266 LOG(ERROR) << "Tab closed, download failed on URL:" << info.url.spec(); 270 LOG(ERROR) << "Tab closed, download failed on URL:" << info.url.spec();
267 return; 271 return;
268 } 272 }
269 273
270 base::string16 filename = 274 base::string16 filename =
271 net::GetSuggestedFilename(info.url, info.content_disposition, 275 net::GetSuggestedFilename(info.url, info.content_disposition,
272 std::string(), // referrer_charset 276 std::string(), // referrer_charset
273 std::string(), // suggested_name 277 std::string(), // suggested_name
274 info.original_mime_type, default_file_name_); 278 info.original_mime_type, default_file_name_);
275 ChromeDownloadDelegate::FromWebContents(web_contents) 279 ChromeDownloadDelegate::FromWebContents(web_contents)
276 ->EnqueueDownloadManagerRequest(info.url.spec(), info.user_agent, 280 ->EnqueueDownloadManagerRequest(info.url.spec(), info.user_agent,
277 filename, info.original_mime_type, 281 filename, info.original_mime_type,
278 info.cookie, info.referer); 282 info.cookie, info.referer);
279 } 283 }
280 284
281 bool DownloadController::HasFileAccessPermission( 285 bool DownloadController::HasFileAccessPermission() {
282 ui::WindowAndroid* window_android) {
283 ScopedJavaLocalRef<jobject> jwindow_android = window_android->GetJavaObject();
284
285 DCHECK_CURRENTLY_ON(BrowserThread::UI); 286 DCHECK_CURRENTLY_ON(BrowserThread::UI);
286 DCHECK(!jwindow_android.is_null());
287 287
288 JNIEnv* env = base::android::AttachCurrentThread(); 288 JNIEnv* env = base::android::AttachCurrentThread();
289 return Java_DownloadController_hasFileAccess( 289 return Java_DownloadController_hasFileAccess(
290 env, GetJavaObject()->Controller(env), jwindow_android); 290 env, GetJavaObject()->Controller(env));
291 } 291 }
292 292
293 void DownloadController::OnDownloadStarted( 293 void DownloadController::OnDownloadStarted(
294 DownloadItem* download_item) { 294 DownloadItem* download_item) {
295 DCHECK_CURRENTLY_ON(BrowserThread::UI); 295 DCHECK_CURRENTLY_ON(BrowserThread::UI);
296 WebContents* web_contents = download_item->GetWebContents(); 296 WebContents* web_contents = download_item->GetWebContents();
297 if (!web_contents) 297 if (!web_contents)
298 return; 298 return;
299 299
300 // Register for updates to the DownloadItem. 300 // Register for updates to the DownloadItem.
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 383
384 DCHECK(java_object_); 384 DCHECK(java_object_);
385 return java_object_; 385 return java_object_;
386 } 386 }
387 387
388 void DownloadController::StartContextMenuDownload( 388 void DownloadController::StartContextMenuDownload(
389 const ContextMenuParams& params, WebContents* web_contents, bool is_link, 389 const ContextMenuParams& params, WebContents* web_contents, bool is_link,
390 const std::string& extra_headers) { 390 const std::string& extra_headers) {
391 int process_id = web_contents->GetRenderProcessHost()->GetID(); 391 int process_id = web_contents->GetRenderProcessHost()->GetID();
392 int routing_id = web_contents->GetRenderViewHost()->GetRoutingID(); 392 int routing_id = web_contents->GetRenderViewHost()->GetRoutingID();
393
394 const content::ResourceRequestInfo::WebContentsGetter& wc_getter(
395 base::Bind(&GetWebContents, process_id, routing_id));
396
393 AcquireFileAccessPermission( 397 AcquireFileAccessPermission(
394 web_contents, base::Bind(&CreateContextMenuDownload, process_id, 398 wc_getter, base::Bind(&CreateContextMenuDownload, wc_getter, params,
395 routing_id, params, is_link, extra_headers)); 399 is_link, extra_headers));
396 } 400 }
397 401
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698