Chromium Code Reviews| 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 |