blob: 478e6eea14fd315cc80cb35715723b5ad647f8ad [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;
Robbie McElrath8d5602a2022-04-01 17:39:1827class RenderFrameHost;
28class RenderProcessHost;
Clark DuVall6b73c742020-03-11 19:00:1529}
30
Clark DuVall484c2562020-01-23 22:05:0931namespace permissions {
Clark DuValla11361ad32020-02-20 22:14:2732class PermissionContextBase;
timlohc6911802017-03-01 05:37:0333struct PermissionResult;
mlamouri4e372022015-03-29 14:51:0634
mlamouri4e372022015-03-29 14:51:0635class PermissionManager : public KeyedService,
Andrey Lushnikovf3500102018-07-16 19:55:2236 public content::PermissionControllerDelegate,
James Hollyerd281a7312021-04-29 21:07:5937 public permissions::Observer {
mlamouri4e372022015-03-29 14:51:0638 public:
Clark DuVall6b73c742020-03-11 19:00:1539 using PermissionContextMap =
40 std::unordered_map<ContentSettingsType,
41 std::unique_ptr<PermissionContextBase>,
42 ContentSettingsTypeHash>;
43 PermissionManager(content::BrowserContext* browser_context,
44 PermissionContextMap permission_contexts);
Peter Boström09c01822021-09-20 22:43:2745
46 PermissionManager(const PermissionManager&) = delete;
47 PermissionManager& operator=(const PermissionManager&) = delete;
48
mlamouri4e372022015-03-29 14:51:0649 ~PermissionManager() override;
50
Marc Treib9e4bd922017-09-25 08:32:1351 // Converts from |url|'s actual origin to the "canonical origin" that should
52 // be used for the purpose of requesting/storing permissions. For example, the
Raymes Khouryb474c642018-02-28 06:16:2853 // origin of the local NTP gets mapped to the Google base URL instead. With
54 // Permission Delegation it will transform the requesting origin into
55 // the embedding origin because all permission checks happen on the top level
56 // origin.
57 //
58 // All the public methods below, such as RequestPermission or
59 // GetPermissionStatus, take the actual origin and do the canonicalization
60 // internally. You only need to call this directly if you do something else
61 // with the origin, such as display it in the UI.
Balazs Engedyf39e22b2019-07-30 11:16:2462 GURL GetCanonicalOrigin(ContentSettingsType permission,
63 const GURL& requesting_origin,
Raymes Khouryb474c642018-02-28 06:16:2864 const GURL& embedding_origin) const;
Marc Treib9e4bd922017-09-25 08:32:1365
timloh9a180ad2017-02-20 07:15:2366 // Callers from within chrome/ should use the methods which take the
67 // ContentSettingsType enum. The methods which take PermissionType values
Andrey Lushnikovf3500102018-07-16 19:55:2268 // are for the content::PermissionControllerDelegate overrides and shouldn't
69 // be used from chrome/.
Illia Klimovfa8fa512021-07-14 20:36:3470 // Deprecated. Use `RequestPermissionFromCurrentDocument` instead.
Balazs Engedye30e9612021-04-02 10:37:2971 void RequestPermission(ContentSettingsType permission,
72 content::RenderFrameHost* render_frame_host,
73 const GURL& requesting_origin,
74 bool user_gesture,
75 base::OnceCallback<void(ContentSetting)> callback);
Illia Klimovfa8fa512021-07-14 20:36:3476 // Deprecated. Use `RequestPermissionsFromCurrentDocument` instead.
Balazs Engedye30e9612021-04-02 10:37:2977 void RequestPermissions(
timloh592d7322017-02-23 07:23:5478 const std::vector<ContentSettingsType>& permissions,
79 content::RenderFrameHost* render_frame_host,
80 const GURL& requesting_origin,
81 bool user_gesture,
danakj47c8fb52019-05-02 16:34:3682 base::OnceCallback<void(const std::vector<ContentSetting>&)> callback);
Illia Klimovfa8fa512021-07-14 20:36:3483 void RequestPermissionFromCurrentDocument(
84 ContentSettingsType permission,
85 content::RenderFrameHost* render_frame_host,
86 bool user_gesture,
87 base::OnceCallback<void(ContentSetting)> callback);
88 // Requests the given `permission` on behalf of the last committed document in
89 // `render_frame_host`, also performing additional checks such as Permission
90 // Policy.
91 void RequestPermissionsFromCurrentDocument(
92 const std::vector<ContentSettingsType>& permissions,
93 content::RenderFrameHost* render_frame_host,
94 bool user_gesture,
95 base::OnceCallback<void(const std::vector<ContentSetting>&)> callback);
timloh592d7322017-02-23 07:23:5496
Clark DuVall6b73c742020-03-11 19:00:1597 PermissionResult GetPermissionStatus(ContentSettingsType permission,
98 const GURL& requesting_origin,
99 const GURL& embedding_origin);
timloh9a180ad2017-02-20 07:15:23100
Illia Klimov678d9fca2022-03-28 11:03:54101 // Returns the permission status for a given `permission` and displayed,
102 // top-level `origin`. This should be used only for displaying on the
103 // browser's native UI (PageInfo, Settings, etc.). This method does not take
104 // context specific restrictions (e.g. permission policy) into consideration.
105 PermissionResult GetPermissionStatusForDisplayOnSettingsUI(
106 ContentSettingsType permission,
107 const GURL& origin);
108
raymesf6104d492017-03-09 01:20:18109 // Returns the permission status for a given frame. This should be preferred
110 // over GetPermissionStatus as additional checks can be performed when we know
111 // the exact context the request is coming from.
raymes79f22a612017-03-13 05:28:10112 // TODO(raymes): Currently we still pass the |requesting_origin| as a separate
113 // parameter because we can't yet guarantee that it matches the last committed
114 // origin of the RenderFrameHost. See crbug.com/698985.
Illia Klimovfa8fa512021-07-14 20:36:34115 // Deprecated. Use `GetPermissionStatusForCurrentDocument` instead.
Clark DuVall6b73c742020-03-11 19:00:15116 PermissionResult GetPermissionStatusForFrame(
raymesf6104d492017-03-09 01:20:18117 ContentSettingsType permission,
raymes79f22a612017-03-13 05:28:10118 content::RenderFrameHost* render_frame_host,
119 const GURL& requesting_origin);
raymesf6104d492017-03-09 01:20:18120
Illia Klimovfa8fa512021-07-14 20:36:34121 // Returns the status for the given `permission` on behalf of the last
122 // committed document in `render_frame_host`, also performing additional
123 // checks such as Permission Policy.
124 PermissionResult GetPermissionStatusForCurrentDocument(
125 ContentSettingsType permission,
126 content::RenderFrameHost* render_frame_host);
127
Robbie McElrath8d5602a2022-04-01 17:39:18128 // Returns the status of the given `permission` for a worker on `origin`
129 // running in the renderer corresponding to `render_process_host`.
130 PermissionResult GetPermissionStatusForWorker(
131 ContentSettingsType permission,
132 content::RenderProcessHost* render_process_host,
133 const url::Origin& worker_origin);
134
Andrey Lushnikovf3500102018-07-16 19:55:22135 // content::PermissionControllerDelegate implementation.
Balazs Engedye30e9612021-04-02 10:37:29136 void RequestPermission(
137 content::PermissionType permission,
138 content::RenderFrameHost* render_frame_host,
139 const GURL& requesting_origin,
140 bool user_gesture,
141 base::OnceCallback<void(blink::mojom::PermissionStatus)> callback)
142 override;
143 void RequestPermissions(
mlamouri8b5ec902015-10-24 00:52:03144 const std::vector<content::PermissionType>& permissions,
145 content::RenderFrameHost* render_frame_host,
146 const GURL& requesting_origin,
benwellsfd2b1552016-07-05 04:26:53147 bool user_gesture,
danakj47c8fb52019-05-02 16:34:36148 base::OnceCallback<
149 void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
leon.han06e55662016-03-26 17:19:42150 override;
mlamouri4e372022015-03-29 14:51:06151 void ResetPermission(content::PermissionType permission,
152 const GURL& requesting_origin,
153 const GURL& embedding_origin) override;
mathpcc29ae52016-05-04 15:22:17154 blink::mojom::PermissionStatus GetPermissionStatus(
mlamouri4e372022015-03-29 14:51:06155 content::PermissionType permission,
156 const GURL& requesting_origin,
157 const GURL& embedding_origin) override;
Raymes Khoury4ead6c32018-03-07 04:43:48158 blink::mojom::PermissionStatus GetPermissionStatusForFrame(
159 content::PermissionType permission,
160 content::RenderFrameHost* render_frame_host,
161 const GURL& requesting_origin) override;
Illia Klimovf2842842022-03-22 11:33:39162 blink::mojom::PermissionStatus GetPermissionStatusForCurrentDocument(
163 content::PermissionType permission,
164 content::RenderFrameHost* render_frame_host) override;
Robbie McElrath8d5602a2022-04-01 17:39:18165 blink::mojom::PermissionStatus GetPermissionStatusForWorker(
166 content::PermissionType permission,
167 content::RenderProcessHost* render_process_host,
168 const GURL& worker_origin) override;
Pavel Feldman446a91b2020-03-13 17:39:55169 bool IsPermissionOverridableByDevTools(
170 content::PermissionType permission,
Anton Bikineev1156b5f2021-05-15 22:35:36171 const absl::optional<url::Origin>& origin) override;
Balazs Engedyad1489b2021-03-31 07:47:19172 SubscriptionId SubscribePermissionStatusChange(
mlamouri23957a22015-04-01 10:37:56173 content::PermissionType permission,
Robbie McElrath8d5602a2022-04-01 17:39:18174 content::RenderProcessHost* render_process_host,
Raymes Khoury3ef4f6e2018-08-09 09:34:48175 content::RenderFrameHost* render_frame_host,
mlamouri23957a22015-04-01 10:37:56176 const GURL& requesting_origin,
danakj47c8fb52019-05-02 16:34:36177 base::RepeatingCallback<void(blink::mojom::PermissionStatus)> callback)
mathpcc29ae52016-05-04 15:22:17178 override;
Balazs Engedyad1489b2021-03-31 07:47:19179 void UnsubscribePermissionStatusChange(
180 SubscriptionId subscription_id) override;
mlamouri4e372022015-03-29 14:51:06181
timlohc6911802017-03-01 05:37:03182 // TODO(raymes): Rather than exposing this, use the denial reason from
183 // GetPermissionStatus in callers to determine whether a permission is
raymes893dbdd602016-12-19 22:49:29184 // denied due to the kill switch.
timloh9a180ad2017-02-20 07:15:23185 bool IsPermissionKillSwitchOn(ContentSettingsType);
raymes893dbdd602016-12-19 22:49:29186
Rohan Pavonefaf64572019-07-30 17:50:20187 // For the given |origin|, overrides permissions that belong to |overrides|.
188 // These permissions are in-sync with the PermissionController.
189 void SetPermissionOverridesForDevTools(
Anton Bikineev1156b5f2021-05-15 22:35:36190 const absl::optional<url::Origin>& origin,
Rohan Pavonefaf64572019-07-30 17:50:20191 const PermissionOverrides& overrides) override;
192 void ResetPermissionOverridesForDevTools() override;
Pavel Feldman73b22022018-11-02 02:55:30193
Alexey Baskakov386f1742019-09-03 04:08:47194 // KeyedService implementation
195 void Shutdown() override;
196
Clark DuVall2c6c8672020-03-18 18:41:20197 // Helper method to convert PermissionType to ContentSettingType.
198 static ContentSettingsType PermissionTypeToContentSetting(
199 content::PermissionType permission);
200
Clark DuVall6b73c742020-03-11 19:00:15201 PermissionContextBase* GetPermissionContextForTesting(
202 ContentSettingsType type);
203
mlamouri4e372022015-03-29 14:51:06204 private:
raymes158a8c12017-07-06 02:52:59205 friend class PermissionManagerTest;
raymese3afee6b2016-04-18 02:00:50206
Balazs Engedye15473b2021-04-14 09:09:21207 // The `PendingRequestLocalId` will be unique within the `PermissionManager`
208 // instance, thus within a `BrowserContext`, which overachieves the
209 // requirement from `PermissionRequestID` that the `RequestLocalId` be unique
210 // within each frame.
mlamouri8b5ec902015-10-24 00:52:03211 class PendingRequest;
Balazs Engedye15473b2021-04-14 09:09:21212 using PendingRequestLocalId = PermissionRequestID::RequestLocalId;
213 using PendingRequestsMap =
214 base::IDMap<std::unique_ptr<PendingRequest>, PendingRequestLocalId>;
lalitm27583e92015-10-02 11:34:17215
raymes158a8c12017-07-06 02:52:59216 class PermissionResponseCallback;
217
mlamouri23957a22015-04-01 10:37:56218 struct Subscription;
Balazs Engedyad1489b2021-03-31 07:47:19219 using SubscriptionsMap =
220 base::IDMap<std::unique_ptr<Subscription>, SubscriptionId>;
James Hollyerd281a7312021-04-29 21:07:59221 using SubscriptionTypeCounts = base::flat_map<ContentSettingsType, size_t>;
mlamouri23957a22015-04-01 10:37:56222
Clark DuVall6b73c742020-03-11 19:00:15223 PermissionContextBase* GetPermissionContext(ContentSettingsType type);
raymese3afee6b2016-04-18 02:00:50224
mlamouri8b5ec902015-10-24 00:52:03225 // Called when a permission was decided for a given PendingRequest. The
Balazs Engedye15473b2021-04-14 09:09:21226 // PendingRequest is identified by its |request_local_id| and the permission
227 // is identified by its |permission_id|. If the PendingRequest contains more
228 // than one permission, it will wait for the remaining permissions to be
229 // resolved. When all the permissions have been resolved, the PendingRequest's
230 // callback is run.
231 void OnPermissionsRequestResponseStatus(
232 PendingRequestLocalId request_local_id,
233 int permission_id,
234 ContentSetting status);
lalitm27583e92015-10-02 11:34:17235
James Hollyerd281a7312021-04-29 21:07:59236 // permissions::Observer:
237 void OnPermissionChanged(const ContentSettingsPattern& primary_pattern,
238 const ContentSettingsPattern& secondary_pattern,
Christian Dullweber2c4c71d2021-10-14 15:07:43239 ContentSettingsTypeSet content_type_set) override;
mlamouri23957a22015-04-01 10:37:56240
Robbie McElrath8d5602a2022-04-01 17:39:18241 // Only one of |render_process_host| and |render_frame_host| should be set,
242 // or neither. RenderProcessHost will be inferred from |render_frame_host|.
Clark DuVall6b73c742020-03-11 19:00:15243 PermissionResult GetPermissionStatusHelper(
raymesf6104d492017-03-09 01:20:18244 ContentSettingsType permission,
Robbie McElrath8d5602a2022-04-01 17:39:18245 content::RenderProcessHost* render_process_host,
raymesf6104d492017-03-09 01:20:18246 content::RenderFrameHost* render_frame_host,
247 const GURL& requesting_origin,
248 const GURL& embedding_origin);
249
Pavel Feldman73b22022018-11-02 02:55:30250 ContentSetting GetPermissionOverrideForDevTools(
Rohan Pavone8180cba62019-08-26 20:55:09251 const url::Origin& origin,
Pavel Feldman73b22022018-11-02 02:55:30252 ContentSettingsType permission);
253
Keishi Hattori0e45c022021-11-27 09:25:52254 raw_ptr<content::BrowserContext> browser_context_;
Balazs Engedye15473b2021-04-14 09:09:21255
lalitm27583e92015-10-02 11:34:17256 PendingRequestsMap pending_requests_;
Balazs Engedye15473b2021-04-14 09:09:21257 PendingRequestLocalId::Generator request_local_id_generator_;
258
mlamouri23957a22015-04-01 10:37:56259 SubscriptionsMap subscriptions_;
Balazs Engedyad1489b2021-03-31 07:47:19260 SubscriptionId::Generator subscription_id_generator_;
mlamouri4e372022015-03-29 14:51:06261
James Hollyerd281a7312021-04-29 21:07:59262 // Tracks the number of Subscriptions in |subscriptions_| which have a
263 // certain ContentSettingsType. An entry for a given ContentSettingsType key
264 // is added on first use and never removed. This is done to utilize the
265 // flat_map's efficiency in accessing/editing items and minimize the use of
266 // the unefficient addition/removal of items.
267 SubscriptionTypeCounts subscription_type_counts_;
268
Clark DuVall6b73c742020-03-11 19:00:15269 PermissionContextMap permission_contexts_;
Rohan Pavonefaf64572019-07-30 17:50:20270 using ContentSettingsTypeOverrides =
271 base::flat_map<ContentSettingsType, ContentSetting>;
272 std::map<url::Origin, ContentSettingsTypeOverrides>
273 devtools_permission_overrides_;
Pavel Feldman446a91b2020-03-13 17:39:55274 url::Origin devtools_global_overrides_origin_;
raymese3afee6b2016-04-18 02:00:50275
Alexey Baskakov386f1742019-09-03 04:08:47276 bool is_shutting_down_ = false;
mlamouri4e372022015-03-29 14:51:06277};
278
Clark DuVall6b73c742020-03-11 19:00:15279} // namespace permissions
280
281#endif // COMPONENTS_PERMISSIONS_PERMISSION_MANAGER_H_