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 b38ee5edd010edea28f76564337c263b2f75c207..97834772a53a020cf6ae1aa3ad7c76d6e52b7bb1 100644 |
--- a/chrome/browser/permissions/permission_decision_auto_blocker.cc |
+++ b/chrome/browser/permissions/permission_decision_auto_blocker.cc |
@@ -10,13 +10,18 @@ |
#include "base/logging.h" |
#include "base/memory/ptr_util.h" |
#include "base/strings/string_number_conversions.h" |
-#include "base/time/time.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/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" |
@@ -36,6 +41,14 @@ int g_blacklist_embargo_days = 7; |
// permission due to repeated dismissals. |
int g_dismissal_embargo_days = 7; |
+// 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; |
+ |
+// 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) { |
@@ -102,6 +115,42 @@ int GetActionCount(const GURL& url, |
} // namespace |
+// PermissionDecisionAutoBlocker::Factory -------------------------------------- |
+ |
+// static |
+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); |
+} |
+ |
+// PermissionDecisionAutoBlocker ----------------------------------------------- |
+ |
// static |
const char PermissionDecisionAutoBlocker::kPromptDismissCountKey[] = |
"dismiss_count"; |
@@ -119,11 +168,28 @@ const char PermissionDecisionAutoBlocker::kPermissionDismissalEmbargoKey[] = |
"dismissal_embargo_days"; |
// static |
+PermissionDecisionAutoBlocker* PermissionDecisionAutoBlocker::GetForProfile( |
+ Profile* profile) { |
+ return PermissionDecisionAutoBlocker::Factory::GetForProfile(profile); |
+} |
+ |
+PermissionDecisionAutoBlocker::PermissionDecisionAutoBlocker(Profile* profile) |
+ : profile_(profile), |
+ db_manager_(nullptr), |
+ safe_browsing_timeout_(kCheckUrlTimeoutMs), |
+ clock_(new base::DefaultClock()) { |
+ safe_browsing::SafeBrowsingService* sb_service = |
+ g_browser_process->safe_browsing_service(); |
+ if (sb_service) |
+ db_manager_ = sb_service->database_manager(); |
+} |
+ |
+PermissionDecisionAutoBlocker::~PermissionDecisionAutoBlocker() {} |
+ |
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); |
@@ -141,62 +207,37 @@ 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, 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 |
@@ -228,30 +269,27 @@ 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_) { |
+ // The CheckSafeBrowsingResult callback won't be called if the profile is |
+ // destroyed before a result is received. In that case this object will have |
+ // been destroyed by that point. |
PermissionBlacklistClient::CheckSafeBrowsingBlacklist( |
- 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, |
+ base::Unretained(this), permission, request_origin, |
callback)); |
return; |
} |
@@ -259,14 +297,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( |
@@ -274,6 +309,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)) { |
@@ -293,40 +329,52 @@ bool PermissionDecisionAutoBlocker::IsUnderEmbargo( |
is_under_dismiss_embargo = true; |
} |
} |
- // If either embargoes is still in effect, return true. |
+ |
+ // If either embargo is still in effect, return true. |
return is_under_dismiss_embargo || is_under_blacklist_embargo; |
} |
+// static |
+void PermissionDecisionAutoBlocker::CheckSafeBrowsingResult( |
+ content::PermissionType permission, |
+ const GURL& request_origin, |
+ 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, |
+ kPermissionBlacklistEmbargoKey); |
+ } |
+ callback.Run(should_be_embargoed /* permission blocked */); |
+} |
+ |
+// static |
void PermissionDecisionAutoBlocker::PlaceUnderEmbargo( |
content::PermissionType permission, |
const GURL& request_origin, |
- HostContentSettingsMap* map, |
- base::Time current_time, |
const char* key) { |
+ 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)); |
- permission_dict->SetDouble(key, current_time.ToInternalValue()); |
+ permission_dict->SetDouble(key, clock_->Now().ToInternalValue()); |
map->SetWebsiteSettingDefaultScope( |
request_origin, GURL(), CONTENT_SETTINGS_TYPE_PROMPT_NO_DECISION_COUNT, |
std::string(), std::move(dict)); |
} |
-// 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 */); |
+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); |
} |