blob: 4ad9276a272890bb913569b06aaf7dcbad2a9877 [file]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/permissions/abusive_origin_permission_revocation_request.h"
#include "base/files/scoped_temp_dir.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/permissions/abusive_origin_notifications_permission_revocation_config.h"
#include "chrome/browser/permissions/crowd_deny_fake_safe_browsing_database_manager.h"
#include "chrome/browser/permissions/crowd_deny_preload_data.h"
#include "chrome/browser/safe_browsing/test_safe_browsing_service.h"
#include "chrome/common/chrome_features.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/prefs/pref_service.h"
#include "content/public/test/browser_task_environment.h"
class AbusiveOriginPermissionRevocationRequestTestBase : public testing::Test {
public:
using Outcome = AbusiveOriginPermissionRevocationRequest::Outcome;
using SiteReputation = CrowdDenyPreloadData::SiteReputation;
AbusiveOriginPermissionRevocationRequestTestBase() = default;
~AbusiveOriginPermissionRevocationRequestTestBase() override = default;
protected:
void SetUp() override {
testing::Test::SetUp();
DCHECK(profile_dir_.CreateUniqueTempDir());
TestingProfile::Builder profile_builder;
profile_builder.SetPath(profile_dir_.GetPath());
profile_builder.AddTestingFactory(
HistoryServiceFactory::GetInstance(),
HistoryServiceFactory::GetDefaultFactory());
testing_profile_ = profile_builder.Build();
fake_database_manager_ =
base::MakeRefCounted<CrowdDenyFakeSafeBrowsingDatabaseManager>();
safe_browsing_factory_ =
std::make_unique<safe_browsing::TestSafeBrowsingServiceFactory>();
safe_browsing_factory_->SetTestDatabaseManager(
fake_database_manager_.get());
TestingBrowserProcess::GetGlobal()->SetSafeBrowsingService(
safe_browsing_factory_->CreateSafeBrowsingService());
}
void TearDown() override {
TestingBrowserProcess::GetGlobal()->SetSafeBrowsingService(nullptr);
testing::Test::TearDown();
}
void AddToSafeBrowsingBlocklist(const GURL& url) {
safe_browsing::ThreatMetadata test_metadata;
test_metadata.api_permissions.emplace("NOTIFICATIONS");
fake_database_manager_->SetSimulatedMetadataForUrl(url, test_metadata);
}
void ClearSafeBrowsingBlocklist() {
fake_database_manager_->RemoveAllBlocklistedUrls();
}
void AddToPreloadDataBlocklist(
const GURL& origin,
chrome_browser_crowd_deny::
SiteReputation_NotificationUserExperienceQuality reputation_type,
bool has_warning) {
SiteReputation reputation;
reputation.set_notification_ux_quality(reputation_type);
reputation.set_warning_only(has_warning);
testing_preload_data_.SetOriginReputation(url::Origin::Create(origin),
std::move(reputation));
}
void QueryAndExpectDecisionForUrl(const GURL& origin,
Outcome expected_result) {
base::MockOnceCallback<void(Outcome)> mock_callback_receiver;
permission_revocation_ =
std::make_unique<AbusiveOriginPermissionRevocationRequest>(
testing_profile_.get(), origin, mock_callback_receiver.Get());
EXPECT_CALL(mock_callback_receiver, Run(expected_result));
task_environment_.RunUntilIdle();
permission_revocation_.reset();
}
void SetPermission(const GURL& origin, const ContentSetting value) {
HostContentSettingsMap* host_content_settings_map =
HostContentSettingsMapFactory::GetForProfile(testing_profile_.get());
host_content_settings_map->SetContentSettingDefaultScope(
origin, GURL(), ContentSettingsType::NOTIFICATIONS, value);
}
void VerifyNotificationsPermission(const GURL& origin,
const ContentSetting value) {
HostContentSettingsMap* host_content_settings_map =
HostContentSettingsMapFactory::GetForProfile(testing_profile_.get());
ContentSetting result = host_content_settings_map->GetContentSetting(
origin, GURL(), ContentSettingsType::NOTIFICATIONS);
EXPECT_EQ(value, result);
}
TestingProfile* GetTestingProfile() { return testing_profile_.get(); }
private:
base::ScopedTempDir profile_dir_;
content::BrowserTaskEnvironment task_environment_;
testing::ScopedCrowdDenyPreloadDataOverride testing_preload_data_;
std::unique_ptr<TestingProfile> testing_profile_;
std::unique_ptr<AbusiveOriginPermissionRevocationRequest>
permission_revocation_;
scoped_refptr<CrowdDenyFakeSafeBrowsingDatabaseManager>
fake_database_manager_;
std::unique_ptr<safe_browsing::TestSafeBrowsingServiceFactory>
safe_browsing_factory_;
DISALLOW_COPY_AND_ASSIGN(AbusiveOriginPermissionRevocationRequestTestBase);
};
class AbusiveOriginPermissionRevocationRequestTest
: public AbusiveOriginPermissionRevocationRequestTestBase {
public:
AbusiveOriginPermissionRevocationRequestTest() {
feature_list_.InitAndEnableFeature(
features::kAbusiveNotificationPermissionRevocation);
}
~AbusiveOriginPermissionRevocationRequestTest() override = default;
private:
base::test::ScopedFeatureList feature_list_;
};
TEST_F(AbusiveOriginPermissionRevocationRequestTest,
OriginIsNotOnBlockingLists) {
const GURL origin_to_revoke = GURL("https://origin.com/");
SetPermission(origin_to_revoke, CONTENT_SETTING_ALLOW);
QueryAndExpectDecisionForUrl(origin_to_revoke,
Outcome::PERMISSION_NOT_REVOKED);
VerifyNotificationsPermission(origin_to_revoke, CONTENT_SETTING_ALLOW);
}
TEST_F(AbusiveOriginPermissionRevocationRequestTest, SafeBrowsingTest) {
const GURL origin_to_revoke = GURL("https://origin.com/");
SetPermission(origin_to_revoke, CONTENT_SETTING_ALLOW);
// The origin is not on any blocking lists. Notifications permission is not
// revoked.
QueryAndExpectDecisionForUrl(origin_to_revoke,
Outcome::PERMISSION_NOT_REVOKED);
AddToSafeBrowsingBlocklist(origin_to_revoke);
// Origin is not on CrowdDeny blocking lists.
QueryAndExpectDecisionForUrl(origin_to_revoke,
Outcome::PERMISSION_NOT_REVOKED);
VerifyNotificationsPermission(origin_to_revoke, CONTENT_SETTING_ALLOW);
EXPECT_FALSE(
AbusiveOriginPermissionRevocationRequest::HasPreviouslyRevokedPermission(
GetTestingProfile(), origin_to_revoke));
AddToPreloadDataBlocklist(origin_to_revoke, SiteReputation::ABUSIVE_CONTENT,
/*has_warning=*/false);
QueryAndExpectDecisionForUrl(origin_to_revoke,
Outcome::PERMISSION_REVOKED_DUE_TO_ABUSE);
VerifyNotificationsPermission(origin_to_revoke, CONTENT_SETTING_ASK);
EXPECT_TRUE(
AbusiveOriginPermissionRevocationRequest::HasPreviouslyRevokedPermission(
GetTestingProfile(), origin_to_revoke));
}
TEST_F(AbusiveOriginPermissionRevocationRequestTest, PreloadDataTest) {
const GURL abusive_content_origin_to_revoke =
GURL("https://abusive-content.com/");
const GURL abusive_prompts_origin_to_revoke =
GURL("https://abusive-prompts.com/");
const GURL unsolicited_prompts_origin =
GURL("https://unsolicited-prompts.com/");
const GURL acceptable_origin = GURL("https://acceptable-origin.com/");
const GURL unknown_origin = GURL("https://unknown-origin.com/");
auto origins = {abusive_content_origin_to_revoke,
abusive_prompts_origin_to_revoke, unsolicited_prompts_origin,
acceptable_origin, unknown_origin};
for (auto origin : origins)
SetPermission(origin, CONTENT_SETTING_ALLOW);
// The origins are not on any blocking lists.
for (auto origin : origins)
QueryAndExpectDecisionForUrl(origin, Outcome::PERMISSION_NOT_REVOKED);
AddToPreloadDataBlocklist(abusive_content_origin_to_revoke,
SiteReputation::ABUSIVE_CONTENT,
/*has_warning=*/false);
AddToPreloadDataBlocklist(abusive_prompts_origin_to_revoke,
SiteReputation::ABUSIVE_PROMPTS,
/*has_warning=*/false);
AddToPreloadDataBlocklist(unsolicited_prompts_origin,
SiteReputation::UNSOLICITED_PROMPTS,
/*has_warning=*/false);
AddToPreloadDataBlocklist(acceptable_origin, SiteReputation::ACCEPTABLE,
/*has_warning=*/false);
AddToPreloadDataBlocklist(unknown_origin, SiteReputation::UNKNOWN,
/*has_warning=*/false);
// The origins are on CrowdDeny blocking lists, but not on SafeBrowsing.
for (auto origin : origins)
QueryAndExpectDecisionForUrl(origin, Outcome::PERMISSION_NOT_REVOKED);
for (auto origin : origins)
AddToSafeBrowsingBlocklist(origin);
QueryAndExpectDecisionForUrl(abusive_content_origin_to_revoke,
Outcome::PERMISSION_REVOKED_DUE_TO_ABUSE);
QueryAndExpectDecisionForUrl(abusive_prompts_origin_to_revoke,
Outcome::PERMISSION_REVOKED_DUE_TO_ABUSE);
QueryAndExpectDecisionForUrl(unsolicited_prompts_origin,
Outcome::PERMISSION_NOT_REVOKED);
QueryAndExpectDecisionForUrl(acceptable_origin,
Outcome::PERMISSION_NOT_REVOKED);
QueryAndExpectDecisionForUrl(unknown_origin, Outcome::PERMISSION_NOT_REVOKED);
}
TEST_F(AbusiveOriginPermissionRevocationRequestTest,
PreloadDataTestWithWarning) {
const GURL abusive_content_origin_to_revoke =
GURL("https://abusive-content.com/");
const GURL abusive_prompts_origin_to_revoke =
GURL("https://abusive-prompts.com/");
const GURL unsolicited_prompts_origin =
GURL("https://unsolicited-prompts.com/");
const GURL acceptable_origin = GURL("https://acceptable-origin.com/");
const GURL unknown_origin = GURL("https://unknown-origin.com/");
auto origins = {abusive_content_origin_to_revoke,
abusive_prompts_origin_to_revoke, unsolicited_prompts_origin,
acceptable_origin, unknown_origin};
for (auto origin : origins)
SetPermission(origin, CONTENT_SETTING_ALLOW);
// The origins are not on any blocking lists.
for (auto origin : origins)
QueryAndExpectDecisionForUrl(origin, Outcome::PERMISSION_NOT_REVOKED);
AddToPreloadDataBlocklist(abusive_content_origin_to_revoke,
SiteReputation::ABUSIVE_CONTENT,
/*has_warning=*/true);
AddToPreloadDataBlocklist(abusive_prompts_origin_to_revoke,
SiteReputation::ABUSIVE_PROMPTS,
/*has_warning=*/true);
AddToPreloadDataBlocklist(unsolicited_prompts_origin,
SiteReputation::UNSOLICITED_PROMPTS,
/*has_warning=*/true);
AddToPreloadDataBlocklist(acceptable_origin, SiteReputation::ACCEPTABLE,
/*has_warning=*/true);
AddToPreloadDataBlocklist(unknown_origin, SiteReputation::UNKNOWN,
/*has_warning=*/true);
// The origins are on CrowdDeny blocking lists, but not on SafeBrowsing.
for (auto origin : origins)
QueryAndExpectDecisionForUrl(origin, Outcome::PERMISSION_NOT_REVOKED);
for (auto origin : origins)
AddToSafeBrowsingBlocklist(origin);
// The warning is enabled for all origin, permission should not be revoked.
for (auto origin : origins)
QueryAndExpectDecisionForUrl(origin, Outcome::PERMISSION_NOT_REVOKED);
}
TEST_F(AbusiveOriginPermissionRevocationRequestTest, ExemptAbusiveOriginTest) {
const GURL origin_to_exempt = GURL("https://origin-allow.com/");
const GURL origin_to_revoke = GURL("https://origin.com/");
AbusiveOriginPermissionRevocationRequest::ExemptOriginFromFutureRevocations(
GetTestingProfile(), origin_to_exempt);
SetPermission(origin_to_exempt, CONTENT_SETTING_ALLOW);
AddToPreloadDataBlocklist(origin_to_exempt, SiteReputation::ABUSIVE_CONTENT,
/*has_warning=*/false);
AddToSafeBrowsingBlocklist(origin_to_exempt);
SetPermission(origin_to_revoke, CONTENT_SETTING_ALLOW);
AddToPreloadDataBlocklist(origin_to_revoke, SiteReputation::ABUSIVE_CONTENT,
/*has_warning=*/false);
AddToSafeBrowsingBlocklist(origin_to_revoke);
// The origin added to the exempt list will not be revoked.
QueryAndExpectDecisionForUrl(origin_to_exempt,
Outcome::PERMISSION_NOT_REVOKED);
VerifyNotificationsPermission(origin_to_revoke, CONTENT_SETTING_ALLOW);
QueryAndExpectDecisionForUrl(origin_to_revoke,
Outcome::PERMISSION_REVOKED_DUE_TO_ABUSE);
VerifyNotificationsPermission(origin_to_revoke, CONTENT_SETTING_ASK);
}
TEST_F(AbusiveOriginPermissionRevocationRequestTest, SafeBrowsingDisabledTest) {
const GURL origin_to_revoke = GURL("https://origin.com/");
SetPermission(origin_to_revoke, CONTENT_SETTING_ALLOW);
AddToSafeBrowsingBlocklist(origin_to_revoke);
AddToPreloadDataBlocklist(origin_to_revoke, SiteReputation::ABUSIVE_CONTENT,
/*has_warning=*/false);
QueryAndExpectDecisionForUrl(origin_to_revoke,
Outcome::PERMISSION_REVOKED_DUE_TO_ABUSE);
GetTestingProfile()->GetPrefs()->SetBoolean(prefs::kSafeBrowsingEnabled,
false);
// Permission should not be revoked because Safe Browsing is disabled.
const GURL origin_to_not_revoke = GURL("https://origin-not_revoked.com/");
SetPermission(origin_to_not_revoke, CONTENT_SETTING_ALLOW);
AddToSafeBrowsingBlocklist(origin_to_not_revoke);
AddToPreloadDataBlocklist(origin_to_not_revoke,
SiteReputation::ABUSIVE_CONTENT,
/*has_warning=*/false);
QueryAndExpectDecisionForUrl(origin_to_not_revoke,
Outcome::PERMISSION_NOT_REVOKED);
VerifyNotificationsPermission(origin_to_not_revoke, CONTENT_SETTING_ALLOW);
}
class AbusiveOriginPermissionRevocationRequestDisabledTest
: public AbusiveOriginPermissionRevocationRequestTestBase {
public:
AbusiveOriginPermissionRevocationRequestDisabledTest() = default;
~AbusiveOriginPermissionRevocationRequestDisabledTest() override = default;
};
TEST_F(AbusiveOriginPermissionRevocationRequestDisabledTest,
PermissionRevocationFeatureDisabled) {
const GURL origin_to_revoke = GURL("https://origin.com/");
SetPermission(origin_to_revoke, CONTENT_SETTING_ALLOW);
QueryAndExpectDecisionForUrl(origin_to_revoke,
Outcome::PERMISSION_NOT_REVOKED);
VerifyNotificationsPermission(origin_to_revoke, CONTENT_SETTING_ALLOW);
}