Avi Drissman | 4e1b7bc3 | 2022-09-15 14:03:50 | [diff] [blame] | 1 | // Copyright 2017 The Chromium Authors |
Conley Owens | 47f4fbf1 | 2017-08-02 01:56:52 | [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 | |
| 5 | #include "content/browser/geolocation/geolocation_service_impl.h" |
| 6 | |
Jan Wilken Dörrie | 1494205b | 2020-03-26 09:32:53 | [diff] [blame] | 7 | #include <utility> |
| 8 | |
Avi Drissman | adac2199 | 2023-01-11 23:46:39 | [diff] [blame] | 9 | #include "base/functional/bind.h" |
Florian Jacky | 80e3530 | 2023-09-15 16:40:42 | [diff] [blame] | 10 | #include "content/browser/permissions/permission_controller_impl.h" |
Illia Klimov | a181b7d | 2022-03-15 08:17:47 | [diff] [blame] | 11 | #include "content/public/browser/browser_context.h" |
| 12 | #include "content/public/browser/permission_controller.h" |
Florian Jacky | 65b7d10 | 2025-04-07 10:02:52 | [diff] [blame] | 13 | #include "content/public/browser/permission_descriptor_util.h" |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 14 | #include "content/public/browser/permission_request_description.h" |
Conley Owens | 47f4fbf1 | 2017-08-02 01:56:52 | [diff] [blame] | 15 | #include "content/public/browser/render_frame_host.h" |
Mario Sanchez Prada | fa6dda8c | 2019-11-25 18:20:19 | [diff] [blame] | 16 | #include "content/public/browser/render_process_host.h" |
Matt Reynolds | f10fd2f | 2019-04-01 19:39:29 | [diff] [blame] | 17 | #include "mojo/public/cpp/bindings/callback_helpers.h" |
Florian Jacky | 80e3530 | 2023-09-15 16:40:42 | [diff] [blame] | 18 | #include "services/device/public/mojom/geoposition.mojom.h" |
Sandor «Alex» Major | c41217f | 2025-02-14 23:33:13 | [diff] [blame] | 19 | #include "services/network/public/mojom/permissions_policy/permissions_policy_feature.mojom.h" |
Andy Paicu | a6d6d85 | 2022-04-28 18:08:36 | [diff] [blame] | 20 | #include "third_party/blink/public/common/permissions/permission_utils.h" |
Conley Owens | 47f4fbf1 | 2017-08-02 01:56:52 | [diff] [blame] | 21 | |
Alvin Ji | 0ff2727 | 2024-03-13 21:57:27 | [diff] [blame] | 22 | #if BUILDFLAG(IS_IOS) |
| 23 | #include "services/device/public/cpp/geolocation/geolocation_system_permission_manager.h" |
| 24 | #endif |
| 25 | |
Conley Owens | 47f4fbf1 | 2017-08-02 01:56:52 | [diff] [blame] | 26 | namespace content { |
| 27 | |
Illia Klimov | a181b7d | 2022-03-15 08:17:47 | [diff] [blame] | 28 | GeolocationServiceImplContext::GeolocationServiceImplContext() = default; |
Conley Owens | 47f4fbf1 | 2017-08-02 01:56:52 | [diff] [blame] | 29 | |
Illia Klimov | a181b7d | 2022-03-15 08:17:47 | [diff] [blame] | 30 | GeolocationServiceImplContext::~GeolocationServiceImplContext() = default; |
Conley Owens | 47f4fbf1 | 2017-08-02 01:56:52 | [diff] [blame] | 31 | |
| 32 | void GeolocationServiceImplContext::RequestPermission( |
| 33 | RenderFrameHost* render_frame_host, |
| 34 | bool user_gesture, |
WangHui | 4dafed92 | 2021-03-09 01:02:17 | [diff] [blame] | 35 | PermissionCallback callback) { |
Balazs Engedy | e30e961 | 2021-04-02 10:37:29 | [diff] [blame] | 36 | if (has_pending_permission_request_) { |
Conley Owens | 9613ff9a | 2017-11-27 21:06:55 | [diff] [blame] | 37 | mojo::ReportBadMessage( |
| 38 | "GeolocationService client may only create one Geolocation at a " |
| 39 | "time."); |
| 40 | return; |
| 41 | } |
| 42 | |
Balazs Engedy | e30e961 | 2021-04-02 10:37:29 | [diff] [blame] | 43 | has_pending_permission_request_ = true; |
Illia Klimov | a181b7d | 2022-03-15 08:17:47 | [diff] [blame] | 44 | |
| 45 | render_frame_host->GetBrowserContext() |
| 46 | ->GetPermissionController() |
| 47 | ->RequestPermissionFromCurrentDocument( |
Andy Paicu | 0a6d4b50 | 2023-08-29 15:13:09 | [diff] [blame] | 48 | render_frame_host, |
Florian Jacky | 65b7d10 | 2025-04-07 10:02:52 | [diff] [blame] | 49 | PermissionRequestDescription( |
| 50 | content::PermissionDescriptorUtil:: |
| 51 | CreatePermissionDescriptorForPermissionType( |
| 52 | blink::PermissionType::GEOLOCATION), |
| 53 | user_gesture), |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 54 | base::BindOnce(&GeolocationServiceImplContext::HandlePermissionResult, |
Illia Klimov | a181b7d | 2022-03-15 08:17:47 | [diff] [blame] | 55 | weak_factory_.GetWeakPtr(), std::move(callback))); |
Conley Owens | 47f4fbf1 | 2017-08-02 01:56:52 | [diff] [blame] | 56 | } |
| 57 | |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 58 | void GeolocationServiceImplContext::HandlePermissionResult( |
WangHui | 4dafed92 | 2021-03-09 01:02:17 | [diff] [blame] | 59 | PermissionCallback callback, |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 60 | PermissionResult permission_result) { |
Balazs Engedy | e30e961 | 2021-04-02 10:37:29 | [diff] [blame] | 61 | has_pending_permission_request_ = false; |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 62 | std::move(callback).Run(permission_result); |
Conley Owens | 47f4fbf1 | 2017-08-02 01:56:52 | [diff] [blame] | 63 | } |
| 64 | |
| 65 | GeolocationServiceImpl::GeolocationServiceImpl( |
Ke He | 7319dbe | 2017-11-09 05:54:44 | [diff] [blame] | 66 | device::mojom::GeolocationContext* geolocation_context, |
Conley Owens | 47f4fbf1 | 2017-08-02 01:56:52 | [diff] [blame] | 67 | RenderFrameHost* render_frame_host) |
| 68 | : geolocation_context_(geolocation_context), |
Conley Owens | 47f4fbf1 | 2017-08-02 01:56:52 | [diff] [blame] | 69 | render_frame_host_(render_frame_host) { |
| 70 | DCHECK(geolocation_context); |
Conley Owens | 47f4fbf1 | 2017-08-02 01:56:52 | [diff] [blame] | 71 | DCHECK(render_frame_host); |
| 72 | } |
| 73 | |
Yifan Luo | 8e5d3d5 | 2024-10-22 19:18:16 | [diff] [blame] | 74 | GeolocationServiceImpl::~GeolocationServiceImpl() { |
| 75 | DecrementActivityCount(); |
| 76 | } |
Conley Owens | 47f4fbf1 | 2017-08-02 01:56:52 | [diff] [blame] | 77 | |
| 78 | void GeolocationServiceImpl::Bind( |
Mario Sanchez Prada | fa6dda8c | 2019-11-25 18:20:19 | [diff] [blame] | 79 | mojo::PendingReceiver<blink::mojom::GeolocationService> receiver) { |
Illia Klimov | a181b7d | 2022-03-15 08:17:47 | [diff] [blame] | 80 | receiver_set_.Add(this, std::move(receiver), |
| 81 | std::make_unique<GeolocationServiceImplContext>()); |
Yifan Luo | 8e5d3d5 | 2024-10-22 19:18:16 | [diff] [blame] | 82 | receiver_set_.set_disconnect_handler(base::BindRepeating( |
| 83 | &GeolocationServiceImpl::OnDisconnected, base::Unretained(this))); |
Jan Lanik | 819b6037 | 2024-01-12 12:58:26 | [diff] [blame] | 84 | #if BUILDFLAG(IS_IOS) |
Alvin Ji | 0ff2727 | 2024-03-13 21:57:27 | [diff] [blame] | 85 | device::GeolocationSystemPermissionManager* |
| 86 | geolocation_system_permission_manager = |
| 87 | device::GeolocationSystemPermissionManager::GetInstance(); |
| 88 | if (geolocation_system_permission_manager) { |
| 89 | geolocation_system_permission_manager->RequestSystemPermission(); |
Jan Lanik | 819b6037 | 2024-01-12 12:58:26 | [diff] [blame] | 90 | } |
| 91 | #endif |
Conley Owens | 47f4fbf1 | 2017-08-02 01:56:52 | [diff] [blame] | 92 | } |
| 93 | |
| 94 | void GeolocationServiceImpl::CreateGeolocation( |
Gyuyoung Kim | 0c32116d | 2019-08-30 03:27:35 | [diff] [blame] | 95 | mojo::PendingReceiver<device::mojom::Geolocation> receiver, |
Matt Reynolds | f10fd2f | 2019-04-01 19:39:29 | [diff] [blame] | 96 | bool user_gesture, |
| 97 | CreateGeolocationCallback callback) { |
Raymes Khoury | 8dbfbd7 | 2018-08-21 07:31:16 | [diff] [blame] | 98 | if (!render_frame_host_->IsFeatureEnabled( |
Sandor «Alex» Major | e9545a7 | 2025-01-31 20:40:46 | [diff] [blame] | 99 | network::mojom::PermissionsPolicyFeature::kGeolocation)) { |
Matt Reynolds | f10fd2f | 2019-04-01 19:39:29 | [diff] [blame] | 100 | std::move(callback).Run(blink::mojom::PermissionStatus::DENIED); |
Conley Owens | 47f4fbf1 | 2017-08-02 01:56:52 | [diff] [blame] | 101 | return; |
| 102 | } |
| 103 | |
Matt Reynolds | f10fd2f | 2019-04-01 19:39:29 | [diff] [blame] | 104 | // If the geolocation service is destroyed before the callback is run, ensure |
| 105 | // it is called with DENIED status. |
| 106 | auto scoped_callback = mojo::WrapCallbackWithDefaultInvokeIfNotRun( |
| 107 | std::move(callback), blink::mojom::PermissionStatus::DENIED); |
| 108 | |
Mario Sanchez Prada | fa6dda8c | 2019-11-25 18:20:19 | [diff] [blame] | 109 | receiver_set_.current_context()->RequestPermission( |
Conley Owens | 47f4fbf1 | 2017-08-02 01:56:52 | [diff] [blame] | 110 | render_frame_host_, user_gesture, |
Alvin Ji | 9e137ea | 2025-02-20 05:03:02 | [diff] [blame] | 111 | // The owning RenderFrameHost might be destroyed before the permission |
| 112 | // request finishes. To avoid calling a callback on a destroyed object, |
| 113 | // use a WeakPtr and skip the callback if the object is invalid. |
Makoto Shimazu | 51176e6 | 2019-10-10 14:43:17 | [diff] [blame] | 114 | base::BindOnce( |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 115 | &GeolocationServiceImpl::CreateGeolocationWithPermissionResult, |
Alvin Ji | 8c6078e | 2025-02-14 22:52:27 | [diff] [blame] | 116 | weak_factory_.GetWeakPtr(), std::move(receiver), |
Jan Wilken Dörrie | 1494205b | 2020-03-26 09:32:53 | [diff] [blame] | 117 | std::move(scoped_callback))); |
Conley Owens | 47f4fbf1 | 2017-08-02 01:56:52 | [diff] [blame] | 118 | } |
| 119 | |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 120 | void GeolocationServiceImpl::CreateGeolocationWithPermissionResult( |
Gyuyoung Kim | 0c32116d | 2019-08-30 03:27:35 | [diff] [blame] | 121 | mojo::PendingReceiver<device::mojom::Geolocation> receiver, |
Matt Reynolds | f10fd2f | 2019-04-01 19:39:29 | [diff] [blame] | 122 | CreateGeolocationCallback callback, |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 123 | PermissionResult permission_result) { |
| 124 | std::move(callback).Run(permission_result.status); |
| 125 | if (permission_result.status != blink::mojom::PermissionStatus::GRANTED) { |
Conley Owens | 47f4fbf1 | 2017-08-02 01:56:52 | [diff] [blame] | 126 | return; |
Florian Jacky | aaf4283 | 2025-08-19 04:03:26 | [diff] [blame] | 127 | } |
Conley Owens | 47f4fbf1 | 2017-08-02 01:56:52 | [diff] [blame] | 128 | |
Yifan Luo | 8e5d3d5 | 2024-10-22 19:18:16 | [diff] [blame] | 129 | IncrementActivityCount(); |
| 130 | |
Florian Jacky | 80e3530 | 2023-09-15 16:40:42 | [diff] [blame] | 131 | requesting_origin_ = |
| 132 | render_frame_host_->GetMainFrame()->GetLastCommittedOrigin(); |
| 133 | auto requesting_url = |
Ella Ge | a4791e43d | 2022-09-01 06:14:31 | [diff] [blame] | 134 | render_frame_host_->GetMainFrame()->GetLastCommittedURL(); |
Florian Jacky | 80e3530 | 2023-09-15 16:40:42 | [diff] [blame] | 135 | |
Matt Reynolds | 9e506294 | 2024-06-11 21:27:56 | [diff] [blame] | 136 | geolocation_context_->BindGeolocation( |
| 137 | std::move(receiver), requesting_url, |
| 138 | device::mojom::GeolocationClientId::kGeolocationServiceImpl); |
Florian Jacky | 80e3530 | 2023-09-15 16:40:42 | [diff] [blame] | 139 | subscription_id_ = |
| 140 | PermissionControllerImpl::FromBrowserContext( |
| 141 | render_frame_host_->GetBrowserContext()) |
Balazs Engedy | 33b441e | 2023-12-12 18:53:42 | [diff] [blame] | 142 | ->SubscribeToPermissionStatusChange( |
Florian Jacky | 80e3530 | 2023-09-15 16:40:42 | [diff] [blame] | 143 | blink::PermissionType::GEOLOCATION, |
| 144 | /*render_process_host=*/nullptr, render_frame_host_, |
| 145 | requesting_url, |
Andy Paicu | 9d70da4 | 2024-05-10 22:24:39 | [diff] [blame] | 146 | /*should_include_device_status=*/false, |
Florian Jacky | 80e3530 | 2023-09-15 16:40:42 | [diff] [blame] | 147 | base::BindRepeating( |
| 148 | &GeolocationServiceImpl::HandlePermissionStatusChange, |
| 149 | weak_factory_.GetWeakPtr())); |
| 150 | } |
| 151 | |
| 152 | void GeolocationServiceImpl::HandlePermissionStatusChange( |
| 153 | blink::mojom::PermissionStatus permission_status) { |
| 154 | if (permission_status != blink::mojom::PermissionStatus::GRANTED && |
| 155 | subscription_id_.value()) { |
| 156 | PermissionControllerImpl::FromBrowserContext( |
| 157 | render_frame_host_->GetBrowserContext()) |
Balazs Engedy | 33b441e | 2023-12-12 18:53:42 | [diff] [blame] | 158 | ->UnsubscribeFromPermissionStatusChange(subscription_id_); |
Florian Jacky | 80e3530 | 2023-09-15 16:40:42 | [diff] [blame] | 159 | geolocation_context_->OnPermissionRevoked(requesting_origin_); |
Yifan Luo | 8e5d3d5 | 2024-10-22 19:18:16 | [diff] [blame] | 160 | DecrementActivityCount(); |
| 161 | } |
| 162 | } |
| 163 | |
| 164 | void GeolocationServiceImpl::OnDisconnected() { |
| 165 | if (receiver_set_.empty()) { |
| 166 | DecrementActivityCount(); |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | void GeolocationServiceImpl::IncrementActivityCount() { |
| 171 | is_sending_updates_ = true; |
| 172 | auto* web_contents = WebContents::FromRenderFrameHost(render_frame_host_); |
| 173 | static_cast<WebContentsImpl*>(web_contents) |
| 174 | ->IncrementGeolocationActiveFrameCount(); |
| 175 | } |
| 176 | |
| 177 | void GeolocationServiceImpl::DecrementActivityCount() { |
| 178 | if (is_sending_updates_) { |
| 179 | is_sending_updates_ = false; |
| 180 | auto* web_contents = WebContents::FromRenderFrameHost(render_frame_host_); |
| 181 | static_cast<WebContentsImpl*>(web_contents) |
| 182 | ->DecrementGeolocationActiveFrameCount(); |
Florian Jacky | 80e3530 | 2023-09-15 16:40:42 | [diff] [blame] | 183 | } |
Conley Owens | 47f4fbf1 | 2017-08-02 01:56:52 | [diff] [blame] | 184 | } |
| 185 | |
| 186 | } // namespace content |