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

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

Issue 2184823007: Add a feature which, when enabled, blocks permissions after X prompt dismissals. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Unify implementation in permission_context_base, make log static Created 4 years, 4 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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_context_base.h" 5 #include "chrome/browser/permissions/permission_context_base.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/feature_list.h"
11 #include "base/macros.h" 12 #include "base/macros.h"
12 #include "base/metrics/field_trial.h" 13 #include "base/metrics/field_trial.h"
14 #include "base/test/histogram_tester.h"
13 #include "base/test/mock_entropy_provider.h" 15 #include "base/test/mock_entropy_provider.h"
14 #include "build/build_config.h" 16 #include "build/build_config.h"
15 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" 17 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
16 #include "chrome/browser/infobars/infobar_service.h" 18 #include "chrome/browser/infobars/infobar_service.h"
19 #include "chrome/browser/permissions/permission_prompt_decision_log.h"
17 #include "chrome/browser/permissions/permission_queue_controller.h" 20 #include "chrome/browser/permissions/permission_queue_controller.h"
18 #include "chrome/browser/permissions/permission_request_id.h" 21 #include "chrome/browser/permissions/permission_request_id.h"
19 #include "chrome/browser/permissions/permission_util.h" 22 #include "chrome/browser/permissions/permission_util.h"
23 #include "chrome/common/chrome_features.h"
20 #include "chrome/common/chrome_switches.h" 24 #include "chrome/common/chrome_switches.h"
21 #include "chrome/test/base/chrome_render_view_host_test_harness.h" 25 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
22 #include "chrome/test/base/testing_profile.h" 26 #include "chrome/test/base/testing_profile.h"
23 #include "components/content_settings/core/browser/host_content_settings_map.h" 27 #include "components/content_settings/core/browser/host_content_settings_map.h"
24 #include "components/content_settings/core/common/content_settings.h" 28 #include "components/content_settings/core/common/content_settings.h"
25 #include "components/content_settings/core/common/content_settings_types.h" 29 #include "components/content_settings/core/common/content_settings_types.h"
26 #include "components/variations/variations_associated_data.h" 30 #include "components/variations/variations_associated_data.h"
27 #include "content/public/browser/permission_type.h" 31 #include "content/public/browser/permission_type.h"
28 #include "content/public/browser/render_frame_host.h" 32 #include "content/public/browser/render_frame_host.h"
29 #include "content/public/browser/web_contents.h" 33 #include "content/public/browser/web_contents.h"
30 #include "content/public/test/mock_render_process_host.h" 34 #include "content/public/test/mock_render_process_host.h"
31 #include "testing/gtest/include/gtest/gtest.h" 35 #include "testing/gtest/include/gtest/gtest.h"
32 36
33 #if defined(OS_ANDROID) 37 #if defined(OS_ANDROID)
34 #include "chrome/browser/permissions/permission_queue_controller.h" 38 #include "chrome/browser/permissions/permission_queue_controller.h"
35 #else 39 #else
36 #include "chrome/browser/permissions/permission_request_manager.h" 40 #include "chrome/browser/permissions/permission_request_manager.h"
37 #endif 41 #endif
38 42
39 const char* kPermissionsKillSwitchFieldStudy = 43 const char* kPermissionsKillSwitchFieldStudy =
40 PermissionContextBase::kPermissionsKillSwitchFieldStudy; 44 PermissionContextBase::kPermissionsKillSwitchFieldStudy;
41 const char* kPermissionsKillSwitchBlockedValue = 45 const char* kPermissionsKillSwitchBlockedValue =
42 PermissionContextBase::kPermissionsKillSwitchBlockedValue; 46 PermissionContextBase::kPermissionsKillSwitchBlockedValue;
43 const char kPermissionsKillSwitchTestGroup[] = "TestGroup"; 47 const char kPermissionsKillSwitchTestGroup[] = "TestGroup";
48 const char* kPromptGroupName = kPermissionsKillSwitchTestGroup;
49 const char kPromptTrialName[] = "PermissionPromptsUX";
50 const char* kPromptDismissCountKey =
51 PermissionPromptDecisionLog::kPromptDismissCountKey;
44 52
45 class TestPermissionContext : public PermissionContextBase { 53 class TestPermissionContext : public PermissionContextBase {
46 public: 54 public:
47 TestPermissionContext(Profile* profile, 55 TestPermissionContext(Profile* profile,
48 const content::PermissionType permission_type, 56 const content::PermissionType permission_type,
49 const ContentSettingsType content_settings_type) 57 const ContentSettingsType content_settings_type)
50 : PermissionContextBase(profile, permission_type, content_settings_type), 58 : PermissionContextBase(profile, permission_type, content_settings_type),
51 tab_context_updated_(false), 59 tab_context_updated_(false),
52 field_trial_list_( 60 field_trial_list_(
53 new base::FieldTrialList(new base::MockEntropyProvider)) {} 61 new base::FieldTrialList(new base::MockEntropyProvider)) {}
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 base::Unretained(&permission_context))); 191 base::Unretained(&permission_context)));
184 192
185 RespondToPermission(&permission_context, id, url, CONTENT_SETTING_ASK); 193 RespondToPermission(&permission_context, id, url, CONTENT_SETTING_ASK);
186 EXPECT_EQ(1u, permission_context.decisions().size()); 194 EXPECT_EQ(1u, permission_context.decisions().size());
187 EXPECT_EQ(CONTENT_SETTING_ASK, permission_context.decisions()[0]); 195 EXPECT_EQ(CONTENT_SETTING_ASK, permission_context.decisions()[0]);
188 EXPECT_TRUE(permission_context.tab_context_updated()); 196 EXPECT_TRUE(permission_context.tab_context_updated());
189 EXPECT_EQ(CONTENT_SETTING_ASK, 197 EXPECT_EQ(CONTENT_SETTING_ASK,
190 permission_context.GetContentSettingFromMap(url, url)); 198 permission_context.GetContentSettingFromMap(url, url));
191 } 199 }
192 200
201 void DismissMultipleTimesAndExpectBlock(
202 const GURL& url,
203 content::PermissionType permission_type,
204 ContentSettingsType content_settings_type,
205 unsigned int iterations) {
raymes 2016/08/05 03:27:48 nit: I think uint32/64_t is preferred over unsigne
dominickn 2016/08/05 04:29:30 Done.
206 base::HistogramTester histograms;
207
208 // Dismiss |iterations| times. The final dismiss should change the decision
209 // from dismiss to block, and hence change the persisted content setting.
210 for (unsigned int i = 0; i < iterations; ++i) {
211 TestPermissionContext permission_context(
212 profile(), permission_type, content_settings_type);
213 ContentSetting expected =
214 (i < (iterations - 1)) ? CONTENT_SETTING_ASK : CONTENT_SETTING_BLOCK;
215
216 const PermissionRequestID id(
217 web_contents()->GetRenderProcessHost()->GetID(),
218 web_contents()->GetMainFrame()->GetRoutingID(), i);
219 permission_context.RequestPermission(
220 web_contents(), id, url, true /* user_gesture */,
221 base::Bind(&TestPermissionContext::TrackPermissionDecision,
222 base::Unretained(&permission_context)));
223
224 RespondToPermission(&permission_context, id, url, CONTENT_SETTING_ASK);
225 histograms.ExpectTotalCount(
226 "Permissions.DismissCount." +
227 PermissionUtil::GetPermissionString(permission_type),
228 i + 1);
229
230 EXPECT_EQ(1u, permission_context.decisions().size());
231 EXPECT_EQ(expected, permission_context.decisions()[0]);
232 EXPECT_TRUE(permission_context.tab_context_updated());
233 EXPECT_EQ(expected,
234 permission_context.GetContentSettingFromMap(url, url));
235 }
raymes 2016/08/05 03:27:47 nit: as a sanity check against an off-by-one bug i
dominickn 2016/08/05 04:29:30 Done.
236 }
237
238 void TestBlockOnSeveralDismissals_TestContent() {
239 GURL url("https://www.google.com");
240 NavigateAndCommit(url);
241 base::HistogramTester histograms;
242
243 // First, ensure that > 3 dismissals behaves correctly.
244 for (unsigned int i = 0; i < 4; ++i) {
245 TestPermissionContext permission_context(
246 profile(), content::PermissionType::GEOLOCATION,
247 CONTENT_SETTINGS_TYPE_GEOLOCATION);
248
249 const PermissionRequestID id(
250 web_contents()->GetRenderProcessHost()->GetID(),
251 web_contents()->GetMainFrame()->GetRoutingID(), i);
252 permission_context.RequestPermission(
253 web_contents(), id, url, true /* user_gesture */,
254 base::Bind(&TestPermissionContext::TrackPermissionDecision,
255 base::Unretained(&permission_context)));
256
257 RespondToPermission(&permission_context, id, url, CONTENT_SETTING_ASK);
258 histograms.ExpectTotalCount("Permissions.DismissCount.Geolocation",
259 i + 1);
260 EXPECT_EQ(1u, permission_context.decisions().size());
261 EXPECT_EQ(CONTENT_SETTING_ASK, permission_context.decisions()[0]);
262 EXPECT_TRUE(permission_context.tab_context_updated());
263 EXPECT_EQ(CONTENT_SETTING_ASK,
264 permission_context.GetContentSettingFromMap(url, url));
265 }
266
267 // Flush the dismissal counts. Enable the block on too many dismissals
268 // feature, which is disabled by default.
269 HostContentSettingsMapFactory::GetForProfile(profile())
270 ->ClearSettingsForOneType(
271 CONTENT_SETTINGS_TYPE_PROMPT_NO_DECISION_COUNT);
272
273 {
274 // Set up the custom parameter. This must be within a scope to correctly
275 // instantiate the field trial global.
276 base::FieldTrialList field_trials_(nullptr);
277
278 base::FieldTrial* trial = base::FieldTrialList::CreateFieldTrial(
279 kPromptTrialName, kPromptGroupName);
280 base::FeatureList::ClearInstanceForTesting();
281 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
282 feature_list->RegisterFieldTrialOverride(
283 features::kBlockPromptsIfDismissedOften.name,
284 base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial);
285 base::FeatureList::SetInstance(std::move(feature_list));
286 EXPECT_EQ(base::FeatureList::GetFieldTrial(
287 features::kBlockPromptsIfDismissedOften),
288 trial);
289 }
290
291 EXPECT_TRUE(
292 base::FeatureList::IsEnabled(features::kBlockPromptsIfDismissedOften));
293
294 // Sanity check independence per permission type by checking two of them.
295 DismissMultipleTimesAndExpectBlock(url,
296 content::PermissionType::GEOLOCATION,
297 CONTENT_SETTINGS_TYPE_GEOLOCATION, 3);
298 DismissMultipleTimesAndExpectBlock(url,
299 content::PermissionType::NOTIFICATIONS,
300 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, 3);
301 base::FeatureList::ClearInstanceForTesting();
302 }
303
304 void TestVariationBlockOnSeveralDismissals_TestContent() {
305 GURL url("https://www.google.com");
306 NavigateAndCommit(url);
307
308 {
309 // Set up the custom parameter. This must be within a scope to correctly
310 // instantiate the field trial global.
311 base::FieldTrialList field_trials_(nullptr);
312
313 base::FieldTrial* trial = base::FieldTrialList::CreateFieldTrial(
314 kPromptTrialName, kPromptGroupName);
315 std::map<std::string, std::string> params;
316 params[kPromptDismissCountKey] = "5";
317 ASSERT_TRUE(variations::AssociateVariationParams(
318 kPromptTrialName, kPromptGroupName, params));
319
320 base::FeatureList::ClearInstanceForTesting();
321 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
322 feature_list->RegisterFieldTrialOverride(
323 features::kBlockPromptsIfDismissedOften.name,
324 base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial);
325 base::FeatureList::SetInstance(std::move(feature_list));
326 EXPECT_EQ(base::FeatureList::GetFieldTrial(
327 features::kBlockPromptsIfDismissedOften),
328 trial);
329
330 std::map<std::string, std::string> actualParams;
331 EXPECT_TRUE(variations::GetVariationParamsByFeature(
332 features::kBlockPromptsIfDismissedOften, &actualParams));
333 EXPECT_EQ(params, actualParams);
334
335 PermissionContextBase::prompt_decision_log_.Get().UpdateFromVariations();
336 }
337
338 for (unsigned int i = 0; i < 5; ++i) {
339 TestPermissionContext permission_context(
340 profile(), content::PermissionType::MIDI_SYSEX,
341 CONTENT_SETTINGS_TYPE_MIDI_SYSEX);
342
343 ContentSetting expected =
344 (i < 4) ? CONTENT_SETTING_ASK : CONTENT_SETTING_BLOCK;
345 const PermissionRequestID id(
346 web_contents()->GetRenderProcessHost()->GetID(),
347 web_contents()->GetMainFrame()->GetRoutingID(), i);
348 permission_context.RequestPermission(
349 web_contents(), id, url, true /* user_gesture */,
350 base::Bind(&TestPermissionContext::TrackPermissionDecision,
351 base::Unretained(&permission_context)));
352
353 RespondToPermission(&permission_context, id, url, CONTENT_SETTING_ASK);
354 EXPECT_EQ(1u, permission_context.decisions().size());
355 EXPECT_EQ(expected, permission_context.decisions()[0]);
356 EXPECT_TRUE(permission_context.tab_context_updated());
357 EXPECT_EQ(expected,
358 permission_context.GetContentSettingFromMap(url, url));
359 }
raymes 2016/08/05 03:27:48 A similar sanity check here would be good.
dominickn 2016/08/05 04:29:30 Done.
360 base::FeatureList::ClearInstanceForTesting();
361 variations::testing::ClearAllVariationParams();
362 }
363
193 void TestRequestPermissionInvalidUrl( 364 void TestRequestPermissionInvalidUrl(
194 content::PermissionType permission_type, 365 content::PermissionType permission_type,
195 ContentSettingsType content_settings_type) { 366 ContentSettingsType content_settings_type) {
196 TestPermissionContext permission_context(profile(), permission_type, 367 TestPermissionContext permission_context(profile(), permission_type,
197 content_settings_type); 368 content_settings_type);
198 GURL url; 369 GURL url;
199 ASSERT_FALSE(url.is_valid()); 370 ASSERT_FALSE(url.is_valid());
200 NavigateAndCommit(url); 371 NavigateAndCommit(url);
201 372
202 const PermissionRequestID id( 373 const PermissionRequestID id(
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 TEST_F(PermissionContextBaseTests, TestAskAndGrant) { 497 TEST_F(PermissionContextBaseTests, TestAskAndGrant) {
327 TestAskAndGrant_TestContent(); 498 TestAskAndGrant_TestContent();
328 } 499 }
329 500
330 // Simulates clicking Dismiss (X) in the infobar/bubble. 501 // Simulates clicking Dismiss (X) in the infobar/bubble.
331 // The permission should be denied but not saved for future use. 502 // The permission should be denied but not saved for future use.
332 TEST_F(PermissionContextBaseTests, TestAskAndDismiss) { 503 TEST_F(PermissionContextBaseTests, TestAskAndDismiss) {
333 TestAskAndDismiss_TestContent(); 504 TestAskAndDismiss_TestContent();
334 } 505 }
335 506
507 // Simulates clicking Dismiss (X) in the infobar/bubble with the block on too
508 // many dismissals feature active.
509 // The permission should be blocked after several dismissals.
raymes 2016/08/05 03:27:47 nit: fill 80 chars on previous line or add a newli
dominickn 2016/08/05 04:29:30 Done.
510 TEST_F(PermissionContextBaseTests, TestDismissUntilBlocked) {
511 TestBlockOnSeveralDismissals_TestContent();
512 }
513
514 // Test setting a custom number of dismissals before block via variations.
515 TEST_F(PermissionContextBaseTests, TestDismissVariations) {
516 TestVariationBlockOnSeveralDismissals_TestContent();
517 }
518
336 // Simulates non-valid requesting URL. 519 // Simulates non-valid requesting URL.
337 // The permission should be denied but not saved for future use. 520 // The permission should be denied but not saved for future use.
338 TEST_F(PermissionContextBaseTests, TestNonValidRequestingUrl) { 521 TEST_F(PermissionContextBaseTests, TestNonValidRequestingUrl) {
339 TestRequestPermissionInvalidUrl(content::PermissionType::GEOLOCATION, 522 TestRequestPermissionInvalidUrl(content::PermissionType::GEOLOCATION,
340 CONTENT_SETTINGS_TYPE_GEOLOCATION); 523 CONTENT_SETTINGS_TYPE_GEOLOCATION);
341 TestRequestPermissionInvalidUrl(content::PermissionType::NOTIFICATIONS, 524 TestRequestPermissionInvalidUrl(content::PermissionType::NOTIFICATIONS,
342 CONTENT_SETTINGS_TYPE_NOTIFICATIONS); 525 CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
343 TestRequestPermissionInvalidUrl(content::PermissionType::MIDI_SYSEX, 526 TestRequestPermissionInvalidUrl(content::PermissionType::MIDI_SYSEX,
344 CONTENT_SETTINGS_TYPE_MIDI_SYSEX); 527 CONTENT_SETTINGS_TYPE_MIDI_SYSEX);
345 TestRequestPermissionInvalidUrl(content::PermissionType::PUSH_MESSAGING, 528 TestRequestPermissionInvalidUrl(content::PermissionType::PUSH_MESSAGING,
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 TestParallelRequests(CONTENT_SETTING_ALLOW); 603 TestParallelRequests(CONTENT_SETTING_ALLOW);
421 } 604 }
422 605
423 TEST_F(PermissionContextBaseTests, TestParallelRequestsBlocked) { 606 TEST_F(PermissionContextBaseTests, TestParallelRequestsBlocked) {
424 TestParallelRequests(CONTENT_SETTING_BLOCK); 607 TestParallelRequests(CONTENT_SETTING_BLOCK);
425 } 608 }
426 609
427 TEST_F(PermissionContextBaseTests, TestParallelRequestsDismissed) { 610 TEST_F(PermissionContextBaseTests, TestParallelRequestsDismissed) {
428 TestParallelRequests(CONTENT_SETTING_ASK); 611 TestParallelRequests(CONTENT_SETTING_ASK);
429 } 612 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698