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 "chrome/browser/download/download_request_limiter.h" | 5 #include "chrome/browser/download/download_request_limiter.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
9 #include "chrome/browser/chrome_notification_types.h" | 9 #include "chrome/browser/chrome_notification_types.h" |
10 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" | 10 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" |
11 #include "chrome/browser/content_settings/tab_specific_content_settings.h" | 11 #include "chrome/browser/content_settings/tab_specific_content_settings.h" |
12 #include "chrome/browser/infobars/infobar_service.h" | 12 #include "chrome/browser/infobars/infobar_service.h" |
13 #include "chrome/browser/profiles/profile.h" | 13 #include "chrome/browser/profiles/profile.h" |
14 #include "chrome/browser/tab_contents/tab_util.h" | 14 #include "chrome/browser/tab_contents/tab_util.h" |
15 #include "chrome/common/features.h" | 15 #include "chrome/common/features.h" |
16 #include "components/content_settings/core/browser/host_content_settings_map.h" | 16 #include "components/content_settings/core/browser/host_content_settings_map.h" |
17 #include "content/public/browser/browser_context.h" | 17 #include "content/public/browser/browser_context.h" |
18 #include "content/public/browser/browser_thread.h" | 18 #include "content/public/browser/browser_thread.h" |
19 #include "content/public/browser/navigation_controller.h" | 19 #include "content/public/browser/navigation_controller.h" |
20 #include "content/public/browser/navigation_entry.h" | 20 #include "content/public/browser/navigation_entry.h" |
21 #include "content/public/browser/navigation_handle.h" | |
21 #include "content/public/browser/notification_source.h" | 22 #include "content/public/browser/notification_source.h" |
22 #include "content/public/browser/notification_types.h" | 23 #include "content/public/browser/notification_types.h" |
23 #include "content/public/browser/render_process_host.h" | 24 #include "content/public/browser/render_process_host.h" |
24 #include "content/public/browser/resource_dispatcher_host.h" | 25 #include "content/public/browser/resource_dispatcher_host.h" |
25 #include "content/public/browser/web_contents.h" | 26 #include "content/public/browser/web_contents.h" |
26 #include "content/public/browser/web_contents_delegate.h" | 27 #include "content/public/browser/web_contents_delegate.h" |
28 #include "content/public/common/browser_side_navigation_policy.h" | |
27 #include "url/gurl.h" | 29 #include "url/gurl.h" |
28 | 30 |
29 #if BUILDFLAG(ANDROID_JAVA_UI) | 31 #if BUILDFLAG(ANDROID_JAVA_UI) |
30 #include "chrome/browser/download/download_request_infobar_delegate_android.h" | 32 #include "chrome/browser/download/download_request_infobar_delegate_android.h" |
31 #else | 33 #else |
32 #include "chrome/browser/download/download_permission_request.h" | 34 #include "chrome/browser/download/download_permission_request.h" |
33 #include "chrome/browser/ui/website_settings/permission_bubble_manager.h" | 35 #include "chrome/browser/ui/website_settings/permission_bubble_manager.h" |
34 #endif | 36 #endif |
35 | 37 |
36 using content::BrowserThread; | 38 using content::BrowserThread; |
(...skipping 10 matching lines...) Expand all Loading... | |
47 web_contents_(contents), | 49 web_contents_(contents), |
48 host_(host), | 50 host_(host), |
49 status_(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD), | 51 status_(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD), |
50 download_count_(0), | 52 download_count_(0), |
51 factory_(this) { | 53 factory_(this) { |
52 registrar_.Add( | 54 registrar_.Add( |
53 this, content::NOTIFICATION_NAV_ENTRY_PENDING, | 55 this, content::NOTIFICATION_NAV_ENTRY_PENDING, |
54 content::Source<NavigationController>(&contents->GetController())); | 56 content::Source<NavigationController>(&contents->GetController())); |
55 registrar_.Add(this, chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED, | 57 registrar_.Add(this, chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED, |
56 content::Source<content::WebContents>(contents)); | 58 content::Source<content::WebContents>(contents)); |
57 NavigationEntry* last_entry = originating_web_contents ? | 59 NavigationEntry* last_entry = |
58 originating_web_contents->GetController().GetLastCommittedEntry() : | 60 originating_web_contents |
59 contents->GetController().GetLastCommittedEntry(); | 61 ? originating_web_contents->GetController().GetLastCommittedEntry() |
62 : contents->GetController().GetLastCommittedEntry(); | |
60 if (last_entry) | 63 if (last_entry) |
61 initial_page_host_ = last_entry->GetURL().host(); | 64 initial_page_host_ = last_entry->GetURL().host(); |
62 } | 65 } |
63 | 66 |
64 DownloadRequestLimiter::TabDownloadState::~TabDownloadState() { | 67 DownloadRequestLimiter::TabDownloadState::~TabDownloadState() { |
65 // We should only be destroyed after the callbacks have been notified. | 68 // We should only be destroyed after the callbacks have been notified. |
66 DCHECK(callbacks_.empty()); | 69 DCHECK(callbacks_.empty()); |
67 | 70 |
68 // And we should have invalidated the back pointer. | 71 // And we should have invalidated the back pointer. |
69 DCHECK(!factory_.HasWeakPtrs()); | 72 DCHECK(!factory_.HasWeakPtrs()); |
70 } | 73 } |
71 | 74 |
72 void DownloadRequestLimiter::TabDownloadState::DidNavigateMainFrame( | 75 void DownloadRequestLimiter::TabDownloadState::DidStartNavigation( |
73 const content::LoadCommittedDetails& details, | 76 content::NavigationHandle* navigation_handle) { |
74 const content::FrameNavigateParams& params) { | 77 if (!navigation_handle->IsInMainFrame()) |
Charlie Reis
2016/05/11 21:50:03
Sanity check: Do we limit downloads in subframes s
dominickn
2016/05/12 04:22:58
There is one limiter per WebContents, and that lim
| |
75 switch (status_) { | 78 return; |
76 case ALLOW_ONE_DOWNLOAD: | 79 |
77 case PROMPT_BEFORE_DOWNLOAD: | 80 // If the navigation is renderer-initiated, ensure that a prompting or |
78 // When the user reloads the page without responding to the infobar, they | 81 // blocking limiter state is not reset, so window.location.href or meta |
79 // are expecting DownloadRequestLimiter to behave as if they had just | 82 // refresh can't be abused to avoid the limiter. |
80 // initially navigated to this page. See http://crbug.com/171372 | 83 // NOTE: this can only ever be true when PlzNavigate launches (or when |
81 NotifyCallbacks(false); | 84 // content::IsBrowserSideNavigationEnabled() returns true). |
Charlie Reis
2016/05/11 21:50:03
This doesn't sound right. We should know IsRender
dominickn
2016/05/12 04:22:58
This comment was added because I couldn't get the
| |
82 host_->Remove(this, web_contents()); | 85 if (navigation_handle->IsRendererInitiated() && |
83 // WARNING: We've been deleted. | 86 (status_ == PROMPT_BEFORE_DOWNLOAD || status_ == DOWNLOADS_NOT_ALLOWED)) { |
84 break; | 87 return; |
85 case DOWNLOADS_NOT_ALLOWED: | 88 } |
86 case ALLOW_ALL_DOWNLOADS: | 89 |
87 // Don't drop this information. The user has explicitly said that they | 90 if (status_ == DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS || |
88 // do/don't want downloads from this host. If they accidentally Accepted | 91 status_ == DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED) { |
89 // or Canceled, they can adjust the limiter state by adjusting the | 92 // User has either allowed all downloads or canceled all downloads. Only |
90 // automatic downloads content settings. Alternatively, they can copy the | 93 // reset the download state if the user is navigating to a different host |
91 // URL into a new tab, which will make a new DownloadRequestLimiter. | 94 // (or host is empty). |
92 // See also the initial_page_host_ logic in Observe() for | 95 if (!initial_page_host_.empty() && |
93 // NOTIFICATION_NAV_ENTRY_PENDING. | 96 navigation_handle->GetURL().host() == initial_page_host_) { |
94 break; | 97 return; |
95 default: | 98 } |
96 NOTREACHED(); | 99 } |
100 | |
101 NotifyCallbacks(false); | |
102 host_->Remove(this, web_contents()); | |
103 } | |
104 | |
105 void DownloadRequestLimiter::TabDownloadState::DidFinishNavigation( | |
106 content::NavigationHandle* navigation_handle) { | |
107 if (!navigation_handle->IsInMainFrame()) | |
108 return; | |
109 | |
110 // When the status is ALLOW_ALL_DOWNLOADS or DOWNLOADS_NOT_ALLOWED, don't drop | |
111 // this information. The user has explicitly said that they | |
112 // do/don't want downloads from this host. If they accidentally Accepted | |
113 // or Canceled, they can adjust the limiter state by adjusting the | |
114 // automatic downloads content settings. Alternatively, they can copy | |
115 // the URL into a new tab, which will make a new DownloadRequestLimiter. | |
116 // See also the initial_page_host_ logic in DidStartNavigation or Observe() | |
117 // for NOTIFICATION_NAV_ENTRY_PENDING. | |
118 if (status_ == ALLOW_ONE_DOWNLOAD || | |
119 (status_ == PROMPT_BEFORE_DOWNLOAD && | |
120 !navigation_handle->IsRendererInitiated())) { | |
121 // When the user reloads the page without responding to the infobar, | |
122 // they are expecting DownloadRequestLimiter to behave as if they had | |
123 // just initially navigated to this page. See http://crbug.com/171372. | |
124 // However, explicitly leave the limiter in place if the navigation was | |
125 // renderer-initiated and we are in a prompt state. | |
126 NotifyCallbacks(false); | |
127 host_->Remove(this, web_contents()); | |
128 // WARNING: We've been deleted. | |
97 } | 129 } |
98 } | 130 } |
99 | 131 |
100 void DownloadRequestLimiter::TabDownloadState::DidGetUserInteraction( | 132 void DownloadRequestLimiter::TabDownloadState::DidGetUserInteraction( |
101 const blink::WebInputEvent::Type type) { | 133 const blink::WebInputEvent::Type type) { |
102 if (is_showing_prompt() || type == blink::WebInputEvent::GestureScrollBegin) { | 134 if (is_showing_prompt() || type == blink::WebInputEvent::GestureScrollBegin) { |
103 // Don't change state if a prompt is showing or if the user has scrolled. | 135 // Don't change state if a prompt is showing or if the user has scrolled. |
104 return; | 136 return; |
105 } | 137 } |
106 | 138 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
138 if (is_showing_prompt()) | 170 if (is_showing_prompt()) |
139 return; | 171 return; |
140 | 172 |
141 #if BUILDFLAG(ANDROID_JAVA_UI) | 173 #if BUILDFLAG(ANDROID_JAVA_UI) |
142 DownloadRequestInfoBarDelegateAndroid::Create( | 174 DownloadRequestInfoBarDelegateAndroid::Create( |
143 InfoBarService::FromWebContents(web_contents_), factory_.GetWeakPtr()); | 175 InfoBarService::FromWebContents(web_contents_), factory_.GetWeakPtr()); |
144 #else | 176 #else |
145 PermissionBubbleManager* bubble_manager = | 177 PermissionBubbleManager* bubble_manager = |
146 PermissionBubbleManager::FromWebContents(web_contents_); | 178 PermissionBubbleManager::FromWebContents(web_contents_); |
147 if (bubble_manager) { | 179 if (bubble_manager) { |
148 bubble_manager->AddRequest(new DownloadPermissionRequest( | 180 bubble_manager->AddRequest( |
149 factory_.GetWeakPtr())); | 181 new DownloadPermissionRequest(factory_.GetWeakPtr())); |
150 } else { | 182 } else { |
151 Cancel(); | 183 Cancel(); |
152 } | 184 } |
153 #endif | 185 #endif |
154 } | 186 } |
155 | 187 |
156 void DownloadRequestLimiter::TabDownloadState::SetContentSetting( | 188 void DownloadRequestLimiter::TabDownloadState::SetContentSetting( |
157 ContentSetting setting) { | 189 ContentSetting setting) { |
158 if (!web_contents_) | 190 if (!web_contents_) |
159 return; | 191 return; |
160 HostContentSettingsMap* settings = | 192 HostContentSettingsMap* settings = |
161 DownloadRequestLimiter::GetContentSettings(web_contents_); | 193 DownloadRequestLimiter::GetContentSettings(web_contents_); |
162 if (!settings) | 194 if (!settings) |
163 return; | 195 return; |
164 settings->SetContentSettingDefaultScope( | 196 settings->SetContentSettingDefaultScope( |
165 web_contents_->GetURL(), GURL(), | 197 web_contents_->GetURL(), GURL(), |
166 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, std::string(), setting); | 198 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, std::string(), setting); |
167 } | 199 } |
168 | 200 |
169 void DownloadRequestLimiter::TabDownloadState::Cancel() { | 201 void DownloadRequestLimiter::TabDownloadState::Cancel() { |
170 SetContentSetting(CONTENT_SETTING_BLOCK); | 202 SetContentSetting(CONTENT_SETTING_BLOCK); |
171 NotifyCallbacks(false); | 203 NotifyCallbacks(false); |
172 } | 204 } |
173 | 205 |
174 void DownloadRequestLimiter::TabDownloadState::CancelOnce() { | 206 void DownloadRequestLimiter::TabDownloadState::CancelOnce() { |
175 NotifyCallbacks(false); | 207 NotifyCallbacks(false); |
176 } | 208 } |
177 | 209 |
178 void DownloadRequestLimiter::TabDownloadState::Accept() { | 210 void DownloadRequestLimiter::TabDownloadState::Accept() { |
179 SetContentSetting(CONTENT_SETTING_ALLOW); | 211 SetContentSetting(CONTENT_SETTING_ALLOW); |
180 NotifyCallbacks(true); | 212 NotifyCallbacks(true); |
181 } | 213 } |
182 | 214 |
183 DownloadRequestLimiter::TabDownloadState::TabDownloadState() | 215 DownloadRequestLimiter::TabDownloadState::TabDownloadState() |
184 : web_contents_(NULL), | 216 : web_contents_(NULL), |
185 host_(NULL), | 217 host_(NULL), |
186 status_(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD), | 218 status_(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD), |
187 download_count_(0), | 219 download_count_(0), |
188 factory_(this) { | 220 factory_(this) {} |
189 } | |
190 | 221 |
191 bool DownloadRequestLimiter::TabDownloadState::is_showing_prompt() const { | 222 bool DownloadRequestLimiter::TabDownloadState::is_showing_prompt() const { |
192 return factory_.HasWeakPtrs(); | 223 return factory_.HasWeakPtrs(); |
193 } | 224 } |
194 | 225 |
195 void DownloadRequestLimiter::TabDownloadState::Observe( | 226 void DownloadRequestLimiter::TabDownloadState::Observe( |
196 int type, | 227 int type, |
197 const content::NotificationSource& source, | 228 const content::NotificationSource& source, |
198 const content::NotificationDetails& details) { | 229 const content::NotificationDetails& details) { |
199 DCHECK(type == chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED || | 230 DCHECK(type == chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED || |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
233 case CONTENT_SETTING_SESSION_ONLY: | 264 case CONTENT_SETTING_SESSION_ONLY: |
234 set_download_status(PROMPT_BEFORE_DOWNLOAD); | 265 set_download_status(PROMPT_BEFORE_DOWNLOAD); |
235 break; | 266 break; |
236 case CONTENT_SETTING_NUM_SETTINGS: | 267 case CONTENT_SETTING_NUM_SETTINGS: |
237 case CONTENT_SETTING_DETECT_IMPORTANT_CONTENT: | 268 case CONTENT_SETTING_DETECT_IMPORTANT_CONTENT: |
238 NOTREACHED(); | 269 NOTREACHED(); |
239 return; | 270 return; |
240 } | 271 } |
241 } | 272 } |
242 return; | 273 return; |
274 } else if (!content::IsBrowserSideNavigationEnabled()) { | |
275 // TODO(dominickn): remove this branch entirely when PlzNavigate launches. | |
276 content::NavigationController* controller = | |
277 &web_contents()->GetController(); | |
278 DCHECK_EQ(controller, content::Source<NavigationController>(source).ptr()); | |
279 | |
280 // NOTE: Resetting state on a pending navigate isn't ideal. In particular it | |
281 // is possible that queued up downloads for the page before the pending | |
282 // navigation will be delivered to us after we process this request. If this | |
283 // happens we may let a download through that we shouldn't have. But this is | |
284 // rather rare, and it is difficult to get 100% right, so we don't deal with | |
285 // it. | |
286 NavigationEntry* entry = controller->GetPendingEntry(); | |
287 if (!entry) | |
288 return; | |
289 | |
290 // Redirects don't count. | |
291 if (ui::PageTransitionIsRedirect(entry->GetTransitionType())) | |
292 return; | |
293 | |
294 if (status_ == DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS || | |
295 status_ == DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED) { | |
296 // User has either allowed all downloads or canceled all downloads. Only | |
297 // reset the download state if the user is navigating to a different host | |
298 // (or host is empty). | |
299 if (!initial_page_host_.empty() && !entry->GetURL().host().empty() && | |
300 entry->GetURL().host() == initial_page_host_) | |
301 return; | |
302 } | |
303 | |
304 NotifyCallbacks(false); | |
305 host_->Remove(this, web_contents()); | |
243 } | 306 } |
244 | |
245 // Otherwise, there is a pending navigation entry. | |
246 content::NavigationController* controller = &web_contents()->GetController(); | |
247 DCHECK_EQ(controller, content::Source<NavigationController>(source).ptr()); | |
248 | |
249 // NOTE: Resetting state on a pending navigate isn't ideal. In particular it | |
250 // is possible that queued up downloads for the page before the pending | |
251 // navigation will be delivered to us after we process this request. If this | |
252 // happens we may let a download through that we shouldn't have. But this is | |
253 // rather rare, and it is difficult to get 100% right, so we don't deal with | |
254 // it. | |
255 NavigationEntry* entry = controller->GetPendingEntry(); | |
256 if (!entry) | |
257 return; | |
258 | |
259 // Redirects don't count. | |
260 if (ui::PageTransitionIsRedirect(entry->GetTransitionType())) | |
261 return; | |
262 | |
263 if (status_ == DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS || | |
264 status_ == DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED) { | |
265 // User has either allowed all downloads or canceled all downloads. Only | |
266 // reset the download state if the user is navigating to a different host | |
267 // (or host is empty). | |
268 if (!initial_page_host_.empty() && !entry->GetURL().host().empty() && | |
269 entry->GetURL().host() == initial_page_host_) | |
270 return; | |
271 } | |
272 | |
273 NotifyCallbacks(false); | |
274 host_->Remove(this, web_contents()); | |
275 } | 307 } |
276 | 308 |
277 void DownloadRequestLimiter::TabDownloadState::NotifyCallbacks(bool allow) { | 309 void DownloadRequestLimiter::TabDownloadState::NotifyCallbacks(bool allow) { |
278 set_download_status(allow ? | 310 set_download_status(allow ? DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS |
279 DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS : | 311 : DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED); |
280 DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED); | |
281 std::vector<DownloadRequestLimiter::Callback> callbacks; | 312 std::vector<DownloadRequestLimiter::Callback> callbacks; |
282 bool change_status = false; | 313 bool change_status = false; |
283 | 314 |
284 // Selectively send first few notifications only if number of downloads exceed | 315 // Selectively send first few notifications only if number of downloads exceed |
285 // kMaxDownloadsAtOnce. In that case, we also retain the infobar instance and | 316 // kMaxDownloadsAtOnce. In that case, we also retain the infobar instance and |
286 // don't close it. If allow is false, we send all the notifications to cancel | 317 // don't close it. If allow is false, we send all the notifications to cancel |
287 // all remaining downloads and close the infobar. | 318 // all remaining downloads and close the infobar. |
288 if (!allow || (callbacks_.size() < kMaxDownloadsAtOnce)) { | 319 if (!allow || (callbacks_.size() < kMaxDownloadsAtOnce)) { |
289 // Null the generated weak pointer so we don't get notified again. | 320 // Null the generated weak pointer so we don't get notified again. |
290 factory_.InvalidateWeakPtrs(); | 321 factory_.InvalidateWeakPtrs(); |
(...skipping 19 matching lines...) Expand all Loading... | |
310 | 341 |
311 // DownloadRequestLimiter ------------------------------------------------------ | 342 // DownloadRequestLimiter ------------------------------------------------------ |
312 | 343 |
313 HostContentSettingsMap* DownloadRequestLimiter::content_settings_ = NULL; | 344 HostContentSettingsMap* DownloadRequestLimiter::content_settings_ = NULL; |
314 | 345 |
315 void DownloadRequestLimiter::SetContentSettingsForTesting( | 346 void DownloadRequestLimiter::SetContentSettingsForTesting( |
316 HostContentSettingsMap* content_settings) { | 347 HostContentSettingsMap* content_settings) { |
317 content_settings_ = content_settings; | 348 content_settings_ = content_settings; |
318 } | 349 } |
319 | 350 |
320 DownloadRequestLimiter::DownloadRequestLimiter() | 351 DownloadRequestLimiter::DownloadRequestLimiter() : factory_(this) {} |
321 : factory_(this) { | |
322 } | |
323 | 352 |
324 DownloadRequestLimiter::~DownloadRequestLimiter() { | 353 DownloadRequestLimiter::~DownloadRequestLimiter() { |
325 // All the tabs should have closed before us, which sends notification and | 354 // All the tabs should have closed before us, which sends notification and |
326 // removes from state_map_. As such, there should be no pending callbacks. | 355 // removes from state_map_. As such, there should be no pending callbacks. |
327 DCHECK(state_map_.empty()); | 356 DCHECK(state_map_.empty()); |
328 } | 357 } |
329 | 358 |
330 DownloadRequestLimiter::DownloadStatus | 359 DownloadRequestLimiter::DownloadStatus |
331 DownloadRequestLimiter::GetDownloadStatus(content::WebContents* web_contents) { | 360 DownloadRequestLimiter::GetDownloadStatus(content::WebContents* web_contents) { |
332 TabDownloadState* state = GetDownloadState(web_contents, NULL, false); | 361 TabDownloadState* state = GetDownloadState(web_contents, NULL, false); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
371 return; | 400 return; |
372 } | 401 } |
373 | 402 |
374 // Note that because |originating_contents| might go away before | 403 // Note that because |originating_contents| might go away before |
375 // OnCanDownloadDecided is invoked, we look it up by |render_process_host_id| | 404 // OnCanDownloadDecided is invoked, we look it up by |render_process_host_id| |
376 // and |render_view_id|. | 405 // and |render_view_id|. |
377 base::Callback<void(bool)> can_download_callback = base::Bind( | 406 base::Callback<void(bool)> can_download_callback = base::Bind( |
378 &DownloadRequestLimiter::OnCanDownloadDecided, factory_.GetWeakPtr(), | 407 &DownloadRequestLimiter::OnCanDownloadDecided, factory_.GetWeakPtr(), |
379 web_contents_getter, request_method, callback); | 408 web_contents_getter, request_method, callback); |
380 | 409 |
381 originating_contents->GetDelegate()->CanDownload( | 410 originating_contents->GetDelegate()->CanDownload(url, request_method, |
382 url, | 411 can_download_callback); |
383 request_method, | |
384 can_download_callback); | |
385 } | 412 } |
386 | 413 |
387 void DownloadRequestLimiter::OnCanDownloadDecided( | 414 void DownloadRequestLimiter::OnCanDownloadDecided( |
388 const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter, | 415 const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter, |
389 const std::string& request_method, | 416 const std::string& request_method, |
390 const Callback& orig_callback, | 417 const Callback& orig_callback, |
391 bool allow) { | 418 bool allow) { |
392 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 419 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
393 content::WebContents* originating_contents = web_contents_getter.Run(); | 420 content::WebContents* originating_contents = web_contents_getter.Run(); |
394 if (!originating_contents || !allow) { | 421 if (!originating_contents || !allow) { |
395 orig_callback.Run(false); | 422 orig_callback.Run(false); |
396 return; | 423 return; |
397 } | 424 } |
398 | 425 |
399 CanDownloadImpl(originating_contents, | 426 CanDownloadImpl(originating_contents, request_method, orig_callback); |
400 request_method, | |
401 orig_callback); | |
402 } | 427 } |
403 | 428 |
404 HostContentSettingsMap* DownloadRequestLimiter::GetContentSettings( | 429 HostContentSettingsMap* DownloadRequestLimiter::GetContentSettings( |
405 content::WebContents* contents) { | 430 content::WebContents* contents) { |
406 return content_settings_ ? content_settings_ : | 431 return content_settings_ |
407 HostContentSettingsMapFactory::GetForProfile( | 432 ? content_settings_ |
408 Profile::FromBrowserContext(contents->GetBrowserContext())); | 433 : HostContentSettingsMapFactory::GetForProfile( |
434 Profile::FromBrowserContext(contents->GetBrowserContext())); | |
409 } | 435 } |
410 | 436 |
411 void DownloadRequestLimiter::CanDownloadImpl( | 437 void DownloadRequestLimiter::CanDownloadImpl( |
412 content::WebContents* originating_contents, | 438 content::WebContents* originating_contents, |
413 const std::string& request_method, | 439 const std::string& request_method, |
414 const Callback& callback) { | 440 const Callback& callback) { |
415 DCHECK(originating_contents); | 441 DCHECK(originating_contents); |
416 | 442 |
417 TabDownloadState* state = GetDownloadState( | 443 TabDownloadState* state = |
418 originating_contents, originating_contents, true); | 444 GetDownloadState(originating_contents, originating_contents, true); |
419 switch (state->download_status()) { | 445 switch (state->download_status()) { |
420 case ALLOW_ALL_DOWNLOADS: | 446 case ALLOW_ALL_DOWNLOADS: |
421 if (state->download_count() && !(state->download_count() % | 447 if (state->download_count() && |
448 !(state->download_count() % | |
422 DownloadRequestLimiter::kMaxDownloadsAtOnce)) | 449 DownloadRequestLimiter::kMaxDownloadsAtOnce)) |
423 state->set_download_status(PROMPT_BEFORE_DOWNLOAD); | 450 state->set_download_status(PROMPT_BEFORE_DOWNLOAD); |
424 callback.Run(true); | 451 callback.Run(true); |
425 state->increment_download_count(); | 452 state->increment_download_count(); |
426 break; | 453 break; |
427 | 454 |
428 case ALLOW_ONE_DOWNLOAD: | 455 case ALLOW_ONE_DOWNLOAD: |
429 state->set_download_status(PROMPT_BEFORE_DOWNLOAD); | 456 state->set_download_status(PROMPT_BEFORE_DOWNLOAD); |
430 callback.Run(true); | 457 callback.Run(true); |
431 state->increment_download_count(); | 458 state->increment_download_count(); |
432 break; | 459 break; |
433 | 460 |
434 case DOWNLOADS_NOT_ALLOWED: | 461 case DOWNLOADS_NOT_ALLOWED: |
435 callback.Run(false); | 462 callback.Run(false); |
436 break; | 463 break; |
437 | 464 |
438 case PROMPT_BEFORE_DOWNLOAD: { | 465 case PROMPT_BEFORE_DOWNLOAD: { |
439 HostContentSettingsMap* content_settings = GetContentSettings( | 466 HostContentSettingsMap* content_settings = |
440 originating_contents); | 467 GetContentSettings(originating_contents); |
441 ContentSetting setting = CONTENT_SETTING_ASK; | 468 ContentSetting setting = CONTENT_SETTING_ASK; |
442 if (content_settings) | 469 if (content_settings) |
443 setting = content_settings->GetContentSetting( | 470 setting = content_settings->GetContentSetting( |
444 originating_contents->GetURL(), | 471 originating_contents->GetURL(), originating_contents->GetURL(), |
445 originating_contents->GetURL(), | 472 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, std::string()); |
446 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, | |
447 std::string()); | |
448 switch (setting) { | 473 switch (setting) { |
449 case CONTENT_SETTING_ALLOW: { | 474 case CONTENT_SETTING_ALLOW: { |
450 TabSpecificContentSettings* settings = | 475 TabSpecificContentSettings* settings = |
451 TabSpecificContentSettings::FromWebContents( | 476 TabSpecificContentSettings::FromWebContents(originating_contents); |
452 originating_contents); | |
453 if (settings) | 477 if (settings) |
454 settings->SetDownloadsBlocked(false); | 478 settings->SetDownloadsBlocked(false); |
455 callback.Run(true); | 479 callback.Run(true); |
456 state->increment_download_count(); | 480 state->increment_download_count(); |
457 return; | 481 return; |
458 } | 482 } |
459 case CONTENT_SETTING_BLOCK: { | 483 case CONTENT_SETTING_BLOCK: { |
460 TabSpecificContentSettings* settings = | 484 TabSpecificContentSettings* settings = |
461 TabSpecificContentSettings::FromWebContents( | 485 TabSpecificContentSettings::FromWebContents(originating_contents); |
462 originating_contents); | |
463 if (settings) | 486 if (settings) |
464 settings->SetDownloadsBlocked(true); | 487 settings->SetDownloadsBlocked(true); |
465 callback.Run(false); | 488 callback.Run(false); |
466 return; | 489 return; |
467 } | 490 } |
468 case CONTENT_SETTING_DEFAULT: | 491 case CONTENT_SETTING_DEFAULT: |
469 case CONTENT_SETTING_ASK: | 492 case CONTENT_SETTING_ASK: |
470 case CONTENT_SETTING_SESSION_ONLY: | 493 case CONTENT_SETTING_SESSION_ONLY: |
471 state->PromptUserForDownload(callback); | 494 state->PromptUserForDownload(callback); |
472 state->increment_download_count(); | 495 state->increment_download_count(); |
(...skipping 10 matching lines...) Expand all Loading... | |
483 NOTREACHED(); | 506 NOTREACHED(); |
484 } | 507 } |
485 } | 508 } |
486 | 509 |
487 void DownloadRequestLimiter::Remove(TabDownloadState* state, | 510 void DownloadRequestLimiter::Remove(TabDownloadState* state, |
488 content::WebContents* contents) { | 511 content::WebContents* contents) { |
489 DCHECK(ContainsKey(state_map_, contents)); | 512 DCHECK(ContainsKey(state_map_, contents)); |
490 state_map_.erase(contents); | 513 state_map_.erase(contents); |
491 delete state; | 514 delete state; |
492 } | 515 } |
OLD | NEW |