[cr140] Overriding PermissionManager

The previous override for `ContentSettingPermissionContextBase` has been
changed into an override for `PermissionManager`, as this is the new
correct customisation point for what we were doing with the previous
class.

Chromium changes:
https://chromium.googlesource.com/chromium/src/+/171d2ac0366c1eaf877525ce85f678395cc9759e
https://chromium.googlesource.com/chromium/src/+/171d2ac0366c1eaf877525ce85f678395cc9759e

commit 171d2ac0366c1eaf877525ce85f678395cc9759e
Author: Florian Jacky <fjacky@google.com>
Date:   Wed Jun 25 04:51:48 2025 -0700

    [PermissionOptions] Fix PCB used in PermissionManager

    While currently all contexts are ContentSettingPermissionContextBase
    based contexts, this won't be the case anymore shortly. The permission manager should use PermissionContextBase.

    Bug: 411025625
    Change-Id: If479bdd650e0dfa3a2580f27c190c3d9be24f7aa
    Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6652828
    Commit-Queue: Andy Paicu <andypaicu@chromium.org>
    Auto-Submit: Florian Jacky <fjacky@chromium.org>
    Reviewed-by: Andy Paicu <andypaicu@chromium.org>
    Cr-Commit-Position: refs/heads/main@{#1478467}

commit 9f8c396a492dffad7b93c7d8adfe0fbdaee0dc45
Author: Florian Jacky <fjacky@google.com>
Date:   Tue Jun 10 02:50:36 2025 -0700

    [PermissionOptions] Rename PermissionContextBase to ContentSettingPermissionContextBase

    Bug: 411025625
    Change-Id: I45387e54e147dfe830330378fc5b978d2095ddab
    Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6618750
    Reviewed-by: Nico Weber <thakis@chromium.org>
    Reviewed-by: Andy Paicu <andypaicu@chromium.org>
    Commit-Queue: Florian Jacky <fjacky@chromium.org>
    Cr-Commit-Position: refs/heads/main@{#1471670}
This commit is contained in:
Claudio DeSouza
2025-08-19 19:54:15 +01:00
parent 8e6529c463
commit 92bb0f991f
6 changed files with 258 additions and 311 deletions
@@ -118,7 +118,7 @@ class PermissionManagerBrowserTest : public InProcessBrowserTest {
BravePermissionManager* permission_manager() { return permission_manager_; }
bool IsPendingGroupedRequestsEmpty(ContentSettingsType type) {
ContentSettingPermissionContextBase* context =
PermissionContextBase* context =
permission_manager()->GetPermissionContextForTesting(type);
return context->IsPendingGroupedRequestsEmptyForTesting();
}
@@ -1,195 +0,0 @@
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
#include "components/permissions/content_setting_permission_context_base.h"
#include "base/check.h"
#include "components/permissions/permissions_client.h"
#define ContentSettingPermissionContextBase \
ContentSettingPermissionContextBase_ChromiumImpl
#include <components/permissions/content_setting_permission_context_base.cc>
#undef ContentSettingPermissionContextBase
#include "brave/components/permissions/permission_lifetime_manager.h"
namespace {
bool IsGroupedPermissionType(ContentSettingsType type) {
return type == ContentSettingsType::BRAVE_ETHEREUM ||
type == ContentSettingsType::BRAVE_SOLANA ||
type == ContentSettingsType::BRAVE_CARDANO;
}
} // namespace
namespace permissions {
ContentSettingPermissionContextBase::ContentSettingPermissionContextBase(
content::BrowserContext* browser_context,
ContentSettingsType content_settings_type,
network::mojom::PermissionsPolicyFeature permissions_policy_feature)
: ContentSettingPermissionContextBase_ChromiumImpl(
browser_context,
content_settings_type,
permissions_policy_feature) {}
ContentSettingPermissionContextBase::~ContentSettingPermissionContextBase() =
default;
void ContentSettingPermissionContextBase::SetPermissionLifetimeManagerFactory(
const base::RepeatingCallback<
PermissionLifetimeManager*(content::BrowserContext*)>& factory) {
permission_lifetime_manager_factory_ = factory;
}
void ContentSettingPermissionContextBase::PermissionDecided(
PermissionDecision decision,
bool is_final_decision,
const PermissionRequestData& request_data) {
if (permission_lifetime_manager_factory_) {
const auto request_it = pending_requests_.find(request_data.id.ToString());
if (request_it != pending_requests_.end()) {
const PermissionRequest* permission_request =
request_it->second.first.get();
DCHECK(permission_request);
if (auto* permission_lifetime_manager =
permission_lifetime_manager_factory_.Run(browser_context_)) {
permission_lifetime_manager->PermissionDecided(
*permission_request, request_data.requesting_origin,
request_data.embedding_origin, decision);
}
}
const auto group_request_it =
pending_grouped_requests_.find(request_data.id.ToString());
if (group_request_it != pending_grouped_requests_.end()) {
for (const auto& request : group_request_it->second->Requests()) {
const PermissionRequest* permission_request = request.first.get();
DCHECK(permission_request);
if (auto* permission_lifetime_manager =
permission_lifetime_manager_factory_.Run(browser_context_)) {
permission_lifetime_manager->PermissionDecided(
*permission_request, request_data.requesting_origin,
request_data.embedding_origin, decision);
}
}
}
}
if (!IsGroupedPermissionType(content_settings_type())) {
ContentSettingPermissionContextBase_ChromiumImpl::PermissionDecided(
decision, is_final_decision, request_data);
return;
}
DCHECK(decision == PermissionDecision::kAllow ||
decision == PermissionDecision::kDeny ||
decision == PermissionDecision::kNone);
UserMadePermissionDecision(request_data.id, request_data.requesting_origin,
request_data.embedding_origin, decision);
bool persist = (decision == PermissionDecision::kAllow ||
decision == PermissionDecision::kDeny);
auto grouped_request =
pending_grouped_requests_.find(request_data.id.ToString());
DCHECK(grouped_request != pending_grouped_requests_.end());
DCHECK(grouped_request->second);
if (grouped_request->second->IsDone()) {
return;
}
auto callback = grouped_request->second->GetNextCallback();
if (callback) {
NotifyPermissionSet(request_data, std::move(callback), persist, decision,
is_final_decision);
}
}
void ContentSettingPermissionContextBase::DecidePermission(
std::unique_ptr<permissions::PermissionRequestData> request_data,
BrowserPermissionCallback callback) {
auto id = request_data->id;
ContentSettingPermissionContextBase_ChromiumImpl::DecidePermission(
std::move(request_data), std::move(callback));
if (!IsGroupedPermissionType(content_settings_type())) {
return;
}
// Move added pending request from pending_requests_ to
// pending_grouped_requests_, because otherwise Chromium will replace this
// pending_request with next sub-request because it does not expect multiple
// sub-requests in the same type for one RequestPermissions request.
auto pending_request = pending_requests_.find(id.ToString());
DCHECK(pending_request != pending_requests_.end());
auto it = pending_grouped_requests_.find(id.ToString());
if (it == pending_grouped_requests_.end()) {
it = pending_grouped_requests_
.insert(std::make_pair(
id.ToString(), std::make_unique<GroupedPermissionRequests>()))
.first;
}
it->second->AddRequest(std::move(pending_request->second));
pending_requests_.erase(pending_request);
}
void ContentSettingPermissionContextBase::CleanUpRequest(
content::WebContents* web_contents,
const PermissionRequestID& id,
bool embedded_permission_element_initiated) {
if (!IsGroupedPermissionType(content_settings_type())) {
ContentSettingPermissionContextBase_ChromiumImpl::CleanUpRequest(
web_contents, id, embedded_permission_element_initiated);
return;
}
// A sub-request is done, increase finish count. If all sub-requests are
// done, remove all sub-requests.
auto requests = pending_grouped_requests_.find(id.ToString());
DCHECK(requests != pending_grouped_requests_.end());
requests->second->RequestFinished();
if (requests->second->IsDone()) {
pending_grouped_requests_.erase(id.ToString());
}
}
ContentSettingPermissionContextBase::GroupedPermissionRequests::
GroupedPermissionRequests() = default;
ContentSettingPermissionContextBase::GroupedPermissionRequests::
~GroupedPermissionRequests() = default;
bool ContentSettingPermissionContextBase::GroupedPermissionRequests::IsDone()
const {
return finished_request_count_ == requests_.size();
}
void ContentSettingPermissionContextBase::GroupedPermissionRequests::AddRequest(
std::pair<base::WeakPtr<PermissionRequest>, BrowserPermissionCallback>
request) {
requests_.push_back(std::move(request));
}
BrowserPermissionCallback ContentSettingPermissionContextBase::
GroupedPermissionRequests::GetNextCallback() {
DCHECK(!IsDone());
DCHECK(next_callback_index_ < requests_.size());
return std::move(requests_[next_callback_index_++].second);
}
void ContentSettingPermissionContextBase::GroupedPermissionRequests::
RequestFinished() {
finished_request_count_++;
}
bool ContentSettingPermissionContextBase::
IsPendingGroupedRequestsEmptyForTesting() {
return pending_grouped_requests_.empty();
}
} // namespace permissions
@@ -1,100 +0,0 @@
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
#ifndef BRAVE_CHROMIUM_SRC_COMPONENTS_PERMISSIONS_CONTENT_SETTING_PERMISSION_CONTEXT_BASE_H_
#define BRAVE_CHROMIUM_SRC_COMPONENTS_PERMISSIONS_CONTENT_SETTING_PERMISSION_CONTEXT_BASE_H_
#include "base/functional/callback.h"
#include "components/permissions/permission_context_base.h"
namespace permissions {
class ContentSettingPermissionContextBase;
using ContentSettingPermissionContextBase_BraveImpl =
ContentSettingPermissionContextBase;
class PermissionLifetimeManager;
} // namespace permissions
#define ContentSettingPermissionContextBase \
ContentSettingPermissionContextBase_ChromiumImpl
#define BRAVE_CONTENT_SETTING_PERMISSION_CONTEXT_BASE_ \
friend ContentSettingPermissionContextBase_BraveImpl;
#include <components/permissions/content_setting_permission_context_base.h> // IWYU pragma: export
#undef BRAVE_CONTENT_SETTING_PERMISSION_CONTEXT_BASE_
#undef ContentSettingPermissionContextBase
#include <map>
namespace permissions {
class ContentSettingPermissionContextBase
: public ContentSettingPermissionContextBase_ChromiumImpl {
public:
ContentSettingPermissionContextBase(
content::BrowserContext* browser_context,
ContentSettingsType content_settings_type,
network::mojom::PermissionsPolicyFeature permissions_policy_feature);
~ContentSettingPermissionContextBase() override;
void SetPermissionLifetimeManagerFactory(
const base::RepeatingCallback<
PermissionLifetimeManager*(content::BrowserContext*)>& factory);
void DecidePermission(
std::unique_ptr<permissions::PermissionRequestData> request_data,
BrowserPermissionCallback callback) override;
bool IsPendingGroupedRequestsEmptyForTesting();
private:
/**
* This class is map to one PermissionManager::RequestPermissions request,
* sub-requests will be kept in requests_.
* Chromium does not expect multiple sub-requests for a same permission type,
* this class is created to support tracking multiple sub-requests
* for each RequestPermissions request. It will clear all pending
* sub-requests for one RequestPermissions request after all of its
* sub-requests are finished.
*/
class GroupedPermissionRequests {
public:
GroupedPermissionRequests();
~GroupedPermissionRequests();
using GroupedRequests = std::vector<
std::pair<base::WeakPtr<PermissionRequest>, BrowserPermissionCallback>>;
bool IsDone() const;
void AddRequest(std::pair<base::WeakPtr<PermissionRequest>,
BrowserPermissionCallback> request);
BrowserPermissionCallback GetNextCallback();
void RequestFinished();
const GroupedRequests& Requests() const { return requests_; }
private:
GroupedRequests requests_;
size_t finished_request_count_ = 0;
size_t next_callback_index_ = 0;
};
void PermissionDecided(PermissionDecision decision,
bool is_final_decision,
const PermissionRequestData& request_data) override;
void CleanUpRequest(content::WebContents* web_contents,
const PermissionRequestID& id,
bool embedded_permission_element_initiated) override;
base::RepeatingCallback<PermissionLifetimeManager*(content::BrowserContext*)>
permission_lifetime_manager_factory_;
std::map<std::string, std::unique_ptr<GroupedPermissionRequests>>
pending_grouped_requests_;
};
} // namespace permissions
#endif // BRAVE_CHROMIUM_SRC_COMPONENTS_PERMISSIONS_CONTENT_SETTING_PERMISSION_CONTEXT_BASE_H_
@@ -5,11 +5,188 @@
#include "components/permissions/permission_context_base.h"
#include "base/check.h"
#include "brave/components/permissions/permission_lifetime_manager.h"
#include "components/permissions/permissions_client.h"
#define CanBypassEmbeddingOriginCheck(REQUESTING_ORIGIN, EMBEDDING_ORIGIN) \
BraveCanBypassEmbeddingOriginCheck(REQUESTING_ORIGIN, EMBEDDING_ORIGIN, \
content_settings_type_)
#define PermissionContextBase PermissionContextBase_ChromiumImpl
#include <components/permissions/permission_context_base.cc>
#undef CanBypassEmbeddingOriginCheck
#undef PermissionContextBase
namespace {
bool IsGroupedPermissionType(ContentSettingsType type) {
return type == ContentSettingsType::BRAVE_ETHEREUM ||
type == ContentSettingsType::BRAVE_SOLANA ||
type == ContentSettingsType::BRAVE_CARDANO;
}
} // namespace
namespace permissions {
PermissionContextBase::PermissionContextBase(
content::BrowserContext* browser_context,
ContentSettingsType content_settings_type,
network::mojom::PermissionsPolicyFeature permissions_policy_feature)
: PermissionContextBase_ChromiumImpl(browser_context,
content_settings_type,
permissions_policy_feature) {}
PermissionContextBase::~PermissionContextBase() = default;
void PermissionContextBase::SetPermissionLifetimeManagerFactory(
const base::RepeatingCallback<
PermissionLifetimeManager*(content::BrowserContext*)>& factory) {
permission_lifetime_manager_factory_ = factory;
}
void PermissionContextBase::PermissionDecided(
PermissionDecision decision,
bool is_final_decision,
const PermissionRequestData& request_data) {
if (permission_lifetime_manager_factory_) {
const auto request_it = pending_requests_.find(request_data.id.ToString());
if (request_it != pending_requests_.end()) {
const PermissionRequest* permission_request =
request_it->second.first.get();
DCHECK(permission_request);
if (auto* permission_lifetime_manager =
permission_lifetime_manager_factory_.Run(browser_context_)) {
permission_lifetime_manager->PermissionDecided(
*permission_request, request_data.requesting_origin,
request_data.embedding_origin, decision);
}
}
const auto group_request_it =
pending_grouped_requests_.find(request_data.id.ToString());
if (group_request_it != pending_grouped_requests_.end()) {
for (const auto& request : group_request_it->second->Requests()) {
const PermissionRequest* permission_request = request.first.get();
DCHECK(permission_request);
if (auto* permission_lifetime_manager =
permission_lifetime_manager_factory_.Run(browser_context_)) {
permission_lifetime_manager->PermissionDecided(
*permission_request, request_data.requesting_origin,
request_data.embedding_origin, decision);
}
}
}
}
if (!IsGroupedPermissionType(content_settings_type())) {
PermissionContextBase_ChromiumImpl::PermissionDecided(
decision, is_final_decision, request_data);
return;
}
DCHECK(decision == PermissionDecision::kAllow ||
decision == PermissionDecision::kDeny ||
decision == PermissionDecision::kNone);
UserMadePermissionDecision(request_data.id, request_data.requesting_origin,
request_data.embedding_origin, decision);
bool persist = (decision == PermissionDecision::kAllow ||
decision == PermissionDecision::kDeny);
auto grouped_request =
pending_grouped_requests_.find(request_data.id.ToString());
DCHECK(grouped_request != pending_grouped_requests_.end());
DCHECK(grouped_request->second);
if (grouped_request->second->IsDone()) {
return;
}
auto callback = grouped_request->second->GetNextCallback();
if (callback) {
NotifyPermissionSet(request_data, std::move(callback), persist, decision,
is_final_decision);
}
}
void PermissionContextBase::DecidePermission(
std::unique_ptr<permissions::PermissionRequestData> request_data,
BrowserPermissionCallback callback) {
auto id = request_data->id;
PermissionContextBase_ChromiumImpl::DecidePermission(std::move(request_data),
std::move(callback));
if (!IsGroupedPermissionType(content_settings_type())) {
return;
}
// Move added pending request from pending_requests_ to
// pending_grouped_requests_, because otherwise Chromium will replace this
// pending_request with next sub-request because it does not expect multiple
// sub-requests in the same type for one RequestPermissions request.
auto pending_request = pending_requests_.find(id.ToString());
DCHECK(pending_request != pending_requests_.end());
auto it = pending_grouped_requests_.find(id.ToString());
if (it == pending_grouped_requests_.end()) {
it = pending_grouped_requests_
.insert(std::make_pair(
id.ToString(), std::make_unique<GroupedPermissionRequests>()))
.first;
}
it->second->AddRequest(std::move(pending_request->second));
pending_requests_.erase(pending_request);
}
void PermissionContextBase::CleanUpRequest(
content::WebContents* web_contents,
const PermissionRequestID& id,
bool embedded_permission_element_initiated) {
if (!IsGroupedPermissionType(content_settings_type())) {
PermissionContextBase_ChromiumImpl::CleanUpRequest(
web_contents, id, embedded_permission_element_initiated);
return;
}
// A sub-request is done, increase finish count. If all sub-requests are
// done, remove all sub-requests.
auto requests = pending_grouped_requests_.find(id.ToString());
DCHECK(requests != pending_grouped_requests_.end());
requests->second->RequestFinished();
if (requests->second->IsDone()) {
pending_grouped_requests_.erase(id.ToString());
}
}
PermissionContextBase::GroupedPermissionRequests::GroupedPermissionRequests() =
default;
PermissionContextBase::GroupedPermissionRequests::~GroupedPermissionRequests() =
default;
bool PermissionContextBase::GroupedPermissionRequests::IsDone() const {
return finished_request_count_ == requests_.size();
}
void PermissionContextBase::GroupedPermissionRequests::AddRequest(
std::pair<base::WeakPtr<PermissionRequest>, BrowserPermissionCallback>
request) {
requests_.push_back(std::move(request));
}
BrowserPermissionCallback
PermissionContextBase::GroupedPermissionRequests::GetNextCallback() {
DCHECK(!IsDone());
DCHECK(next_callback_index_ < requests_.size());
return std::move(requests_[next_callback_index_++].second);
}
void PermissionContextBase::GroupedPermissionRequests::RequestFinished() {
finished_request_count_++;
}
bool PermissionContextBase::IsPendingGroupedRequestsEmptyForTesting() {
return pending_grouped_requests_.empty();
}
} // namespace permissions
@@ -6,21 +6,98 @@
#ifndef BRAVE_CHROMIUM_SRC_COMPONENTS_PERMISSIONS_PERMISSION_CONTEXT_BASE_H_
#define BRAVE_CHROMIUM_SRC_COMPONENTS_PERMISSIONS_PERMISSION_CONTEXT_BASE_H_
#include <map>
#include "components/permissions/permission_request_data.h"
namespace permissions {
class ContentSettingPermissionContextBase;
class PermissionContextBase;
using PermissionContextBase_BraveImpl = PermissionContextBase;
class PermissionLifetimeManager;
} // namespace permissions
#define PermissionContextBaseTests \
PermissionContextBaseTests; \
friend ContentSettingPermissionContextBase
friend PermissionContextBase_BraveImpl
#define PermissionContextBase PermissionContextBase_ChromiumImpl
#define PermissionDecided virtual PermissionDecided
#define CleanUpRequest virtual CleanUpRequest
#include <components/permissions/permission_context_base.h> // IWYU pragma: export
#undef PermissionContextBaseTests
#undef PermissionContextBase
#undef PermissionDecided
#undef CleanUpRequest
namespace permissions {
class PermissionContextBase : public PermissionContextBase_ChromiumImpl {
public:
PermissionContextBase(
content::BrowserContext* browser_context,
ContentSettingsType content_settings_type,
network::mojom::PermissionsPolicyFeature permissions_policy_feature);
~PermissionContextBase() override;
void SetPermissionLifetimeManagerFactory(
const base::RepeatingCallback<
PermissionLifetimeManager*(content::BrowserContext*)>& factory);
void DecidePermission(
std::unique_ptr<permissions::PermissionRequestData> request_data,
BrowserPermissionCallback callback) override;
bool IsPendingGroupedRequestsEmptyForTesting();
private:
/**
* This class is map to one PermissionManager::RequestPermissions request,
* sub-requests will be kept in requests_.
* Chromium does not expect multiple sub-requests for a same permission type,
* this class is created to support tracking multiple sub-requests
* for each RequestPermissions request. It will clear all pending
* sub-requests for one RequestPermissions request after all of its
* sub-requests are finished.
*/
class GroupedPermissionRequests {
public:
GroupedPermissionRequests();
~GroupedPermissionRequests();
using GroupedRequests = std::vector<
std::pair<base::WeakPtr<PermissionRequest>, BrowserPermissionCallback>>;
bool IsDone() const;
void AddRequest(std::pair<base::WeakPtr<PermissionRequest>,
BrowserPermissionCallback> request);
BrowserPermissionCallback GetNextCallback();
void RequestFinished();
const GroupedRequests& Requests() const { return requests_; }
private:
GroupedRequests requests_;
size_t finished_request_count_ = 0;
size_t next_callback_index_ = 0;
};
void PermissionDecided(PermissionDecision decision,
bool is_final_decision,
const PermissionRequestData& request_data) override;
void CleanUpRequest(content::WebContents* web_contents,
const PermissionRequestID& id,
bool embedded_permission_element_initiated) override;
base::RepeatingCallback<PermissionLifetimeManager*(content::BrowserContext*)>
permission_lifetime_manager_factory_;
std::map<std::string, std::unique_ptr<GroupedPermissionRequests>>
pending_grouped_requests_;
};
} // namespace permissions
#endif // BRAVE_CHROMIUM_SRC_COMPONENTS_PERMISSIONS_PERMISSION_CONTEXT_BASE_H_
@@ -1,12 +0,0 @@
diff --git a/components/permissions/content_setting_permission_context_base.h b/components/permissions/content_setting_permission_context_base.h
index 30bb4bcc559864fd253ab77c11808e3a6ba65fa5..ba3c24fec8e13bcc35541fc9511c310e9df72ce3 100644
--- a/components/permissions/content_setting_permission_context_base.h
+++ b/components/permissions/content_setting_permission_context_base.h
@@ -26,6 +26,7 @@ class ContentSettingPermissionContextBase : public PermissionContextBase {
void ResetPermission(const GURL& requesting_origin,
const GURL& embedding_origin) override;
+ BRAVE_CONTENT_SETTING_PERMISSION_CONTEXT_BASE_
protected:
// Store the decided permission state. Virtual since the permission might be
// stored with different restrictions (for example for desktop notifications).