blob: e1a64dde564580b16f2fc4dec84f1235c889a66d [file] [log] [blame]
// Copyright 2016 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.
#ifndef COMPONENTS_PERMISSIONS_PERMISSION_DECISION_AUTO_BLOCKER_H_
#define COMPONENTS_PERMISSIONS_PERMISSION_DECISION_AUTO_BLOCKER_H_
#include <set>
#include "base/callback.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/time/default_clock.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/permissions/permission_result.h"
#include "url/gurl.h"
class GURL;
namespace settings {
FORWARD_DECLARE_TEST(SiteSettingsHandlerTest, GetAllSites);
FORWARD_DECLARE_TEST(SiteSettingsHandlerTest, GetRecentSitePermissions);
} // namespace settings
namespace site_settings {
FORWARD_DECLARE_TEST(RecentSiteSettingsHelperTest, CheckRecentSitePermissions);
} // namespace site_settings
namespace permissions {
// The PermissionDecisionAutoBlocker decides whether or not a given origin
// should be automatically blocked from requesting a permission. When an origin
// is blocked, it is placed under an "embargo". Until the embargo expires, any
// requests made by the origin are automatically blocked. Once the embargo is
// lifted, the origin will be permitted to request a permission again, which may
// result in it being placed under embargo again. Currently, an origin can be
// placed under embargo if it has a number of prior dismissals greater than a
// threshold.
class PermissionDecisionAutoBlocker : public KeyedService {
public:
PermissionDecisionAutoBlocker() = delete;
explicit PermissionDecisionAutoBlocker(HostContentSettingsMap* settings_map);
PermissionDecisionAutoBlocker(const PermissionDecisionAutoBlocker&) = delete;
PermissionDecisionAutoBlocker& operator=(
const PermissionDecisionAutoBlocker&) = delete;
~PermissionDecisionAutoBlocker() override;
// Returns whether the permission auto blocker is enabled for the passed-in
// content setting.
static bool IsEnabledForContentSetting(ContentSettingsType content_setting);
// Checks the status of the content setting to determine if |request_origin|
// is under embargo for |permission|. This checks all types of embargo.
// Prefer to use PermissionManager::GetPermissionStatus when possible. This
// method is only exposed to facilitate permission checks from threads other
// than the UI thread. See https://crbug.com/658020.
static PermissionResult GetEmbargoResult(HostContentSettingsMap* settings_map,
const GURL& request_origin,
ContentSettingsType permission,
base::Time current_time);
// Updates the threshold to start blocking prompts from the field trial.
static void UpdateFromVariations();
// Checks the status of the content setting to determine if |request_origin|
// is under embargo for |permission|. This checks all types of embargo.
PermissionResult GetEmbargoResult(const GURL& request_origin,
ContentSettingsType permission);
// Returns the most recent recorded time either an ignore or dismiss embargo
// was started. Records of embargo start times persist beyond the duration of
// the embargo, but are removed along with embargoes when
// RemoveEmbargoAndResetCounts is used. Returns base::Time() if no record is
// found.
base::Time GetEmbargoStartTime(const GURL& request_origin,
ContentSettingsType permission);
// Returns the current number of dismisses recorded for |permission| type at
// |url|.
int GetDismissCount(const GURL& url, ContentSettingsType permission);
// Returns the current number of ignores recorded for |permission|
// type at |url|.
int GetIgnoreCount(const GURL& url, ContentSettingsType permission);
// Returns a set of urls currently under embargo for |content_type|.
std::set<GURL> GetEmbargoedOrigins(ContentSettingsType content_type);
// Returns a set of urls currently under embargo for the provided
// |content_type| types.
std::set<GURL> GetEmbargoedOrigins(
std::vector<ContentSettingsType> content_types);
// Records that a dismissal of a prompt for |permission| was made. If the
// total number of dismissals exceeds a threshhold and
// features::kBlockPromptsIfDismissedOften is enabled, it will place |url|
// under embargo for |permission|. |dismissed_prompt_was_quiet| will inform
// the decision of which threshold to pick, depending on whether the prompt
// that was presented to the user was quiet or not.
bool RecordDismissAndEmbargo(const GURL& url,
ContentSettingsType permission,
bool dismissed_prompt_was_quiet);
// Records that an ignore of a prompt for |permission| was made. If the total
// number of ignores exceeds a threshold and
// features::kBlockPromptsIfIgnoredOften is enabled, it will place |url| under
// embargo for |permission|. |ignored_prompt_was_quiet| will inform the
// decision of which threshold to pick, depending on whether the prompt that
// was presented to the user was quiet or not.
bool RecordIgnoreAndEmbargo(const GURL& url,
ContentSettingsType permission,
bool ignored_prompt_was_quiet);
// Clears any existing embargo status for |url|, |permission|. For permissions
// embargoed under repeated dismissals, this means a prompt will be shown to
// the user on next permission request. Clears dismiss and ignore counts.
void RemoveEmbargoAndResetCounts(const GURL& url,
ContentSettingsType permission);
// Same as above, but cleans the slate for all permissions and for all URLs
// matching |filter|.
void RemoveEmbargoAndResetCounts(
base::RepeatingCallback<bool(const GURL& url)> filter);
static const char* GetPromptDismissCountKeyForTesting();
private:
friend class PermissionDecisionAutoBlockerUnitTest;
FRIEND_TEST_ALL_PREFIXES(site_settings::RecentSiteSettingsHelperTest,
CheckRecentSitePermissions);
FRIEND_TEST_ALL_PREFIXES(settings::SiteSettingsHandlerTest, GetAllSites);
FRIEND_TEST_ALL_PREFIXES(settings::SiteSettingsHandlerTest,
GetRecentSitePermissions);
void PlaceUnderEmbargo(const GURL& request_origin,
ContentSettingsType permission,
const char* key);
void SetClockForTesting(base::Clock* clock);
// Keys used for storing count data in a website setting.
static const char kPromptDismissCountKey[];
static const char kPromptIgnoreCountKey[];
static const char kPromptDismissCountWithQuietUiKey[];
static const char kPromptIgnoreCountWithQuietUiKey[];
static const char kPermissionDismissalEmbargoKey[];
static const char kPermissionIgnoreEmbargoKey[];
raw_ptr<HostContentSettingsMap> settings_map_;
raw_ptr<base::Clock> clock_;
};
} // namespace permissions
#endif // COMPONENTS_PERMISSIONS_PERMISSION_DECISION_AUTO_BLOCKER_H_