Index: chrome/browser/download/download_request_limiter.cc |
diff --git a/chrome/browser/download/download_request_limiter.cc b/chrome/browser/download/download_request_limiter.cc |
index 00e471659f68a97fa98006c9ad3d006fdc7cc282..886f9cd32a2df9eaf1c6b90c296326382effc2c7 100644 |
--- a/chrome/browser/download/download_request_limiter.cc |
+++ b/chrome/browser/download/download_request_limiter.cc |
@@ -8,18 +8,17 @@ |
#include "base/stl_util.h" |
#include "chrome/browser/chrome_notification_types.h" |
#include "chrome/browser/content_settings/host_content_settings_map_factory.h" |
-#include "chrome/browser/content_settings/tab_specific_content_settings.h" |
#include "chrome/browser/infobars/infobar_service.h" |
#include "chrome/browser/profiles/profile.h" |
#include "chrome/browser/tab_contents/tab_util.h" |
+#include "components/content_settings/core/browser/content_settings_details.h" |
#include "components/content_settings/core/browser/host_content_settings_map.h" |
#include "content/public/browser/browser_context.h" |
#include "content/public/browser/browser_thread.h" |
#include "content/public/browser/navigation_controller.h" |
#include "content/public/browser/navigation_entry.h" |
#include "content/public/browser/navigation_handle.h" |
-#include "content/public/browser/notification_source.h" |
-#include "content/public/browser/notification_types.h" |
+#include "content/public/browser/notification_service.h" |
#include "content/public/browser/render_process_host.h" |
#include "content/public/browser/resource_dispatcher_host.h" |
#include "content/public/browser/web_contents.h" |
@@ -37,6 +36,44 @@ using content::BrowserThread; |
using content::NavigationController; |
using content::NavigationEntry; |
+namespace { |
+ |
+ContentSetting GetSettingFromStatus( |
+ DownloadRequestLimiter::DownloadStatus status) { |
+ switch (status) { |
+ case DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD: |
+ case DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD: |
+ return CONTENT_SETTING_ASK; |
+ case DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS: |
+ return CONTENT_SETTING_ALLOW; |
+ case DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED: |
+ return CONTENT_SETTING_BLOCK; |
+ default: |
+ NOTREACHED(); |
+ return CONTENT_SETTING_DEFAULT; |
+ } |
+} |
+ |
+DownloadRequestLimiter::DownloadStatus GetStatusFromSetting( |
+ ContentSetting setting) { |
+ switch (setting) { |
+ case CONTENT_SETTING_ALLOW: |
+ return DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS; |
+ case CONTENT_SETTING_BLOCK: |
+ return DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED; |
+ case CONTENT_SETTING_ASK: |
+ case CONTENT_SETTING_DEFAULT: |
Bernhard Bauer
2017/01/25 19:01:14
Are these content settings actually used? DEFAULT
alshabalin
2017/02/07 16:16:29
Added NOTREACHED() for SESSION_ONLY. But left the
|
+ case CONTENT_SETTING_SESSION_ONLY: |
+ return DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD; |
+ case CONTENT_SETTING_NUM_SETTINGS: |
+ case CONTENT_SETTING_DETECT_IMPORTANT_CONTENT: |
+ NOTREACHED(); |
+ return DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD; |
+ } |
+} |
+ |
+} // namespace |
+ |
// TabDownloadState ------------------------------------------------------------ |
DownloadRequestLimiter::TabDownloadState::TabDownloadState( |
@@ -48,9 +85,9 @@ DownloadRequestLimiter::TabDownloadState::TabDownloadState( |
host_(host), |
status_(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD), |
download_count_(0), |
+ observer_(this), |
factory_(this) { |
- registrar_.Add(this, chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED, |
- content::Source<content::WebContents>(contents)); |
+ observer_.Add(DownloadRequestLimiter::GetContentSettings(contents)); |
Bernhard Bauer
2017/01/25 19:01:14
The DownloadRequestLimiter:: prefix doesn't seem n
alshabalin
2017/02/07 16:16:29
Done.
|
NavigationEntry* last_entry = |
originating_web_contents |
? originating_web_contents->GetController().GetLastCommittedEntry() |
@@ -67,6 +104,22 @@ DownloadRequestLimiter::TabDownloadState::~TabDownloadState() { |
DCHECK(!factory_.HasWeakPtrs()); |
} |
+void DownloadRequestLimiter::TabDownloadState::SetDownloadStatusAndNotify( |
+ DownloadRequestLimiter::DownloadStatus status) { |
+ DownloadStatus last_status = status_; |
+ status_ = status; |
+ if (!web_contents()) |
+ return; |
+ ContentSetting last_setting = GetSettingFromStatus(last_status); |
+ ContentSetting current_setting = GetSettingFromStatus(status_); |
+ if (current_setting == last_setting) |
+ return; |
+ content::NotificationService::current()->Notify( |
+ chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED, |
+ content::Source<content::WebContents>(web_contents()), |
+ content::NotificationService::NoDetails()); |
+} |
+ |
void DownloadRequestLimiter::TabDownloadState::DidStartNavigation( |
content::NavigationHandle* navigation_handle) { |
if (!navigation_handle->IsInMainFrame()) |
@@ -194,16 +247,22 @@ void DownloadRequestLimiter::TabDownloadState::SetContentSetting( |
void DownloadRequestLimiter::TabDownloadState::Cancel() { |
SetContentSetting(CONTENT_SETTING_BLOCK); |
- NotifyCallbacks(false); |
+ bool throttled = NotifyCallbacks(false); |
+ SetDownloadStatusAndNotify(throttled ? PROMPT_BEFORE_DOWNLOAD |
+ : DOWNLOADS_NOT_ALLOWED); |
} |
void DownloadRequestLimiter::TabDownloadState::CancelOnce() { |
- NotifyCallbacks(false); |
+ bool throttled = NotifyCallbacks(false); |
+ SetDownloadStatusAndNotify(throttled ? PROMPT_BEFORE_DOWNLOAD |
+ : DOWNLOADS_NOT_ALLOWED); |
} |
void DownloadRequestLimiter::TabDownloadState::Accept() { |
SetContentSetting(CONTENT_SETTING_ALLOW); |
- NotifyCallbacks(true); |
+ bool throttled = NotifyCallbacks(true); |
+ SetDownloadStatusAndNotify(throttled ? PROMPT_BEFORE_DOWNLOAD |
+ : ALLOW_ALL_DOWNLOADS); |
} |
DownloadRequestLimiter::TabDownloadState::TabDownloadState() |
@@ -211,17 +270,33 @@ DownloadRequestLimiter::TabDownloadState::TabDownloadState() |
host_(NULL), |
status_(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD), |
download_count_(0), |
+ observer_(this), |
factory_(this) {} |
bool DownloadRequestLimiter::TabDownloadState::is_showing_prompt() const { |
return factory_.HasWeakPtrs(); |
} |
-void DownloadRequestLimiter::TabDownloadState::Observe( |
- int type, |
- const content::NotificationSource& source, |
- const content::NotificationDetails& details) { |
- DCHECK_EQ(chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED, type); |
+void DownloadRequestLimiter::TabDownloadState::OnContentSettingChanged( |
+ const ContentSettingsPattern& primary_pattern, |
+ const ContentSettingsPattern& secondary_pattern, |
+ ContentSettingsType content_type, |
+ std::string resource_identifier) { |
+ if (content_type != CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS) |
+ return; |
+ |
+ // Analogous to TabSpecificContentSettings::OnContentSettingChanged: |
+ const ContentSettingsDetails details(primary_pattern, secondary_pattern, |
+ content_type, resource_identifier); |
+ const NavigationController& controller = web_contents()->GetController(); |
+ // The visible NavigationEntry is the URL in the URL field of a tab. |
+ // Currently this should be matched by the |primary_pattern|. |
+ NavigationEntry* entry = controller.GetVisibleEntry(); |
+ GURL entry_url; |
+ if (entry) |
+ entry_url = entry->GetURL(); |
+ if (!details.update_all() && !details.primary_pattern().Matches(entry_url)) |
+ return; |
// Content settings have been updated for our web contents, e.g. via the OIB |
// or the settings page. Check to see if the automatic downloads setting is |
@@ -231,45 +306,24 @@ void DownloadRequestLimiter::TabDownloadState::Observe( |
// |
// NotifyCallbacks is not called as this notification should be triggered when |
// a download is not pending. |
- content::WebContents* contents = |
- content::Source<content::WebContents>(source).ptr(); |
- DCHECK_EQ(contents, web_contents()); |
- |
+ // |
// Fetch the content settings map for this web contents, and extract the |
// automatic downloads permission value. |
- HostContentSettingsMap* content_settings = GetContentSettings(contents); |
+ HostContentSettingsMap* content_settings = GetContentSettings(web_contents()); |
if (!content_settings) |
return; |
ContentSetting setting = content_settings->GetContentSetting( |
- contents->GetURL(), contents->GetURL(), |
+ web_contents()->GetURL(), web_contents()->GetURL(), |
CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, std::string()); |
// Update the internal state to match if necessary. |
- switch (setting) { |
- case CONTENT_SETTING_ALLOW: |
- set_download_status(ALLOW_ALL_DOWNLOADS); |
- break; |
- case CONTENT_SETTING_BLOCK: |
- set_download_status(DOWNLOADS_NOT_ALLOWED); |
- break; |
- case CONTENT_SETTING_ASK: |
- case CONTENT_SETTING_DEFAULT: |
- case CONTENT_SETTING_SESSION_ONLY: |
- set_download_status(PROMPT_BEFORE_DOWNLOAD); |
- break; |
- case CONTENT_SETTING_NUM_SETTINGS: |
- case CONTENT_SETTING_DETECT_IMPORTANT_CONTENT: |
- NOTREACHED(); |
- return; |
- } |
+ SetDownloadStatusAndNotify(GetStatusFromSetting(setting)); |
Bernhard Bauer
2017/01/25 19:01:14
Here you convert the setting to a status, and the
alshabalin
2017/02/07 16:16:29
Added UpdateDownloadStatusAndNotify taking Content
|
} |
-void DownloadRequestLimiter::TabDownloadState::NotifyCallbacks(bool allow) { |
- set_download_status(allow ? DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS |
- : DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED); |
+bool DownloadRequestLimiter::TabDownloadState::NotifyCallbacks(bool allow) { |
std::vector<DownloadRequestLimiter::Callback> callbacks; |
- bool change_status = false; |
+ bool throttled = false; |
// Selectively send first few notifications only if number of downloads exceed |
// kMaxDownloadsAtOnce. In that case, we also retain the infobar instance and |
@@ -285,7 +339,7 @@ void DownloadRequestLimiter::TabDownloadState::NotifyCallbacks(bool allow) { |
end = callbacks_.begin() + kMaxDownloadsAtOnce; |
callbacks.assign(start, end); |
callbacks_.erase(start, end); |
- change_status = true; |
+ throttled = true; |
} |
for (const auto& callback : callbacks) { |
@@ -294,8 +348,7 @@ void DownloadRequestLimiter::TabDownloadState::NotifyCallbacks(bool allow) { |
base::Bind(callback, allow)); |
} |
- if (change_status) |
- set_download_status(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD); |
+ return throttled; |
} |
// DownloadRequestLimiter ------------------------------------------------------ |
@@ -406,13 +459,13 @@ void DownloadRequestLimiter::CanDownloadImpl( |
if (state->download_count() && |
!(state->download_count() % |
DownloadRequestLimiter::kMaxDownloadsAtOnce)) |
- state->set_download_status(PROMPT_BEFORE_DOWNLOAD); |
+ state->SetDownloadStatusAndNotify(PROMPT_BEFORE_DOWNLOAD); |
callback.Run(true); |
state->increment_download_count(); |
break; |
case ALLOW_ONE_DOWNLOAD: |
- state->set_download_status(PROMPT_BEFORE_DOWNLOAD); |
+ state->SetDownloadStatusAndNotify(PROMPT_BEFORE_DOWNLOAD); |
callback.Run(true); |
state->increment_download_count(); |
break; |
@@ -431,19 +484,13 @@ void DownloadRequestLimiter::CanDownloadImpl( |
CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, std::string()); |
switch (setting) { |
case CONTENT_SETTING_ALLOW: { |
- TabSpecificContentSettings* settings = |
- TabSpecificContentSettings::FromWebContents(originating_contents); |
- if (settings) |
- settings->SetDownloadsBlocked(false); |
+ state->SetDownloadStatusAndNotify(ALLOW_ALL_DOWNLOADS); |
callback.Run(true); |
state->increment_download_count(); |
return; |
} |
case CONTENT_SETTING_BLOCK: { |
- TabSpecificContentSettings* settings = |
- TabSpecificContentSettings::FromWebContents(originating_contents); |
- if (settings) |
- settings->SetDownloadsBlocked(true); |
+ state->SetDownloadStatusAndNotify(DOWNLOADS_NOT_ALLOWED); |
callback.Run(false); |
return; |
} |