| // Copyright 2017 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/geolocation/geolocation_service_impl.h" |
| |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "content/public/browser/browser_context.h" |
| #include "content/public/browser/permission_controller.h" |
| #include "content/public/browser/render_frame_host.h" |
| #include "content/public/browser/render_process_host.h" |
| #include "mojo/public/cpp/bindings/callback_helpers.h" |
| #include "third_party/blink/public/common/permissions/permission_utils.h" |
| #include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom.h" |
| |
| namespace content { |
| |
| GeolocationServiceImplContext::GeolocationServiceImplContext() = default; |
| |
| GeolocationServiceImplContext::~GeolocationServiceImplContext() = default; |
| |
| void GeolocationServiceImplContext::RequestPermission( |
| RenderFrameHost* render_frame_host, |
| bool user_gesture, |
| PermissionCallback callback) { |
| if (has_pending_permission_request_) { |
| mojo::ReportBadMessage( |
| "GeolocationService client may only create one Geolocation at a " |
| "time."); |
| return; |
| } |
| |
| has_pending_permission_request_ = true; |
| |
| render_frame_host->GetBrowserContext() |
| ->GetPermissionController() |
| ->RequestPermissionFromCurrentDocument( |
| blink::PermissionType::GEOLOCATION, render_frame_host, user_gesture, |
| base::BindOnce(&GeolocationServiceImplContext::HandlePermissionStatus, |
| weak_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void GeolocationServiceImplContext::HandlePermissionStatus( |
| PermissionCallback callback, |
| blink::mojom::PermissionStatus permission_status) { |
| has_pending_permission_request_ = false; |
| std::move(callback).Run(permission_status); |
| } |
| |
| GeolocationServiceImpl::GeolocationServiceImpl( |
| device::mojom::GeolocationContext* geolocation_context, |
| RenderFrameHost* render_frame_host) |
| : geolocation_context_(geolocation_context), |
| render_frame_host_(render_frame_host) { |
| DCHECK(geolocation_context); |
| DCHECK(render_frame_host); |
| } |
| |
| GeolocationServiceImpl::~GeolocationServiceImpl() {} |
| |
| void GeolocationServiceImpl::Bind( |
| mojo::PendingReceiver<blink::mojom::GeolocationService> receiver) { |
| receiver_set_.Add(this, std::move(receiver), |
| std::make_unique<GeolocationServiceImplContext>()); |
| } |
| |
| void GeolocationServiceImpl::CreateGeolocation( |
| mojo::PendingReceiver<device::mojom::Geolocation> receiver, |
| bool user_gesture, |
| CreateGeolocationCallback callback) { |
| if (!render_frame_host_->IsFeatureEnabled( |
| blink::mojom::PermissionsPolicyFeature::kGeolocation)) { |
| std::move(callback).Run(blink::mojom::PermissionStatus::DENIED); |
| return; |
| } |
| |
| // If the geolocation service is destroyed before the callback is run, ensure |
| // it is called with DENIED status. |
| auto scoped_callback = mojo::WrapCallbackWithDefaultInvokeIfNotRun( |
| std::move(callback), blink::mojom::PermissionStatus::DENIED); |
| |
| receiver_set_.current_context()->RequestPermission( |
| render_frame_host_, user_gesture, |
| // There is an assumption here that the GeolocationServiceImplContext will |
| // outlive the GeolocationServiceImpl. |
| base::BindOnce( |
| &GeolocationServiceImpl::CreateGeolocationWithPermissionStatus, |
| base::Unretained(this), std::move(receiver), |
| std::move(scoped_callback))); |
| } |
| |
| void GeolocationServiceImpl::CreateGeolocationWithPermissionStatus( |
| mojo::PendingReceiver<device::mojom::Geolocation> receiver, |
| CreateGeolocationCallback callback, |
| blink::mojom::PermissionStatus permission_status) { |
| std::move(callback).Run(permission_status); |
| if (permission_status != blink::mojom::PermissionStatus::GRANTED) |
| return; |
| |
| const auto& requesting_url = |
| render_frame_host_->GetMainFrame()->GetLastCommittedURL(); |
| geolocation_context_->BindGeolocation(std::move(receiver), requesting_url); |
| } |
| |
| } // namespace content |