Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(594)

Side by Side Diff: chrome/browser/permissions/permission_decision_auto_blocker.cc

Issue 2790493002: Implement permissions embargo for prompts which are repeatedly ignored. (Closed)
Patch Set: Not for plugins Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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, &current_count); 116 permission_dict->GetInteger(key, &current_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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698