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

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

Issue 2622983003: Implement embargo in PermissionDecisionAutoBlocker (Closed)
Patch Set: Block on nth dismissal and tests Created 3 years, 11 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/logging.h" 10 #include "base/logging.h"
11 #include "base/memory/ptr_util.h" 11 #include "base/memory/ptr_util.h"
12 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
13 #include "base/time/time.h"
13 #include "base/values.h" 14 #include "base/values.h"
14 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" 15 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
16 #include "chrome/browser/permissions/permission_blacklist_client.h"
15 #include "chrome/browser/permissions/permission_util.h" 17 #include "chrome/browser/permissions/permission_util.h"
16 #include "chrome/common/chrome_features.h" 18 #include "chrome/common/chrome_features.h"
17 #include "components/content_settings/core/browser/host_content_settings_map.h" 19 #include "components/content_settings/core/browser/host_content_settings_map.h"
18 #include "components/variations/variations_associated_data.h" 20 #include "components/variations/variations_associated_data.h"
19 #include "content/public/browser/permission_type.h" 21 #include "content/public/browser/permission_type.h"
22 #include "content/public/browser/web_contents.h"
20 #include "url/gurl.h" 23 #include "url/gurl.h"
21 24
22 namespace { 25 namespace {
23 26
24 // The number of times that users may explicitly dismiss a permission prompt 27 // The number of times that users may explicitly dismiss a permission prompt
25 // from an origin before it is automatically blocked. 28 // from an origin before it is automatically blocked.
26 int g_prompt_dismissals_before_block = 3; 29 int g_prompt_dismissals_before_block = 3;
27 30
31 // The number of days that an origin will stay under embargo for a requested
32 // permission due to blacklisting.
33 int g_blacklist_embargo_days = 7;
34
35 // The number of days that an origin will stay under embargo for a requested
36 // permission due to repeated dismissals.
37 int g_dismissal_embargo_days = 7;
38
28 std::unique_ptr<base::DictionaryValue> GetOriginDict( 39 std::unique_ptr<base::DictionaryValue> GetOriginDict(
29 HostContentSettingsMap* settings, 40 HostContentSettingsMap* settings,
30 const GURL& origin_url) { 41 const GURL& origin_url) {
31 std::unique_ptr<base::DictionaryValue> dict = 42 std::unique_ptr<base::DictionaryValue> dict =
32 base::DictionaryValue::From(settings->GetWebsiteSetting( 43 base::DictionaryValue::From(settings->GetWebsiteSetting(
33 origin_url, origin_url, 44 origin_url, GURL(), CONTENT_SETTINGS_TYPE_PROMPT_NO_DECISION_COUNT,
34 CONTENT_SETTINGS_TYPE_PROMPT_NO_DECISION_COUNT, std::string(), 45 std::string(), nullptr));
35 nullptr));
36 if (!dict) 46 if (!dict)
37 return base::MakeUnique<base::DictionaryValue>(); 47 return base::MakeUnique<base::DictionaryValue>();
38 48
39 return dict; 49 return dict;
40 } 50 }
41 51
42 base::DictionaryValue* GetOrCreatePermissionDict( 52 base::DictionaryValue* GetOrCreatePermissionDict(
43 base::DictionaryValue* origin_dict, 53 base::DictionaryValue* origin_dict,
44 const std::string& permission) { 54 const std::string& permission) {
45 base::DictionaryValue* permission_dict = nullptr; 55 base::DictionaryValue* permission_dict = nullptr;
(...skipping 29 matching lines...) Expand all
75 return current_count; 85 return current_count;
76 } 86 }
77 87
78 int GetActionCount(const GURL& url, 88 int GetActionCount(const GURL& url,
79 content::PermissionType permission, 89 content::PermissionType permission,
80 const char* key, 90 const char* key,
81 Profile* profile) { 91 Profile* profile) {
82 HostContentSettingsMap* map = 92 HostContentSettingsMap* map =
83 HostContentSettingsMapFactory::GetForProfile(profile); 93 HostContentSettingsMapFactory::GetForProfile(profile);
84 std::unique_ptr<base::DictionaryValue> dict = GetOriginDict(map, url); 94 std::unique_ptr<base::DictionaryValue> dict = GetOriginDict(map, url);
85
86 base::DictionaryValue* permission_dict = GetOrCreatePermissionDict( 95 base::DictionaryValue* permission_dict = GetOrCreatePermissionDict(
87 dict.get(), PermissionUtil::GetPermissionString(permission)); 96 dict.get(), PermissionUtil::GetPermissionString(permission));
88 97
89 int current_count = 0; 98 int current_count = 0;
90 permission_dict->GetInteger(key, &current_count); 99 permission_dict->GetInteger(key, &current_count);
91 return current_count; 100 return current_count;
92 } 101 }
93 102
103 void PlaceUnderEmbargo(content::PermissionType permission,
104 const GURL& request_origin,
105 HostContentSettingsMap* map,
106 base::Time current_time,
107 const char* key) {
108 std::unique_ptr<base::DictionaryValue> dict =
109 GetOriginDict(map, request_origin);
110 base::DictionaryValue* permission_dict = GetOrCreatePermissionDict(
111 dict.get(), PermissionUtil::GetPermissionString(permission));
112 permission_dict->SetDouble(key, current_time.ToInternalValue());
113 map->SetWebsiteSettingDefaultScope(
114 request_origin, GURL(), CONTENT_SETTINGS_TYPE_PROMPT_NO_DECISION_COUNT,
115 std::string(), std::move(dict));
116 }
117
94 } // namespace 118 } // namespace
95 119
96 // static 120 // static
97 const char PermissionDecisionAutoBlocker::kPromptDismissCountKey[] = 121 const char PermissionDecisionAutoBlocker::kPromptDismissCountKey[] =
98 "dismiss_count"; 122 "dismiss_count";
99 123
100 // static 124 // static
101 const char PermissionDecisionAutoBlocker::kPromptIgnoreCountKey[] = 125 const char PermissionDecisionAutoBlocker::kPromptIgnoreCountKey[] =
102 "ignore_count"; 126 "ignore_count";
103 127
104 // static 128 // static
129 const char PermissionDecisionAutoBlocker::kPermissionBlacklistEmbargoKey[] =
130 "blacklisting_embargo_days";
131
132 // static
133 const char PermissionDecisionAutoBlocker::kPermissionDismissalEmbargoKey[] =
134 "dismissal_embargo_days";
135
136 // static
105 void PermissionDecisionAutoBlocker::RemoveCountsByUrl( 137 void PermissionDecisionAutoBlocker::RemoveCountsByUrl(
106 Profile* profile, 138 Profile* profile,
107 base::Callback<bool(const GURL& url)> filter) { 139 base::Callback<bool(const GURL& url)> filter) {
108 HostContentSettingsMap* map = 140 HostContentSettingsMap* map =
109 HostContentSettingsMapFactory::GetForProfile(profile); 141 HostContentSettingsMapFactory::GetForProfile(profile);
110 142
111 std::unique_ptr<ContentSettingsForOneType> settings( 143 std::unique_ptr<ContentSettingsForOneType> settings(
112 new ContentSettingsForOneType); 144 new ContentSettingsForOneType);
113 map->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PROMPT_NO_DECISION_COUNT, 145 map->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PROMPT_NO_DECISION_COUNT,
114 std::string(), settings.get()); 146 std::string(), settings.get());
(...skipping 19 matching lines...) Expand all
134 166
135 // static 167 // static
136 int PermissionDecisionAutoBlocker::GetIgnoreCount( 168 int PermissionDecisionAutoBlocker::GetIgnoreCount(
137 const GURL& url, 169 const GURL& url,
138 content::PermissionType permission, 170 content::PermissionType permission,
139 Profile* profile) { 171 Profile* profile) {
140 return GetActionCount(url, permission, kPromptIgnoreCountKey, profile); 172 return GetActionCount(url, permission, kPromptIgnoreCountKey, profile);
141 } 173 }
142 174
143 // static 175 // static
144 int PermissionDecisionAutoBlocker::RecordDismiss( 176 bool PermissionDecisionAutoBlocker::RecordDismissAndEmbargo(
145 const GURL& url, 177 const GURL& url,
146 content::PermissionType permission, 178 content::PermissionType permission,
147 Profile* profile) { 179 Profile* profile,
148 return RecordActionInWebsiteSettings(url, permission, kPromptDismissCountKey, 180 base::Time current_time) {
149 profile); 181 int current_dismissal_count = RecordActionInWebsiteSettings(
182 url, permission, kPromptDismissCountKey, profile);
183 if (base::FeatureList::IsEnabled(features::kBlockPromptsIfDismissedOften) &&
184 current_dismissal_count >= g_prompt_dismissals_before_block) {
185 HostContentSettingsMap* map =
186 HostContentSettingsMapFactory::GetForProfile(profile);
187 PlaceUnderEmbargo(permission, url, map, current_time,
188 kPermissionDismissalEmbargoKey);
189 return true;
190 }
191 return false;
150 } 192 }
151 193
152 // static 194 // static
153 int PermissionDecisionAutoBlocker::RecordIgnore( 195 int PermissionDecisionAutoBlocker::RecordIgnore(
154 const GURL& url, 196 const GURL& url,
155 content::PermissionType permission, 197 content::PermissionType permission,
156 Profile* profile) { 198 Profile* profile) {
157 return RecordActionInWebsiteSettings(url, permission, kPromptIgnoreCountKey, 199 return RecordActionInWebsiteSettings(url, permission, kPromptIgnoreCountKey,
158 profile); 200 profile);
159 } 201 }
160 202
161 // static 203 // static
162 bool PermissionDecisionAutoBlocker::ShouldChangeDismissalToBlock( 204 bool PermissionDecisionAutoBlocker::ShouldChangeDismissalToBlock(
163 const GURL& url, 205 const GURL& url,
164 content::PermissionType permission, 206 content::PermissionType permission,
165 Profile* profile) { 207 Profile* profile) {
166 int current_dismissal_count = RecordDismiss(url, permission, profile); 208 int current_dismissal_count =
209 RecordDismissAndEmbargo(url, permission, profile, base::Time::Now());
167 210
168 if (!base::FeatureList::IsEnabled(features::kBlockPromptsIfDismissedOften)) 211 if (!base::FeatureList::IsEnabled(features::kBlockPromptsIfDismissedOften))
169 return false; 212 return false;
170 213
171 return current_dismissal_count >= g_prompt_dismissals_before_block; 214 return current_dismissal_count >= g_prompt_dismissals_before_block;
172 } 215 }
173 216
174 // static 217 // static
175 void PermissionDecisionAutoBlocker::UpdateFromVariations() { 218 void PermissionDecisionAutoBlocker::UpdateFromVariations() {
176 int prompt_dismissals = -1; 219 int prompt_dismissals = -1;
177 std::string value = variations::GetVariationParamValueByFeature( 220 int blacklist_embargo_days = -1;
221 int dismissal_embargo_days = -1;
222 std::string dismissals_value = variations::GetVariationParamValueByFeature(
178 features::kBlockPromptsIfDismissedOften, kPromptDismissCountKey); 223 features::kBlockPromptsIfDismissedOften, kPromptDismissCountKey);
224 std::string blacklist_embargo_value =
225 variations::GetVariationParamValueByFeature(
226 features::kPermissionsBlacklist, kPermissionBlacklistEmbargoKey);
227 std::string dismissal_embargo_value =
228 variations::GetVariationParamValueByFeature(
229 features::kBlockPromptsIfDismissedOften,
230 kPermissionDismissalEmbargoKey);
231 // If converting the value fails, stick with the current value.
232 if (base::StringToInt(dismissals_value, &prompt_dismissals) &&
233 prompt_dismissals > 0) {
234 g_prompt_dismissals_before_block = prompt_dismissals;
235 }
236 if (base::StringToInt(blacklist_embargo_value, &blacklist_embargo_days) &&
237 blacklist_embargo_days > 0) {
238 g_blacklist_embargo_days = blacklist_embargo_days;
239 }
240 if (base::StringToInt(dismissal_embargo_value, &dismissal_embargo_days) &&
241 dismissal_embargo_days > 0) {
242 g_dismissal_embargo_days = dismissal_embargo_days;
243 }
244 }
179 245
180 // If converting the value fails, stick with the current value. 246 // static
181 if (base::StringToInt(value, &prompt_dismissals) && prompt_dismissals > 0) 247 // TODO(meredithl): Have PermissionDecisionAutoBlocker handle the database
182 g_prompt_dismissals_before_block = prompt_dismissals; 248 // manager, rather than passing it in.
249 void PermissionDecisionAutoBlocker::UpdateEmbargoedStatus(
250 scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager,
251 content::PermissionType permission,
252 const GURL& request_origin,
253 content::WebContents* web_contents,
254 int timeout,
255 Profile* profile,
256 base::Time current_time,
257 base::Callback<void(bool)> callback) {
258 // Check if origin is currently under embargo for the requested permission.
259 if (IsUnderEmbargo(permission, profile, request_origin, current_time)) {
260 callback.Run(true /* permission_blocked */);
261 return;
262 }
263
264 if (base::FeatureList::IsEnabled(features::kPermissionsBlacklist) &&
265 db_manager) {
266 PermissionBlacklistClient::CheckSafeBrowsingBlacklist(
267 db_manager, permission, request_origin, web_contents, timeout,
268 base::Bind(&PermissionDecisionAutoBlocker::CheckSafeBrowsingResult,
269 permission, profile, request_origin, current_time,
270 callback));
271 }
272
273 callback.Run(false /* permission blocked */);
183 } 274 }
275
276 // static
277 bool PermissionDecisionAutoBlocker::IsUnderEmbargo(
278 content::PermissionType permission,
279 Profile* profile,
280 const GURL& request_origin,
281 base::Time current_time) {
282 HostContentSettingsMap* map =
283 HostContentSettingsMapFactory::GetForProfile(profile);
284 std::unique_ptr<base::DictionaryValue> dict =
285 GetOriginDict(map, request_origin);
286 base::DictionaryValue* permission_dict = GetOrCreatePermissionDict(
287 dict.get(), PermissionUtil::GetPermissionString(permission));
288 double embargo_date = -1;
289 bool is_under_dismiss_embargo = false, is_under_blacklist_embargo = false;
raymes 2017/01/18 23:35:00 nit: Put each declaration on a new line.
meredithl 2017/01/19 02:11:43 Done.
290 if (base::FeatureList::IsEnabled(features::kPermissionsBlacklist) &&
291 permission_dict->GetDouble(kPermissionBlacklistEmbargoKey,
292 &embargo_date)) {
293 if (current_time <
294 base::Time::FromInternalValue(embargo_date) +
295 base::TimeDelta::FromDays(g_blacklist_embargo_days)) {
296 is_under_blacklist_embargo = true;
297 }
298 }
299
300 if (base::FeatureList::IsEnabled(features::kBlockPromptsIfDismissedOften) &&
301 permission_dict->GetDouble(kPermissionDismissalEmbargoKey,
302 &embargo_date)) {
303 if (current_time <
304 base::Time::FromInternalValue(embargo_date) +
305 base::TimeDelta::FromDays(g_dismissal_embargo_days)) {
306 is_under_dismiss_embargo = true;
307 }
308 }
309 // If either embargoes are still in effect, return true.
raymes 2017/01/18 23:35:00 nit: // If either of the embargoes is still in eff
meredithl 2017/01/19 02:11:43 Done.
310 return is_under_dismiss_embargo || is_under_blacklist_embargo;
311 }
312
313 // static
314 void PermissionDecisionAutoBlocker::CheckSafeBrowsingResult(
315 content::PermissionType permission,
316 Profile* profile,
317 const GURL& request_origin,
318 base::Time current_time,
319 base::Callback<void(bool)> callback,
320 bool should_be_embargoed) {
321 if (should_be_embargoed) {
322 // Requesting site is blacklisted for this permission, update the content
323 // setting to place it under embargo.
324 PlaceUnderEmbargo(permission, request_origin,
325 HostContentSettingsMapFactory::GetForProfile(profile),
326 current_time, kPermissionBlacklistEmbargoKey);
327 }
328 callback.Run(should_be_embargoed /* permission blocked */);
329 }
330
331 // static
332 void PermissionDecisionAutoBlocker::PlaceUnderEmbargoForTest(
333 content::PermissionType permission,
334 const GURL& request_origin,
335 HostContentSettingsMap* map,
336 base::Time current_time) {
337 PlaceUnderEmbargo(permission, request_origin, map, current_time,
338 kPermissionBlacklistEmbargoKey);
339 }
340
341 // static
342 bool PermissionDecisionAutoBlocker::GetEmbargoStatusForTest(
343 content::PermissionType permission,
344 const GURL& request_origin,
345 HostContentSettingsMap* map) {
346 std::unique_ptr<base::DictionaryValue> dict =
347 GetOriginDict(map, request_origin);
348 base::DictionaryValue* permission_dict = GetOrCreatePermissionDict(
349 dict.get(), PermissionUtil::GetPermissionString(permission));
350 return permission_dict->GetDouble(kPermissionBlacklistEmbargoKey, nullptr);
351 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698