Avi Drissman | 4e1b7bc3 | 2022-09-15 14:03:50 | [diff] [blame] | 1 | // Copyright 2018 The Chromium Authors |
Andrey Lushnikov | ebff044 | 2018-07-12 20:02:58 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Andrey Lushnikov | ebff044 | 2018-07-12 20:02:58 | [diff] [blame] | 5 | #include "content/browser/permissions/permission_controller_impl.h" |
Thomas Nguyen | 5fe1927 | 2022-12-15 10:38:00 | [diff] [blame] | 6 | |
jalonthomas | b3f862a | 2025-07-22 16:02:23 | [diff] [blame] | 7 | #include <optional> |
Peter Kasting | 47250048 | 2024-11-21 18:36:25 | [diff] [blame] | 8 | #include <string> |
| 9 | |
Avi Drissman | adac2199 | 2023-01-11 23:46:39 | [diff] [blame] | 10 | #include "base/functional/bind.h" |
Illia Klimov | e406ecc1 | 2022-11-22 15:53:29 | [diff] [blame] | 11 | #include "content/browser/permissions/permission_service_context.h" |
Illia Klimov | 7709f0ce | 2021-07-05 09:42:39 | [diff] [blame] | 12 | #include "content/browser/permissions/permission_util.h" |
danakj | 22c9ee2 | 2020-09-16 16:37:28 | [diff] [blame] | 13 | #include "content/browser/renderer_host/render_frame_host_impl.h" |
Andrey Lushnikov | ebff044 | 2018-07-12 20:02:58 | [diff] [blame] | 14 | #include "content/public/browser/browser_context.h" |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 15 | #include "content/public/browser/disallow_activation_reason.h" |
Sonja Laurila | e9208bfe | 2022-08-22 13:38:46 | [diff] [blame] | 16 | #include "content/public/browser/permission_controller.h" |
Andrey Lushnikov | f350010 | 2018-07-16 19:55:22 | [diff] [blame] | 17 | #include "content/public/browser/permission_controller_delegate.h" |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 18 | #include "content/public/browser/permission_descriptor_util.h" |
Illia Klimov | 15550f75 | 2022-08-11 19:33:10 | [diff] [blame] | 19 | #include "content/public/browser/permission_result.h" |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 20 | #include "content/public/browser/render_frame_host.h" |
| 21 | #include "content/public/browser/render_process_host.h" |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 22 | #include "content/public/browser/web_contents.h" |
Andy Paicu | a6d6d85 | 2022-04-28 18:08:36 | [diff] [blame] | 23 | #include "third_party/blink/public/common/permissions/permission_utils.h" |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 24 | #include "third_party/blink/public/common/web_preferences/web_preferences.h" |
| 25 | #include "third_party/blink/public/mojom/devtools/console_message.mojom.h" |
Julie Jeongeun Kim | 162c2d28 | 2019-03-13 07:23:52 | [diff] [blame] | 26 | #include "third_party/blink/public/mojom/permissions/permission_status.mojom.h" |
Matt Reichhoff | 56f6228 | 2022-09-12 20:36:00 | [diff] [blame] | 27 | #include "url/origin.h" |
Andrey Lushnikov | ebff044 | 2018-07-12 20:02:58 | [diff] [blame] | 28 | |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 29 | #if !BUILDFLAG(IS_ANDROID) |
| 30 | #include "content/common/features.h" |
| 31 | #endif |
| 32 | |
Andrey Lushnikov | ebff044 | 2018-07-12 20:02:58 | [diff] [blame] | 33 | namespace content { |
| 34 | |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 35 | namespace { |
| 36 | |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 37 | std::optional<blink::scheduler::WebSchedulerTrackedFeature> |
Alexander Timin | 5afc73e | 2019-06-24 01:03:10 | [diff] [blame] | 38 | PermissionToSchedulingFeature(PermissionType permission_name) { |
| 39 | switch (permission_name) { |
Alexander Timin | 5afc73e | 2019-06-24 01:03:10 | [diff] [blame] | 40 | case PermissionType::MIDI: |
| 41 | case PermissionType::MIDI_SYSEX: |
| 42 | return blink::scheduler::WebSchedulerTrackedFeature:: |
| 43 | kRequestedMIDIPermission; |
| 44 | case PermissionType::AUDIO_CAPTURE: |
| 45 | return blink::scheduler::WebSchedulerTrackedFeature:: |
| 46 | kRequestedAudioCapturePermission; |
| 47 | case PermissionType::VIDEO_CAPTURE: |
| 48 | return blink::scheduler::WebSchedulerTrackedFeature:: |
| 49 | kRequestedVideoCapturePermission; |
Alexander Timin | 5afc73e | 2019-06-24 01:03:10 | [diff] [blame] | 50 | case PermissionType::BACKGROUND_SYNC: |
| 51 | case PermissionType::BACKGROUND_FETCH: |
| 52 | case PermissionType::PERIODIC_BACKGROUND_SYNC: |
| 53 | return blink::scheduler::WebSchedulerTrackedFeature:: |
| 54 | kRequestedBackgroundWorkPermission; |
Brandon Maslen | 68e89bd | 2020-02-19 01:28:45 | [diff] [blame] | 55 | case PermissionType::STORAGE_ACCESS_GRANT: |
Matt Reichhoff | 2dbcfbd | 2023-01-03 17:48:33 | [diff] [blame] | 56 | // These two permissions are in the process of being split; they share logic |
Alison Gale | 47d1537d | 2024-04-19 21:31:46 | [diff] [blame] | 57 | // for now. TODO(crbug.com/40246640): split and consolidate as much as |
Matt Reichhoff | 2dbcfbd | 2023-01-03 17:48:33 | [diff] [blame] | 58 | // possible. |
| 59 | case PermissionType::TOP_LEVEL_STORAGE_ACCESS: |
Brandon Maslen | 68e89bd | 2020-02-19 01:28:45 | [diff] [blame] | 60 | return blink::scheduler::WebSchedulerTrackedFeature:: |
| 61 | kRequestedStorageAccessGrant; |
Alexander Timin | 5afc73e | 2019-06-24 01:03:10 | [diff] [blame] | 62 | case PermissionType::PROTECTED_MEDIA_IDENTIFIER: |
| 63 | case PermissionType::DURABLE_STORAGE: |
Darwin Huang | f666174 | 2019-12-06 23:31:31 | [diff] [blame] | 64 | case PermissionType::CLIPBOARD_READ_WRITE: |
| 65 | case PermissionType::CLIPBOARD_SANITIZED_WRITE: |
Alexander Timin | 5afc73e | 2019-06-24 01:03:10 | [diff] [blame] | 66 | case PermissionType::PAYMENT_HANDLER: |
| 67 | case PermissionType::IDLE_DETECTION: |
| 68 | case PermissionType::WAKE_LOCK_SCREEN: |
| 69 | case PermissionType::WAKE_LOCK_SYSTEM: |
Francois Beaufort | 51f9ee3 | 2019-11-05 06:48:16 | [diff] [blame] | 70 | case PermissionType::NFC: |
Alexander Timin | 5afc73e | 2019-06-24 01:03:10 | [diff] [blame] | 71 | case PermissionType::NUM: |
Fergal Daly | 4289f93 | 2019-11-27 03:09:30 | [diff] [blame] | 72 | case PermissionType::SENSORS: |
Alex Cooper | 530cfbb9 | 2019-12-19 03:19:54 | [diff] [blame] | 73 | case PermissionType::AR: |
| 74 | case PermissionType::VR: |
Alexander Cooper | edef12b | 2024-08-22 18:42:36 | [diff] [blame] | 75 | case PermissionType::HAND_TRACKING: |
François Beaufort | 087e3211 | 2020-04-15 06:01:12 | [diff] [blame] | 76 | case PermissionType::CAMERA_PAN_TILT_ZOOM: |
Brad Triebwasser | 334d00e | 2022-10-17 18:47:57 | [diff] [blame] | 77 | case PermissionType::WINDOW_MANAGEMENT: |
Daseul Lee | 5ff7048 | 2022-04-08 19:02:50 | [diff] [blame] | 78 | case PermissionType::LOCAL_FONTS: |
Elad Alon | c0f52c9 | 2020-12-10 11:38:02 | [diff] [blame] | 79 | case PermissionType::DISPLAY_CAPTURE: |
Darren W | 154cf34 | 2021-07-13 05:27:19 | [diff] [blame] | 80 | case PermissionType::GEOLOCATION: |
Mingyu Lei | a989b896 | 2022-10-28 09:54:46 | [diff] [blame] | 81 | case PermissionType::NOTIFICATIONS: |
Elad Alon | dac5de9d | 2023-12-11 15:54:06 | [diff] [blame] | 82 | case PermissionType::CAPTURED_SURFACE_CONTROL: |
Daniel d'Andrada | d6cd88f5 | 2023-12-12 14:35:51 | [diff] [blame] | 83 | case PermissionType::SMART_CARD: |
Andrew Rayskiy | 890ffd11 | 2024-01-08 17:51:44 | [diff] [blame] | 84 | case PermissionType::WEB_PRINTING: |
Sunggook Chue | 3d430a4 | 2024-02-16 21:27:42 | [diff] [blame] | 85 | case PermissionType::SPEAKER_SELECTION: |
Takumi Fujimoto | fd7005c | 2024-03-11 02:57:29 | [diff] [blame] | 86 | case PermissionType::KEYBOARD_LOCK: |
| 87 | case PermissionType::POINTER_LOCK: |
Mike Wasserman | 740e873 | 2024-06-19 19:39:19 | [diff] [blame] | 88 | case PermissionType::AUTOMATIC_FULLSCREEN: |
Kristin Lee | cf661251 | 2024-08-23 19:12:12 | [diff] [blame] | 89 | case PermissionType::WEB_APP_INSTALLATION: |
Chris Thompson | a9d4580 | 2025-03-12 21:59:57 | [diff] [blame] | 90 | case PermissionType::LOCAL_NETWORK_ACCESS: |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 91 | return std::nullopt; |
Alexander Timin | 5afc73e | 2019-06-24 01:03:10 | [diff] [blame] | 92 | } |
| 93 | } |
| 94 | |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 95 | #if !BUILDFLAG(IS_ANDROID) |
| 96 | bool PermissionAllowedByPermissionsPolicy(PermissionType permission_type, |
| 97 | RenderFrameHost* rfh) { |
| 98 | const auto permission_policy = |
| 99 | blink::PermissionTypeToPermissionsPolicyFeature(permission_type); |
| 100 | // Some features don't have an associated permissions policy yet. Allow those. |
| 101 | if (!permission_policy.has_value()) { |
| 102 | return true; |
| 103 | } |
| 104 | |
| 105 | return rfh->IsFeatureEnabled(permission_policy.value()); |
| 106 | } |
| 107 | #endif |
| 108 | |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 109 | PermissionResult VerifyContextOfCurrentDocument( |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 110 | PermissionType permission, |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 111 | RenderFrameHost* render_frame_host) { |
| 112 | WebContents* web_contents = |
| 113 | WebContents::FromRenderFrameHost(render_frame_host); |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 114 | |
| 115 | DCHECK(web_contents); |
| 116 | |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 117 | // Permissions are denied for fenced frames. |
| 118 | if (render_frame_host->IsNestedWithinFencedFrame()) { |
Illia Klimov | 2c6138b | 2023-08-14 09:39:25 | [diff] [blame] | 119 | return PermissionResult(PermissionStatus::DENIED, |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 120 | PermissionStatusSource::FENCED_FRAME); |
| 121 | } |
| 122 | |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 123 | #if !BUILDFLAG(IS_ANDROID) |
| 124 | if (base::FeatureList::IsEnabled( |
| 125 | features::kPermissionsPolicyVerificationInContent)) { |
| 126 | // Check whether the feature is enabled for the frame by permissions policy. |
| 127 | if (!PermissionAllowedByPermissionsPolicy(permission, render_frame_host)) { |
| 128 | return PermissionResult(PermissionStatus::DENIED, |
| 129 | PermissionStatusSource::FEATURE_POLICY); |
| 130 | } |
| 131 | } |
| 132 | #endif |
| 133 | |
Illia Klimov | 2c6138b | 2023-08-14 09:39:25 | [diff] [blame] | 134 | return PermissionResult(PermissionStatus::ASK, |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 135 | PermissionStatusSource::UNSPECIFIED); |
| 136 | } |
| 137 | |
| 138 | bool IsRequestAllowed( |
Florian Jacky | 65b7d10 | 2025-04-07 10:02:52 | [diff] [blame] | 139 | const std::vector<blink::mojom::PermissionDescriptorPtr>& permissions, |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 140 | RenderFrameHost* render_frame_host, |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 141 | base::OnceCallback<void(const std::vector<PermissionResult>&)>& callback) { |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 142 | if (!render_frame_host) { |
| 143 | // Permission request is not allowed without a valid RenderFrameHost. |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 144 | std::move(callback).Run(std::vector<PermissionResult>( |
| 145 | permissions.size(), |
| 146 | PermissionResult(PermissionStatus::ASK, |
| 147 | PermissionStatusSource::UNSPECIFIED))); |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 148 | return false; |
| 149 | } |
| 150 | |
| 151 | // Verifies and evicts `render_frame_host` from BFcache. Returns true if |
| 152 | // render_frame_host was evicted, returns false otherwise. |
| 153 | if (render_frame_host->IsInactiveAndDisallowActivation( |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 154 | DisallowActivationReasonId::kRequestPermission)) { |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 155 | std::move(callback).Run(std::vector<PermissionResult>( |
| 156 | permissions.size(), |
| 157 | PermissionResult(PermissionStatus::ASK, |
| 158 | PermissionStatusSource::UNSPECIFIED))); |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 159 | return false; |
| 160 | } |
| 161 | |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 162 | auto permission_results = std::vector<PermissionResult>(); |
| 163 | |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 164 | // Verify each permission independently to generate proper warning messages. |
| 165 | bool is_permission_allowed = true; |
Florian Jacky | 65b7d10 | 2025-04-07 10:02:52 | [diff] [blame] | 166 | for (const auto& permission : permissions) { |
| 167 | PermissionType permission_type = |
| 168 | blink::PermissionDescriptorToPermissionType(permission); |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 169 | PermissionResult result = |
Florian Jacky | 65b7d10 | 2025-04-07 10:02:52 | [diff] [blame] | 170 | VerifyContextOfCurrentDocument(permission_type, render_frame_host); |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 171 | permission_results.push_back(result); |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 172 | |
Illia Klimov | 2c6138b | 2023-08-14 09:39:25 | [diff] [blame] | 173 | if (result.status == PermissionStatus::DENIED) { |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 174 | switch (result.source) { |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 175 | case PermissionStatusSource::FENCED_FRAME: |
Peter Kasting | 47250048 | 2024-11-21 18:36:25 | [diff] [blame] | 176 | render_frame_host->GetOutermostMainFrame()->AddMessageToConsole( |
| 177 | blink::mojom::ConsoleMessageLevel::kWarning, |
Florian Jacky | 65b7d10 | 2025-04-07 10:02:52 | [diff] [blame] | 178 | blink::GetPermissionString(permission_type) + |
Peter Kasting | 47250048 | 2024-11-21 18:36:25 | [diff] [blame] | 179 | " permission has been blocked because it was requested " |
| 180 | "inside a fenced frame. Fenced frames don't currently " |
| 181 | "support permission requests."); |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 182 | break; |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 183 | #if !BUILDFLAG(IS_ANDROID) |
| 184 | case PermissionStatusSource::FEATURE_POLICY: |
Peter Kasting | 47250048 | 2024-11-21 18:36:25 | [diff] [blame] | 185 | render_frame_host->GetOutermostMainFrame()->AddMessageToConsole( |
| 186 | blink::mojom::ConsoleMessageLevel::kWarning, |
Florian Jacky | 65b7d10 | 2025-04-07 10:02:52 | [diff] [blame] | 187 | blink::GetPermissionString(permission_type) + |
Peter Kasting | 47250048 | 2024-11-21 18:36:25 | [diff] [blame] | 188 | " permission has been blocked because of a permissions " |
| 189 | "policy applied to the current document. See " |
Elias Klim | 8897d61 | 2025-04-29 11:06:10 | [diff] [blame] | 190 | "https://crbug.com/414348233 for more details."); |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 191 | break; |
| 192 | #endif |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 193 | default: |
| 194 | break; |
| 195 | } |
| 196 | |
| 197 | is_permission_allowed = false; |
| 198 | } |
| 199 | } |
| 200 | |
| 201 | if (!is_permission_allowed) { |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 202 | std::move(callback).Run(permission_results); |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 203 | return false; |
| 204 | } |
| 205 | |
| 206 | return true; |
| 207 | } |
| 208 | |
Alexander Timin | 5afc73e | 2019-06-24 01:03:10 | [diff] [blame] | 209 | void NotifySchedulerAboutPermissionRequest(RenderFrameHost* render_frame_host, |
| 210 | PermissionType permission_name) { |
| 211 | DCHECK(render_frame_host); |
| 212 | |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 213 | std::optional<blink::scheduler::WebSchedulerTrackedFeature> feature = |
Alexander Timin | 5afc73e | 2019-06-24 01:03:10 | [diff] [blame] | 214 | PermissionToSchedulingFeature(permission_name); |
| 215 | |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 216 | if (!feature) { |
Alexander Timin | 5afc73e | 2019-06-24 01:03:10 | [diff] [blame] | 217 | return; |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 218 | } |
Alexander Timin | 5afc73e | 2019-06-24 01:03:10 | [diff] [blame] | 219 | |
| 220 | static_cast<RenderFrameHostImpl*>(render_frame_host) |
Yuzu Saijo | 08d13d4 | 2021-10-20 05:25:13 | [diff] [blame] | 221 | ->OnBackForwardCacheDisablingStickyFeatureUsed(feature.value()); |
Alexander Timin | 5afc73e | 2019-06-24 01:03:10 | [diff] [blame] | 222 | } |
| 223 | |
Rohan Pavone | b4de9515 | 2019-08-07 22:26:01 | [diff] [blame] | 224 | // Calls |original_cb|, a callback expecting the PermissionStatus of a set of |
| 225 | // permissions, after joining the results of overridden permissions and |
| 226 | // non-overridden permissions. |
| 227 | // |overridden_results| is an array of permissions that have already been |
| 228 | // overridden by DevTools. |
| 229 | // |delegated_results| contains results that did not have overrides - they |
| 230 | // were delegated - their results need to be inserted in order. |
| 231 | void MergeOverriddenAndDelegatedResults( |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 232 | base::OnceCallback<void(const std::vector<PermissionResult>&)> original_cb, |
| 233 | std::vector<std::optional<PermissionResult>> overridden_results, |
| 234 | const std::vector<PermissionResult>& delegated_results) { |
| 235 | std::vector<PermissionResult> full_results; |
Rohan Pavone | b4de9515 | 2019-08-07 22:26:01 | [diff] [blame] | 236 | full_results.reserve(overridden_results.size()); |
| 237 | auto delegated_it = delegated_results.begin(); |
| 238 | for (auto& status : overridden_results) { |
Illia Klimov | f284284 | 2022-03-22 11:33:39 | [diff] [blame] | 239 | if (!status) { |
Rohan Pavone | b4de9515 | 2019-08-07 22:26:01 | [diff] [blame] | 240 | CHECK(delegated_it != delegated_results.end()); |
| 241 | status.emplace(*delegated_it++); |
| 242 | } |
| 243 | full_results.emplace_back(*status); |
| 244 | } |
| 245 | CHECK(delegated_it == delegated_results.end()); |
| 246 | |
| 247 | std::move(original_cb).Run(full_results); |
| 248 | } |
| 249 | |
Illia Klimov | 27239edc | 2022-05-11 17:14:59 | [diff] [blame] | 250 | void PermissionStatusCallbackWrapper( |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 251 | base::OnceCallback<void(PermissionResult)> callback, |
| 252 | const std::vector<PermissionResult>& vector) { |
Illia Klimov | 27239edc | 2022-05-11 17:14:59 | [diff] [blame] | 253 | DCHECK_EQ(1ul, vector.size()); |
| 254 | std::move(callback).Run(vector.at(0)); |
| 255 | } |
| 256 | |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 257 | // Removes from |description.permissions| the entries that have an override |
| 258 | // status (as per the provided overrides). Returns a result vector that contains |
| 259 | // all the statuses for permissions after applying overrides, using `nullopt` |
| 260 | // for those permissions that do not have an override. |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 261 | std::vector<std::optional<PermissionResult>> OverridePermissions( |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 262 | PermissionRequestDescription& description, |
| 263 | RenderFrameHost* render_frame_host, |
| 264 | const PermissionOverrides& permission_overrides) { |
Florian Jacky | 65b7d10 | 2025-04-07 10:02:52 | [diff] [blame] | 265 | std::vector<blink::mojom::PermissionDescriptorPtr> |
| 266 | permissions_without_overrides; |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 267 | std::vector<std::optional<PermissionResult>> results; |
jalonthomas | b3f862a | 2025-07-22 16:02:23 | [diff] [blame] | 268 | |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 269 | for (const auto& permission : description.permissions) { |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 270 | std::optional<PermissionResult> override_status = permission_overrides.Get( |
| 271 | render_frame_host->GetLastCommittedOrigin(), |
| 272 | render_frame_host->GetMainFrame()->GetLastCommittedOrigin(), |
| 273 | blink::PermissionDescriptorToPermissionType(permission)); |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 274 | if (!override_status) { |
Florian Jacky | 65b7d10 | 2025-04-07 10:02:52 | [diff] [blame] | 275 | permissions_without_overrides.push_back(permission.Clone()); |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 276 | } |
| 277 | results.push_back(override_status); |
| 278 | } |
| 279 | |
| 280 | description.permissions = std::move(permissions_without_overrides); |
| 281 | return results; |
| 282 | } |
| 283 | |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 284 | } // namespace |
| 285 | |
Andrey Lushnikov | ebff044 | 2018-07-12 20:02:58 | [diff] [blame] | 286 | PermissionControllerImpl::PermissionControllerImpl( |
| 287 | BrowserContext* browser_context) |
| 288 | : browser_context_(browser_context) {} |
| 289 | |
Thomas Nguyen | 5fe1927 | 2022-12-15 10:38:00 | [diff] [blame] | 290 | // static |
Andrey Lushnikov | ebff044 | 2018-07-12 20:02:58 | [diff] [blame] | 291 | PermissionControllerImpl* PermissionControllerImpl::FromBrowserContext( |
| 292 | BrowserContext* browser_context) { |
| 293 | return static_cast<PermissionControllerImpl*>( |
Lukasz Anforowicz | 8206115 | 2021-05-14 02:14:26 | [diff] [blame] | 294 | browser_context->GetPermissionController()); |
Andrey Lushnikov | ebff044 | 2018-07-12 20:02:58 | [diff] [blame] | 295 | } |
| 296 | |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 297 | PermissionControllerImpl::~PermissionControllerImpl() { |
| 298 | // Ideally we need to unsubscribe from delegate subscriptions here, |
| 299 | // but browser_context_ is already destroyed by this point, so |
| 300 | // we can't fetch our delegate. |
| 301 | } |
| 302 | |
Illia Klimov | 2c6138b | 2023-08-14 09:39:25 | [diff] [blame] | 303 | PermissionStatus PermissionControllerImpl::GetSubscriptionCurrentValue( |
Yifan Luo | 006519d9 | 2024-08-22 16:11:34 | [diff] [blame] | 304 | const PermissionStatusSubscription& subscription) { |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 305 | // The RFH may be null if the request is for a worker. |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 306 | RenderFrameHost* rfh = RenderFrameHost::FromID(subscription.render_process_id, |
| 307 | subscription.render_frame_id); |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 308 | // TODO(crbug.com/408965890): Add support for multi-state permissions. The |
| 309 | // following won't work for detecting changes in permission options. |
| 310 | const auto descriptor = |
| 311 | PermissionDescriptorUtil::CreatePermissionDescriptorForPermissionType( |
| 312 | subscription.permission); |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 313 | if (rfh) { |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 314 | return GetPermissionStatusForCurrentDocument(descriptor, rfh); |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 315 | } |
Robbie McElrath | 8d5602a | 2022-04-01 17:39:18 | [diff] [blame] | 316 | |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 317 | RenderProcessHost* rph = |
| 318 | RenderProcessHost::FromID(subscription.render_process_id); |
Robbie McElrath | 8d5602a | 2022-04-01 17:39:18 | [diff] [blame] | 319 | if (rph) { |
| 320 | return GetPermissionStatusForWorker( |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 321 | descriptor, rph, url::Origin::Create(subscription.requesting_origin)); |
Robbie McElrath | 8d5602a | 2022-04-01 17:39:18 | [diff] [blame] | 322 | } |
| 323 | |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 324 | return GetPermissionStatusInternal(descriptor, subscription.requesting_origin, |
Illia Klimov | 15550f75 | 2022-08-11 19:33:10 | [diff] [blame] | 325 | subscription.embedding_origin); |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 326 | } |
| 327 | |
Rohan Pavone | faf6457 | 2019-07-30 17:50:20 | [diff] [blame] | 328 | PermissionControllerImpl::SubscriptionsStatusMap |
| 329 | PermissionControllerImpl::GetSubscriptionsStatuses( |
jalonthomas | 3a00d59 | 2025-07-28 14:16:53 | [diff] [blame] | 330 | const std::optional<GURL>& requesting_origin, |
| 331 | const std::optional<GURL>& embedding_origin) { |
Rohan Pavone | faf6457 | 2019-07-30 17:50:20 | [diff] [blame] | 332 | SubscriptionsStatusMap statuses; |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 333 | for (SubscriptionsMap::iterator iter(&subscriptions_); !iter.IsAtEnd(); |
| 334 | iter.Advance()) { |
Yifan Luo | 006519d9 | 2024-08-22 16:11:34 | [diff] [blame] | 335 | PermissionStatusSubscription* subscription = iter.GetCurrentValue(); |
jalonthomas | 3a00d59 | 2025-07-28 14:16:53 | [diff] [blame] | 336 | if (requesting_origin.has_value() && embedding_origin.has_value() && |
| 337 | subscription->requesting_origin != *requesting_origin && |
| 338 | subscription->embedding_origin != *embedding_origin) { |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 339 | continue; |
Illia Klimov | 7df05f2 | 2023-01-20 20:30:31 | [diff] [blame] | 340 | } |
Rohan Pavone | faf6457 | 2019-07-30 17:50:20 | [diff] [blame] | 341 | statuses[iter.GetCurrentKey()] = GetSubscriptionCurrentValue(*subscription); |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 342 | } |
Rohan Pavone | faf6457 | 2019-07-30 17:50:20 | [diff] [blame] | 343 | return statuses; |
| 344 | } |
| 345 | |
| 346 | void PermissionControllerImpl::NotifyChangedSubscriptions( |
| 347 | const SubscriptionsStatusMap& old_statuses) { |
Makoto Shimazu | 37225d76 | 2019-10-09 18:35:00 | [diff] [blame] | 348 | std::vector<base::OnceClosure> callbacks; |
Rohan Pavone | faf6457 | 2019-07-30 17:50:20 | [diff] [blame] | 349 | for (const auto& it : old_statuses) { |
| 350 | auto key = it.first; |
Yifan Luo | 006519d9 | 2024-08-22 16:11:34 | [diff] [blame] | 351 | PermissionStatusSubscription* subscription = subscriptions_.Lookup(key); |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 352 | if (!subscription) { |
Rohan Pavone | faf6457 | 2019-07-30 17:50:20 | [diff] [blame] | 353 | continue; |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 354 | } |
Illia Klimov | 2c6138b | 2023-08-14 09:39:25 | [diff] [blame] | 355 | PermissionStatus old_status = it.second; |
| 356 | PermissionStatus new_status = GetSubscriptionCurrentValue(*subscription); |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 357 | if (new_status != old_status) { |
Yifan Luo | 006519d9 | 2024-08-22 16:11:34 | [diff] [blame] | 358 | // This is a private method that is called internally if a permission |
| 359 | // status was set by DevTools. Suppress permission status override |
| 360 | // verification and always notify listeners. |
| 361 | callbacks.push_back(base::BindOnce(subscription->callback, new_status, |
| 362 | /*ignore_status_override=*/true)); |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 363 | } |
Rohan Pavone | faf6457 | 2019-07-30 17:50:20 | [diff] [blame] | 364 | } |
Elias Klim | 8897d61 | 2025-04-29 11:06:10 | [diff] [blame] | 365 | for (auto& callback : callbacks) { |
Makoto Shimazu | 37225d76 | 2019-10-09 18:35:00 | [diff] [blame] | 366 | std::move(callback).Run(); |
Elias Klim | 8897d61 | 2025-04-29 11:06:10 | [diff] [blame] | 367 | } |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 368 | } |
| 369 | |
Rohan Pavone | 013c400 | 2019-08-21 20:13:52 | [diff] [blame] | 370 | PermissionControllerImpl::OverrideStatus |
Illia Klimov | 9af808913 | 2022-10-07 16:42:30 | [diff] [blame] | 371 | PermissionControllerImpl::GrantOverridesForDevTools( |
jalonthomas | 468c58a | 2025-08-06 16:47:46 | [diff] [blame] | 372 | base::optional_ref<const url::Origin> requesting_origin, |
| 373 | base::optional_ref<const url::Origin> embedding_origin, |
Illia Klimov | 9af808913 | 2022-10-07 16:42:30 | [diff] [blame] | 374 | const std::vector<PermissionType>& permissions) { |
jalonthomas | 468c58a | 2025-08-06 16:47:46 | [diff] [blame] | 375 | return GrantPermissionOverrides(requesting_origin, embedding_origin, |
| 376 | permissions); |
Illia Klimov | 9af808913 | 2022-10-07 16:42:30 | [diff] [blame] | 377 | } |
| 378 | |
| 379 | PermissionControllerImpl::OverrideStatus |
Rohan Pavone | 013c400 | 2019-08-21 20:13:52 | [diff] [blame] | 380 | PermissionControllerImpl::SetOverrideForDevTools( |
jalonthomas | 468c58a | 2025-08-06 16:47:46 | [diff] [blame] | 381 | base::optional_ref<const url::Origin> requesting_origin, |
| 382 | base::optional_ref<const url::Origin> embedding_origin, |
Pavel Feldman | 446a91b | 2020-03-13 17:39:55 | [diff] [blame] | 383 | PermissionType permission, |
Illia Klimov | 2c6138b | 2023-08-14 09:39:25 | [diff] [blame] | 384 | const PermissionStatus& status) { |
jalonthomas | 468c58a | 2025-08-06 16:47:46 | [diff] [blame] | 385 | return SetPermissionOverride(requesting_origin, embedding_origin, permission, |
| 386 | status); |
Illia Klimov | 9af808913 | 2022-10-07 16:42:30 | [diff] [blame] | 387 | } |
| 388 | |
| 389 | void PermissionControllerImpl::ResetOverridesForDevTools() { |
| 390 | ResetPermissionOverrides(); |
| 391 | } |
| 392 | |
| 393 | PermissionControllerImpl::OverrideStatus |
| 394 | PermissionControllerImpl::SetPermissionOverride( |
jalonthomas | 468c58a | 2025-08-06 16:47:46 | [diff] [blame] | 395 | base::optional_ref<const url::Origin> requesting_origin, |
| 396 | base::optional_ref<const url::Origin> embedding_origin, |
Illia Klimov | 9af808913 | 2022-10-07 16:42:30 | [diff] [blame] | 397 | PermissionType permission, |
Illia Klimov | 2c6138b | 2023-08-14 09:39:25 | [diff] [blame] | 398 | const PermissionStatus& status) { |
jalonthomas | 468c58a | 2025-08-06 16:47:46 | [diff] [blame] | 399 | CHECK_EQ(requesting_origin.has_value(), embedding_origin.has_value()); |
| 400 | |
Rohan Pavone | 013c400 | 2019-08-21 20:13:52 | [diff] [blame] | 401 | PermissionControllerDelegate* delegate = |
| 402 | browser_context_->GetPermissionControllerDelegate(); |
jalonthomas | 468c58a | 2025-08-06 16:47:46 | [diff] [blame] | 403 | if (delegate && !delegate->IsPermissionOverridable( |
| 404 | permission, requesting_origin, embedding_origin)) { |
Rohan Pavone | 013c400 | 2019-08-21 20:13:52 | [diff] [blame] | 405 | return OverrideStatus::kOverrideNotSet; |
| 406 | } |
jalonthomas | 3a00d59 | 2025-07-28 14:16:53 | [diff] [blame] | 407 | |
jalonthomas | 468c58a | 2025-08-06 16:47:46 | [diff] [blame] | 408 | const std::optional<GURL> requesting_origin_url = |
| 409 | requesting_origin.has_value() |
| 410 | ? std::make_optional(requesting_origin->GetURL()) |
| 411 | : std::nullopt; |
| 412 | const std::optional<GURL> embedding_origin_url = |
| 413 | embedding_origin.has_value() |
| 414 | ? std::make_optional(embedding_origin->GetURL()) |
| 415 | : std::nullopt; |
| 416 | const auto old_statuses = |
| 417 | GetSubscriptionsStatuses(requesting_origin_url, embedding_origin_url); |
| 418 | |
| 419 | permission_overrides_.Set(requesting_origin, embedding_origin, permission, |
| 420 | status); |
Rohan Pavone | b4de9515 | 2019-08-07 22:26:01 | [diff] [blame] | 421 | NotifyChangedSubscriptions(old_statuses); |
| 422 | |
Rohan Pavone | 013c400 | 2019-08-21 20:13:52 | [diff] [blame] | 423 | return OverrideStatus::kOverrideSet; |
Rohan Pavone | b4de9515 | 2019-08-07 22:26:01 | [diff] [blame] | 424 | } |
| 425 | |
Rohan Pavone | 013c400 | 2019-08-21 20:13:52 | [diff] [blame] | 426 | PermissionControllerImpl::OverrideStatus |
Illia Klimov | 9af808913 | 2022-10-07 16:42:30 | [diff] [blame] | 427 | PermissionControllerImpl::GrantPermissionOverrides( |
jalonthomas | 468c58a | 2025-08-06 16:47:46 | [diff] [blame] | 428 | base::optional_ref<const url::Origin> requesting_origin, |
| 429 | base::optional_ref<const url::Origin> embedding_origin, |
Rohan Pavone | faf6457 | 2019-07-30 17:50:20 | [diff] [blame] | 430 | const std::vector<PermissionType>& permissions) { |
jalonthomas | 468c58a | 2025-08-06 16:47:46 | [diff] [blame] | 431 | CHECK_EQ(requesting_origin.has_value(), embedding_origin.has_value()); |
| 432 | |
Rohan Pavone | 013c400 | 2019-08-21 20:13:52 | [diff] [blame] | 433 | PermissionControllerDelegate* delegate = |
| 434 | browser_context_->GetPermissionControllerDelegate(); |
Pavel Feldman | 446a91b | 2020-03-13 17:39:55 | [diff] [blame] | 435 | if (delegate) { |
| 436 | for (const auto permission : permissions) { |
jalonthomas | 468c58a | 2025-08-06 16:47:46 | [diff] [blame] | 437 | if (!delegate->IsPermissionOverridable(permission, requesting_origin, |
| 438 | embedding_origin)) { |
Rohan Pavone | 013c400 | 2019-08-21 20:13:52 | [diff] [blame] | 439 | return OverrideStatus::kOverrideNotSet; |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 440 | } |
Pavel Feldman | 446a91b | 2020-03-13 17:39:55 | [diff] [blame] | 441 | } |
| 442 | } |
Rohan Pavone | 013c400 | 2019-08-21 20:13:52 | [diff] [blame] | 443 | |
jalonthomas | 468c58a | 2025-08-06 16:47:46 | [diff] [blame] | 444 | const std::optional<GURL> requesting_origin_url = |
| 445 | requesting_origin.has_value() |
| 446 | ? std::make_optional(requesting_origin->GetURL()) |
| 447 | : std::nullopt; |
| 448 | const std::optional<GURL> embedding_origin_url = |
| 449 | embedding_origin.has_value() |
| 450 | ? std::make_optional(embedding_origin->GetURL()) |
| 451 | : std::nullopt; |
| 452 | const auto old_statuses = |
| 453 | GetSubscriptionsStatuses(requesting_origin_url, embedding_origin_url); |
| 454 | |
| 455 | permission_overrides_.GrantPermissions(requesting_origin, embedding_origin, |
| 456 | permissions); |
Rohan Pavone | faf6457 | 2019-07-30 17:50:20 | [diff] [blame] | 457 | // If any statuses changed because they lose overrides or the new overrides |
| 458 | // modify their previous state (overridden or not), subscribers must be |
| 459 | // notified manually. |
| 460 | NotifyChangedSubscriptions(old_statuses); |
| 461 | |
Rohan Pavone | 013c400 | 2019-08-21 20:13:52 | [diff] [blame] | 462 | return OverrideStatus::kOverrideSet; |
Rohan Pavone | faf6457 | 2019-07-30 17:50:20 | [diff] [blame] | 463 | } |
| 464 | |
Illia Klimov | 9af808913 | 2022-10-07 16:42:30 | [diff] [blame] | 465 | void PermissionControllerImpl::ResetPermissionOverrides() { |
Rohan Pavone | faf6457 | 2019-07-30 17:50:20 | [diff] [blame] | 466 | const auto old_statuses = GetSubscriptionsStatuses(); |
Illia Klimov | 9af808913 | 2022-10-07 16:42:30 | [diff] [blame] | 467 | permission_overrides_ = PermissionOverrides(); |
Rohan Pavone | faf6457 | 2019-07-30 17:50:20 | [diff] [blame] | 468 | |
Alex Rudenko | c728e63 | 2022-05-11 09:32:24 | [diff] [blame] | 469 | // If any statuses changed because they lost their overrides, the subscribers |
| 470 | // must be notified manually. |
| 471 | NotifyChangedSubscriptions(old_statuses); |
Rohan Pavone | faf6457 | 2019-07-30 17:50:20 | [diff] [blame] | 472 | } |
| 473 | |
Matt Reichhoff | 56f6228 | 2022-09-12 20:36:00 | [diff] [blame] | 474 | void PermissionControllerImpl::RequestPermissions( |
Matt Reichhoff | 56f6228 | 2022-09-12 20:36:00 | [diff] [blame] | 475 | RenderFrameHost* render_frame_host, |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 476 | PermissionRequestDescription request_description, |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 477 | base::OnceCallback<void(const std::vector<PermissionResult>&)> callback) { |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 478 | if (!IsRequestAllowed(request_description.permissions, render_frame_host, |
| 479 | callback)) { |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 480 | return; |
| 481 | } |
| 482 | |
Florian Jacky | 65b7d10 | 2025-04-07 10:02:52 | [diff] [blame] | 483 | for (const blink::mojom::PermissionDescriptorPtr& permission : |
| 484 | request_description.permissions) { |
| 485 | NotifySchedulerAboutPermissionRequest( |
| 486 | render_frame_host, |
| 487 | blink::PermissionDescriptorToPermissionType(permission)); |
Matt Reichhoff | 56f6228 | 2022-09-12 20:36:00 | [diff] [blame] | 488 | } |
| 489 | |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 490 | std::vector<std::optional<PermissionResult>> override_results = |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 491 | OverridePermissions(request_description, render_frame_host, |
| 492 | permission_overrides_); |
| 493 | |
Matt Reichhoff | 56f6228 | 2022-09-12 20:36:00 | [diff] [blame] | 494 | auto wrapper = base::BindOnce(&MergeOverriddenAndDelegatedResults, |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 495 | std::move(callback), override_results); |
| 496 | if (request_description.permissions.empty()) { |
Matt Reichhoff | 56f6228 | 2022-09-12 20:36:00 | [diff] [blame] | 497 | std::move(wrapper).Run({}); |
| 498 | return; |
| 499 | } |
| 500 | |
| 501 | // Use delegate to find statuses of other permissions that have been requested |
| 502 | // but do not have overrides. |
| 503 | PermissionControllerDelegate* delegate = |
| 504 | browser_context_->GetPermissionControllerDelegate(); |
| 505 | if (!delegate) { |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 506 | std::move(wrapper).Run(std::vector<PermissionResult>( |
| 507 | request_description.permissions.size(), |
| 508 | PermissionResult(PermissionStatus::DENIED, |
| 509 | PermissionStatusSource::UNSPECIFIED))); |
Matt Reichhoff | 56f6228 | 2022-09-12 20:36:00 | [diff] [blame] | 510 | return; |
| 511 | } |
| 512 | |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 513 | delegate->RequestPermissions(render_frame_host, request_description, |
Matt Reichhoff | 56f6228 | 2022-09-12 20:36:00 | [diff] [blame] | 514 | std::move(wrapper)); |
| 515 | } |
| 516 | |
Illia Klimov | 27239edc | 2022-05-11 17:14:59 | [diff] [blame] | 517 | void PermissionControllerImpl::RequestPermissionFromCurrentDocument( |
Andrey Lushnikov | ebff044 | 2018-07-12 20:02:58 | [diff] [blame] | 518 | RenderFrameHost* render_frame_host, |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 519 | PermissionRequestDescription request_description, |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 520 | base::OnceCallback<void(PermissionResult)> callback) { |
Illia Klimov | 27239edc | 2022-05-11 17:14:59 | [diff] [blame] | 521 | RequestPermissionsFromCurrentDocument( |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 522 | render_frame_host, std::move(request_description), |
Illia Klimov | 27239edc | 2022-05-11 17:14:59 | [diff] [blame] | 523 | base::BindOnce(&PermissionStatusCallbackWrapper, std::move(callback))); |
Andrey Lushnikov | ebff044 | 2018-07-12 20:02:58 | [diff] [blame] | 524 | } |
| 525 | |
Illia Klimov | 27239edc | 2022-05-11 17:14:59 | [diff] [blame] | 526 | void PermissionControllerImpl::RequestPermissionsFromCurrentDocument( |
Andrey Lushnikov | ebff044 | 2018-07-12 20:02:58 | [diff] [blame] | 527 | RenderFrameHost* render_frame_host, |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 528 | PermissionRequestDescription request_description, |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 529 | base::OnceCallback<void(const std::vector<PermissionResult>&)> callback) { |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 530 | if (!IsRequestAllowed(request_description.permissions, render_frame_host, |
| 531 | callback)) { |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 532 | return; |
Rohan Pavone | b4de9515 | 2019-08-07 22:26:01 | [diff] [blame] | 533 | } |
Rohan Pavone | faf6457 | 2019-07-30 17:50:20 | [diff] [blame] | 534 | |
Florian Jacky | 65b7d10 | 2025-04-07 10:02:52 | [diff] [blame] | 535 | for (const auto& permission : request_description.permissions) { |
| 536 | NotifySchedulerAboutPermissionRequest( |
| 537 | render_frame_host, |
| 538 | blink::PermissionDescriptorToPermissionType(permission)); |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 539 | } |
| 540 | |
| 541 | request_description.requesting_origin = |
| 542 | render_frame_host->GetLastCommittedOrigin().GetURL(); |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 543 | std::vector<std::optional<PermissionResult>> override_results = |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 544 | OverridePermissions(request_description, render_frame_host, |
| 545 | permission_overrides_); |
| 546 | |
Rohan Pavone | b4de9515 | 2019-08-07 22:26:01 | [diff] [blame] | 547 | auto wrapper = base::BindOnce(&MergeOverriddenAndDelegatedResults, |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 548 | std::move(callback), override_results); |
| 549 | if (request_description.permissions.empty()) { |
Rohan Pavone | b4de9515 | 2019-08-07 22:26:01 | [diff] [blame] | 550 | std::move(wrapper).Run({}); |
Balazs Engedy | e30e961 | 2021-04-02 10:37:29 | [diff] [blame] | 551 | return; |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 552 | } |
| 553 | |
Rohan Pavone | b4de9515 | 2019-08-07 22:26:01 | [diff] [blame] | 554 | // Use delegate to find statuses of other permissions that have been requested |
| 555 | // but do not have overrides. |
Andrey Lushnikov | f350010 | 2018-07-16 19:55:22 | [diff] [blame] | 556 | PermissionControllerDelegate* delegate = |
| 557 | browser_context_->GetPermissionControllerDelegate(); |
Andrey Lushnikov | ebff044 | 2018-07-12 20:02:58 | [diff] [blame] | 558 | if (!delegate) { |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 559 | std::move(wrapper).Run(std::vector<PermissionResult>( |
| 560 | request_description.permissions.size(), |
| 561 | PermissionResult(PermissionStatus::DENIED, |
| 562 | PermissionStatusSource::UNSPECIFIED))); |
Balazs Engedy | e30e961 | 2021-04-02 10:37:29 | [diff] [blame] | 563 | return; |
Andrey Lushnikov | ebff044 | 2018-07-12 20:02:58 | [diff] [blame] | 564 | } |
Andrey Lushnikov | ebff044 | 2018-07-12 20:02:58 | [diff] [blame] | 565 | |
Illia Klimov | 27239edc | 2022-05-11 17:14:59 | [diff] [blame] | 566 | delegate->RequestPermissionsFromCurrentDocument( |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 567 | render_frame_host, request_description, std::move(wrapper)); |
Illia Klimov | a181b7d | 2022-03-15 08:17:47 | [diff] [blame] | 568 | } |
| 569 | |
Illia Klimov | 4b72378ed | 2022-07-18 13:46:57 | [diff] [blame] | 570 | void PermissionControllerImpl::ResetPermission(blink::PermissionType permission, |
| 571 | const url::Origin& origin) { |
| 572 | ResetPermission(permission, origin.GetURL(), origin.GetURL()); |
| 573 | } |
| 574 | |
Illia Klimov | 2c6138b | 2023-08-14 09:39:25 | [diff] [blame] | 575 | PermissionStatus PermissionControllerImpl::GetPermissionStatusInternal( |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 576 | const blink::mojom::PermissionDescriptorPtr& permission_descriptor, |
Andrey Lushnikov | ebff044 | 2018-07-12 20:02:58 | [diff] [blame] | 577 | const GURL& requesting_origin, |
| 578 | const GURL& embedding_origin) { |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 579 | std::optional<PermissionResult> prermission_result = |
| 580 | permission_overrides_.Get( |
| 581 | url::Origin::Create(requesting_origin), |
| 582 | url::Origin::Create(embedding_origin), |
| 583 | blink::PermissionDescriptorToPermissionType(permission_descriptor)); |
| 584 | if (prermission_result) { |
| 585 | return prermission_result->status; |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 586 | } |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 587 | |
Andrey Lushnikov | f350010 | 2018-07-16 19:55:22 | [diff] [blame] | 588 | PermissionControllerDelegate* delegate = |
| 589 | browser_context_->GetPermissionControllerDelegate(); |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 590 | if (!delegate) { |
Illia Klimov | 2c6138b | 2023-08-14 09:39:25 | [diff] [blame] | 591 | return PermissionStatus::DENIED; |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 592 | } |
Florian Jacky | 8373f04 | 2025-04-16 14:20:53 | [diff] [blame] | 593 | return delegate->GetPermissionStatus(permission_descriptor, requesting_origin, |
| 594 | embedding_origin); |
Andrey Lushnikov | ebff044 | 2018-07-12 20:02:58 | [diff] [blame] | 595 | } |
| 596 | |
Thomas Nguyen | 23593332 | 2024-05-27 14:52:11 | [diff] [blame] | 597 | PermissionStatus |
| 598 | PermissionControllerImpl::GetPermissionStatusForCurrentDocumentInternal( |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 599 | const blink::mojom::PermissionDescriptorPtr& permission_descriptor, |
Thomas Nguyen | 23593332 | 2024-05-27 14:52:11 | [diff] [blame] | 600 | RenderFrameHost* render_frame_host, |
| 601 | bool should_include_device_status) { |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 602 | auto permission_type = |
| 603 | blink::PermissionDescriptorToPermissionType(permission_descriptor); |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 604 | std::optional<PermissionResult> permission_result = permission_overrides_.Get( |
jalonthomas | b3f862a | 2025-07-22 16:02:23 | [diff] [blame] | 605 | render_frame_host->GetLastCommittedOrigin(), |
| 606 | render_frame_host->GetMainFrame()->GetLastCommittedOrigin(), |
| 607 | permission_type); |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 608 | if (permission_result) { |
| 609 | return permission_result->status; |
Thomas Nguyen | 23593332 | 2024-05-27 14:52:11 | [diff] [blame] | 610 | } |
| 611 | PermissionControllerDelegate* delegate = |
| 612 | browser_context_->GetPermissionControllerDelegate(); |
| 613 | if (!delegate) { |
| 614 | return PermissionStatus::DENIED; |
| 615 | } |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 616 | if (VerifyContextOfCurrentDocument(permission_type, render_frame_host) |
| 617 | .status == PermissionStatus::DENIED) { |
Thomas Nguyen | 23593332 | 2024-05-27 14:52:11 | [diff] [blame] | 618 | return PermissionStatus::DENIED; |
| 619 | } |
| 620 | return delegate->GetPermissionStatusForCurrentDocument( |
Florian Jacky | 8373f04 | 2025-04-16 14:20:53 | [diff] [blame] | 621 | permission_descriptor, render_frame_host, should_include_device_status); |
Thomas Nguyen | 23593332 | 2024-05-27 14:52:11 | [diff] [blame] | 622 | } |
| 623 | |
Illia Klimov | 2c6138b | 2023-08-14 09:39:25 | [diff] [blame] | 624 | PermissionStatus PermissionControllerImpl::GetPermissionStatusForWorker( |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 625 | const blink::mojom::PermissionDescriptorPtr& permission_descriptor, |
Robbie McElrath | 8d5602a | 2022-04-01 17:39:18 | [diff] [blame] | 626 | RenderProcessHost* render_process_host, |
| 627 | const url::Origin& worker_origin) { |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 628 | auto permission_type = |
| 629 | blink::PermissionDescriptorToPermissionType(permission_descriptor); |
jalonthomas | b3f862a | 2025-07-22 16:02:23 | [diff] [blame] | 630 | |
| 631 | // TODO(crbug.com/428178708): This is likely incorrect for partitioned |
| 632 | // contexts and requires impact evaluation before updating to use embedding |
| 633 | // and requesting origins. |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 634 | std::optional<PermissionResult> permission_result = |
jalonthomas | b3f862a | 2025-07-22 16:02:23 | [diff] [blame] | 635 | permission_overrides_.Get(worker_origin, worker_origin, permission_type); |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 636 | if (permission_result) { |
| 637 | return permission_result->status; |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 638 | } |
Robbie McElrath | 8d5602a | 2022-04-01 17:39:18 | [diff] [blame] | 639 | |
| 640 | PermissionControllerDelegate* delegate = |
| 641 | browser_context_->GetPermissionControllerDelegate(); |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 642 | if (!delegate) { |
Illia Klimov | 2c6138b | 2023-08-14 09:39:25 | [diff] [blame] | 643 | return PermissionStatus::DENIED; |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 644 | } |
| 645 | |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 646 | return delegate->GetPermissionStatusForWorker( |
Florian Jacky | 8373f04 | 2025-04-16 14:20:53 | [diff] [blame] | 647 | permission_descriptor, render_process_host, worker_origin.GetURL()); |
Illia Klimov | 4a2cb19 | 2022-03-15 06:31:35 | [diff] [blame] | 648 | } |
| 649 | |
Illia Klimov | 2c6138b | 2023-08-14 09:39:25 | [diff] [blame] | 650 | PermissionStatus |
Illia Klimov | 4a2cb19 | 2022-03-15 06:31:35 | [diff] [blame] | 651 | PermissionControllerImpl::GetPermissionStatusForCurrentDocument( |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 652 | const blink::mojom::PermissionDescriptorPtr& permission_descriptor, |
Illia Klimov | 4a2cb19 | 2022-03-15 06:31:35 | [diff] [blame] | 653 | RenderFrameHost* render_frame_host) { |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 654 | return GetPermissionStatusForCurrentDocumentInternal(permission_descriptor, |
Thomas Nguyen | 23593332 | 2024-05-27 14:52:11 | [diff] [blame] | 655 | render_frame_host); |
Illia Klimov | 4a2cb19 | 2022-03-15 06:31:35 | [diff] [blame] | 656 | } |
| 657 | |
Illia Klimov | 15550f75 | 2022-08-11 19:33:10 | [diff] [blame] | 658 | PermissionResult |
| 659 | PermissionControllerImpl::GetPermissionResultForCurrentDocument( |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 660 | const blink::mojom::PermissionDescriptorPtr& permission_descriptor, |
Illia Klimov | 15550f75 | 2022-08-11 19:33:10 | [diff] [blame] | 661 | RenderFrameHost* render_frame_host) { |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 662 | auto permission_type = |
| 663 | blink::PermissionDescriptorToPermissionType(permission_descriptor); |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 664 | std::optional<PermissionResult> permission_result = permission_overrides_.Get( |
jalonthomas | b3f862a | 2025-07-22 16:02:23 | [diff] [blame] | 665 | render_frame_host->GetLastCommittedOrigin(), |
| 666 | render_frame_host->GetMainFrame()->GetLastCommittedOrigin(), |
| 667 | permission_type); |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 668 | if (permission_result) { |
| 669 | return permission_result.value(); |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 670 | } |
Illia Klimov | 15550f75 | 2022-08-11 19:33:10 | [diff] [blame] | 671 | |
| 672 | PermissionControllerDelegate* delegate = |
| 673 | browser_context_->GetPermissionControllerDelegate(); |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 674 | if (!delegate) { |
Illia Klimov | 2c6138b | 2023-08-14 09:39:25 | [diff] [blame] | 675 | return PermissionResult(PermissionStatus::DENIED, |
Illia Klimov | 15550f75 | 2022-08-11 19:33:10 | [diff] [blame] | 676 | PermissionStatusSource::UNSPECIFIED); |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 677 | } |
Illia Klimov | 15550f75 | 2022-08-11 19:33:10 | [diff] [blame] | 678 | |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 679 | PermissionResult result = |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 680 | VerifyContextOfCurrentDocument(permission_type, render_frame_host); |
Illia Klimov | 2c6138b | 2023-08-14 09:39:25 | [diff] [blame] | 681 | if (result.status == PermissionStatus::DENIED) { |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 682 | return result; |
Illia Klimov | 2c6138b | 2023-08-14 09:39:25 | [diff] [blame] | 683 | } |
Illia Klimov | 9777bbb | 2022-10-11 11:02:01 | [diff] [blame] | 684 | |
Thomas Nguyen | 23593332 | 2024-05-27 14:52:11 | [diff] [blame] | 685 | return delegate->GetPermissionResultForCurrentDocument( |
Florian Jacky | 8373f04 | 2025-04-16 14:20:53 | [diff] [blame] | 686 | permission_descriptor, render_frame_host, |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 687 | /*should_include_device_status=*/false); |
Illia Klimov | 15550f75 | 2022-08-11 19:33:10 | [diff] [blame] | 688 | } |
| 689 | |
| 690 | PermissionResult |
| 691 | PermissionControllerImpl::GetPermissionResultForOriginWithoutContext( |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 692 | const blink::mojom::PermissionDescriptorPtr& permission_descriptor, |
Illia Klimov | 15550f75 | 2022-08-11 19:33:10 | [diff] [blame] | 693 | const url::Origin& origin) { |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 694 | return GetPermissionResultForOriginWithoutContext(permission_descriptor, |
| 695 | origin, origin); |
Illia Klimov | 15550f75 | 2022-08-11 19:33:10 | [diff] [blame] | 696 | } |
| 697 | |
Christian Dullweber | a475f4a | 2023-08-07 17:04:13 | [diff] [blame] | 698 | PermissionResult |
| 699 | PermissionControllerImpl::GetPermissionResultForOriginWithoutContext( |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 700 | const blink::mojom::PermissionDescriptorPtr& permission_descriptor, |
Illia Klimov | 15550f75 | 2022-08-11 19:33:10 | [diff] [blame] | 701 | const url::Origin& requesting_origin, |
| 702 | const url::Origin& embedding_origin) { |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 703 | auto permission_type = |
| 704 | blink::PermissionDescriptorToPermissionType(permission_descriptor); |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 705 | std::optional<PermissionResult> permission_result = permission_overrides_.Get( |
jalonthomas | b3f862a | 2025-07-22 16:02:23 | [diff] [blame] | 706 | requesting_origin, embedding_origin, permission_type); |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 707 | if (permission_result) { |
| 708 | return permission_result.value(); |
Christian Dullweber | a475f4a | 2023-08-07 17:04:13 | [diff] [blame] | 709 | } |
| 710 | |
| 711 | PermissionControllerDelegate* delegate = |
| 712 | browser_context_->GetPermissionControllerDelegate(); |
| 713 | if (!delegate) { |
Illia Klimov | 2c6138b | 2023-08-14 09:39:25 | [diff] [blame] | 714 | return PermissionResult(PermissionStatus::DENIED, |
Christian Dullweber | a475f4a | 2023-08-07 17:04:13 | [diff] [blame] | 715 | PermissionStatusSource::UNSPECIFIED); |
| 716 | } |
| 717 | |
| 718 | return delegate->GetPermissionResultForOriginWithoutContext( |
Florian Jacky | 8373f04 | 2025-04-16 14:20:53 | [diff] [blame] | 719 | permission_descriptor, requesting_origin, embedding_origin); |
Illia Klimov | 4a2cb19 | 2022-03-15 06:31:35 | [diff] [blame] | 720 | } |
| 721 | |
Illia Klimov | 2c6138b | 2023-08-14 09:39:25 | [diff] [blame] | 722 | PermissionStatus |
Illia Klimov | 20badfdf | 2023-03-16 19:53:10 | [diff] [blame] | 723 | PermissionControllerImpl::GetPermissionStatusForEmbeddedRequester( |
Florian Jacky | 8373f04 | 2025-04-16 14:20:53 | [diff] [blame] | 724 | const blink::mojom::PermissionDescriptorPtr& permission_descriptor, |
Illia Klimov | 20badfdf | 2023-03-16 19:53:10 | [diff] [blame] | 725 | RenderFrameHost* render_frame_host, |
| 726 | const url::Origin& requesting_origin) { |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 727 | auto permission_type = |
Florian Jacky | 8373f04 | 2025-04-16 14:20:53 | [diff] [blame] | 728 | blink::PermissionDescriptorToPermissionType(permission_descriptor); |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 729 | |
Illia Klimov | 20badfdf | 2023-03-16 19:53:10 | [diff] [blame] | 730 | // This API is suited only for `TOP_LEVEL_STORAGE_ACCESS`. Do not use it for |
| 731 | // other permissions unless discussed with `permissions-core@`. |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 732 | DCHECK(permission_type == blink::PermissionType::TOP_LEVEL_STORAGE_ACCESS); |
Illia Klimov | 20badfdf | 2023-03-16 19:53:10 | [diff] [blame] | 733 | |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 734 | if (permission_type != blink::PermissionType::TOP_LEVEL_STORAGE_ACCESS) { |
Illia Klimov | 2c6138b | 2023-08-14 09:39:25 | [diff] [blame] | 735 | return PermissionStatus::DENIED; |
Illia Klimov | 20badfdf | 2023-03-16 19:53:10 | [diff] [blame] | 736 | } |
| 737 | |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 738 | std::optional<PermissionResult> permission_result = permission_overrides_.Get( |
jalonthomas | b3f862a | 2025-07-22 16:02:23 | [diff] [blame] | 739 | requesting_origin, |
| 740 | render_frame_host->GetMainFrame()->GetLastCommittedOrigin(), |
| 741 | permission_type); |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 742 | if (permission_result) { |
| 743 | return permission_result->status; |
Illia Klimov | 20badfdf | 2023-03-16 19:53:10 | [diff] [blame] | 744 | } |
| 745 | |
| 746 | PermissionControllerDelegate* delegate = |
| 747 | browser_context_->GetPermissionControllerDelegate(); |
| 748 | if (!delegate) { |
Illia Klimov | 2c6138b | 2023-08-14 09:39:25 | [diff] [blame] | 749 | return PermissionStatus::DENIED; |
Illia Klimov | 20badfdf | 2023-03-16 19:53:10 | [diff] [blame] | 750 | } |
| 751 | |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 752 | if (VerifyContextOfCurrentDocument(permission_type, render_frame_host) |
| 753 | .status == PermissionStatus::DENIED) { |
Illia Klimov | 2c6138b | 2023-08-14 09:39:25 | [diff] [blame] | 754 | return PermissionStatus::DENIED; |
Illia Klimov | 20badfdf | 2023-03-16 19:53:10 | [diff] [blame] | 755 | } |
| 756 | |
| 757 | return delegate->GetPermissionStatusForEmbeddedRequester( |
Florian Jacky | 8373f04 | 2025-04-16 14:20:53 | [diff] [blame] | 758 | permission_descriptor, render_frame_host, requesting_origin); |
Illia Klimov | 20badfdf | 2023-03-16 19:53:10 | [diff] [blame] | 759 | } |
| 760 | |
Thomas Nguyen | 23593332 | 2024-05-27 14:52:11 | [diff] [blame] | 761 | PermissionStatus PermissionControllerImpl::GetCombinedPermissionAndDeviceStatus( |
Florian Jacky | a857d58 | 2025-04-10 10:13:33 | [diff] [blame] | 762 | const blink::mojom::PermissionDescriptorPtr& permission, |
Thomas Nguyen | 23593332 | 2024-05-27 14:52:11 | [diff] [blame] | 763 | RenderFrameHost* render_frame_host) { |
Mike West | dfbafc5a | 2025-06-23 09:56:57 | [diff] [blame] | 764 | CHECK(PermissionUtil::IsDevicePermission(permission)); |
Thomas Nguyen | 23593332 | 2024-05-27 14:52:11 | [diff] [blame] | 765 | return GetPermissionStatusForCurrentDocumentInternal( |
| 766 | permission, render_frame_host, /*should_include_device_status=*/true); |
| 767 | } |
| 768 | |
Andrey Lushnikov | ebff044 | 2018-07-12 20:02:58 | [diff] [blame] | 769 | void PermissionControllerImpl::ResetPermission(PermissionType permission, |
| 770 | const GURL& requesting_origin, |
| 771 | const GURL& embedding_origin) { |
Andrey Lushnikov | f350010 | 2018-07-16 19:55:22 | [diff] [blame] | 772 | PermissionControllerDelegate* delegate = |
| 773 | browser_context_->GetPermissionControllerDelegate(); |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 774 | if (!delegate) { |
Andrey Lushnikov | ebff044 | 2018-07-12 20:02:58 | [diff] [blame] | 775 | return; |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 776 | } |
Andrey Lushnikov | ebff044 | 2018-07-12 20:02:58 | [diff] [blame] | 777 | delegate->ResetPermission(permission, requesting_origin, embedding_origin); |
| 778 | } |
| 779 | |
Yifan Luo | 006519d9 | 2024-08-22 16:11:34 | [diff] [blame] | 780 | void PermissionControllerImpl::PermissionStatusChange( |
| 781 | const base::RepeatingCallback<void(PermissionStatus)>& callback, |
Ravjit | 5f6183e | 2021-07-09 11:12:37 | [diff] [blame] | 782 | SubscriptionId subscription_id, |
Yifan Luo | 006519d9 | 2024-08-22 16:11:34 | [diff] [blame] | 783 | PermissionStatus status, |
| 784 | bool ignore_status_override) { |
| 785 | // Check if the permission status override should be ignored. The verification |
| 786 | // is suppressed if a permission status change was initiated by DevTools. In |
| 787 | // all other cases permission status override is always checked. |
| 788 | if (ignore_status_override) { |
| 789 | callback.Run(status); |
| 790 | return; |
| 791 | } |
| 792 | PermissionStatusSubscription* subscription = |
| 793 | subscriptions_.Lookup(subscription_id); |
Ravjit | 5f6183e | 2021-07-09 11:12:37 | [diff] [blame] | 794 | DCHECK(subscription); |
Alison Gale | 59c007a | 2024-04-20 03:05:40 | [diff] [blame] | 795 | // TODO(crbug.com/40056329) Adding this block to prevent crashes while we |
Ravjit | 5f6183e | 2021-07-09 11:12:37 | [diff] [blame] | 796 | // investigate the root cause of the crash. This block will be removed as the |
Yifan Luo | 006519d9 | 2024-08-22 16:11:34 | [diff] [blame] | 797 | // DCHECK() above should be enough. |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 798 | if (!subscription) { |
Ravjit | 5f6183e | 2021-07-09 11:12:37 | [diff] [blame] | 799 | return; |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 800 | } |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 801 | std::optional<PermissionResult> permission_result = permission_overrides_.Get( |
Illia Klimov | 2c6138b | 2023-08-14 09:39:25 | [diff] [blame] | 802 | url::Origin::Create(subscription->requesting_origin), |
jalonthomas | b3f862a | 2025-07-22 16:02:23 | [diff] [blame] | 803 | url::Origin::Create(subscription->embedding_origin), |
Illia Klimov | 2c6138b | 2023-08-14 09:39:25 | [diff] [blame] | 804 | subscription->permission); |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 805 | if (!permission_result.has_value()) { |
Yifan Luo | 006519d9 | 2024-08-22 16:11:34 | [diff] [blame] | 806 | callback.Run(status); |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 807 | } |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 808 | } |
| 809 | |
Yifan Luo | 006519d9 | 2024-08-22 16:11:34 | [diff] [blame] | 810 | PermissionController::SubscriptionId |
Balazs Engedy | 33b441e | 2023-12-12 18:53:42 | [diff] [blame] | 811 | PermissionControllerImpl::SubscribeToPermissionStatusChange( |
Andrey Lushnikov | ebff044 | 2018-07-12 20:02:58 | [diff] [blame] | 812 | PermissionType permission, |
Robbie McElrath | 8d5602a | 2022-04-01 17:39:18 | [diff] [blame] | 813 | RenderProcessHost* render_process_host, |
Raymes Khoury | 3ef4f6e | 2018-08-09 09:34:48 | [diff] [blame] | 814 | RenderFrameHost* render_frame_host, |
Andrey Lushnikov | ebff044 | 2018-07-12 20:02:58 | [diff] [blame] | 815 | const GURL& requesting_origin, |
Andy Paicu | 9d70da4 | 2024-05-10 22:24:39 | [diff] [blame] | 816 | bool should_include_device_status, |
Illia Klimov | 2c6138b | 2023-08-14 09:39:25 | [diff] [blame] | 817 | const base::RepeatingCallback<void(PermissionStatus)>& callback) { |
Robbie McElrath | 8d5602a | 2022-04-01 17:39:18 | [diff] [blame] | 818 | DCHECK(!render_process_host || !render_frame_host); |
Yifan Luo | 006519d9 | 2024-08-22 16:11:34 | [diff] [blame] | 819 | |
| 820 | auto id = subscription_id_generator_.GenerateNextId(); |
| 821 | auto subscription = std::make_unique<PermissionStatusSubscription>(); |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 822 | subscription->permission = permission; |
Yifan Luo | 006519d9 | 2024-08-22 16:11:34 | [diff] [blame] | 823 | subscription->callback = |
| 824 | base::BindRepeating(&PermissionControllerImpl::PermissionStatusChange, |
| 825 | base::Unretained(this), callback, id); |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 826 | subscription->requesting_origin = requesting_origin; |
Yifan Luo | 006519d9 | 2024-08-22 16:11:34 | [diff] [blame] | 827 | subscription->should_include_device_status = should_include_device_status; |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 828 | |
| 829 | // The RFH may be null if the request is for a worker. |
| 830 | if (render_frame_host) { |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 831 | subscription->embedding_origin = |
Henrique Ferreiro | f89870f | 2022-03-30 17:08:13 | [diff] [blame] | 832 | PermissionUtil::GetLastCommittedOriginAsURL( |
| 833 | render_frame_host->GetMainFrame()); |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 834 | subscription->render_frame_id = render_frame_host->GetRoutingID(); |
Emily Andrews | d15fd76 | 2024-12-10 20:41:54 | [diff] [blame] | 835 | subscription->render_process_id = |
| 836 | render_frame_host->GetProcess()->GetDeprecatedID(); |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 837 | } else { |
| 838 | subscription->embedding_origin = requesting_origin; |
| 839 | subscription->render_frame_id = -1; |
Robbie McElrath | 8d5602a | 2022-04-01 17:39:18 | [diff] [blame] | 840 | subscription->render_process_id = |
Emily Andrews | d15fd76 | 2024-12-10 20:41:54 | [diff] [blame] | 841 | render_process_host ? render_process_host->GetDeprecatedID() : -1; |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 842 | } |
Yifan Luo | 006519d9 | 2024-08-22 16:11:34 | [diff] [blame] | 843 | subscriptions_.AddWithID(std::move(subscription), id); |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 844 | |
Andrey Lushnikov | f350010 | 2018-07-16 19:55:22 | [diff] [blame] | 845 | PermissionControllerDelegate* delegate = |
| 846 | browser_context_->GetPermissionControllerDelegate(); |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 847 | if (delegate) { |
Yifan Luo | 006519d9 | 2024-08-22 16:11:34 | [diff] [blame] | 848 | delegate->SetSubscriptions(&subscriptions_); |
| 849 | delegate->OnPermissionStatusChangeSubscriptionAdded(id); |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 850 | } |
Balazs Engedy | ad1489b | 2021-03-31 07:47:19 | [diff] [blame] | 851 | return id; |
Andrey Lushnikov | ebff044 | 2018-07-12 20:02:58 | [diff] [blame] | 852 | } |
| 853 | |
Balazs Engedy | 33b441e | 2023-12-12 18:53:42 | [diff] [blame] | 854 | void PermissionControllerImpl::UnsubscribeFromPermissionStatusChange( |
Balazs Engedy | ad1489b | 2021-03-31 07:47:19 | [diff] [blame] | 855 | SubscriptionId subscription_id) { |
Yifan Luo | 006519d9 | 2024-08-22 16:11:34 | [diff] [blame] | 856 | PermissionStatusSubscription* subscription = |
| 857 | subscriptions_.Lookup(subscription_id); |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 858 | if (!subscription) { |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 859 | return; |
Elias Klim | 1e5178a3 | 2023-12-12 21:15:29 | [diff] [blame] | 860 | } |
Andrey Lushnikov | f350010 | 2018-07-16 19:55:22 | [diff] [blame] | 861 | PermissionControllerDelegate* delegate = |
| 862 | browser_context_->GetPermissionControllerDelegate(); |
Balazs Engedy | ad1489b | 2021-03-31 07:47:19 | [diff] [blame] | 863 | if (delegate) { |
Yifan Luo | 006519d9 | 2024-08-22 16:11:34 | [diff] [blame] | 864 | delegate->UnsubscribeFromPermissionStatusChange(subscription_id); |
Andrey Lushnikov | 36299bc | 2018-08-23 22:09:54 | [diff] [blame] | 865 | } |
| 866 | subscriptions_.Remove(subscription_id); |
Andrey Lushnikov | ebff044 | 2018-07-12 20:02:58 | [diff] [blame] | 867 | } |
| 868 | |
Illia Klimov | e406ecc1 | 2022-11-22 15:53:29 | [diff] [blame] | 869 | bool PermissionControllerImpl::IsSubscribedToPermissionChangeEvent( |
| 870 | blink::PermissionType permission, |
| 871 | RenderFrameHost* render_frame_host) { |
| 872 | PermissionServiceContext* permission_service_context = |
| 873 | PermissionServiceContext::GetForCurrentDocument(render_frame_host); |
Thomas Nguyen | 1c30015 | 2023-02-02 09:56:11 | [diff] [blame] | 874 | if (!permission_service_context) { |
| 875 | return false; |
| 876 | } |
Illia Klimov | e406ecc1 | 2022-11-22 15:53:29 | [diff] [blame] | 877 | |
| 878 | return permission_service_context->GetOnchangeEventListeners().find( |
| 879 | permission) != |
| 880 | permission_service_context->GetOnchangeEventListeners().end(); |
| 881 | } |
| 882 | |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 883 | std::optional<gfx::Rect> |
Thomas Nguyen | 583f07e | 2023-07-19 17:45:37 | [diff] [blame] | 884 | PermissionControllerImpl::GetExclusionAreaBoundsInScreen( |
| 885 | WebContents* web_contents) const { |
| 886 | if (exclusion_area_bounds_for_tests_.has_value()) { |
| 887 | return exclusion_area_bounds_for_tests_; |
| 888 | } |
| 889 | PermissionControllerDelegate* delegate = |
| 890 | browser_context_->GetPermissionControllerDelegate(); |
| 891 | return delegate ? delegate->GetExclusionAreaBoundsInScreen(web_contents) |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 892 | : std::nullopt; |
Thomas Nguyen | 583f07e | 2023-07-19 17:45:37 | [diff] [blame] | 893 | } |
| 894 | |
Illia Klimov | e406ecc1 | 2022-11-22 15:53:29 | [diff] [blame] | 895 | void PermissionControllerImpl::NotifyEventListener() { |
Arthur Sonzogni | fd1e08d | 2024-03-05 15:59:36 | [diff] [blame] | 896 | if (onchange_listeners_callback_for_tests_) { |
| 897 | onchange_listeners_callback_for_tests_.Run(); |
Illia Klimov | e406ecc1 | 2022-11-22 15:53:29 | [diff] [blame] | 898 | } |
| 899 | } |
| 900 | |
Matt Reichhoff | 2dbcfbd | 2023-01-03 17:48:33 | [diff] [blame] | 901 | } // namespace content |