[go: nahoru, domu]

blob: e34bbce6f43ca58fc16877f429d736cd59c3458b [file] [log] [blame]
Avi Drissman4e1b7bc2022-09-15 14:03:501// Copyright 2014 The Chromium Authors
mlamouri4ebe69f2014-11-14 17:25:212// 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/permissions/permission_service_context.h"
6
Arthur Sonzognic686e8f2024-01-11 08:36:377#include <optional>
dcheng36b6aec92015-12-26 06:16:368#include <utility>
9
Avi Drissmanadac21992023-01-11 23:46:3910#include "base/functional/bind.h"
Keishi Hattori0e45c022021-11-27 09:25:5211#include "base/memory/raw_ptr.h"
Thomas Nguyena4cf2342022-12-01 13:15:4112#include "base/memory/weak_ptr.h"
Andrey Lushnikovebff0442018-07-12 20:02:5813#include "content/browser/permissions/permission_controller_impl.h"
mlamouri4ebe69f2014-11-14 17:25:2114#include "content/browser/permissions/permission_service_impl.h"
Illia Klimov7709f0c2021-07-05 09:42:3915#include "content/browser/permissions/permission_util.h"
reillyg86dfcea2017-01-04 22:27:5716#include "content/public/browser/browser_context.h"
jam5c2473dc2017-02-06 15:51:2117#include "content/public/browser/navigation_handle.h"
mlamouri4ebe69f2014-11-14 17:25:2118#include "content/public/browser/render_frame_host.h"
timvolodine089c07c2014-12-11 19:32:2619#include "content/public/browser/render_process_host.h"
mlamouri4ebe69f2014-11-14 17:25:2120#include "content/public/browser/web_contents.h"
Mario Sanchez Prada97f66162019-08-06 21:56:4821#include "mojo/public/cpp/bindings/remote.h"
Andy Paicua6d6d852022-04-28 18:08:3622#include "third_party/blink/public/common/permissions/permission_utils.h"
Andy Paicubdb19c72022-04-22 09:24:3123#include "url/origin.h"
reillyg86dfcea2017-01-04 22:27:5724
mlamouri4ebe69f2014-11-14 17:25:2125namespace content {
26
Alexander Timin72a2f0c2021-10-01 01:56:0727// A holder owning document-associated PermissionServiceContext. The holder is
28// used as PermissionServiceContext itself can't inherit from
Sreeja Kamishetty0a0961f2021-10-11 16:23:5329// DocumentUserData, as PermissionServiceContext (unlike
30// DocumentUserData) can be created when RenderFrameHost doesn't exist
Alexander Timin72a2f0c2021-10-01 01:56:0731// (e.g. for service workers).
32struct PermissionServiceContext::DocumentPermissionServiceContextHolder
Sreeja Kamishetty0a0961f2021-10-11 16:23:5333 : public DocumentUserData<DocumentPermissionServiceContextHolder> {
Lukasz Anforowiczcfeb95c2021-10-01 19:33:3534 explicit DocumentPermissionServiceContextHolder(RenderFrameHost* rfh)
Sreeja Kamishetty0a0961f2021-10-11 16:23:5335 : DocumentUserData<DocumentPermissionServiceContextHolder>(rfh),
Lukasz Anforowiczcfeb95c2021-10-01 19:33:3536 permission_service_context(rfh) {}
Alexander Timin72a2f0c2021-10-01 01:56:0737
38 PermissionServiceContext permission_service_context;
39
Sreeja Kamishetty0a0961f2021-10-11 16:23:5340 DOCUMENT_USER_DATA_KEY_DECL();
Alexander Timin72a2f0c2021-10-01 01:56:0741};
42
Sreeja Kamishetty0a0961f2021-10-11 16:23:5343DOCUMENT_USER_DATA_KEY_IMPL(
Daniel Cheng383df852021-10-02 03:28:0144 PermissionServiceContext::DocumentPermissionServiceContextHolder);
Alexander Timin72a2f0c2021-10-01 01:56:0745
reillyg86dfcea2017-01-04 22:27:5746class PermissionServiceContext::PermissionSubscription {
47 public:
Mario Sanchez Prada97f66162019-08-06 21:56:4848 PermissionSubscription(
Illia Klimov2c6138b2023-08-14 09:39:2549 PermissionStatus last_known_status,
Mario Sanchez Prada97f66162019-08-06 21:56:4850 PermissionServiceContext* context,
51 mojo::PendingRemote<blink::mojom::PermissionObserver> observer)
Thomas Nguyen5fe19272022-12-15 10:38:0052 : last_known_status_(last_known_status),
53 context_(context),
54 observer_(std::move(observer)) {
Mario Sanchez Prada97f66162019-08-06 21:56:4855 observer_.set_disconnect_handler(base::BindOnce(
reillyg86dfcea2017-01-04 22:27:5756 &PermissionSubscription::OnConnectionError, base::Unretained(this)));
57 }
Lei Zhang67b7bf32019-10-08 18:46:0158 PermissionSubscription(const PermissionSubscription&) = delete;
59 PermissionSubscription& operator=(const PermissionSubscription&) = delete;
reillyg86dfcea2017-01-04 22:27:5760
reillyg9c28b5c2017-01-06 20:51:3161 ~PermissionSubscription() {
Balazs Engedyad1489b2021-03-31 07:47:1962 DCHECK(id_);
reillyg9c28b5c2017-01-06 20:51:3163 BrowserContext* browser_context = context_->GetBrowserContext();
Andrey Lushnikovebff0442018-07-12 20:02:5864 if (browser_context) {
65 PermissionControllerImpl::FromBrowserContext(browser_context)
Balazs Engedy33b441e2023-12-12 18:53:4266 ->UnsubscribeFromPermissionStatusChange(id_);
reillyg9c28b5c2017-01-06 20:51:3167 }
68 }
reillyg86dfcea2017-01-04 22:27:5769
70 void OnConnectionError() {
Balazs Engedyad1489b2021-03-31 07:47:1971 DCHECK(id_);
reillyg86dfcea2017-01-04 22:27:5772 context_->ObserverHadConnectionError(id_);
73 }
74
Thomas Nguyen5fe19272022-12-15 10:38:0075 void StoreStatusAtBFCacheEntry() {
76 status_at_bf_cache_entry_ =
Arthur Sonzognic686e8f2024-01-11 08:36:3777 std::make_optional<PermissionStatus>(last_known_status_);
Thomas Nguyen5fe19272022-12-15 10:38:0078 }
79
80 void NotifyPermissionStatusChangedIfNeeded() {
81 DCHECK(status_at_bf_cache_entry_.has_value());
Thomas Nguyenf9ccec82023-02-20 14:35:3882 if (status_at_bf_cache_entry_ != last_known_status_) {
Thomas Nguyen5fe19272022-12-15 10:38:0083 observer_->OnPermissionStatusChange(last_known_status_);
84 }
85 status_at_bf_cache_entry_.reset();
86 }
87
Illia Klimov2c6138b2023-08-14 09:39:2588 void OnPermissionStatusChanged(PermissionStatus status) {
Thomas Nguyen5fe19272022-12-15 10:38:0089 if (!observer_.is_connected()) {
90 return;
91 }
92
93 last_known_status_ = status;
94
95 // Dispatching events while in BFCache is redundant. Permissions code in
96 // renderer process would decide to drop the event by looking at document's
97 // active status.
98 if (!status_at_bf_cache_entry_.has_value()) {
Ravjit Singh Uppale306d3fa2021-07-05 13:47:4599 observer_->OnPermissionStatusChange(status);
Thomas Nguyen5fe19272022-12-15 10:38:00100 }
reillyg86dfcea2017-01-04 22:27:57101 }
102
Balazs Engedyad1489b2021-03-31 07:47:19103 void set_id(PermissionController::SubscriptionId id) { id_ = id; }
reillyg86dfcea2017-01-04 22:27:57104
Thomas Nguyena4cf2342022-12-01 13:15:41105 base::WeakPtr<PermissionSubscription> GetWeakPtr() {
106 return weak_ptr_factory_.GetWeakPtr();
107 }
108
reillyg86dfcea2017-01-04 22:27:57109 private:
Illia Klimov2c6138b2023-08-14 09:39:25110 PermissionStatus last_known_status_ = PermissionStatus::LAST;
Keishi Hattori0e45c022021-11-27 09:25:52111 const raw_ptr<PermissionServiceContext> context_;
Mario Sanchez Prada97f66162019-08-06 21:56:48112 mojo::Remote<blink::mojom::PermissionObserver> observer_;
Balazs Engedyad1489b2021-03-31 07:47:19113 PermissionController::SubscriptionId id_;
Thomas Nguyena4cf2342022-12-01 13:15:41114
Thomas Nguyen5fe19272022-12-15 10:38:00115 // Optional variable to store the last status before the corresponding
116 // RenderFrameHost enters BFCache, and will be cleared when the
117 // RenderFrameHost is restored from BFCache. Non-empty value indicates that
118 // the RenderFrameHost is in BFCache.
Arthur Sonzognic686e8f2024-01-11 08:36:37119 std::optional<PermissionStatus> status_at_bf_cache_entry_;
Thomas Nguyena4cf2342022-12-01 13:15:41120 base::WeakPtrFactory<PermissionSubscription> weak_ptr_factory_{this};
reillyg86dfcea2017-01-04 22:27:57121};
122
Alexander Timin72a2f0c2021-10-01 01:56:07123// static
Thomas Nguyen1c300152023-02-02 09:56:11124PermissionServiceContext*
125PermissionServiceContext::GetOrCreateForCurrentDocument(
Alexander Timin72a2f0c2021-10-01 01:56:07126 RenderFrameHost* render_frame_host) {
127 return &DocumentPermissionServiceContextHolder::GetOrCreateForCurrentDocument(
128 render_frame_host)
129 ->permission_service_context;
130}
Carlos Caballeroa09553482021-03-17 15:51:06131
Thomas Nguyen1c300152023-02-02 09:56:11132// static
133PermissionServiceContext* PermissionServiceContext::GetForCurrentDocument(
134 RenderFrameHost* render_frame_host) {
135 auto* holder = DocumentPermissionServiceContextHolder::GetForCurrentDocument(
136 render_frame_host);
137 return holder ? &holder->permission_service_context : nullptr;
138}
139
mlamouri4ebe69f2014-11-14 17:25:21140PermissionServiceContext::PermissionServiceContext(
141 RenderFrameHost* render_frame_host)
Ravjit715c2b42021-07-15 15:25:01142 : render_frame_host_(render_frame_host), render_process_host_(nullptr) {
143 render_frame_host->GetProcess()->AddObserver(this);
144}
timvolodine089c07c2014-12-11 19:32:26145
146PermissionServiceContext::PermissionServiceContext(
147 RenderProcessHost* render_process_host)
Carlos Caballeroa09553482021-03-17 15:51:06148 : render_frame_host_(nullptr), render_process_host_(render_process_host) {}
mlamouri4ebe69f2014-11-14 17:25:21149
150PermissionServiceContext::~PermissionServiceContext() {
Thomas Nguyen5fe19272022-12-15 10:38:00151 if (render_frame_host_) {
Ravjit715c2b42021-07-15 15:25:01152 render_frame_host_->GetProcess()->RemoveObserver(this);
Thomas Nguyen5fe19272022-12-15 10:38:00153 }
mlamouri4ebe69f2014-11-14 17:25:21154}
155
156void PermissionServiceContext::CreateService(
Mario Sanchez Prada97f66162019-08-06 21:56:48157 mojo::PendingReceiver<blink::mojom::PermissionService> receiver) {
Sam McNally2e5c71f2017-12-11 03:24:27158 DCHECK(render_frame_host_);
Andy Paicubdb19c72022-04-22 09:24:31159 services_.Add(
160 std::make_unique<PermissionServiceImpl>(
161 this, url::Origin::Create(PermissionUtil::GetLastCommittedOriginAsURL(
162 render_frame_host_))),
163 std::move(receiver));
Sam McNally2e5c71f2017-12-11 03:24:27164}
165
166void PermissionServiceContext::CreateServiceForWorker(
Miyoung Shine676be1f2019-09-25 00:47:02167 const url::Origin& origin,
168 mojo::PendingReceiver<blink::mojom::PermissionService> receiver) {
Mario Sanchez Prada97f66162019-08-06 21:56:48169 services_.Add(std::make_unique<PermissionServiceImpl>(this, origin),
170 std::move(receiver));
reillyg86dfcea2017-01-04 22:27:57171}
172
173void PermissionServiceContext::CreateSubscription(
Andy Paicua6d6d852022-04-28 18:08:36174 blink::PermissionType permission_type,
reillyg86dfcea2017-01-04 22:27:57175 const url::Origin& origin,
Illia Klimov2c6138b2023-08-14 09:39:25176 PermissionStatus current_status,
177 PermissionStatus last_known_status,
Mario Sanchez Prada97f66162019-08-06 21:56:48178 mojo::PendingRemote<blink::mojom::PermissionObserver> observer) {
reillyg86dfcea2017-01-04 22:27:57179 BrowserContext* browser_context = GetBrowserContext();
Thomas Nguyen5fe19272022-12-15 10:38:00180 if (!browser_context) {
reillyg86dfcea2017-01-04 22:27:57181 return;
Thomas Nguyen5fe19272022-12-15 10:38:00182 }
reillyg86dfcea2017-01-04 22:27:57183
Thomas Nguyen5fe19272022-12-15 10:38:00184 auto subscription = std::make_unique<PermissionSubscription>(
185 last_known_status, this, std::move(observer));
Mario Sanchez Prada97f66162019-08-06 21:56:48186
187 if (current_status != last_known_status) {
188 subscription->OnPermissionStatusChanged(current_status);
Mario Sanchez Prada97f66162019-08-06 21:56:48189 }
190
Thomas Nguyenf9ccec82023-02-20 14:35:38191 if (render_frame_host_ &&
192 render_frame_host_->IsInLifecycleState(
193 content::RenderFrameHost::LifecycleState::kInBackForwardCache)) {
194 subscription->StoreStatusAtBFCacheEntry();
195 }
196
reillyg86dfcea2017-01-04 22:27:57197 GURL requesting_origin(origin.Serialize());
Balazs Engedyad1489b2021-03-31 07:47:19198 auto subscription_id =
Andrey Lushnikovebff0442018-07-12 20:02:58199 PermissionControllerImpl::FromBrowserContext(browser_context)
Balazs Engedy33b441e2023-12-12 18:53:42200 ->SubscribeToPermissionStatusChange(
Robbie McElrath8d5602a2022-04-01 17:39:18201 permission_type, render_process_host_, render_frame_host_,
202 requesting_origin,
Lei Zhang67b7bf32019-10-08 18:46:01203 base::BindRepeating(
204 &PermissionSubscription::OnPermissionStatusChanged,
Thomas Nguyena4cf2342022-12-01 13:15:41205 subscription->GetWeakPtr()));
reillyg86dfcea2017-01-04 22:27:57206 subscription->set_id(subscription_id);
207 subscriptions_[subscription_id] = std::move(subscription);
mlamouri4ebe69f2014-11-14 17:25:21208}
209
Balazs Engedyad1489b2021-03-31 07:47:19210void PermissionServiceContext::ObserverHadConnectionError(
211 PermissionController::SubscriptionId subscription_id) {
Lei Zhang67b7bf32019-10-08 18:46:01212 size_t erased = subscriptions_.erase(subscription_id);
213 DCHECK_EQ(1u, erased);
reillyg86dfcea2017-01-04 22:27:57214}
215
timvolodine089c07c2014-12-11 19:32:26216BrowserContext* PermissionServiceContext::GetBrowserContext() const {
Carlos Caballeroa09553482021-03-17 15:51:06217 if (render_frame_host_)
218 return render_frame_host_->GetBrowserContext();
Dominic Mazzoni94e567b2017-08-29 18:07:02219
220 if (render_process_host_)
timvolodine089c07c2014-12-11 19:32:26221 return render_process_host_->GetBrowserContext();
Dominic Mazzoni94e567b2017-08-29 18:07:02222
223 return nullptr;
timvolodine089c07c2014-12-11 19:32:26224}
225
226GURL PermissionServiceContext::GetEmbeddingOrigin() const {
Henrique Ferreirof89870f2022-03-30 17:08:13227 return render_frame_host_ ? PermissionUtil::GetLastCommittedOriginAsURL(
228 render_frame_host_->GetMainFrame())
229 : GURL();
timvolodine089c07c2014-12-11 19:32:26230}
231
Ravjit715c2b42021-07-15 15:25:01232void PermissionServiceContext::RenderProcessHostDestroyed(
233 RenderProcessHost* host) {
234 DCHECK(host == render_frame_host_->GetProcess());
235 subscriptions_.clear();
236 // RenderProcessHostImpl will always outlive 'this', but it gets cleaned up
237 // earlier so we need to listen to this event so we can do our clean up as
238 // well.
239 host->RemoveObserver(this);
Thomas Nguyen5fe19272022-12-15 10:38:00240}
241
Thomas Nguyen1c300152023-02-02 09:56:11242void PermissionServiceContext::StoreStatusAtBFCacheEntry() {
Thomas Nguyen5fe19272022-12-15 10:38:00243 for (auto& iter : subscriptions_) {
244 iter.second->StoreStatusAtBFCacheEntry();
245 }
246}
247
Thomas Nguyen1c300152023-02-02 09:56:11248void PermissionServiceContext::NotifyPermissionStatusChangedIfNeeded() {
Thomas Nguyen5fe19272022-12-15 10:38:00249 for (auto& iter : subscriptions_) {
250 iter.second->NotifyPermissionStatusChangedIfNeeded();
251 }
Ravjit715c2b42021-07-15 15:25:01252}
253
Lei Zhang67b7bf32019-10-08 18:46:01254} // namespace content