Chromium Code Reviews| Index: chrome/browser/permissions/permission_decision_auto_blocker.cc |
| diff --git a/chrome/browser/permissions/permission_decision_auto_blocker.cc b/chrome/browser/permissions/permission_decision_auto_blocker.cc |
| index b53fe83b542dc18bf3a3578bf989007440dabfcf..f585758dd198eede7bc49806532c999fe3b449b2 100644 |
| --- a/chrome/browser/permissions/permission_decision_auto_blocker.cc |
| +++ b/chrome/browser/permissions/permission_decision_auto_blocker.cc |
| @@ -10,15 +10,19 @@ |
| #include "base/logging.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/strings/string_number_conversions.h" |
| -#include "base/time/time.h" |
| +#include "base/time/default_clock.h" |
| #include "base/values.h" |
| +#include "chrome/browser/browser_process.h" |
| #include "chrome/browser/content_settings/host_content_settings_map_factory.h" |
| #include "chrome/browser/permissions/permission_blacklist_client.h" |
| #include "chrome/browser/permissions/permission_util.h" |
| -#include "chrome/browser/permissions/permission_blacklist_client.h" |
| -#include "chrome/browser/permissions/permission_util.h" |
| +#include "chrome/browser/profiles/incognito_helpers.h" |
| +#include "chrome/browser/profiles/profile.h" |
| +#include "chrome/browser/safe_browsing/safe_browsing_service.h" |
| #include "chrome/common/chrome_features.h" |
| #include "components/content_settings/core/browser/host_content_settings_map.h" |
| +#include "components/keyed_service/content/browser_context_dependency_manager.h" |
| +#include "components/safe_browsing_db/database_manager.h" |
| #include "components/variations/variations_associated_data.h" |
| #include "content/public/browser/permission_type.h" |
| #include "content/public/browser/web_contents.h" |
| @@ -38,6 +42,8 @@ int g_blacklist_embargo_days = 7; |
| // permission due to repeated dismissals. |
| int g_dismissal_embargo_days = 7; |
| +// TODO(meredithl): Migrate to a new and more fitting type, once metrics have |
| +// been gathered, and deprecate CONTENT_SETTINGS_TYPE_PROMPT_NO_DECISION_COUNT. |
| std::unique_ptr<base::DictionaryValue> GetOriginDict( |
| HostContentSettingsMap* settings, |
| const GURL& origin_url) { |
| @@ -104,6 +110,8 @@ int GetActionCount(const GURL& url, |
| } // namespace |
| +// PermissionDecisionAutoBlocker ----------------------------------------------- |
| + |
| // static |
| const char PermissionDecisionAutoBlocker::kPromptDismissCountKey[] = |
| "dismiss_count"; |
| @@ -120,12 +128,35 @@ const char PermissionDecisionAutoBlocker::kPermissionBlacklistEmbargoKey[] = |
| const char PermissionDecisionAutoBlocker::kPermissionDismissalEmbargoKey[] = |
| "dismissal_embargo_days"; |
| -// static |
| +// Maximum time in milliseconds to wait for safe browsing service to check a |
| +// url for blacklisting. After this amount of time, the check will be aborted |
| +// and the url will be treated as not safe. |
| +// TODO(meredithl): Revisit this once UMA metrics have data about request time. |
| +const int kCheckUrlTimeoutMs = 2000; |
| + |
| +PermissionDecisionAutoBlocker::PermissionDecisionAutoBlocker(Profile* profile) |
| + : profile_(profile), |
| + safe_browsing_timeout_(kCheckUrlTimeoutMs), |
| + clock_(new base::DefaultClock()) { |
| + if (!db_manager_) { |
|
raymes
2017/01/24 03:31:08
The db_manager_ will always be null at the start,
meredithl
2017/01/24 04:52:25
Done. But that means I still need to add a null ch
|
| + safe_browsing::SafeBrowsingService* sb_service = |
| + g_browser_process->safe_browsing_service(); |
| + if (sb_service) |
| + db_manager_ = sb_service->database_manager(); |
| + } |
| +} |
| + |
| +PermissionDecisionAutoBlocker::~PermissionDecisionAutoBlocker() {} |
| + |
| +PermissionDecisionAutoBlocker* PermissionDecisionAutoBlocker::GetForProfile( |
|
raymes
2017/01/24 03:31:08
nit: // static
meredithl
2017/01/24 04:52:25
Done.
|
| + Profile* profile) { |
| + return PermissionDecisionAutoBlocker::Factory::GetForProfile(profile); |
| +} |
| + |
| void PermissionDecisionAutoBlocker::RemoveCountsByUrl( |
| - Profile* profile, |
| base::Callback<bool(const GURL& url)> filter) { |
| HostContentSettingsMap* map = |
| - HostContentSettingsMapFactory::GetForProfile(profile); |
| + HostContentSettingsMapFactory::GetForProfile(profile_); |
| std::unique_ptr<ContentSettingsForOneType> settings( |
| new ContentSettingsForOneType); |
| @@ -143,62 +174,39 @@ void PermissionDecisionAutoBlocker::RemoveCountsByUrl( |
| } |
| } |
| -// static |
| int PermissionDecisionAutoBlocker::GetDismissCount( |
| const GURL& url, |
| - content::PermissionType permission, |
| - Profile* profile) { |
| - return GetActionCount(url, permission, kPromptDismissCountKey, profile); |
| + content::PermissionType permission) { |
| + return GetActionCount(url, permission, kPromptDismissCountKey, profile_); |
| } |
| -// static |
| int PermissionDecisionAutoBlocker::GetIgnoreCount( |
| const GURL& url, |
| - content::PermissionType permission, |
| - Profile* profile) { |
| - return GetActionCount(url, permission, kPromptIgnoreCountKey, profile); |
| + content::PermissionType permission) { |
| + return GetActionCount(url, permission, kPromptIgnoreCountKey, profile_); |
| } |
| -// static |
| bool PermissionDecisionAutoBlocker::RecordDismissAndEmbargo( |
| const GURL& url, |
| - content::PermissionType permission, |
| - Profile* profile, |
| - base::Time current_time) { |
| + content::PermissionType permission) { |
| int current_dismissal_count = RecordActionInWebsiteSettings( |
| - url, permission, kPromptDismissCountKey, profile); |
| + url, permission, kPromptDismissCountKey, profile_); |
| + |
| if (base::FeatureList::IsEnabled(features::kBlockPromptsIfDismissedOften) && |
| current_dismissal_count >= g_prompt_dismissals_before_block) { |
| - HostContentSettingsMap* map = |
| - HostContentSettingsMapFactory::GetForProfile(profile); |
| - PlaceUnderEmbargo(permission, url, map, current_time, |
| - kPermissionDismissalEmbargoKey); |
| + PlaceUnderEmbargo(permission, url, |
| + HostContentSettingsMapFactory::GetForProfile(profile_), |
| + clock_->Now(), kPermissionDismissalEmbargoKey); |
| return true; |
| } |
| return false; |
| } |
| -// static |
| int PermissionDecisionAutoBlocker::RecordIgnore( |
| const GURL& url, |
| - content::PermissionType permission, |
| - Profile* profile) { |
| + content::PermissionType permission) { |
| return RecordActionInWebsiteSettings(url, permission, kPromptIgnoreCountKey, |
| - profile); |
| -} |
| - |
| -// static |
| -bool PermissionDecisionAutoBlocker::ShouldChangeDismissalToBlock( |
| - const GURL& url, |
| - content::PermissionType permission, |
| - Profile* profile) { |
| - int current_dismissal_count = |
| - RecordDismissAndEmbargo(url, permission, profile, base::Time::Now()); |
| - |
| - if (!base::FeatureList::IsEnabled(features::kBlockPromptsIfDismissedOften)) |
| - return false; |
| - |
| - return current_dismissal_count >= g_prompt_dismissals_before_block; |
| + profile_); |
| } |
| // static |
| @@ -230,30 +238,24 @@ void PermissionDecisionAutoBlocker::UpdateFromVariations() { |
| } |
| } |
| -// static |
| -// TODO(meredithl): Have PermissionDecisionAutoBlocker handle the database |
| -// manager, rather than passing it in. |
| void PermissionDecisionAutoBlocker::UpdateEmbargoedStatus( |
| - scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager, |
| content::PermissionType permission, |
| const GURL& request_origin, |
| content::WebContents* web_contents, |
| - int timeout, |
| - Profile* profile, |
| - base::Time current_time, |
| base::Callback<void(bool)> callback) { |
| // Check if origin is currently under embargo for the requested permission. |
| - if (IsUnderEmbargo(permission, profile, request_origin, current_time)) { |
| + if (IsUnderEmbargo(permission, request_origin)) { |
| callback.Run(true /* permission_blocked */); |
| return; |
| } |
| if (base::FeatureList::IsEnabled(features::kPermissionsBlacklist) && |
| - db_manager) { |
| + db_manager_) { |
| PermissionBlacklistClient::CheckSafeBrowsingBlacklist( |
|
raymes
2017/01/24 03:31:08
nit: I discussed about lifetimes with Dom. Could y
meredithl
2017/01/24 04:52:25
Done.
|
| - db_manager, permission, request_origin, web_contents, timeout, |
| + db_manager_, permission, request_origin, web_contents, |
| + safe_browsing_timeout_, |
| base::Bind(&PermissionDecisionAutoBlocker::CheckSafeBrowsingResult, |
| - permission, profile, request_origin, current_time, |
| + permission, profile_, request_origin, clock_->Now(), |
| callback)); |
| return; |
| } |
| @@ -261,14 +263,11 @@ void PermissionDecisionAutoBlocker::UpdateEmbargoedStatus( |
| callback.Run(false /* permission blocked */); |
| } |
| -// static |
| bool PermissionDecisionAutoBlocker::IsUnderEmbargo( |
| content::PermissionType permission, |
| - Profile* profile, |
| - const GURL& request_origin, |
| - base::Time current_time) { |
| + const GURL& request_origin) { |
| HostContentSettingsMap* map = |
| - HostContentSettingsMapFactory::GetForProfile(profile); |
| + HostContentSettingsMapFactory::GetForProfile(profile_); |
| std::unique_ptr<base::DictionaryValue> dict = |
| GetOriginDict(map, request_origin); |
| base::DictionaryValue* permission_dict = GetOrCreatePermissionDict( |
| @@ -276,6 +275,7 @@ bool PermissionDecisionAutoBlocker::IsUnderEmbargo( |
| double embargo_date = -1; |
| bool is_under_dismiss_embargo = false; |
| bool is_under_blacklist_embargo = false; |
| + base::Time current_time = clock_->Now(); |
| if (base::FeatureList::IsEnabled(features::kPermissionsBlacklist) && |
| permission_dict->GetDouble(kPermissionBlacklistEmbargoKey, |
| &embargo_date)) { |
| @@ -295,24 +295,9 @@ bool PermissionDecisionAutoBlocker::IsUnderEmbargo( |
| is_under_dismiss_embargo = true; |
| } |
| } |
| - // If either embargoes is still in effect, return true. |
| - return is_under_dismiss_embargo || is_under_blacklist_embargo; |
| -} |
| -void PermissionDecisionAutoBlocker::PlaceUnderEmbargo( |
| - content::PermissionType permission, |
| - const GURL& request_origin, |
| - HostContentSettingsMap* map, |
| - base::Time current_time, |
| - const char* key) { |
| - std::unique_ptr<base::DictionaryValue> dict = |
| - GetOriginDict(map, request_origin); |
| - base::DictionaryValue* permission_dict = GetOrCreatePermissionDict( |
| - dict.get(), PermissionUtil::GetPermissionString(permission)); |
| - permission_dict->SetDouble(key, current_time.ToInternalValue()); |
| - map->SetWebsiteSettingDefaultScope( |
| - request_origin, GURL(), CONTENT_SETTINGS_TYPE_PROMPT_NO_DECISION_COUNT, |
| - std::string(), std::move(dict)); |
| + // If either embargo is still in effect, return true. |
| + return is_under_dismiss_embargo || is_under_blacklist_embargo; |
| } |
| // static |
| @@ -334,73 +319,6 @@ void PermissionDecisionAutoBlocker::CheckSafeBrowsingResult( |
| } |
| // static |
| -// TODO(meredithl): Have PermissionDecisionAutoBlocker handle the database |
| -// manager, rather than passing it in. |
| -void PermissionDecisionAutoBlocker::UpdateEmbargoedStatus( |
| - scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager, |
| - content::PermissionType permission, |
| - const GURL& request_origin, |
| - content::WebContents* web_contents, |
| - int timeout, |
| - Profile* profile, |
| - base::Time current_time, |
| - base::Callback<void(bool)> callback) { |
| - // Check if origin is currently under embargo for the requested permission. |
| - if (IsUnderEmbargo(permission, profile, request_origin, current_time)) { |
| - callback.Run(true /* permission_blocked */); |
| - return; |
| - } |
| - |
| - if (base::FeatureList::IsEnabled(features::kPermissionsBlacklist) && |
| - db_manager) { |
| - PermissionBlacklistClient::CheckSafeBrowsingBlacklist( |
| - db_manager, permission, request_origin, web_contents, timeout, |
| - base::Bind(&PermissionDecisionAutoBlocker::CheckSafeBrowsingResult, |
| - permission, profile, request_origin, current_time, |
| - callback)); |
| - } |
| - |
| - callback.Run(false /* permission blocked */); |
| -} |
| - |
| -// static |
| -bool PermissionDecisionAutoBlocker::IsUnderEmbargo( |
| - content::PermissionType permission, |
| - Profile* profile, |
| - const GURL& request_origin, |
| - base::Time current_time) { |
| - HostContentSettingsMap* map = |
| - HostContentSettingsMapFactory::GetForProfile(profile); |
| - std::unique_ptr<base::DictionaryValue> dict = |
| - GetOriginDict(map, request_origin); |
| - base::DictionaryValue* permission_dict = GetOrCreatePermissionDict( |
| - dict.get(), PermissionUtil::GetPermissionString(permission)); |
| - double embargo_date = -1; |
| - bool is_under_dismiss_embargo = false; |
| - bool is_under_blacklist_embargo = false; |
| - if (base::FeatureList::IsEnabled(features::kPermissionsBlacklist) && |
| - permission_dict->GetDouble(kPermissionBlacklistEmbargoKey, |
| - &embargo_date)) { |
| - if (current_time < |
| - base::Time::FromInternalValue(embargo_date) + |
| - base::TimeDelta::FromDays(g_blacklist_embargo_days)) { |
| - is_under_blacklist_embargo = true; |
| - } |
| - } |
| - |
| - if (base::FeatureList::IsEnabled(features::kBlockPromptsIfDismissedOften) && |
| - permission_dict->GetDouble(kPermissionDismissalEmbargoKey, |
| - &embargo_date)) { |
| - if (current_time < |
| - base::Time::FromInternalValue(embargo_date) + |
| - base::TimeDelta::FromDays(g_dismissal_embargo_days)) { |
| - is_under_dismiss_embargo = true; |
| - } |
| - } |
| - // If either embargoes is still in effect, return true. |
| - return is_under_dismiss_embargo || is_under_blacklist_embargo; |
| -} |
| - |
| void PermissionDecisionAutoBlocker::PlaceUnderEmbargo( |
| content::PermissionType permission, |
| const GURL& request_origin, |
| @@ -417,20 +335,49 @@ void PermissionDecisionAutoBlocker::PlaceUnderEmbargo( |
| std::string(), std::move(dict)); |
| } |
| +void PermissionDecisionAutoBlocker:: |
| + SetSafeBrowsingDatabaseManagerAndTimeoutForTesting( |
| + scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager, |
| + int timeout) { |
| + db_manager_ = db_manager; |
| + safe_browsing_timeout_ = timeout; |
| +} |
| + |
| +void PermissionDecisionAutoBlocker::SetClockForTesting( |
| + std::unique_ptr<base::Clock> clock) { |
| + clock_ = std::move(clock); |
| +} |
| + |
| +// PermissionDecisionAutoBlocker::Factory -------------------------------------- |
|
raymes
2017/01/24 03:31:08
nit: this section should probably move to the top
meredithl
2017/01/24 04:52:25
Done.
|
| + |
| // static |
| -void PermissionDecisionAutoBlocker::CheckSafeBrowsingResult( |
| - content::PermissionType permission, |
| - Profile* profile, |
| - const GURL& request_origin, |
| - base::Time current_time, |
| - base::Callback<void(bool)> callback, |
| - bool should_be_embargoed) { |
| - if (should_be_embargoed) { |
| - // Requesting site is blacklisted for this permission, update the content |
| - // setting to place it under embargo. |
| - PlaceUnderEmbargo(permission, request_origin, |
| - HostContentSettingsMapFactory::GetForProfile(profile), |
| - current_time, kPermissionBlacklistEmbargoKey); |
| - } |
| - callback.Run(should_be_embargoed /* permission blocked */); |
| +PermissionDecisionAutoBlocker* |
| +PermissionDecisionAutoBlocker::Factory::GetForProfile(Profile* profile) { |
| + return static_cast<PermissionDecisionAutoBlocker*>( |
| + GetInstance()->GetServiceForBrowserContext(profile, true)); |
| +} |
| + |
| +// static |
| +PermissionDecisionAutoBlocker::Factory* |
| +PermissionDecisionAutoBlocker::Factory::GetInstance() { |
| + return base::Singleton<PermissionDecisionAutoBlocker::Factory>::get(); |
| +} |
| + |
| +PermissionDecisionAutoBlocker::Factory::Factory() |
| + : BrowserContextKeyedServiceFactory( |
| + "PermissionDecisionAutoBlocker", |
| + BrowserContextDependencyManager::GetInstance()) {} |
| + |
| +PermissionDecisionAutoBlocker::Factory::~Factory() {} |
| + |
| +KeyedService* PermissionDecisionAutoBlocker::Factory::BuildServiceInstanceFor( |
| + content::BrowserContext* context) const { |
| + Profile* profile = static_cast<Profile*>(context); |
| + return new PermissionDecisionAutoBlocker(profile); |
| +} |
| + |
| +content::BrowserContext* |
| +PermissionDecisionAutoBlocker::Factory::GetBrowserContextToUse( |
| + content::BrowserContext* context) const { |
| + return chrome::GetBrowserContextOwnInstanceInIncognito(context); |
| } |