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 11 matching lines...) Expand all Loading... |
22 #include "components/keyed_service/content/browser_context_dependency_manager.h" | 22 #include "components/keyed_service/content/browser_context_dependency_manager.h" |
23 #include "components/safe_browsing_db/database_manager.h" | 23 #include "components/safe_browsing_db/database_manager.h" |
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_dismissals_before_block = 3; |
| 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_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; |
33 | 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 dismissals_before_block = -1; |
| 203 int ignores_before_block = -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_before_block_value = |
178 features::kBlockPromptsIfDismissedOften, kPromptDismissCountKey); | |
179 std::string blacklist_embargo_value = | |
180 variations::GetVariationParamValueByFeature( | 209 variations::GetVariationParamValueByFeature( |
181 features::kPermissionsBlacklist, kPermissionBlacklistEmbargoKey); | 210 features::kBlockPromptsIfDismissedOften, kPromptDismissCountKey); |
182 std::string dismissal_embargo_value = | 211 std::string ignores_before_block_value = |
| 212 variations::GetVariationParamValueByFeature( |
| 213 features::kBlockPromptsIfIgnoredOften, kPromptIgnoreCountKey); |
| 214 std::string dismissal_embargo_days_value = |
183 variations::GetVariationParamValueByFeature( | 215 variations::GetVariationParamValueByFeature( |
184 features::kBlockPromptsIfDismissedOften, | 216 features::kBlockPromptsIfDismissedOften, |
185 kPermissionDismissalEmbargoKey); | 217 kPermissionDismissalEmbargoKey); |
| 218 std::string ignore_embargo_days_value = |
| 219 variations::GetVariationParamValueByFeature( |
| 220 features::kBlockPromptsIfIgnoredOften, kPermissionIgnoreEmbargoKey); |
| 221 std::string blacklist_embargo_days_value = |
| 222 variations::GetVariationParamValueByFeature( |
| 223 features::kPermissionsBlacklist, kPermissionBlacklistEmbargoKey); |
| 224 |
186 // If converting the value fails, stick with the current value. | 225 // If converting the value fails, stick with the current value. |
187 if (base::StringToInt(dismissals_value, &prompt_dismissals) && | 226 if (base::StringToInt(dismissals_before_block_value, |
188 prompt_dismissals > 0) { | 227 &dismissals_before_block) && |
189 g_prompt_dismissals_before_block = prompt_dismissals; | 228 dismissals_before_block > 0) { |
| 229 g_dismissals_before_block = dismissals_before_block; |
190 } | 230 } |
191 if (base::StringToInt(blacklist_embargo_value, &blacklist_embargo_days) && | 231 if (base::StringToInt(ignores_before_block_value, &ignores_before_block) && |
| 232 ignores_before_block > 0) { |
| 233 g_ignores_before_block = ignores_before_block; |
| 234 } |
| 235 if (base::StringToInt(dismissal_embargo_days_value, |
| 236 &dismissal_embargo_days) && |
| 237 dismissal_embargo_days > 0) { |
| 238 g_dismissal_embargo_days = dismissal_embargo_days; |
| 239 } |
| 240 if (base::StringToInt(ignore_embargo_days_value, &ignore_embargo_days) && |
| 241 ignore_embargo_days > 0) { |
| 242 g_ignore_embargo_days = ignore_embargo_days; |
| 243 } |
| 244 if (base::StringToInt(blacklist_embargo_days_value, |
| 245 &blacklist_embargo_days) && |
192 blacklist_embargo_days > 0) { | 246 blacklist_embargo_days > 0) { |
193 g_blacklist_embargo_days = blacklist_embargo_days; | 247 g_blacklist_embargo_days = blacklist_embargo_days; |
194 } | 248 } |
195 if (base::StringToInt(dismissal_embargo_value, &dismissal_embargo_days) && | |
196 dismissal_embargo_days > 0) { | |
197 g_dismissal_embargo_days = dismissal_embargo_days; | |
198 } | |
199 } | 249 } |
200 | 250 |
201 void PermissionDecisionAutoBlocker::CheckSafeBrowsingBlacklist( | 251 void PermissionDecisionAutoBlocker::CheckSafeBrowsingBlacklist( |
202 content::WebContents* web_contents, | 252 content::WebContents* web_contents, |
203 const GURL& request_origin, | 253 const GURL& request_origin, |
204 ContentSettingsType permission, | 254 ContentSettingsType permission, |
205 base::Callback<void(bool)> callback) { | 255 base::Callback<void(bool)> callback) { |
206 DCHECK_EQ(CONTENT_SETTING_ASK, | 256 DCHECK_EQ(CONTENT_SETTING_ASK, |
207 GetEmbargoResult(request_origin, permission).content_setting); | 257 GetEmbargoResult(request_origin, permission).content_setting); |
208 | 258 |
(...skipping 16 matching lines...) Expand all Loading... |
225 | 275 |
226 PermissionResult PermissionDecisionAutoBlocker::GetEmbargoResult( | 276 PermissionResult PermissionDecisionAutoBlocker::GetEmbargoResult( |
227 const GURL& request_origin, | 277 const GURL& request_origin, |
228 ContentSettingsType permission) { | 278 ContentSettingsType permission) { |
229 HostContentSettingsMap* map = | 279 HostContentSettingsMap* map = |
230 HostContentSettingsMapFactory::GetForProfile(profile_); | 280 HostContentSettingsMapFactory::GetForProfile(profile_); |
231 std::unique_ptr<base::DictionaryValue> dict = | 281 std::unique_ptr<base::DictionaryValue> dict = |
232 GetOriginDict(map, request_origin); | 282 GetOriginDict(map, request_origin); |
233 base::DictionaryValue* permission_dict = GetOrCreatePermissionDict( | 283 base::DictionaryValue* permission_dict = GetOrCreatePermissionDict( |
234 dict.get(), PermissionUtil::GetPermissionString(permission)); | 284 dict.get(), PermissionUtil::GetPermissionString(permission)); |
235 double embargo_date = -1; | |
236 | 285 |
237 base::Time current_time = clock_->Now(); | 286 base::Time current_time = clock_->Now(); |
238 if (base::FeatureList::IsEnabled(features::kPermissionsBlacklist) && | 287 if (IsUnderEmbargo(permission_dict, features::kPermissionsBlacklist, |
239 permission_dict->GetDouble(kPermissionBlacklistEmbargoKey, | 288 kPermissionBlacklistEmbargoKey, current_time, |
240 &embargo_date)) { | 289 base::TimeDelta::FromDays(g_blacklist_embargo_days))) { |
241 if (current_time < | 290 return PermissionResult(CONTENT_SETTING_BLOCK, |
242 base::Time::FromInternalValue(embargo_date) + | 291 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 } | 292 } |
248 | 293 |
249 if (base::FeatureList::IsEnabled(features::kBlockPromptsIfDismissedOften) && | 294 if (IsUnderEmbargo(permission_dict, features::kBlockPromptsIfDismissedOften, |
250 permission_dict->GetDouble(kPermissionDismissalEmbargoKey, | 295 kPermissionDismissalEmbargoKey, current_time, |
251 &embargo_date)) { | 296 base::TimeDelta::FromDays(g_dismissal_embargo_days))) { |
252 if (current_time < | 297 return PermissionResult(CONTENT_SETTING_BLOCK, |
253 base::Time::FromInternalValue(embargo_date) + | 298 PermissionStatusSource::MULTIPLE_DISMISSALS); |
254 base::TimeDelta::FromDays(g_dismissal_embargo_days)) { | 299 } |
255 return PermissionResult(CONTENT_SETTING_BLOCK, | 300 |
256 PermissionStatusSource::MULTIPLE_DISMISSALS); | 301 if (IsUnderEmbargo(permission_dict, features::kBlockPromptsIfIgnoredOften, |
257 } | 302 kPermissionIgnoreEmbargoKey, current_time, |
| 303 base::TimeDelta::FromDays(g_ignore_embargo_days))) { |
| 304 return PermissionResult(CONTENT_SETTING_BLOCK, |
| 305 PermissionStatusSource::MULTIPLE_IGNORES); |
258 } | 306 } |
259 | 307 |
260 return PermissionResult(CONTENT_SETTING_ASK, | 308 return PermissionResult(CONTENT_SETTING_ASK, |
261 PermissionStatusSource::UNSPECIFIED); | 309 PermissionStatusSource::UNSPECIFIED); |
262 } | 310 } |
263 | 311 |
264 int PermissionDecisionAutoBlocker::GetDismissCount( | 312 int PermissionDecisionAutoBlocker::GetDismissCount( |
265 const GURL& url, | 313 const GURL& url, |
266 ContentSettingsType permission) { | 314 ContentSettingsType permission) { |
267 return GetActionCount(url, permission, kPromptDismissCountKey, profile_); | 315 return GetActionCount(url, permission, kPromptDismissCountKey, profile_); |
(...skipping 15 matching lines...) Expand all Loading... |
283 // PermissionContextBase::ShouldEmbargoAfterRepeatedDismissals() to specify | 331 // PermissionContextBase::ShouldEmbargoAfterRepeatedDismissals() to specify |
284 // if a permission is opted in. This is difficult right now because: | 332 // if a permission is opted in. This is difficult right now because: |
285 // 1. PermissionQueueController needs to call this method at a point where it | 333 // 1. PermissionQueueController needs to call this method at a point where it |
286 // does not have a PermissionContextBase available | 334 // does not have a PermissionContextBase available |
287 // 2. Not calling RecordDismissAndEmbargo means no repeated dismissal metrics | 335 // 2. Not calling RecordDismissAndEmbargo means no repeated dismissal metrics |
288 // are recorded | 336 // are recorded |
289 // For now, only plugins are explicitly opted out. We should think about how | 337 // For now, only plugins are explicitly opted out. We should think about how |
290 // to make this nicer once PermissionQueueController is removed. | 338 // to make this nicer once PermissionQueueController is removed. |
291 if (base::FeatureList::IsEnabled(features::kBlockPromptsIfDismissedOften) && | 339 if (base::FeatureList::IsEnabled(features::kBlockPromptsIfDismissedOften) && |
292 permission != CONTENT_SETTINGS_TYPE_PLUGINS && | 340 permission != CONTENT_SETTINGS_TYPE_PLUGINS && |
293 current_dismissal_count >= g_prompt_dismissals_before_block) { | 341 current_dismissal_count >= g_dismissals_before_block) { |
294 PlaceUnderEmbargo(url, permission, kPermissionDismissalEmbargoKey); | 342 PlaceUnderEmbargo(url, permission, kPermissionDismissalEmbargoKey); |
295 return true; | 343 return true; |
296 } | 344 } |
297 return false; | 345 return false; |
298 } | 346 } |
299 | 347 |
300 int PermissionDecisionAutoBlocker::RecordIgnore( | 348 bool PermissionDecisionAutoBlocker::RecordIgnoreAndEmbargo( |
301 const GURL& url, | 349 const GURL& url, |
302 ContentSettingsType permission) { | 350 ContentSettingsType permission) { |
303 return RecordActionInWebsiteSettings(url, permission, kPromptIgnoreCountKey, | 351 int current_ignore_count = RecordActionInWebsiteSettings( |
304 profile_); | 352 url, permission, kPromptIgnoreCountKey, profile_); |
| 353 |
| 354 if (base::FeatureList::IsEnabled(features::kBlockPromptsIfIgnoredOften) && |
| 355 permission != CONTENT_SETTINGS_TYPE_PLUGINS && |
| 356 current_ignore_count >= g_ignores_before_block) { |
| 357 PlaceUnderEmbargo(url, permission, kPermissionIgnoreEmbargoKey); |
| 358 return true; |
| 359 } |
| 360 return false; |
305 } | 361 } |
306 | 362 |
307 void PermissionDecisionAutoBlocker::RemoveCountsByUrl( | 363 void PermissionDecisionAutoBlocker::RemoveCountsByUrl( |
308 base::Callback<bool(const GURL& url)> filter) { | 364 base::Callback<bool(const GURL& url)> filter) { |
309 HostContentSettingsMap* map = | 365 HostContentSettingsMap* map = |
310 HostContentSettingsMapFactory::GetForProfile(profile_); | 366 HostContentSettingsMapFactory::GetForProfile(profile_); |
311 | 367 |
312 std::unique_ptr<ContentSettingsForOneType> settings( | 368 std::unique_ptr<ContentSettingsForOneType> settings( |
313 new ContentSettingsForOneType); | 369 new ContentSettingsForOneType); |
314 map->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PERMISSION_AUTOBLOCKER_DATA, | 370 map->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PERMISSION_AUTOBLOCKER_DATA, |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
373 scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager, | 429 scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager, |
374 int timeout) { | 430 int timeout) { |
375 db_manager_ = db_manager; | 431 db_manager_ = db_manager; |
376 safe_browsing_timeout_ = timeout; | 432 safe_browsing_timeout_ = timeout; |
377 } | 433 } |
378 | 434 |
379 void PermissionDecisionAutoBlocker::SetClockForTesting( | 435 void PermissionDecisionAutoBlocker::SetClockForTesting( |
380 std::unique_ptr<base::Clock> clock) { | 436 std::unique_ptr<base::Clock> clock) { |
381 clock_ = std::move(clock); | 437 clock_ = std::move(clock); |
382 } | 438 } |
OLD | NEW |