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" |
11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
12 #include "base/values.h" | 12 #include "base/values.h" |
13 #include "chrome/browser/browser_process.h" | 13 #include "chrome/browser/browser_process.h" |
14 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" | 14 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" |
15 #include "chrome/browser/permissions/permission_blacklist_client.h" | 15 #include "chrome/browser/permissions/permission_blacklist_client.h" |
16 #include "chrome/browser/permissions/permission_util.h" | 16 #include "chrome/browser/permissions/permission_util.h" |
17 #include "chrome/browser/profiles/incognito_helpers.h" | 17 #include "chrome/browser/profiles/incognito_helpers.h" |
18 #include "chrome/browser/profiles/profile.h" | 18 #include "chrome/browser/profiles/profile.h" |
19 #include "chrome/browser/safe_browsing/safe_browsing_service.h" | 19 #include "chrome/browser/safe_browsing/safe_browsing_service.h" |
20 #include "chrome/common/chrome_features.h" | 20 #include "chrome/common/chrome_features.h" |
21 #include "components/content_settings/core/browser/host_content_settings_map.h" | 21 #include "components/content_settings/core/browser/host_content_settings_map.h" |
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/permission_type.h" | |
26 #include "content/public/browser/web_contents.h" | 25 #include "content/public/browser/web_contents.h" |
27 #include "url/gurl.h" | 26 #include "url/gurl.h" |
28 | 27 |
29 namespace { | 28 namespace { |
30 | 29 |
31 // 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 |
32 // from an origin before it is automatically blocked. | 31 // from an origin before it is automatically blocked. |
33 int g_prompt_dismissals_before_block = 3; | 32 int g_prompt_dismissals_before_block = 3; |
34 | 33 |
35 // The number of days that an origin will stay under embargo for a requested | 34 // The number of days that an origin will stay under embargo for a requested |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 &permission_dict)) { | 66 &permission_dict)) { |
68 permission_dict = new base::DictionaryValue(); | 67 permission_dict = new base::DictionaryValue(); |
69 origin_dict->SetWithoutPathExpansion(permission, | 68 origin_dict->SetWithoutPathExpansion(permission, |
70 base::WrapUnique(permission_dict)); | 69 base::WrapUnique(permission_dict)); |
71 } | 70 } |
72 | 71 |
73 return permission_dict; | 72 return permission_dict; |
74 } | 73 } |
75 | 74 |
76 int RecordActionInWebsiteSettings(const GURL& url, | 75 int RecordActionInWebsiteSettings(const GURL& url, |
77 content::PermissionType permission, | 76 ContentSettingsType permission, |
78 const char* key, | 77 const char* key, |
79 Profile* profile) { | 78 Profile* profile) { |
80 HostContentSettingsMap* map = | 79 HostContentSettingsMap* map = |
81 HostContentSettingsMapFactory::GetForProfile(profile); | 80 HostContentSettingsMapFactory::GetForProfile(profile); |
82 std::unique_ptr<base::DictionaryValue> dict = GetOriginDict(map, url); | 81 std::unique_ptr<base::DictionaryValue> dict = GetOriginDict(map, url); |
83 | 82 |
84 base::DictionaryValue* permission_dict = GetOrCreatePermissionDict( | 83 base::DictionaryValue* permission_dict = GetOrCreatePermissionDict( |
85 dict.get(), PermissionUtil::GetPermissionString(permission)); | 84 dict.get(), PermissionUtil::GetPermissionString(permission)); |
86 | 85 |
87 int current_count = 0; | 86 int current_count = 0; |
88 permission_dict->GetInteger(key, ¤t_count); | 87 permission_dict->GetInteger(key, ¤t_count); |
89 permission_dict->SetInteger(key, ++current_count); | 88 permission_dict->SetInteger(key, ++current_count); |
90 | 89 |
91 map->SetWebsiteSettingDefaultScope( | 90 map->SetWebsiteSettingDefaultScope( |
92 url, GURL(), CONTENT_SETTINGS_TYPE_PERMISSION_AUTOBLOCKER_DATA, | 91 url, GURL(), CONTENT_SETTINGS_TYPE_PERMISSION_AUTOBLOCKER_DATA, |
93 std::string(), std::move(dict)); | 92 std::string(), std::move(dict)); |
94 | 93 |
95 return current_count; | 94 return current_count; |
96 } | 95 } |
97 | 96 |
98 int GetActionCount(const GURL& url, | 97 int GetActionCount(const GURL& url, |
99 content::PermissionType permission, | 98 ContentSettingsType permission, |
100 const char* key, | 99 const char* key, |
101 Profile* profile) { | 100 Profile* profile) { |
102 HostContentSettingsMap* map = | 101 HostContentSettingsMap* map = |
103 HostContentSettingsMapFactory::GetForProfile(profile); | 102 HostContentSettingsMapFactory::GetForProfile(profile); |
104 std::unique_ptr<base::DictionaryValue> dict = GetOriginDict(map, url); | 103 std::unique_ptr<base::DictionaryValue> dict = GetOriginDict(map, url); |
105 base::DictionaryValue* permission_dict = GetOrCreatePermissionDict( | 104 base::DictionaryValue* permission_dict = GetOrCreatePermissionDict( |
106 dict.get(), PermissionUtil::GetPermissionString(permission)); | 105 dict.get(), PermissionUtil::GetPermissionString(permission)); |
107 | 106 |
108 int current_count = 0; | 107 int current_count = 0; |
109 permission_dict->GetInteger(key, ¤t_count); | 108 permission_dict->GetInteger(key, ¤t_count); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 if (origin.is_valid() && filter.Run(origin)) { | 198 if (origin.is_valid() && filter.Run(origin)) { |
200 map->SetWebsiteSettingDefaultScope( | 199 map->SetWebsiteSettingDefaultScope( |
201 origin, GURL(), CONTENT_SETTINGS_TYPE_PERMISSION_AUTOBLOCKER_DATA, | 200 origin, GURL(), CONTENT_SETTINGS_TYPE_PERMISSION_AUTOBLOCKER_DATA, |
202 std::string(), nullptr); | 201 std::string(), nullptr); |
203 } | 202 } |
204 } | 203 } |
205 } | 204 } |
206 | 205 |
207 int PermissionDecisionAutoBlocker::GetDismissCount( | 206 int PermissionDecisionAutoBlocker::GetDismissCount( |
208 const GURL& url, | 207 const GURL& url, |
209 content::PermissionType permission) { | 208 ContentSettingsType permission) { |
210 return GetActionCount(url, permission, kPromptDismissCountKey, profile_); | 209 return GetActionCount(url, permission, kPromptDismissCountKey, profile_); |
211 } | 210 } |
212 | 211 |
213 int PermissionDecisionAutoBlocker::GetIgnoreCount( | 212 int PermissionDecisionAutoBlocker::GetIgnoreCount( |
214 const GURL& url, | 213 const GURL& url, |
215 content::PermissionType permission) { | 214 ContentSettingsType permission) { |
216 return GetActionCount(url, permission, kPromptIgnoreCountKey, profile_); | 215 return GetActionCount(url, permission, kPromptIgnoreCountKey, profile_); |
217 } | 216 } |
218 | 217 |
219 bool PermissionDecisionAutoBlocker::RecordDismissAndEmbargo( | 218 bool PermissionDecisionAutoBlocker::RecordDismissAndEmbargo( |
220 const GURL& url, | 219 const GURL& url, |
221 content::PermissionType permission) { | 220 ContentSettingsType permission) { |
222 int current_dismissal_count = RecordActionInWebsiteSettings( | 221 int current_dismissal_count = RecordActionInWebsiteSettings( |
223 url, permission, kPromptDismissCountKey, profile_); | 222 url, permission, kPromptDismissCountKey, profile_); |
224 | 223 |
225 if (base::FeatureList::IsEnabled(features::kBlockPromptsIfDismissedOften) && | 224 if (base::FeatureList::IsEnabled(features::kBlockPromptsIfDismissedOften) && |
226 current_dismissal_count >= g_prompt_dismissals_before_block) { | 225 current_dismissal_count >= g_prompt_dismissals_before_block) { |
227 PlaceUnderEmbargo(permission, url, kPermissionDismissalEmbargoKey); | 226 PlaceUnderEmbargo(permission, url, kPermissionDismissalEmbargoKey); |
228 return true; | 227 return true; |
229 } | 228 } |
230 return false; | 229 return false; |
231 } | 230 } |
232 | 231 |
233 int PermissionDecisionAutoBlocker::RecordIgnore( | 232 int PermissionDecisionAutoBlocker::RecordIgnore( |
234 const GURL& url, | 233 const GURL& url, |
235 content::PermissionType permission) { | 234 ContentSettingsType permission) { |
236 return RecordActionInWebsiteSettings(url, permission, kPromptIgnoreCountKey, | 235 return RecordActionInWebsiteSettings(url, permission, kPromptIgnoreCountKey, |
237 profile_); | 236 profile_); |
238 } | 237 } |
239 | 238 |
240 // static | 239 // static |
241 void PermissionDecisionAutoBlocker::UpdateFromVariations() { | 240 void PermissionDecisionAutoBlocker::UpdateFromVariations() { |
242 int prompt_dismissals = -1; | 241 int prompt_dismissals = -1; |
243 int blacklist_embargo_days = -1; | 242 int blacklist_embargo_days = -1; |
244 int dismissal_embargo_days = -1; | 243 int dismissal_embargo_days = -1; |
245 std::string dismissals_value = variations::GetVariationParamValueByFeature( | 244 std::string dismissals_value = variations::GetVariationParamValueByFeature( |
(...skipping 14 matching lines...) Expand all Loading... |
260 blacklist_embargo_days > 0) { | 259 blacklist_embargo_days > 0) { |
261 g_blacklist_embargo_days = blacklist_embargo_days; | 260 g_blacklist_embargo_days = blacklist_embargo_days; |
262 } | 261 } |
263 if (base::StringToInt(dismissal_embargo_value, &dismissal_embargo_days) && | 262 if (base::StringToInt(dismissal_embargo_value, &dismissal_embargo_days) && |
264 dismissal_embargo_days > 0) { | 263 dismissal_embargo_days > 0) { |
265 g_dismissal_embargo_days = dismissal_embargo_days; | 264 g_dismissal_embargo_days = dismissal_embargo_days; |
266 } | 265 } |
267 } | 266 } |
268 | 267 |
269 void PermissionDecisionAutoBlocker::UpdateEmbargoedStatus( | 268 void PermissionDecisionAutoBlocker::UpdateEmbargoedStatus( |
270 content::PermissionType permission, | 269 ContentSettingsType permission, |
271 const GURL& request_origin, | 270 const GURL& request_origin, |
272 content::WebContents* web_contents, | 271 content::WebContents* web_contents, |
273 base::Callback<void(bool)> callback) { | 272 base::Callback<void(bool)> callback) { |
274 // Check if origin is currently under embargo for the requested permission. | 273 // Check if origin is currently under embargo for the requested permission. |
275 if (IsUnderEmbargo(permission, request_origin)) { | 274 if (IsUnderEmbargo(permission, request_origin)) { |
276 callback.Run(true /* permission_blocked */); | 275 callback.Run(true /* permission_blocked */); |
277 return; | 276 return; |
278 } | 277 } |
279 | 278 |
280 if (base::FeatureList::IsEnabled(features::kPermissionsBlacklist) && | 279 if (base::FeatureList::IsEnabled(features::kPermissionsBlacklist) && |
281 db_manager_) { | 280 db_manager_) { |
282 // The CheckSafeBrowsingResult callback won't be called if the profile is | 281 // The CheckSafeBrowsingResult callback won't be called if the profile is |
283 // destroyed before a result is received. In that case this object will have | 282 // destroyed before a result is received. In that case this object will have |
284 // been destroyed by that point. | 283 // been destroyed by that point. |
285 PermissionBlacklistClient::CheckSafeBrowsingBlacklist( | 284 PermissionBlacklistClient::CheckSafeBrowsingBlacklist( |
286 db_manager_, permission, request_origin, web_contents, | 285 db_manager_, permission, request_origin, web_contents, |
287 safe_browsing_timeout_, | 286 safe_browsing_timeout_, |
288 base::Bind(&PermissionDecisionAutoBlocker::CheckSafeBrowsingResult, | 287 base::Bind(&PermissionDecisionAutoBlocker::CheckSafeBrowsingResult, |
289 base::Unretained(this), permission, request_origin, | 288 base::Unretained(this), permission, request_origin, |
290 callback)); | 289 callback)); |
291 return; | 290 return; |
292 } | 291 } |
293 | 292 |
294 callback.Run(false /* permission blocked */); | 293 callback.Run(false /* permission blocked */); |
295 } | 294 } |
296 | 295 |
297 bool PermissionDecisionAutoBlocker::IsUnderEmbargo( | 296 bool PermissionDecisionAutoBlocker::IsUnderEmbargo( |
298 content::PermissionType permission, | 297 ContentSettingsType permission, |
299 const GURL& request_origin) { | 298 const GURL& request_origin) { |
300 HostContentSettingsMap* map = | 299 HostContentSettingsMap* map = |
301 HostContentSettingsMapFactory::GetForProfile(profile_); | 300 HostContentSettingsMapFactory::GetForProfile(profile_); |
302 std::unique_ptr<base::DictionaryValue> dict = | 301 std::unique_ptr<base::DictionaryValue> dict = |
303 GetOriginDict(map, request_origin); | 302 GetOriginDict(map, request_origin); |
304 base::DictionaryValue* permission_dict = GetOrCreatePermissionDict( | 303 base::DictionaryValue* permission_dict = GetOrCreatePermissionDict( |
305 dict.get(), PermissionUtil::GetPermissionString(permission)); | 304 dict.get(), PermissionUtil::GetPermissionString(permission)); |
306 double embargo_date = -1; | 305 double embargo_date = -1; |
307 bool is_under_dismiss_embargo = false; | 306 bool is_under_dismiss_embargo = false; |
308 bool is_under_blacklist_embargo = false; | 307 bool is_under_blacklist_embargo = false; |
(...skipping 16 matching lines...) Expand all Loading... |
325 base::TimeDelta::FromDays(g_dismissal_embargo_days)) { | 324 base::TimeDelta::FromDays(g_dismissal_embargo_days)) { |
326 is_under_dismiss_embargo = true; | 325 is_under_dismiss_embargo = true; |
327 } | 326 } |
328 } | 327 } |
329 | 328 |
330 // If either embargo is still in effect, return true. | 329 // If either embargo is still in effect, return true. |
331 return is_under_dismiss_embargo || is_under_blacklist_embargo; | 330 return is_under_dismiss_embargo || is_under_blacklist_embargo; |
332 } | 331 } |
333 | 332 |
334 void PermissionDecisionAutoBlocker::CheckSafeBrowsingResult( | 333 void PermissionDecisionAutoBlocker::CheckSafeBrowsingResult( |
335 content::PermissionType permission, | 334 ContentSettingsType permission, |
336 const GURL& request_origin, | 335 const GURL& request_origin, |
337 base::Callback<void(bool)> callback, | 336 base::Callback<void(bool)> callback, |
338 bool should_be_embargoed) { | 337 bool should_be_embargoed) { |
339 if (should_be_embargoed) { | 338 if (should_be_embargoed) { |
340 // Requesting site is blacklisted for this permission, update the content | 339 // Requesting site is blacklisted for this permission, update the content |
341 // setting to place it under embargo. | 340 // setting to place it under embargo. |
342 PlaceUnderEmbargo(permission, request_origin, | 341 PlaceUnderEmbargo(permission, request_origin, |
343 kPermissionBlacklistEmbargoKey); | 342 kPermissionBlacklistEmbargoKey); |
344 } | 343 } |
345 callback.Run(should_be_embargoed /* permission blocked */); | 344 callback.Run(should_be_embargoed /* permission blocked */); |
346 } | 345 } |
347 | 346 |
348 void PermissionDecisionAutoBlocker::PlaceUnderEmbargo( | 347 void PermissionDecisionAutoBlocker::PlaceUnderEmbargo( |
349 content::PermissionType permission, | 348 ContentSettingsType permission, |
350 const GURL& request_origin, | 349 const GURL& request_origin, |
351 const char* key) { | 350 const char* key) { |
352 HostContentSettingsMap* map = | 351 HostContentSettingsMap* map = |
353 HostContentSettingsMapFactory::GetForProfile(profile_); | 352 HostContentSettingsMapFactory::GetForProfile(profile_); |
354 std::unique_ptr<base::DictionaryValue> dict = | 353 std::unique_ptr<base::DictionaryValue> dict = |
355 GetOriginDict(map, request_origin); | 354 GetOriginDict(map, request_origin); |
356 base::DictionaryValue* permission_dict = GetOrCreatePermissionDict( | 355 base::DictionaryValue* permission_dict = GetOrCreatePermissionDict( |
357 dict.get(), PermissionUtil::GetPermissionString(permission)); | 356 dict.get(), PermissionUtil::GetPermissionString(permission)); |
358 permission_dict->SetDouble(key, clock_->Now().ToInternalValue()); | 357 permission_dict->SetDouble(key, clock_->Now().ToInternalValue()); |
359 map->SetWebsiteSettingDefaultScope( | 358 map->SetWebsiteSettingDefaultScope( |
360 request_origin, GURL(), CONTENT_SETTINGS_TYPE_PERMISSION_AUTOBLOCKER_DATA, | 359 request_origin, GURL(), CONTENT_SETTINGS_TYPE_PERMISSION_AUTOBLOCKER_DATA, |
361 std::string(), std::move(dict)); | 360 std::string(), std::move(dict)); |
362 } | 361 } |
363 | 362 |
364 void PermissionDecisionAutoBlocker:: | 363 void PermissionDecisionAutoBlocker:: |
365 SetSafeBrowsingDatabaseManagerAndTimeoutForTesting( | 364 SetSafeBrowsingDatabaseManagerAndTimeoutForTesting( |
366 scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager, | 365 scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager, |
367 int timeout) { | 366 int timeout) { |
368 db_manager_ = db_manager; | 367 db_manager_ = db_manager; |
369 safe_browsing_timeout_ = timeout; | 368 safe_browsing_timeout_ = timeout; |
370 } | 369 } |
371 | 370 |
372 void PermissionDecisionAutoBlocker::SetClockForTesting( | 371 void PermissionDecisionAutoBlocker::SetClockForTesting( |
373 std::unique_ptr<base::Clock> clock) { | 372 std::unique_ptr<base::Clock> clock) { |
374 clock_ = std::move(clock); | 373 clock_ = std::move(clock); |
375 } | 374 } |
OLD | NEW |