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 3 // found in the LICENSE file. 4 5 #ifndef COMPONENTS_PERMISSIONS_PERMISSION_DECISION_AUTO_BLOCKER_H_ 6 #define COMPONENTS_PERMISSIONS_PERMISSION_DECISION_AUTO_BLOCKER_H_ 7 8 #include "base/callback.h" 9 #include "base/gtest_prod_util.h" 10 #include "base/macros.h" 11 #include "base/memory/singleton.h" 12 #include "base/time/default_clock.h" 13 #include "components/content_settings/core/browser/host_content_settings_map.h" 14 #include "components/content_settings/core/common/content_settings_types.h" 15 #include "components/keyed_service/core/keyed_service.h" 16 #include "components/permissions/permission_result.h" 17 #include "url/gurl.h" 18 19 class GURL; 20 21 namespace settings { 22 FORWARD_DECLARE_TEST(SiteSettingsHandlerTest, GetAllSites); 23 FORWARD_DECLARE_TEST(SiteSettingsHandlerTest, GetRecentSitePermissions); 24 } // namespace settings 25 26 namespace site_settings { 27 FORWARD_DECLARE_TEST(RecentSiteSettingsHelperTest, CheckRecentSitePermissions); 28 } // namespace site_settings 29 30 namespace permissions { 31 32 // The PermissionDecisionAutoBlocker decides whether or not a given origin 33 // should be automatically blocked from requesting a permission. When an origin 34 // is blocked, it is placed under an "embargo". Until the embargo expires, any 35 // requests made by the origin are automatically blocked. Once the embargo is 36 // lifted, the origin will be permitted to request a permission again, which may 37 // result in it being placed under embargo again. Currently, an origin can be 38 // placed under embargo if it has a number of prior dismissals greater than a 39 // threshold. 40 class PermissionDecisionAutoBlocker : public KeyedService { 41 public: 42 explicit PermissionDecisionAutoBlocker(HostContentSettingsMap* settings_map); 43 ~PermissionDecisionAutoBlocker() override; 44 45 // Checks the status of the content setting to determine if |request_origin| 46 // is under embargo for |permission|. This checks all types of embargo. 47 // Prefer to use PermissionManager::GetPermissionStatus when possible. This 48 // method is only exposed to facilitate permission checks from threads other 49 // than the UI thread. See https://crbug.com/658020. 50 static PermissionResult GetEmbargoResult(HostContentSettingsMap* settings_map, 51 const GURL& request_origin, 52 ContentSettingsType permission, 53 base::Time current_time); 54 55 // Updates the threshold to start blocking prompts from the field trial. 56 static void UpdateFromVariations(); 57 58 // Checks the status of the content setting to determine if |request_origin| 59 // is under embargo for |permission|. This checks all types of embargo. 60 PermissionResult GetEmbargoResult(const GURL& request_origin, 61 ContentSettingsType permission); 62 63 // Returns the most recent recorded time either an ignore or dismiss embargo 64 // was started. Records of embargo start times persist beyond the duration of 65 // the embargo, but are removed along with embargoes when RemoveEmbargoByUrl 66 // or RemoveCountsByUrl are used. Returns base::Time() if no record is found. 67 base::Time GetEmbargoStartTime(const GURL& request_origin, 68 ContentSettingsType permission); 69 70 // Returns the current number of dismisses recorded for |permission| type at 71 // |url|. 72 int GetDismissCount(const GURL& url, ContentSettingsType permission); 73 74 // Returns the current number of ignores recorded for |permission| 75 // type at |url|. 76 int GetIgnoreCount(const GURL& url, ContentSettingsType permission); 77 78 // Returns a set of urls currently under embargo for |content_type|. 79 std::set<GURL> GetEmbargoedOrigins(ContentSettingsType content_type); 80 81 // Returns a set of urls currently under embargo for the provided 82 // |content_type| types. 83 std::set<GURL> GetEmbargoedOrigins( 84 std::vector<ContentSettingsType> content_types); 85 86 // Records that a dismissal of a prompt for |permission| was made. If the 87 // total number of dismissals exceeds a threshhold and 88 // features::kBlockPromptsIfDismissedOften is enabled, it will place |url| 89 // under embargo for |permission|. |dismissed_prompt_was_quiet| will inform 90 // the decision of which threshold to pick, depending on whether the prompt 91 // that was presented to the user was quiet or not. 92 bool RecordDismissAndEmbargo(const GURL& url, 93 ContentSettingsType permission, 94 bool dismissed_prompt_was_quiet); 95 96 // Records that an ignore of a prompt for |permission| was made. If the total 97 // number of ignores exceeds a threshold and 98 // features::kBlockPromptsIfIgnoredOften is enabled, it will place |url| under 99 // embargo for |permission|. |ignored_prompt_was_quiet| will inform the 100 // decision of which threshold to pick, depending on whether the prompt that 101 // was presented to the user was quiet or not. 102 bool RecordIgnoreAndEmbargo(const GURL& url, 103 ContentSettingsType permission, 104 bool ignored_prompt_was_quiet); 105 106 // Clears any existing embargo status for |url|, |permission|. For permissions 107 // embargoed under repeated dismissals, this means a prompt will be shown to 108 // the user on next permission request. This is a NO-OP for non-embargoed 109 // |url|, |permission| pairs. 110 void RemoveEmbargoByUrl(const GURL& url, ContentSettingsType permission); 111 112 // Removes any recorded counts for urls which match |filter|. 113 void RemoveCountsByUrl(base::Callback<bool(const GURL& url)> filter); 114 115 static const char* GetPromptDismissCountKeyForTesting(); 116 117 private: 118 friend class PermissionDecisionAutoBlockerUnitTest; 119 FRIEND_TEST_ALL_PREFIXES(site_settings::RecentSiteSettingsHelperTest, 120 CheckRecentSitePermissions); 121 FRIEND_TEST_ALL_PREFIXES(settings::SiteSettingsHandlerTest, GetAllSites); 122 FRIEND_TEST_ALL_PREFIXES(settings::SiteSettingsHandlerTest, 123 GetRecentSitePermissions); 124 125 void PlaceUnderEmbargo(const GURL& request_origin, 126 ContentSettingsType permission, 127 const char* key); 128 129 void SetClockForTesting(base::Clock* clock); 130 131 // Keys used for storing count data in a website setting. 132 static const char kPromptDismissCountKey[]; 133 static const char kPromptIgnoreCountKey[]; 134 static const char kPromptDismissCountWithQuietUiKey[]; 135 static const char kPromptIgnoreCountWithQuietUiKey[]; 136 static const char kPermissionDismissalEmbargoKey[]; 137 static const char kPermissionIgnoreEmbargoKey[]; 138 139 HostContentSettingsMap* settings_map_; 140 141 base::Clock* clock_; 142 143 DISALLOW_IMPLICIT_CONSTRUCTORS(PermissionDecisionAutoBlocker); 144 }; 145 146 } // namespace permissions 147 148 #endif // COMPONENTS_PERMISSIONS_PERMISSION_DECISION_AUTO_BLOCKER_H_ 149