Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/permissions/permission_decision_auto_blocker.h" | 5 #include "chrome/browser/permissions/permission_decision_auto_blocker.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "base/feature_list.h" | 9 #include "base/feature_list.h" |
| 10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 24 #include "components/variations/variations_associated_data.h" | 24 #include "components/variations/variations_associated_data.h" |
| 25 #include "content/public/browser/web_contents.h" | 25 #include "content/public/browser/web_contents.h" |
| 26 #include "url/gurl.h" | 26 #include "url/gurl.h" |
| 27 | 27 |
| 28 namespace { | 28 namespace { |
| 29 | 29 |
| 30 // The number of times that users may explicitly dismiss a permission prompt | 30 // The number of times that users may explicitly dismiss a permission prompt |
| 31 // from an origin before it is automatically blocked. | 31 // from an origin before it is automatically blocked. |
| 32 int g_prompt_dismissals_before_block = 3; | 32 int g_prompt_dismissals_before_block = 3; |
| 33 | 33 |
| 34 // The number of times that users may ignore a permission prompt from an origin | |
| 35 // before it is automatically blocked. | |
| 36 int g_prompt_ignores_before_block = 4; | |
| 37 | |
| 38 // The number of days that an origin will stay under embargo for a requested | |
| 39 // permission due to repeated dismissals. | |
| 40 int g_dismissal_embargo_days = 7; | |
| 41 | |
| 42 // The number of days that an origin will stay under embargo for a requested | |
| 43 // permission due to repeated ignores. | |
| 44 int g_ignore_embargo_days = 7; | |
| 45 | |
| 34 // The number of days that an origin will stay under embargo for a requested | 46 // The number of days that an origin will stay under embargo for a requested |
| 35 // permission due to blacklisting. | 47 // permission due to blacklisting. |
| 36 int g_blacklist_embargo_days = 7; | 48 int g_blacklist_embargo_days = 7; |
| 37 | 49 |
| 38 // The number of days that an origin will stay under embargo for a requested | |
| 39 // permission due to repeated dismissals. | |
| 40 int g_dismissal_embargo_days = 7; | |
| 41 | |
| 42 // Maximum time in milliseconds to wait for safe browsing service to check a | 50 // Maximum time in milliseconds to wait for safe browsing service to check a |
| 43 // url for blacklisting. After this amount of time, the check will be aborted | 51 // url for blacklisting. After this amount of time, the check will be aborted |
| 44 // and the url will be treated as not safe. | 52 // and the url will be treated as not safe. |
| 45 // TODO(meredithl): Revisit this once UMA metrics have data about request time. | 53 // TODO(meredithl): Revisit this once UMA metrics have data about request time. |
| 46 const int kCheckUrlTimeoutMs = 2000; | 54 const int kCheckUrlTimeoutMs = 2000; |
| 47 | 55 |
| 48 std::unique_ptr<base::DictionaryValue> GetOriginDict( | 56 std::unique_ptr<base::DictionaryValue> GetOriginDict( |
| 49 HostContentSettingsMap* settings, | 57 HostContentSettingsMap* settings, |
| 50 const GURL& origin_url) { | 58 const GURL& origin_url) { |
| 51 std::unique_ptr<base::DictionaryValue> dict = | 59 std::unique_ptr<base::DictionaryValue> dict = |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 102 HostContentSettingsMapFactory::GetForProfile(profile); | 110 HostContentSettingsMapFactory::GetForProfile(profile); |
| 103 std::unique_ptr<base::DictionaryValue> dict = GetOriginDict(map, url); | 111 std::unique_ptr<base::DictionaryValue> dict = GetOriginDict(map, url); |
| 104 base::DictionaryValue* permission_dict = GetOrCreatePermissionDict( | 112 base::DictionaryValue* permission_dict = GetOrCreatePermissionDict( |
| 105 dict.get(), PermissionUtil::GetPermissionString(permission)); | 113 dict.get(), PermissionUtil::GetPermissionString(permission)); |
| 106 | 114 |
| 107 int current_count = 0; | 115 int current_count = 0; |
| 108 permission_dict->GetInteger(key, ¤t_count); | 116 permission_dict->GetInteger(key, ¤t_count); |
| 109 return current_count; | 117 return current_count; |
| 110 } | 118 } |
| 111 | 119 |
| 120 bool IsUnderEmbargo(base::DictionaryValue* permission_dict, | |
| 121 const base::Feature& feature, | |
| 122 const char* key, | |
| 123 base::Time current_time, | |
| 124 base::TimeDelta offset) { | |
| 125 double embargo_date = -1; | |
| 126 | |
| 127 if (base::FeatureList::IsEnabled(feature) && | |
| 128 permission_dict->GetDouble(key, &embargo_date)) { | |
| 129 if (current_time < base::Time::FromInternalValue(embargo_date) + offset) | |
| 130 return true; | |
| 131 } | |
| 132 | |
| 133 return false; | |
| 134 } | |
| 135 | |
| 112 } // namespace | 136 } // namespace |
| 113 | 137 |
| 114 // PermissionDecisionAutoBlocker::Factory -------------------------------------- | 138 // PermissionDecisionAutoBlocker::Factory -------------------------------------- |
| 115 | 139 |
| 116 // static | 140 // static |
| 117 PermissionDecisionAutoBlocker* | 141 PermissionDecisionAutoBlocker* |
| 118 PermissionDecisionAutoBlocker::Factory::GetForProfile(Profile* profile) { | 142 PermissionDecisionAutoBlocker::Factory::GetForProfile(Profile* profile) { |
| 119 return static_cast<PermissionDecisionAutoBlocker*>( | 143 return static_cast<PermissionDecisionAutoBlocker*>( |
| 120 GetInstance()->GetServiceForBrowserContext(profile, true)); | 144 GetInstance()->GetServiceForBrowserContext(profile, true)); |
| 121 } | 145 } |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 149 | 173 |
| 150 // static | 174 // static |
| 151 const char PermissionDecisionAutoBlocker::kPromptDismissCountKey[] = | 175 const char PermissionDecisionAutoBlocker::kPromptDismissCountKey[] = |
| 152 "dismiss_count"; | 176 "dismiss_count"; |
| 153 | 177 |
| 154 // static | 178 // static |
| 155 const char PermissionDecisionAutoBlocker::kPromptIgnoreCountKey[] = | 179 const char PermissionDecisionAutoBlocker::kPromptIgnoreCountKey[] = |
| 156 "ignore_count"; | 180 "ignore_count"; |
| 157 | 181 |
| 158 // static | 182 // static |
| 183 const char PermissionDecisionAutoBlocker::kPermissionDismissalEmbargoKey[] = | |
| 184 "dismissal_embargo_days"; | |
| 185 | |
| 186 // static | |
| 187 const char PermissionDecisionAutoBlocker::kPermissionIgnoreEmbargoKey[] = | |
| 188 "ignore_embargo_days"; | |
| 189 | |
| 190 // static | |
| 159 const char PermissionDecisionAutoBlocker::kPermissionBlacklistEmbargoKey[] = | 191 const char PermissionDecisionAutoBlocker::kPermissionBlacklistEmbargoKey[] = |
| 160 "blacklisting_embargo_days"; | 192 "blacklisting_embargo_days"; |
| 161 | 193 |
| 162 // static | 194 // static |
| 163 const char PermissionDecisionAutoBlocker::kPermissionDismissalEmbargoKey[] = | |
| 164 "dismissal_embargo_days"; | |
| 165 | |
| 166 // static | |
| 167 PermissionDecisionAutoBlocker* PermissionDecisionAutoBlocker::GetForProfile( | 195 PermissionDecisionAutoBlocker* PermissionDecisionAutoBlocker::GetForProfile( |
| 168 Profile* profile) { | 196 Profile* profile) { |
| 169 return PermissionDecisionAutoBlocker::Factory::GetForProfile(profile); | 197 return PermissionDecisionAutoBlocker::Factory::GetForProfile(profile); |
| 170 } | 198 } |
| 171 | 199 |
| 172 // static | 200 // static |
| 173 void PermissionDecisionAutoBlocker::UpdateFromVariations() { | 201 void PermissionDecisionAutoBlocker::UpdateFromVariations() { |
| 174 int prompt_dismissals = -1; | 202 int prompt_dismissals = -1; |
| 203 int prompt_ignores = -1; | |
| 204 int dismissal_embargo_days = -1; | |
| 205 int ignore_embargo_days = -1; | |
| 175 int blacklist_embargo_days = -1; | 206 int blacklist_embargo_days = -1; |
| 176 int dismissal_embargo_days = -1; | 207 |
| 177 std::string dismissals_value = variations::GetVariationParamValueByFeature( | 208 std::string dismissals_value = variations::GetVariationParamValueByFeature( |
| 178 features::kBlockPromptsIfDismissedOften, kPromptDismissCountKey); | 209 features::kBlockPromptsIfDismissedOften, kPromptDismissCountKey); |
| 179 std::string blacklist_embargo_value = | 210 std::string ignores_value = variations::GetVariationParamValueByFeature( |
| 180 variations::GetVariationParamValueByFeature( | 211 features::kBlockPromptsIfIgnoredOften, kPromptIgnoreCountKey); |
| 181 features::kPermissionsBlacklist, kPermissionBlacklistEmbargoKey); | |
| 182 std::string dismissal_embargo_value = | 212 std::string dismissal_embargo_value = |
| 183 variations::GetVariationParamValueByFeature( | 213 variations::GetVariationParamValueByFeature( |
| 184 features::kBlockPromptsIfDismissedOften, | 214 features::kBlockPromptsIfDismissedOften, |
| 185 kPermissionDismissalEmbargoKey); | 215 kPermissionDismissalEmbargoKey); |
| 216 std::string ignore_embargo_value = | |
| 217 variations::GetVariationParamValueByFeature( | |
| 218 features::kBlockPromptsIfIgnoredOften, kPermissionIgnoreEmbargoKey); | |
| 219 std::string blacklist_embargo_value = | |
| 220 variations::GetVariationParamValueByFeature( | |
| 221 features::kPermissionsBlacklist, kPermissionBlacklistEmbargoKey); | |
| 222 | |
| 186 // If converting the value fails, stick with the current value. | 223 // If converting the value fails, stick with the current value. |
| 187 if (base::StringToInt(dismissals_value, &prompt_dismissals) && | 224 if (base::StringToInt(dismissals_value, &prompt_dismissals) && |
| 188 prompt_dismissals > 0) { | 225 prompt_dismissals > 0) { |
| 189 g_prompt_dismissals_before_block = prompt_dismissals; | 226 g_prompt_dismissals_before_block = prompt_dismissals; |
| 190 } | 227 } |
| 191 if (base::StringToInt(blacklist_embargo_value, &blacklist_embargo_days) && | 228 if (base::StringToInt(ignores_value, &prompt_ignores) && prompt_ignores > 0) { |
| 192 blacklist_embargo_days > 0) { | 229 g_prompt_ignores_before_block = prompt_ignores; |
| 193 g_blacklist_embargo_days = blacklist_embargo_days; | |
| 194 } | 230 } |
| 195 if (base::StringToInt(dismissal_embargo_value, &dismissal_embargo_days) && | 231 if (base::StringToInt(dismissal_embargo_value, &dismissal_embargo_days) && |
| 196 dismissal_embargo_days > 0) { | 232 dismissal_embargo_days > 0) { |
| 197 g_dismissal_embargo_days = dismissal_embargo_days; | 233 g_dismissal_embargo_days = dismissal_embargo_days; |
| 198 } | 234 } |
| 235 if (base::StringToInt(ignore_embargo_value, &ignore_embargo_days) && | |
|
benwells
2017/03/31 04:47:14
These variables are all confusingly named. For g_f
dominickn
2017/04/02 23:45:57
Done.
| |
| 236 ignore_embargo_days > 0) { | |
| 237 g_ignore_embargo_days = ignore_embargo_days; | |
| 238 } | |
| 239 if (base::StringToInt(blacklist_embargo_value, &blacklist_embargo_days) && | |
| 240 blacklist_embargo_days > 0) { | |
| 241 g_blacklist_embargo_days = blacklist_embargo_days; | |
| 242 } | |
| 199 } | 243 } |
| 200 | 244 |
| 201 void PermissionDecisionAutoBlocker::CheckSafeBrowsingBlacklist( | 245 void PermissionDecisionAutoBlocker::CheckSafeBrowsingBlacklist( |
| 202 content::WebContents* web_contents, | 246 content::WebContents* web_contents, |
| 203 const GURL& request_origin, | 247 const GURL& request_origin, |
| 204 ContentSettingsType permission, | 248 ContentSettingsType permission, |
| 205 base::Callback<void(bool)> callback) { | 249 base::Callback<void(bool)> callback) { |
| 206 DCHECK_EQ(CONTENT_SETTING_ASK, | 250 DCHECK_EQ(CONTENT_SETTING_ASK, |
| 207 GetEmbargoResult(request_origin, permission).content_setting); | 251 GetEmbargoResult(request_origin, permission).content_setting); |
| 208 | 252 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 225 | 269 |
| 226 PermissionResult PermissionDecisionAutoBlocker::GetEmbargoResult( | 270 PermissionResult PermissionDecisionAutoBlocker::GetEmbargoResult( |
| 227 const GURL& request_origin, | 271 const GURL& request_origin, |
| 228 ContentSettingsType permission) { | 272 ContentSettingsType permission) { |
| 229 HostContentSettingsMap* map = | 273 HostContentSettingsMap* map = |
| 230 HostContentSettingsMapFactory::GetForProfile(profile_); | 274 HostContentSettingsMapFactory::GetForProfile(profile_); |
| 231 std::unique_ptr<base::DictionaryValue> dict = | 275 std::unique_ptr<base::DictionaryValue> dict = |
| 232 GetOriginDict(map, request_origin); | 276 GetOriginDict(map, request_origin); |
| 233 base::DictionaryValue* permission_dict = GetOrCreatePermissionDict( | 277 base::DictionaryValue* permission_dict = GetOrCreatePermissionDict( |
| 234 dict.get(), PermissionUtil::GetPermissionString(permission)); | 278 dict.get(), PermissionUtil::GetPermissionString(permission)); |
| 235 double embargo_date = -1; | |
| 236 | 279 |
| 237 base::Time current_time = clock_->Now(); | 280 base::Time current_time = clock_->Now(); |
| 238 if (base::FeatureList::IsEnabled(features::kPermissionsBlacklist) && | 281 if (IsUnderEmbargo(permission_dict, features::kPermissionsBlacklist, |
|
benwells
2017/03/31 04:47:14
Nice factoring :)
dominickn
2017/04/02 23:45:57
:)
| |
| 239 permission_dict->GetDouble(kPermissionBlacklistEmbargoKey, | 282 kPermissionBlacklistEmbargoKey, current_time, |
| 240 &embargo_date)) { | 283 base::TimeDelta::FromDays(g_blacklist_embargo_days))) { |
| 241 if (current_time < | 284 return PermissionResult(CONTENT_SETTING_BLOCK, |
| 242 base::Time::FromInternalValue(embargo_date) + | 285 PermissionStatusSource::SAFE_BROWSING_BLACKLIST); |
| 243 base::TimeDelta::FromDays(g_blacklist_embargo_days)) { | |
| 244 return PermissionResult(CONTENT_SETTING_BLOCK, | |
| 245 PermissionStatusSource::SAFE_BROWSING_BLACKLIST); | |
| 246 } | |
| 247 } | 286 } |
| 248 | 287 |
| 249 if (base::FeatureList::IsEnabled(features::kBlockPromptsIfDismissedOften) && | 288 if (IsUnderEmbargo(permission_dict, features::kBlockPromptsIfDismissedOften, |
| 250 permission_dict->GetDouble(kPermissionDismissalEmbargoKey, | 289 kPermissionDismissalEmbargoKey, current_time, |
| 251 &embargo_date)) { | 290 base::TimeDelta::FromDays(g_dismissal_embargo_days))) { |
| 252 if (current_time < | 291 return PermissionResult(CONTENT_SETTING_BLOCK, |
| 253 base::Time::FromInternalValue(embargo_date) + | 292 PermissionStatusSource::MULTIPLE_DISMISSALS); |
| 254 base::TimeDelta::FromDays(g_dismissal_embargo_days)) { | 293 } |
| 255 return PermissionResult(CONTENT_SETTING_BLOCK, | 294 |
| 256 PermissionStatusSource::MULTIPLE_DISMISSALS); | 295 if (IsUnderEmbargo(permission_dict, features::kBlockPromptsIfIgnoredOften, |
| 257 } | 296 kPermissionIgnoreEmbargoKey, current_time, |
| 297 base::TimeDelta::FromDays(g_ignore_embargo_days))) { | |
| 298 return PermissionResult(CONTENT_SETTING_BLOCK, | |
| 299 PermissionStatusSource::MULTIPLE_IGNORES); | |
| 258 } | 300 } |
| 259 | 301 |
| 260 return PermissionResult(CONTENT_SETTING_ASK, | 302 return PermissionResult(CONTENT_SETTING_ASK, |
| 261 PermissionStatusSource::UNSPECIFIED); | 303 PermissionStatusSource::UNSPECIFIED); |
| 262 } | 304 } |
| 263 | 305 |
| 264 int PermissionDecisionAutoBlocker::GetDismissCount( | 306 int PermissionDecisionAutoBlocker::GetDismissCount( |
| 265 const GURL& url, | 307 const GURL& url, |
| 266 ContentSettingsType permission) { | 308 ContentSettingsType permission) { |
| 267 return GetActionCount(url, permission, kPromptDismissCountKey, profile_); | 309 return GetActionCount(url, permission, kPromptDismissCountKey, profile_); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 280 url, permission, kPromptDismissCountKey, profile_); | 322 url, permission, kPromptDismissCountKey, profile_); |
| 281 | 323 |
| 282 if (base::FeatureList::IsEnabled(features::kBlockPromptsIfDismissedOften) && | 324 if (base::FeatureList::IsEnabled(features::kBlockPromptsIfDismissedOften) && |
| 283 current_dismissal_count >= g_prompt_dismissals_before_block) { | 325 current_dismissal_count >= g_prompt_dismissals_before_block) { |
| 284 PlaceUnderEmbargo(url, permission, kPermissionDismissalEmbargoKey); | 326 PlaceUnderEmbargo(url, permission, kPermissionDismissalEmbargoKey); |
| 285 return true; | 327 return true; |
| 286 } | 328 } |
| 287 return false; | 329 return false; |
| 288 } | 330 } |
| 289 | 331 |
| 290 int PermissionDecisionAutoBlocker::RecordIgnore( | 332 bool PermissionDecisionAutoBlocker::RecordIgnoreAndEmbargo( |
| 291 const GURL& url, | 333 const GURL& url, |
| 292 ContentSettingsType permission) { | 334 ContentSettingsType permission) { |
| 293 return RecordActionInWebsiteSettings(url, permission, kPromptIgnoreCountKey, | 335 int current_ignore_count = RecordActionInWebsiteSettings( |
| 294 profile_); | 336 url, permission, kPromptIgnoreCountKey, profile_); |
| 337 | |
| 338 if (base::FeatureList::IsEnabled(features::kBlockPromptsIfIgnoredOften) && | |
| 339 current_ignore_count >= g_prompt_ignores_before_block) { | |
| 340 PlaceUnderEmbargo(url, permission, kPermissionIgnoreEmbargoKey); | |
| 341 return true; | |
| 342 } | |
| 343 return false; | |
| 295 } | 344 } |
| 296 | 345 |
| 297 void PermissionDecisionAutoBlocker::RemoveCountsByUrl( | 346 void PermissionDecisionAutoBlocker::RemoveCountsByUrl( |
| 298 base::Callback<bool(const GURL& url)> filter) { | 347 base::Callback<bool(const GURL& url)> filter) { |
| 299 HostContentSettingsMap* map = | 348 HostContentSettingsMap* map = |
| 300 HostContentSettingsMapFactory::GetForProfile(profile_); | 349 HostContentSettingsMapFactory::GetForProfile(profile_); |
| 301 | 350 |
| 302 std::unique_ptr<ContentSettingsForOneType> settings( | 351 std::unique_ptr<ContentSettingsForOneType> settings( |
| 303 new ContentSettingsForOneType); | 352 new ContentSettingsForOneType); |
| 304 map->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PERMISSION_AUTOBLOCKER_DATA, | 353 map->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PERMISSION_AUTOBLOCKER_DATA, |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 363 scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager, | 412 scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager, |
| 364 int timeout) { | 413 int timeout) { |
| 365 db_manager_ = db_manager; | 414 db_manager_ = db_manager; |
| 366 safe_browsing_timeout_ = timeout; | 415 safe_browsing_timeout_ = timeout; |
| 367 } | 416 } |
| 368 | 417 |
| 369 void PermissionDecisionAutoBlocker::SetClockForTesting( | 418 void PermissionDecisionAutoBlocker::SetClockForTesting( |
| 370 std::unique_ptr<base::Clock> clock) { | 419 std::unique_ptr<base::Clock> clock) { |
| 371 clock_ = std::move(clock); | 420 clock_ = std::move(clock); |
| 372 } | 421 } |
| OLD | NEW |