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/content_settings/host_content_settings_map_factory.h" | 10 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" |
| 10 #include "chrome/browser/content_settings/tab_specific_content_settings.h" | 11 #include "chrome/browser/content_settings/tab_specific_content_settings.h" |
| 11 #include "chrome/browser/infobars/infobar_service.h" | 12 #include "chrome/browser/infobars/infobar_service.h" |
| 12 #include "chrome/browser/profiles/profile.h" | 13 #include "chrome/browser/profiles/profile.h" |
| 13 #include "chrome/browser/tab_contents/tab_util.h" | 14 #include "chrome/browser/tab_contents/tab_util.h" |
| 14 #include "chrome/common/features.h" | 15 #include "chrome/common/features.h" |
| 15 #include "components/content_settings/core/browser/host_content_settings_map.h" | 16 #include "components/content_settings/core/browser/host_content_settings_map.h" |
| 16 #include "content/public/browser/browser_context.h" | 17 #include "content/public/browser/browser_context.h" |
| 17 #include "content/public/browser/browser_thread.h" | 18 #include "content/public/browser/browser_thread.h" |
| 18 #include "content/public/browser/navigation_controller.h" | 19 #include "content/public/browser/navigation_controller.h" |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 41 DownloadRequestLimiter::TabDownloadState::TabDownloadState( | 42 DownloadRequestLimiter::TabDownloadState::TabDownloadState( |
| 42 DownloadRequestLimiter* host, | 43 DownloadRequestLimiter* host, |
| 43 content::WebContents* contents, | 44 content::WebContents* contents, |
| 44 content::WebContents* originating_web_contents) | 45 content::WebContents* originating_web_contents) |
| 45 : content::WebContentsObserver(contents), | 46 : content::WebContentsObserver(contents), |
| 46 web_contents_(contents), | 47 web_contents_(contents), |
| 47 host_(host), | 48 host_(host), |
| 48 status_(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD), | 49 status_(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD), |
| 49 download_count_(0), | 50 download_count_(0), |
| 50 factory_(this) { | 51 factory_(this) { |
| 51 content::Source<NavigationController> notification_source( | 52 registrar_.Add( |
| 52 &contents->GetController()); | 53 this, content::NOTIFICATION_NAV_ENTRY_PENDING, |
| 53 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_PENDING, | 54 content::Source<NavigationController>(&contents->GetController())); |
| 54 notification_source); | 55 registrar_.Add(this, chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED, |
| 56 content::Source<content::WebContents>(contents)); | |
| 55 NavigationEntry* last_entry = originating_web_contents ? | 57 NavigationEntry* last_entry = originating_web_contents ? |
| 56 originating_web_contents->GetController().GetLastCommittedEntry() : | 58 originating_web_contents->GetController().GetLastCommittedEntry() : |
| 57 contents->GetController().GetLastCommittedEntry(); | 59 contents->GetController().GetLastCommittedEntry(); |
| 58 if (last_entry) | 60 if (last_entry) |
| 59 initial_page_host_ = last_entry->GetURL().host(); | 61 initial_page_host_ = last_entry->GetURL().host(); |
| 60 } | 62 } |
| 61 | 63 |
| 62 DownloadRequestLimiter::TabDownloadState::~TabDownloadState() { | 64 DownloadRequestLimiter::TabDownloadState::~TabDownloadState() { |
| 63 // We should only be destroyed after the callbacks have been notified. | 65 // We should only be destroyed after the callbacks have been notified. |
| 64 DCHECK(callbacks_.empty()); | 66 DCHECK(callbacks_.empty()); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 76 // When the user reloads the page without responding to the infobar, they | 78 // When the user reloads the page without responding to the infobar, they |
| 77 // are expecting DownloadRequestLimiter to behave as if they had just | 79 // are expecting DownloadRequestLimiter to behave as if they had just |
| 78 // initially navigated to this page. See http://crbug.com/171372 | 80 // initially navigated to this page. See http://crbug.com/171372 |
| 79 NotifyCallbacks(false); | 81 NotifyCallbacks(false); |
| 80 host_->Remove(this, web_contents()); | 82 host_->Remove(this, web_contents()); |
| 81 // WARNING: We've been deleted. | 83 // WARNING: We've been deleted. |
| 82 break; | 84 break; |
| 83 case DOWNLOADS_NOT_ALLOWED: | 85 case DOWNLOADS_NOT_ALLOWED: |
| 84 case ALLOW_ALL_DOWNLOADS: | 86 case ALLOW_ALL_DOWNLOADS: |
| 85 // Don't drop this information. The user has explicitly said that they | 87 // Don't drop this information. The user has explicitly said that they |
| 86 // do/don't want downloads from this host. If they accidentally Accepted | 88 // do/don't want downloads from this host. If they accidentally Accepted |
| 87 // or Canceled, tough luck, they don't get another chance. They can copy | 89 // or Canceled, they can adjust the limiter state by adjusting the |
| 88 // the URL into a new tab, which will make a new DownloadRequestLimiter. | 90 // automatic downloads content settings. Alternatively, they can copy the |
| 91 // URL into a new tab, which will make a new DownloadRequestLimiter. | |
| 89 // See also the initial_page_host_ logic in Observe() for | 92 // See also the initial_page_host_ logic in Observe() for |
| 90 // NOTIFICATION_NAV_ENTRY_PENDING. | 93 // NOTIFICATION_NAV_ENTRY_PENDING. |
| 91 break; | 94 break; |
| 92 default: | 95 default: |
| 93 NOTREACHED(); | 96 NOTREACHED(); |
| 94 } | 97 } |
| 95 } | 98 } |
| 96 | 99 |
| 97 void DownloadRequestLimiter::TabDownloadState::DidGetUserGesture() { | 100 void DownloadRequestLimiter::TabDownloadState::DidGetUserGesture() { |
| 98 if (is_showing_prompt()) { | 101 if (is_showing_prompt()) { |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 190 } | 193 } |
| 191 | 194 |
| 192 bool DownloadRequestLimiter::TabDownloadState::is_showing_prompt() const { | 195 bool DownloadRequestLimiter::TabDownloadState::is_showing_prompt() const { |
| 193 return factory_.HasWeakPtrs(); | 196 return factory_.HasWeakPtrs(); |
| 194 } | 197 } |
| 195 | 198 |
| 196 void DownloadRequestLimiter::TabDownloadState::Observe( | 199 void DownloadRequestLimiter::TabDownloadState::Observe( |
| 197 int type, | 200 int type, |
| 198 const content::NotificationSource& source, | 201 const content::NotificationSource& source, |
| 199 const content::NotificationDetails& details) { | 202 const content::NotificationDetails& details) { |
| 200 DCHECK_EQ(content::NOTIFICATION_NAV_ENTRY_PENDING, type); | 203 DCHECK(type == chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED || |
| 204 type == content::NOTIFICATION_NAV_ENTRY_PENDING); | |
| 205 | |
| 206 // Content settings have been updated for our web contents, e.g. via the OIB | |
| 207 // or the settings page. Check to see if the automatic downloads setting is | |
| 208 // different to our internal state, and update the internal state to match if | |
| 209 // necessary. If there is no content setting persisted, then retain the | |
| 210 // current state and do nothing. | |
| 211 // | |
| 212 // NotifyCallbacks is not called as this notification should be triggered when | |
| 213 // a download is not pending. | |
| 214 if (type == chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED) { | |
| 215 content::WebContents* contents = | |
| 216 content::Source<content::WebContents>(source).ptr(); | |
| 217 DCHECK_EQ(contents, web_contents()); | |
| 218 | |
| 219 // Fetch the content settings map for this web contents, and extract the | |
| 220 // automatic downloads permission value. | |
| 221 HostContentSettingsMap* content_settings = GetContentSettings(contents); | |
| 222 if (content_settings) { | |
| 223 ContentSetting setting = content_settings->GetContentSetting( | |
| 224 contents->GetURL(), contents->GetURL(), | |
| 225 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, std::string()); | |
| 226 | |
| 227 if (setting == CONTENT_SETTING_ALLOW) { | |
|
asanka
2016/02/08 15:02:14
Nit: use a switch and cover all the settings so th
dominickn
2016/02/11 01:25:53
Done - made this consistent with DownloadRequestLi
| |
| 228 // Case 1: downloads are explicitly allowed in content settings. | |
| 229 set_download_status(ALLOW_ALL_DOWNLOADS); | |
| 230 } else if (setting == CONTENT_SETTING_BLOCK) { | |
| 231 // Case 2: downloads are explicitly blocked in content settings. | |
| 232 set_download_status(DOWNLOADS_NOT_ALLOWED); | |
| 233 } else if (setting == CONTENT_SETTING_ASK) { | |
| 234 // Case 3: downloads are set to ask in content settings. | |
| 235 set_download_status(PROMPT_BEFORE_DOWNLOAD); | |
| 236 } | |
| 237 } | |
| 238 return; | |
| 239 } | |
| 240 | |
| 241 // Otherwise, there is a pending navigation entry. | |
| 201 content::NavigationController* controller = &web_contents()->GetController(); | 242 content::NavigationController* controller = &web_contents()->GetController(); |
| 202 DCHECK_EQ(controller, content::Source<NavigationController>(source).ptr()); | 243 DCHECK_EQ(controller, content::Source<NavigationController>(source).ptr()); |
| 203 | 244 |
| 204 // NOTE: Resetting state on a pending navigate isn't ideal. In particular it | 245 // NOTE: Resetting state on a pending navigate isn't ideal. In particular it |
| 205 // is possible that queued up downloads for the page before the pending | 246 // is possible that queued up downloads for the page before the pending |
| 206 // navigation will be delivered to us after we process this request. If this | 247 // navigation will be delivered to us after we process this request. If this |
| 207 // happens we may let a download through that we shouldn't have. But this is | 248 // happens we may let a download through that we shouldn't have. But this is |
| 208 // rather rare, and it is difficult to get 100% right, so we don't deal with | 249 // rather rare, and it is difficult to get 100% right, so we don't deal with |
| 209 // it. | 250 // it. |
| 210 NavigationEntry* entry = controller->GetPendingEntry(); | 251 NavigationEntry* entry = controller->GetPendingEntry(); |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 438 NOTREACHED(); | 479 NOTREACHED(); |
| 439 } | 480 } |
| 440 } | 481 } |
| 441 | 482 |
| 442 void DownloadRequestLimiter::Remove(TabDownloadState* state, | 483 void DownloadRequestLimiter::Remove(TabDownloadState* state, |
| 443 content::WebContents* contents) { | 484 content::WebContents* contents) { |
| 444 DCHECK(ContainsKey(state_map_, contents)); | 485 DCHECK(ContainsKey(state_map_, contents)); |
| 445 state_map_.erase(contents); | 486 state_map_.erase(contents); |
| 446 delete state; | 487 delete state; |
| 447 } | 488 } |
| OLD | NEW |