blob: 57fa32966089ad0585627d8479a23e3cddaa8969 [file] [log] [blame]
mlamouri4e372022015-03-29 14:51:061// Copyright 2015 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
Clark DuVall6b73c742020-03-11 19:00:155#ifndef COMPONENTS_PERMISSIONS_PERMISSION_MANAGER_H_
6#define COMPONENTS_PERMISSIONS_PERMISSION_MANAGER_H_
mlamouri4e372022015-03-29 14:51:067
Lei Zhang998100f2021-06-25 17:58:198#include <map>
raymese3afee6b2016-04-18 02:00:509#include <unordered_map>
10
mlamouri4e372022015-03-29 14:51:0611#include "base/callback_forward.h"
James Hollyerd281a7312021-04-29 21:07:5912#include "base/containers/flat_map.h"
Brett Wilsonf976d3f2017-08-18 17:23:3913#include "base/containers/id_map.h"
Keishi Hattori0e45c022021-11-27 09:25:5214#include "base/memory/raw_ptr.h"
mlamouri23957a22015-04-01 10:37:5615#include "components/content_settings/core/browser/content_settings_observer.h"
lalitm27583e92015-10-02 11:34:1716#include "components/content_settings/core/common/content_settings.h"
mlamouri4e372022015-03-29 14:51:0617#include "components/keyed_service/core/keyed_service.h"
James Hollyerd281a7312021-04-29 21:07:5918#include "components/permissions/permission_context_base.h"
Balazs Engedye15473b2021-04-14 09:09:2119#include "components/permissions/permission_request_id.h"
Clark DuVall732778e2020-01-27 18:13:5820#include "components/permissions/permission_util.h"
Andrey Lushnikovf3500102018-07-16 19:55:2221#include "content/public/browser/permission_controller_delegate.h"
Pavel Feldman73b22022018-11-02 02:55:3022#include "content/public/browser/permission_type.h"
Rohan Pavonefaf64572019-07-30 17:50:2023#include "url/origin.h"
mlamouri4e372022015-03-29 14:51:0624
Clark DuVall6b73c742020-03-11 19:00:1525namespace content {
26class BrowserContext;
27}
28
Clark DuVall484c2562020-01-23 22:05:0929namespace permissions {
Clark DuValla11361ad32020-02-20 22:14:2730class PermissionContextBase;
timlohc6911802017-03-01 05:37:0331struct PermissionResult;
mlamouri4e372022015-03-29 14:51:0632
mlamouri4e372022015-03-29 14:51:0633class PermissionManager : public KeyedService,
Andrey Lushnikovf3500102018-07-16 19:55:2234 public content::PermissionControllerDelegate,
James Hollyerd281a7312021-04-29 21:07:5935 public permissions::Observer {
mlamouri4e372022015-03-29 14:51:0636 public:
Clark DuVall6b73c742020-03-11 19:00:1537 using PermissionContextMap =
38 std::unordered_map<ContentSettingsType,
39 std::unique_ptr<PermissionContextBase>,
40 ContentSettingsTypeHash>;
41 PermissionManager(content::BrowserContext* browser_context,
42 PermissionContextMap permission_contexts);
Peter Boström09c01822021-09-20 22:43:2743
44 PermissionManager(const PermissionManager&) = delete;
45 PermissionManager& operator=(const PermissionManager&) = delete;
46
mlamouri4e372022015-03-29 14:51:0647 ~PermissionManager() override;
48
Marc Treib9e4bd922017-09-25 08:32:1349 // Converts from |url|'s actual origin to the "canonical origin" that should
50 // be used for the purpose of requesting/storing permissions. For example, the
Raymes Khouryb474c642018-02-28 06:16:2851 // origin of the local NTP gets mapped to the Google base URL instead. With
52 // Permission Delegation it will transform the requesting origin into
53 // the embedding origin because all permission checks happen on the top level
54 // origin.
55 //
56 // All the public methods below, such as RequestPermission or
57 // GetPermissionStatus, take the actual origin and do the canonicalization
58 // internally. You only need to call this directly if you do something else
59 // with the origin, such as display it in the UI.
Balazs Engedyf39e22b2019-07-30 11:16:2460 GURL GetCanonicalOrigin(ContentSettingsType permission,
61 const GURL& requesting_origin,
Raymes Khouryb474c642018-02-28 06:16:2862 const GURL& embedding_origin) const;
Marc Treib9e4bd922017-09-25 08:32:1363
timloh9a180ad2017-02-20 07:15:2364 // Callers from within chrome/ should use the methods which take the
65 // ContentSettingsType enum. The methods which take PermissionType values
Andrey Lushnikovf3500102018-07-16 19:55:2266 // are for the content::PermissionControllerDelegate overrides and shouldn't
67 // be used from chrome/.
Illia Klimovfa8fa512021-07-14 20:36:3468 // Deprecated. Use `RequestPermissionFromCurrentDocument` instead.
Balazs Engedye30e9612021-04-02 10:37:2969 void RequestPermission(ContentSettingsType permission,
70 content::RenderFrameHost* render_frame_host,
71 const GURL& requesting_origin,
72 bool user_gesture,
73 base::OnceCallback<void(ContentSetting)> callback);
Illia Klimovfa8fa512021-07-14 20:36:3474 // Deprecated. Use `RequestPermissionsFromCurrentDocument` instead.
Balazs Engedye30e9612021-04-02 10:37:2975 void RequestPermissions(
timloh592d7322017-02-23 07:23:5476 const std::vector<ContentSettingsType>& permissions,
77 content::RenderFrameHost* render_frame_host,
78 const GURL& requesting_origin,
79 bool user_gesture,
danakj47c8fb52019-05-02 16:34:3680 base::OnceCallback<void(const std::vector<ContentSetting>&)> callback);
Illia Klimovfa8fa512021-07-14 20:36:3481 void RequestPermissionFromCurrentDocument(
82 ContentSettingsType permission,
83 content::RenderFrameHost* render_frame_host,
84 bool user_gesture,
85 base::OnceCallback<void(ContentSetting)> callback);
86 // Requests the given `permission` on behalf of the last committed document in
87 // `render_frame_host`, also performing additional checks such as Permission
88 // Policy.
89 void RequestPermissionsFromCurrentDocument(
90 const std::vector<ContentSettingsType>& permissions,
91 content::RenderFrameHost* render_frame_host,
92 bool user_gesture,
93 base::OnceCallback<void(const std::vector<ContentSetting>&)> callback);
timloh592d7322017-02-23 07:23:5494
Clark DuVall6b73c742020-03-11 19:00:1595 PermissionResult GetPermissionStatus(ContentSettingsType permission,
96 const GURL& requesting_origin,
97 const GURL& embedding_origin);
timloh9a180ad2017-02-20 07:15:2398
Illia Klimov678d9fca2022-03-28 11:03:5499 // Returns the permission status for a given `permission` and displayed,
100 // top-level `origin`. This should be used only for displaying on the
101 // browser's native UI (PageInfo, Settings, etc.). This method does not take
102 // context specific restrictions (e.g. permission policy) into consideration.
103 PermissionResult GetPermissionStatusForDisplayOnSettingsUI(
104 ContentSettingsType permission,
105 const GURL& origin);
106
raymesf6104d492017-03-09 01:20:18107 // Returns the permission status for a given frame. This should be preferred
108 // over GetPermissionStatus as additional checks can be performed when we know
109 // the exact context the request is coming from.
raymes79f22a612017-03-13 05:28:10110 // TODO(raymes): Currently we still pass the |requesting_origin| as a separate
111 // parameter because we can't yet guarantee that it matches the last committed
112 // origin of the RenderFrameHost. See crbug.com/698985.
Illia Klimovfa8fa512021-07-14 20:36:34113 // Deprecated. Use `GetPermissionStatusForCurrentDocument` instead.
Clark DuVall6b73c742020-03-11 19:00:15114 PermissionResult GetPermissionStatusForFrame(
raymesf6104d492017-03-09 01:20:18115 ContentSettingsType permission,
raymes79f22a612017-03-13 05:28:10116 content::RenderFrameHost* render_frame_host,
117 const GURL& requesting_origin);
raymesf6104d492017-03-09 01:20:18118
Illia Klimovfa8fa512021-07-14 20:36:34119 // Returns the status for the given `permission` on behalf of the last
120 // committed document in `render_frame_host`, also performing additional
121 // checks such as Permission Policy.
122 PermissionResult GetPermissionStatusForCurrentDocument(
123 ContentSettingsType permission,
124 content::RenderFrameHost* render_frame_host);
125
Andrey Lushnikovf3500102018-07-16 19:55:22126 // content::PermissionControllerDelegate implementation.
Balazs Engedye30e9612021-04-02 10:37:29127 void RequestPermission(
128 content::PermissionType permission,
129 content::RenderFrameHost* render_frame_host,
130 const GURL& requesting_origin,
131 bool user_gesture,
132 base::OnceCallback<void(blink::mojom::PermissionStatus)> callback)
133 override;
134 void RequestPermissions(
mlamouri8b5ec902015-10-24 00:52:03135 const std::vector<content::PermissionType>& permissions,
136 content::RenderFrameHost* render_frame_host,
137 const GURL& requesting_origin,
benwellsfd2b1552016-07-05 04:26:53138 bool user_gesture,
danakj47c8fb52019-05-02 16:34:36139 base::OnceCallback<
140 void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
leon.han06e55662016-03-26 17:19:42141 override;
mlamouri4e372022015-03-29 14:51:06142 void ResetPermission(content::PermissionType permission,
143 const GURL& requesting_origin,
144 const GURL& embedding_origin) override;
mathpcc29ae52016-05-04 15:22:17145 blink::mojom::PermissionStatus GetPermissionStatus(
mlamouri4e372022015-03-29 14:51:06146 content::PermissionType permission,
147 const GURL& requesting_origin,
148 const GURL& embedding_origin) override;
Raymes Khoury4ead6c32018-03-07 04:43:48149 blink::mojom::PermissionStatus GetPermissionStatusForFrame(
150 content::PermissionType permission,
151 content::RenderFrameHost* render_frame_host,
152 const GURL& requesting_origin) override;
Illia Klimovf2842842022-03-22 11:33:39153 blink::mojom::PermissionStatus GetPermissionStatusForCurrentDocument(
154 content::PermissionType permission,
155 content::RenderFrameHost* render_frame_host) override;
Pavel Feldman446a91b2020-03-13 17:39:55156 bool IsPermissionOverridableByDevTools(
157 content::PermissionType permission,
Anton Bikineev1156b5f2021-05-15 22:35:36158 const absl::optional<url::Origin>& origin) override;
Balazs Engedyad1489b2021-03-31 07:47:19159 SubscriptionId SubscribePermissionStatusChange(
mlamouri23957a22015-04-01 10:37:56160 content::PermissionType permission,
Raymes Khoury3ef4f6e2018-08-09 09:34:48161 content::RenderFrameHost* render_frame_host,
mlamouri23957a22015-04-01 10:37:56162 const GURL& requesting_origin,
danakj47c8fb52019-05-02 16:34:36163 base::RepeatingCallback<void(blink::mojom::PermissionStatus)> callback)
mathpcc29ae52016-05-04 15:22:17164 override;
Balazs Engedyad1489b2021-03-31 07:47:19165 void UnsubscribePermissionStatusChange(
166 SubscriptionId subscription_id) override;
mlamouri4e372022015-03-29 14:51:06167
timlohc6911802017-03-01 05:37:03168 // TODO(raymes): Rather than exposing this, use the denial reason from
169 // GetPermissionStatus in callers to determine whether a permission is
raymes893dbdd602016-12-19 22:49:29170 // denied due to the kill switch.
timloh9a180ad2017-02-20 07:15:23171 bool IsPermissionKillSwitchOn(ContentSettingsType);
raymes893dbdd602016-12-19 22:49:29172
Rohan Pavonefaf64572019-07-30 17:50:20173 // For the given |origin|, overrides permissions that belong to |overrides|.
174 // These permissions are in-sync with the PermissionController.
175 void SetPermissionOverridesForDevTools(
Anton Bikineev1156b5f2021-05-15 22:35:36176 const absl::optional<url::Origin>& origin,
Rohan Pavonefaf64572019-07-30 17:50:20177 const PermissionOverrides& overrides) override;
178 void ResetPermissionOverridesForDevTools() override;
Pavel Feldman73b22022018-11-02 02:55:30179
Alexey Baskakov386f1742019-09-03 04:08:47180 // KeyedService implementation
181 void Shutdown() override;
182
Clark DuVall2c6c8672020-03-18 18:41:20183 // Helper method to convert PermissionType to ContentSettingType.
184 static ContentSettingsType PermissionTypeToContentSetting(
185 content::PermissionType permission);
186
Clark DuVall6b73c742020-03-11 19:00:15187 PermissionContextBase* GetPermissionContextForTesting(
188 ContentSettingsType type);
189
mlamouri4e372022015-03-29 14:51:06190 private:
raymes158a8c12017-07-06 02:52:59191 friend class PermissionManagerTest;
raymese3afee6b2016-04-18 02:00:50192
Balazs Engedye15473b2021-04-14 09:09:21193 // The `PendingRequestLocalId` will be unique within the `PermissionManager`
194 // instance, thus within a `BrowserContext`, which overachieves the
195 // requirement from `PermissionRequestID` that the `RequestLocalId` be unique
196 // within each frame.
mlamouri8b5ec902015-10-24 00:52:03197 class PendingRequest;
Balazs Engedye15473b2021-04-14 09:09:21198 using PendingRequestLocalId = PermissionRequestID::RequestLocalId;
199 using PendingRequestsMap =
200 base::IDMap<std::unique_ptr<PendingRequest>, PendingRequestLocalId>;
lalitm27583e92015-10-02 11:34:17201
raymes158a8c12017-07-06 02:52:59202 class PermissionResponseCallback;
203
mlamouri23957a22015-04-01 10:37:56204 struct Subscription;
Balazs Engedyad1489b2021-03-31 07:47:19205 using SubscriptionsMap =
206 base::IDMap<std::unique_ptr<Subscription>, SubscriptionId>;
James Hollyerd281a7312021-04-29 21:07:59207 using SubscriptionTypeCounts = base::flat_map<ContentSettingsType, size_t>;
mlamouri23957a22015-04-01 10:37:56208
Clark DuVall6b73c742020-03-11 19:00:15209 PermissionContextBase* GetPermissionContext(ContentSettingsType type);
raymese3afee6b2016-04-18 02:00:50210
mlamouri8b5ec902015-10-24 00:52:03211 // Called when a permission was decided for a given PendingRequest. The
Balazs Engedye15473b2021-04-14 09:09:21212 // PendingRequest is identified by its |request_local_id| and the permission
213 // is identified by its |permission_id|. If the PendingRequest contains more
214 // than one permission, it will wait for the remaining permissions to be
215 // resolved. When all the permissions have been resolved, the PendingRequest's
216 // callback is run.
217 void OnPermissionsRequestResponseStatus(
218 PendingRequestLocalId request_local_id,
219 int permission_id,
220 ContentSetting status);
lalitm27583e92015-10-02 11:34:17221
James Hollyerd281a7312021-04-29 21:07:59222 // permissions::Observer:
223 void OnPermissionChanged(const ContentSettingsPattern& primary_pattern,
224 const ContentSettingsPattern& secondary_pattern,
Christian Dullweber2c4c71d2021-10-14 15:07:43225 ContentSettingsTypeSet content_type_set) override;
mlamouri23957a22015-04-01 10:37:56226
Clark DuVall6b73c742020-03-11 19:00:15227 PermissionResult GetPermissionStatusHelper(
raymesf6104d492017-03-09 01:20:18228 ContentSettingsType permission,
229 content::RenderFrameHost* render_frame_host,
230 const GURL& requesting_origin,
231 const GURL& embedding_origin);
232
Pavel Feldman73b22022018-11-02 02:55:30233 ContentSetting GetPermissionOverrideForDevTools(
Rohan Pavone8180cba62019-08-26 20:55:09234 const url::Origin& origin,
Pavel Feldman73b22022018-11-02 02:55:30235 ContentSettingsType permission);
236
Keishi Hattori0e45c022021-11-27 09:25:52237 raw_ptr<content::BrowserContext> browser_context_;
Balazs Engedye15473b2021-04-14 09:09:21238
lalitm27583e92015-10-02 11:34:17239 PendingRequestsMap pending_requests_;
Balazs Engedye15473b2021-04-14 09:09:21240 PendingRequestLocalId::Generator request_local_id_generator_;
241
mlamouri23957a22015-04-01 10:37:56242 SubscriptionsMap subscriptions_;
Balazs Engedyad1489b2021-03-31 07:47:19243 SubscriptionId::Generator subscription_id_generator_;
mlamouri4e372022015-03-29 14:51:06244
James Hollyerd281a7312021-04-29 21:07:59245 // Tracks the number of Subscriptions in |subscriptions_| which have a
246 // certain ContentSettingsType. An entry for a given ContentSettingsType key
247 // is added on first use and never removed. This is done to utilize the
248 // flat_map's efficiency in accessing/editing items and minimize the use of
249 // the unefficient addition/removal of items.
250 SubscriptionTypeCounts subscription_type_counts_;
251
Clark DuVall6b73c742020-03-11 19:00:15252 PermissionContextMap permission_contexts_;
Rohan Pavonefaf64572019-07-30 17:50:20253 using ContentSettingsTypeOverrides =
254 base::flat_map<ContentSettingsType, ContentSetting>;
255 std::map<url::Origin, ContentSettingsTypeOverrides>
256 devtools_permission_overrides_;
Pavel Feldman446a91b2020-03-13 17:39:55257 url::Origin devtools_global_overrides_origin_;
raymese3afee6b2016-04-18 02:00:50258
Alexey Baskakov386f1742019-09-03 04:08:47259 bool is_shutting_down_ = false;
mlamouri4e372022015-03-29 14:51:06260};
261
Clark DuVall6b73c742020-03-11 19:00:15262} // namespace permissions
263
264#endif // COMPONENTS_PERMISSIONS_PERMISSION_MANAGER_H_