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

Unified 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: Addressing nits 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/permissions/permission_context_base_unittest.cc
diff --git a/chrome/browser/permissions/permission_context_base_unittest.cc b/chrome/browser/permissions/permission_context_base_unittest.cc
index fb5b4c8973d4c6bd9e43b47d89f606653de168c5..2225cadd21bd642e3f008af3a87dc65fa3a92dfd 100644
--- a/chrome/browser/permissions/permission_context_base_unittest.cc
+++ b/chrome/browser/permissions/permission_context_base_unittest.cc
@@ -8,15 +8,19 @@
#include "base/bind.h"
#include "base/command_line.h"
+#include "base/feature_list.h"
#include "base/macros.h"
#include "base/metrics/field_trial.h"
+#include "base/test/histogram_tester.h"
#include "base/test/mock_entropy_provider.h"
#include "build/build_config.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/infobars/infobar_service.h"
+#include "chrome/browser/permissions/permission_decision_auto_blocker.h"
#include "chrome/browser/permissions/permission_queue_controller.h"
#include "chrome/browser/permissions/permission_request_id.h"
#include "chrome/browser/permissions/permission_util.h"
+#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "chrome/test/base/testing_profile.h"
@@ -41,6 +45,8 @@ const char* kPermissionsKillSwitchFieldStudy =
const char* kPermissionsKillSwitchBlockedValue =
PermissionContextBase::kPermissionsKillSwitchBlockedValue;
const char kPermissionsKillSwitchTestGroup[] = "TestGroup";
+const char* kPromptGroupName = kPermissionsKillSwitchTestGroup;
+const char kPromptTrialName[] = "PermissionPromptsUX";
class TestPermissionContext : public PermissionContextBase {
public:
@@ -48,9 +54,7 @@ class TestPermissionContext : public PermissionContextBase {
const content::PermissionType permission_type,
const ContentSettingsType content_settings_type)
: PermissionContextBase(profile, permission_type, content_settings_type),
- tab_context_updated_(false),
- field_trial_list_(
- new base::FieldTrialList(new base::MockEntropyProvider)) {}
+ tab_context_updated_(false) {}
~TestPermissionContext() override {}
@@ -70,15 +74,6 @@ class TestPermissionContext : public PermissionContextBase {
decisions_.push_back(content_setting);
}
- void ResetFieldTrialList() {
- // Destroy the existing FieldTrialList before creating a new one to avoid
- // a DCHECK.
- field_trial_list_.reset();
- field_trial_list_.reset(new base::FieldTrialList(
- new base::MockEntropyProvider));
- variations::testing::ClearAllVariationParams();
- }
-
ContentSetting GetContentSettingFromMap(const GURL& url_a,
const GURL& url_b) {
return HostContentSettingsMapFactory::GetForProfile(profile())
@@ -100,6 +95,28 @@ class TestPermissionContext : public PermissionContextBase {
private:
std::vector<ContentSetting> decisions_;
bool tab_context_updated_;
+};
+
+class TestKillSwitchPermissionContext : public TestPermissionContext {
+ public:
+ TestKillSwitchPermissionContext(
+ Profile* profile,
+ const content::PermissionType permission_type,
+ const ContentSettingsType content_settings_type)
+ : TestPermissionContext(profile, permission_type, content_settings_type),
+ field_trial_list_(
+ new base::FieldTrialList(new base::MockEntropyProvider)) {}
+
+ void ResetFieldTrialList() {
+ // Destroy the existing FieldTrialList before creating a new one to avoid
+ // a DCHECK.
+ field_trial_list_.reset();
+ field_trial_list_.reset(new base::FieldTrialList(
+ new base::MockEntropyProvider));
+ variations::testing::ClearAllVariationParams();
+ }
+
+ private:
std::unique_ptr<base::FieldTrialList> field_trial_list_;
};
@@ -190,6 +207,172 @@ class PermissionContextBaseTests : public ChromeRenderViewHostTestHarness {
permission_context.GetContentSettingFromMap(url, url));
}
+ void DismissMultipleTimesAndExpectBlock(
+ const GURL& url,
+ content::PermissionType permission_type,
+ ContentSettingsType content_settings_type,
+ uint32_t iterations) {
+ base::HistogramTester histograms;
+
+ // Dismiss |iterations| times. The final dismiss should change the decision
+ // from dismiss to block, and hence change the persisted content setting.
+ for (uint32_t i = 0; i < iterations; ++i) {
+ TestPermissionContext permission_context(
+ profile(), permission_type, content_settings_type);
+ ContentSetting expected =
+ (i < (iterations - 1)) ? CONTENT_SETTING_ASK : CONTENT_SETTING_BLOCK;
+
+ const PermissionRequestID id(
+ web_contents()->GetRenderProcessHost()->GetID(),
+ web_contents()->GetMainFrame()->GetRoutingID(), i);
+ permission_context.RequestPermission(
+ web_contents(), id, url, true /* user_gesture */,
+ base::Bind(&TestPermissionContext::TrackPermissionDecision,
+ base::Unretained(&permission_context)));
+
+ RespondToPermission(&permission_context, id, url, CONTENT_SETTING_ASK);
+ histograms.ExpectTotalCount(
+ "Permissions.Prompt.DismissCount." +
+ PermissionUtil::GetPermissionString(permission_type),
+ i + 1);
+
+ EXPECT_EQ(1u, permission_context.decisions().size());
+ EXPECT_EQ(expected, permission_context.decisions()[0]);
+ EXPECT_TRUE(permission_context.tab_context_updated());
+ EXPECT_EQ(expected,
+ permission_context.GetContentSettingFromMap(url, url));
+ }
+
+ // Ensure that we finish in the block state.
+ TestPermissionContext permission_context(
+ profile(), permission_type, content_settings_type);
+ EXPECT_EQ(CONTENT_SETTING_BLOCK,
+ permission_context.GetContentSettingFromMap(url, url));
+ }
+
+ void TestBlockOnSeveralDismissals_TestContent() {
+ GURL url("https://www.google.com");
+ NavigateAndCommit(url);
+ base::HistogramTester histograms;
+
+ // First, ensure that > 3 dismissals behaves correctly.
+ for (uint32_t i = 0; i < 4; ++i) {
+ TestPermissionContext permission_context(
+ profile(), content::PermissionType::GEOLOCATION,
+ CONTENT_SETTINGS_TYPE_GEOLOCATION);
+
+ const PermissionRequestID id(
+ web_contents()->GetRenderProcessHost()->GetID(),
+ web_contents()->GetMainFrame()->GetRoutingID(), i);
+ permission_context.RequestPermission(
+ web_contents(), id, url, true /* user_gesture */,
+ base::Bind(&TestPermissionContext::TrackPermissionDecision,
+ base::Unretained(&permission_context)));
+
+ RespondToPermission(&permission_context, id, url, CONTENT_SETTING_ASK);
+ histograms.ExpectTotalCount("Permissions.Prompt.DismissCount.Geolocation",
+ i + 1);
+ EXPECT_EQ(1u, permission_context.decisions().size());
+ EXPECT_EQ(CONTENT_SETTING_ASK, permission_context.decisions()[0]);
+ EXPECT_TRUE(permission_context.tab_context_updated());
+ EXPECT_EQ(CONTENT_SETTING_ASK,
+ permission_context.GetContentSettingFromMap(url, url));
+ }
+
+ // Flush the dismissal counts. Enable the block on too many dismissals
+ // feature, which is disabled by default.
+ HostContentSettingsMapFactory::GetForProfile(profile())
+ ->ClearSettingsForOneType(
+ CONTENT_SETTINGS_TYPE_PROMPT_NO_DECISION_COUNT);
+
+ // Set up the custom parameter.
+ base::FieldTrialList field_trials_(nullptr);
+ base::FieldTrial* trial = base::FieldTrialList::CreateFieldTrial(
+ kPromptTrialName, kPromptGroupName);
+ base::FeatureList::ClearInstanceForTesting();
Lei Zhang 2016/09/27 21:57:51 If you read the comments for ClearInstanceForTesti
+ std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
+ feature_list->RegisterFieldTrialOverride(
+ features::kBlockPromptsIfDismissedOften.name,
+ base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial);
+ base::FeatureList::SetInstance(std::move(feature_list));
+ EXPECT_EQ(base::FeatureList::GetFieldTrial(
+ features::kBlockPromptsIfDismissedOften),
+ trial);
+
+ EXPECT_TRUE(
+ base::FeatureList::IsEnabled(features::kBlockPromptsIfDismissedOften));
+
+ // Sanity check independence per permission type by checking two of them.
+ DismissMultipleTimesAndExpectBlock(url,
+ content::PermissionType::GEOLOCATION,
+ CONTENT_SETTINGS_TYPE_GEOLOCATION, 3);
+ DismissMultipleTimesAndExpectBlock(url,
+ content::PermissionType::NOTIFICATIONS,
+ CONTENT_SETTINGS_TYPE_NOTIFICATIONS, 3);
+ base::FeatureList::ClearInstanceForTesting();
+ }
+
+ void TestVariationBlockOnSeveralDismissals_TestContent() {
+ GURL url("https://www.google.com");
+ NavigateAndCommit(url);
+
+ // Set up the custom parameter and custom value.
+ base::FieldTrialList field_trials_(nullptr);
+ base::FieldTrial* trial = base::FieldTrialList::CreateFieldTrial(
+ kPromptTrialName, kPromptGroupName);
+ std::map<std::string, std::string> params;
+ params[PermissionDecisionAutoBlocker::kPromptDismissCountKey] = "5";
+ ASSERT_TRUE(variations::AssociateVariationParams(
+ kPromptTrialName, kPromptGroupName, params));
+
+ base::FeatureList::ClearInstanceForTesting();
+ std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
+ feature_list->RegisterFieldTrialOverride(
+ features::kBlockPromptsIfDismissedOften.name,
+ base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial);
+ base::FeatureList::SetInstance(std::move(feature_list));
+ EXPECT_EQ(base::FeatureList::GetFieldTrial(
+ features::kBlockPromptsIfDismissedOften),
+ trial);
+
+ std::map<std::string, std::string> actualParams;
+ EXPECT_TRUE(variations::GetVariationParamsByFeature(
+ features::kBlockPromptsIfDismissedOften, &actualParams));
+ EXPECT_EQ(params, actualParams);
+
+ for (uint32_t i = 0; i < 5; ++i) {
+ TestPermissionContext permission_context(
+ profile(), content::PermissionType::MIDI_SYSEX,
+ CONTENT_SETTINGS_TYPE_MIDI_SYSEX);
+
+ ContentSetting expected =
+ (i < 4) ? CONTENT_SETTING_ASK : CONTENT_SETTING_BLOCK;
+ const PermissionRequestID id(
+ web_contents()->GetRenderProcessHost()->GetID(),
+ web_contents()->GetMainFrame()->GetRoutingID(), i);
+ permission_context.RequestPermission(
+ web_contents(), id, url, true /* user_gesture */,
+ base::Bind(&TestPermissionContext::TrackPermissionDecision,
+ base::Unretained(&permission_context)));
+
+ RespondToPermission(&permission_context, id, url, CONTENT_SETTING_ASK);
+ EXPECT_EQ(1u, permission_context.decisions().size());
+ EXPECT_EQ(expected, permission_context.decisions()[0]);
+ EXPECT_TRUE(permission_context.tab_context_updated());
+ EXPECT_EQ(expected,
+ permission_context.GetContentSettingFromMap(url, url));
+ }
+
+ // Ensure that we finish in the block state.
+ TestPermissionContext permission_context(
+ profile(), content::PermissionType::MIDI_SYSEX,
+ CONTENT_SETTINGS_TYPE_MIDI_SYSEX);
+ EXPECT_EQ(CONTENT_SETTING_BLOCK,
+ permission_context.GetContentSettingFromMap(url, url));
+ base::FeatureList::ClearInstanceForTesting();
+ variations::testing::ClearAllVariationParams();
+ }
+
void TestRequestPermissionInvalidUrl(
content::PermissionType permission_type,
ContentSettingsType content_settings_type) {
@@ -254,8 +437,8 @@ class PermissionContextBaseTests : public ChromeRenderViewHostTestHarness {
void TestGlobalPermissionsKillSwitch(
content::PermissionType permission_type,
ContentSettingsType content_settings_type) {
- TestPermissionContext permission_context(profile(), permission_type,
- content_settings_type);
+ TestKillSwitchPermissionContext permission_context(
+ profile(), permission_type, content_settings_type);
permission_context.ResetFieldTrialList();
EXPECT_FALSE(permission_context.IsPermissionKillSwitchOn());
@@ -333,6 +516,18 @@ TEST_F(PermissionContextBaseTests, TestAskAndDismiss) {
TestAskAndDismiss_TestContent();
}
+// Simulates clicking Dismiss (X) in the infobar/bubble with the block on too
+// many dismissals feature active. The permission should be blocked after
+// several dismissals.
+TEST_F(PermissionContextBaseTests, TestDismissUntilBlocked) {
+ TestBlockOnSeveralDismissals_TestContent();
+}
+
+// Test setting a custom number of dismissals before block via variations.
+TEST_F(PermissionContextBaseTests, TestDismissVariations) {
+ TestVariationBlockOnSeveralDismissals_TestContent();
+}
+
// Simulates non-valid requesting URL.
// The permission should be denied but not saved for future use.
TEST_F(PermissionContextBaseTests, TestNonValidRequestingUrl) {
« no previous file with comments | « chrome/browser/permissions/permission_context_base.cc ('k') | chrome/browser/permissions/permission_decision_auto_blocker.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698