summaryrefslogtreecommitdiffstats
path: root/src/core/permission_manager_qt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/permission_manager_qt.cpp')
-rw-r--r--src/core/permission_manager_qt.cpp592
1 files changed, 384 insertions, 208 deletions
diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp
index 8b9eab3eb..95f79bb11 100644
--- a/src/core/permission_manager_qt.cpp
+++ b/src/core/permission_manager_qt.cpp
@@ -1,161 +1,257 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWebEngine module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "permission_manager_qt.h"
+#include "base/threading/thread_restrictions.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/permission_controller.h"
-#include "content/public/browser/permission_type.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"
+#include "third_party/blink/public/common/permissions/permission_utils.h"
+#include "chrome/browser/prefs/chrome_command_line_pref_store.h"
+#include "components/prefs/pref_member.h"
+#include "components/prefs/in_memory_pref_store.h"
+#include "components/prefs/json_pref_store.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/pref_service_factory.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/scoped_user_pref_update.h"
+#include "components/proxy_config/pref_proxy_config_tracker_impl.h"
+#include "components/prefs/pref_service.h"
+#include <QtWebEngineCore/private/qwebenginepermission_p.h>
#include "type_conversion.h"
#include "web_contents_delegate_qt.h"
#include "web_engine_settings.h"
namespace QtWebEngineCore {
-static ProfileAdapter::PermissionType toQt(content::PermissionType type)
+static QWebEnginePermission::Feature toQt(blink::PermissionType type)
{
switch (type) {
- case content::PermissionType::GEOLOCATION:
- return ProfileAdapter::GeolocationPermission;
- case content::PermissionType::AUDIO_CAPTURE:
- return ProfileAdapter::AudioCapturePermission;
- case content::PermissionType::VIDEO_CAPTURE:
- return ProfileAdapter::VideoCapturePermission;
- case content::PermissionType::CLIPBOARD_READ_WRITE:
- return ProfileAdapter::ClipboardRead;
- case content::PermissionType::CLIPBOARD_SANITIZED_WRITE:
- return ProfileAdapter::ClipboardWrite;
- case content::PermissionType::NOTIFICATIONS:
- return ProfileAdapter::NotificationPermission;
- case content::PermissionType::ACCESSIBILITY_EVENTS:
- return ProfileAdapter::UnsupportedPermission;
- case content::PermissionType::FLASH:
- case content::PermissionType::MIDI_SYSEX:
- case content::PermissionType::PROTECTED_MEDIA_IDENTIFIER:
- case content::PermissionType::MIDI:
- case content::PermissionType::DURABLE_STORAGE:
- case content::PermissionType::BACKGROUND_SYNC:
- case content::PermissionType::SENSORS:
- case content::PermissionType::PAYMENT_HANDLER:
- case content::PermissionType::BACKGROUND_FETCH:
- case content::PermissionType::IDLE_DETECTION:
- case content::PermissionType::PERIODIC_BACKGROUND_SYNC:
- case content::PermissionType::WAKE_LOCK_SCREEN:
- case content::PermissionType::WAKE_LOCK_SYSTEM:
- case content::PermissionType::NFC:
- case content::PermissionType::AR:
- case content::PermissionType::VR:
- case content::PermissionType::STORAGE_ACCESS_GRANT:
- case content::PermissionType::NUM:
- LOG(INFO) << "Unsupported permission type: " << static_cast<int>(type);
+ case blink::PermissionType::GEOLOCATION:
+ return QWebEnginePermission::Geolocation;
+ case blink::PermissionType::AUDIO_CAPTURE:
+ return QWebEnginePermission::MediaAudioCapture;
+ case blink::PermissionType::VIDEO_CAPTURE:
+ return QWebEnginePermission::MediaVideoCapture;
+ case blink::PermissionType::DISPLAY_CAPTURE:
+ return QWebEnginePermission::DesktopAudioVideoCapture;
+ // We treat these both as read/write since we do not currently have a
+ // ClipboardSanitizedWrite feature.
+ case blink::PermissionType::CLIPBOARD_READ_WRITE:
+ case blink::PermissionType::CLIPBOARD_SANITIZED_WRITE:
+ return QWebEnginePermission::ClipboardReadWrite;
+ case blink::PermissionType::NOTIFICATIONS:
+ return QWebEnginePermission::Notifications;
+ case blink::PermissionType::LOCAL_FONTS:
+ return QWebEnginePermission::LocalFontsAccess;
+ case blink::PermissionType::ACCESSIBILITY_EVENTS:
+ case blink::PermissionType::CAMERA_PAN_TILT_ZOOM:
+ case blink::PermissionType::WINDOW_MANAGEMENT:
+ return QWebEnginePermission::Unsupported;
+ case blink::PermissionType::MIDI_SYSEX:
+ case blink::PermissionType::PROTECTED_MEDIA_IDENTIFIER:
+ case blink::PermissionType::MIDI:
+ case blink::PermissionType::DURABLE_STORAGE:
+ case blink::PermissionType::BACKGROUND_SYNC:
+ case blink::PermissionType::SENSORS:
+ case blink::PermissionType::PAYMENT_HANDLER:
+ case blink::PermissionType::BACKGROUND_FETCH:
+ case blink::PermissionType::IDLE_DETECTION:
+ case blink::PermissionType::PERIODIC_BACKGROUND_SYNC:
+ case blink::PermissionType::WAKE_LOCK_SCREEN:
+ case blink::PermissionType::WAKE_LOCK_SYSTEM:
+ case blink::PermissionType::NFC:
+ case blink::PermissionType::AR:
+ case blink::PermissionType::VR:
+ case blink::PermissionType::STORAGE_ACCESS_GRANT:
+ case blink::PermissionType::TOP_LEVEL_STORAGE_ACCESS:
+ case blink::PermissionType::CAPTURED_SURFACE_CONTROL:
+ case blink::PermissionType::SMART_CARD:
+ case blink::PermissionType::WEB_PRINTING:
+ case blink::PermissionType::NUM:
+ LOG(INFO) << "Unexpected unsupported Blink permission type: " << static_cast<int>(type);
break;
}
- return ProfileAdapter::UnsupportedPermission;
+ return QWebEnginePermission::Unsupported;
}
-static bool canRequestPermissionFor(ProfileAdapter::PermissionType type)
+static blink::PermissionType toBlink(QWebEnginePermission::Feature feature)
{
- switch (type) {
- case ProfileAdapter::GeolocationPermission:
- case ProfileAdapter::NotificationPermission:
- return true;
- default:
- break;
+ switch (feature) {
+ case QWebEnginePermission::Notifications:
+ return blink::PermissionType::NOTIFICATIONS;
+ case QWebEnginePermission::Geolocation:
+ return blink::PermissionType::GEOLOCATION;
+ case QWebEnginePermission::MediaAudioCapture:
+ return blink::PermissionType::AUDIO_CAPTURE;
+ case QWebEnginePermission::MediaVideoCapture:
+ return blink::PermissionType::VIDEO_CAPTURE;
+ case QWebEnginePermission::DesktopVideoCapture:
+ case QWebEnginePermission::DesktopAudioVideoCapture:
+ return blink::PermissionType::DISPLAY_CAPTURE;
+ case QWebEnginePermission::ClipboardReadWrite:
+ return blink::PermissionType::CLIPBOARD_READ_WRITE;
+ case QWebEnginePermission::LocalFontsAccess:
+ return blink::PermissionType::LOCAL_FONTS;
+ case QWebEnginePermission::MediaAudioVideoCapture:
+ case QWebEnginePermission::Unsupported:
+ LOG(INFO) << "Unexpected unsupported WebEngine permission type: " << static_cast<int>(feature);
+ return blink::PermissionType::NUM;
}
- return false;
+
+ Q_UNREACHABLE();
}
-static blink::mojom::PermissionStatus toBlink(ProfileAdapter::PermissionState reply)
+static QWebEnginePermission::State toQt(blink::mojom::PermissionStatus state)
{
- switch (reply) {
- case ProfileAdapter::AskPermission:
+ switch (state) {
+ case blink::mojom::PermissionStatus::ASK:
+ return QWebEnginePermission::Ask;
+ case blink::mojom::PermissionStatus::GRANTED:
+ return QWebEnginePermission::Granted;
+ case blink::mojom::PermissionStatus::DENIED:
+ return QWebEnginePermission::Denied;
+ }
+}
+
+static blink::mojom::PermissionStatus toBlink(QWebEnginePermission::State state)
+{
+ switch (state) {
+ case QWebEnginePermission::Invalid:
+ case QWebEnginePermission::Ask:
return blink::mojom::PermissionStatus::ASK;
- case ProfileAdapter::AllowedPermission:
+ case QWebEnginePermission::Granted:
return blink::mojom::PermissionStatus::GRANTED;
- case ProfileAdapter::DeniedPermission:
+ case QWebEnginePermission::Denied:
return blink::mojom::PermissionStatus::DENIED;
}
}
-PermissionManagerQt::PermissionManagerQt()
+std::string featureString(QWebEnginePermission::Feature feature)
+{
+ // This is separate from blink::featureString() for the sake of future-proofing;
+ // e.g. in case we add extra Features that do not correspond to a PermissionType, and
+ // we need to store them.
+ switch (feature) {
+ case QWebEnginePermission::Notifications:
+ return "Notifications";
+ case QWebEnginePermission::Geolocation:
+ return "Geolocation";
+ case QWebEnginePermission::ClipboardReadWrite:
+ return "ClipboardReadWrite";
+ case QWebEnginePermission::LocalFontsAccess:
+ return "LocalFontsAccess";
+ case QWebEnginePermission::MediaAudioCapture:
+ return "MediaAudioCapture";
+ case QWebEnginePermission::MediaVideoCapture:
+ return "MediaVideoCapture";
+ case QWebEnginePermission::DesktopAudioVideoCapture:
+ return "DesktopAudioVideoCapture";
+ default:
+ Q_UNREACHABLE();
+ return nullptr;
+ }
+}
+
+static blink::mojom::PermissionStatus getStatusFromSettings(blink::PermissionType type, WebEngineSettings *settings)
+{
+ switch (type) {
+ case blink::PermissionType::CLIPBOARD_READ_WRITE:
+ case blink::PermissionType::CLIPBOARD_SANITIZED_WRITE:
+ if (settings->testAttribute(QWebEngineSettings::JavascriptCanPaste)
+ && settings->testAttribute(QWebEngineSettings::JavascriptCanAccessClipboard))
+ return blink::mojom::PermissionStatus::GRANTED;
+ return blink::mojom::PermissionStatus::ASK;
+ default:
+ return blink::mojom::PermissionStatus::ASK;
+ }
+}
+
+PermissionManagerQt::PermissionManagerQt(ProfileAdapter *profileAdapter)
: m_requestIdCount(0)
- , m_subscriberIdCount(0)
+ , m_persistence(true)
+ , m_profileAdapter(profileAdapter)
{
+ PrefServiceFactory factory;
+ factory.set_async(false);
+ factory.set_command_line_prefs(base::MakeRefCounted<ChromeCommandLinePrefStore>(
+ base::CommandLine::ForCurrentProcess()));
+
+ QString userPrefStorePath = profileAdapter->dataPath();
+ auto prefRegistry = base::MakeRefCounted<PrefRegistrySimple>();
+
+ auto policy = profileAdapter->persistentPermissionsPolicy();
+ if (!profileAdapter->isOffTheRecord() && policy == ProfileAdapter::PersistentPermissionsOnDisk &&
+ !userPrefStorePath.isEmpty() && profileAdapter->ensureDataPathExists()) {
+ userPrefStorePath += QDir::separator();
+ userPrefStorePath += QStringLiteral("permissions.json");
+ factory.set_user_prefs(base::MakeRefCounted<JsonPrefStore>(toFilePath(userPrefStorePath)));
+ } else {
+ factory.set_user_prefs(new InMemoryPrefStore);
+ }
+
+ m_featureTypes.push_back(QWebEnginePermission::Notifications);
+ m_featureTypes.push_back(QWebEnginePermission::Geolocation);
+ m_featureTypes.push_back(QWebEnginePermission::ClipboardReadWrite);
+ m_featureTypes.push_back(QWebEnginePermission::LocalFontsAccess);
+
+ // Transient, but the implementation relies on them being written to storage
+ m_featureTypes.push_back(QWebEnginePermission::MediaAudioCapture);
+ m_featureTypes.push_back(QWebEnginePermission::MediaVideoCapture);
+
+ // Register all preference types as keys prior to doing anything else
+ for (auto &type : m_featureTypes) {
+ prefRegistry->RegisterDictionaryPref(featureString(type));
+ }
+ PrefProxyConfigTrackerImpl::RegisterPrefs(prefRegistry.get());
+
+ if (policy == ProfileAdapter::NoPersistentPermissions)
+ m_persistence = false;
+
+ {
+ base::ScopedAllowBlocking allowBlock;
+ m_prefService = factory.Create(prefRegistry);
+ }
}
PermissionManagerQt::~PermissionManagerQt()
{
+ commit();
}
-void PermissionManagerQt::permissionRequestReply(const QUrl &url, ProfileAdapter::PermissionType type, ProfileAdapter::PermissionState reply)
+void PermissionManagerQt::setPermission(const QUrl &url, QWebEnginePermission::Feature feature, QWebEnginePermission::State state)
{
- // Normalize the QUrl to GURL origin form.
- const GURL gorigin = toGurl(url).GetOrigin();
+ // Normalize the QUrl to Chromium origin form.
+ const GURL gorigin = toGurl(url).DeprecatedGetOriginAsURL();
const QUrl origin = gorigin.is_empty() ? url : toQt(gorigin);
if (origin.isEmpty())
return;
- QPair<QUrl, ProfileAdapter::PermissionType> key(origin, type);
- if (reply == ProfileAdapter::AskPermission)
- m_permissions.remove(key);
+ if (state == QWebEnginePermission::Ask)
+ ResetPermission(toBlink(feature), gorigin, gorigin);
else
- m_permissions[key] = (reply == ProfileAdapter::AllowedPermission);
- blink::mojom::PermissionStatus status = toBlink(reply);
- if (reply != ProfileAdapter::AskPermission) {
+ setPermission(toBlink(feature), gorigin, state == QWebEnginePermission::Granted);
+ blink::mojom::PermissionStatus status = toBlink(state);
+ if (state != QWebEnginePermission::Ask) {
auto it = m_requests.begin();
while (it != m_requests.end()) {
- if (it->origin == origin && it->type == type) {
+ if (it->origin == origin && it->type == feature) {
std::move(it->callback).Run(status);
it = m_requests.erase(it);
} else
++it;
}
}
+
for (const auto &it: m_subscribers) {
- if (it.second.origin == origin && it.second.type == type)
+ if (it.second.origin == origin && it.second.type == feature)
it.second.callback.Run(status);
}
- if (reply == ProfileAdapter::AskPermission)
+ if (state == QWebEnginePermission::Ask)
return;
auto it = m_multiRequests.begin();
@@ -164,22 +260,24 @@ void PermissionManagerQt::permissionRequestReply(const QUrl &url, ProfileAdapter
bool answerable = true;
std::vector<blink::mojom::PermissionStatus> result;
result.reserve(it->types.size());
- for (content::PermissionType permission : it->types) {
- const ProfileAdapter::PermissionType permissionType = toQt(permission);
- if (permissionType == ProfileAdapter::UnsupportedPermission) {
+ for (blink::PermissionType permission : it->types) {
+ if (toQt(permission) == QWebEnginePermission::Unsupported) {
result.push_back(blink::mojom::PermissionStatus::DENIED);
continue;
}
- QPair<QUrl, ProfileAdapter::PermissionType> key(origin, permissionType);
- if (!m_permissions.contains(key)) {
- answerable = false;
- break;
+ blink::mojom::PermissionStatus permissionStatus = GetPermissionStatus(permission, gorigin, GURL());
+ if (permissionStatus == toBlink(state)) {
+ if (permissionStatus == blink::mojom::PermissionStatus::ASK) {
+ answerable = false;
+ break;
+ }
+
+ result.push_back(permissionStatus);
+ } else {
+ // Reached when the PersistentPermissionsPolicy is set to NoPersistentPermissions
+ result.push_back(toBlink(state));
}
- if (m_permissions[key])
- result.push_back(blink::mojom::PermissionStatus::GRANTED);
- else
- result.push_back(blink::mojom::PermissionStatus::DENIED);
}
if (answerable) {
std::move(it->callback).Run(result);
@@ -191,57 +289,66 @@ void PermissionManagerQt::permissionRequestReply(const QUrl &url, ProfileAdapter
}
}
-bool PermissionManagerQt::checkPermission(const QUrl &origin, ProfileAdapter::PermissionType type)
+QWebEnginePermission::State PermissionManagerQt::getPermissionState(const QUrl &origin, QWebEnginePermission::Feature feature)
{
- QPair<QUrl, ProfileAdapter::PermissionType> key(origin, type);
- return m_permissions.contains(key) && m_permissions[key];
+ return toQt(GetPermissionStatus(toBlink(feature), toGurl(origin), GURL()));
}
-int PermissionManagerQt::RequestPermission(content::PermissionType permission,
- content::RenderFrameHost *frameHost,
- const GURL& requesting_origin,
- bool /*user_gesture*/,
- base::OnceCallback<void(blink::mojom::PermissionStatus)> callback)
+QList<QWebEnginePermission> PermissionManagerQt::listPermissions(const QUrl &origin, QWebEnginePermission::Feature feature)
{
- if (requesting_origin.is_empty()) {
- std::move(callback).Run(blink::mojom::PermissionStatus::DENIED);
- return content::PermissionController::kNoPendingOperation;
- }
+ Q_ASSERT(origin.isEmpty() || feature == QWebEnginePermission::Unsupported);
+ QList<QWebEnginePermission> returnList;
+ GURL gorigin = toGurl(origin).DeprecatedGetOriginAsURL();
+ std::string originSpec = gorigin.spec();
- WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt *>(
- content::WebContents::FromRenderFrameHost(frameHost)->GetDelegate());
- Q_ASSERT(contentsDelegate);
+ if (!origin.isEmpty() && !gorigin.is_valid())
+ return returnList;
+
+ std::vector<QWebEnginePermission::Feature> types;
+ if (feature == QWebEnginePermission::Unsupported)
+ types = m_featureTypes;
+ else
+ types.push_back(feature);
+
+ for (auto &type : types) {
+ // Transient types may end up in the permission store as an implementation detail,
+ // but we do not want to expose them to callers.
+ if (QWebEnginePermission::isTransient(type))
+ continue;
+
+ auto *pref = m_prefService->FindPreference(featureString(type));
+ if (!pref)
+ continue;
+
+ auto *prefDict = pref->GetValue()->GetIfDict();
+ Q_ASSERT(prefDict);
- ProfileAdapter::PermissionType permissionType = toQt(permission);
- if (permissionType == ProfileAdapter::ClipboardRead) {
- WebEngineSettings *settings = contentsDelegate->webEngineSettings();
- if (settings->testAttribute(QWebEngineSettings::JavascriptCanAccessClipboard)
- && settings->testAttribute(QWebEngineSettings::JavascriptCanPaste))
- std::move(callback).Run(blink::mojom::PermissionStatus::GRANTED);
- else
- std::move(callback).Run(blink::mojom::PermissionStatus::DENIED);
- return content::PermissionController::kNoPendingOperation;
- } else if (!canRequestPermissionFor(permissionType)) {
- std::move(callback).Run(blink::mojom::PermissionStatus::DENIED);
- return content::PermissionController::kNoPendingOperation;
+ for (const auto &entry : *prefDict) {
+ if (!originSpec.empty() && entry.first != originSpec)
+ continue;
+
+ auto *pvt = new QWebEnginePermissionPrivate(toQt(GURL(std::string_view(entry.first))), type, nullptr, m_profileAdapter.get());
+ returnList.push_back(QWebEnginePermission(pvt));
+ }
}
- int request_id = ++m_requestIdCount;
- auto requestOrigin = toQt(requesting_origin);
- m_requests.push_back({ request_id, permissionType, requestOrigin, std::move(callback) });
- contentsDelegate->requestFeaturePermission(permissionType, requestOrigin);
- return request_id;
+ return returnList;
}
-int PermissionManagerQt::RequestPermissions(const std::vector<content::PermissionType>& permissions,
- content::RenderFrameHost* frameHost,
- const GURL& requesting_origin,
- bool /*user_gesture*/,
- base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
+void PermissionManagerQt::commit()
{
- if (requesting_origin.is_empty()) {
- std::move(callback).Run(std::vector<blink::mojom::PermissionStatus>(permissions.size(), blink::mojom::PermissionStatus::DENIED));
- return content::PermissionController::kNoPendingOperation;
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ // Make sure modified permissions are written to disk
+ m_prefService->CommitPendingWrite();
+}
+
+void PermissionManagerQt::RequestPermissions(content::RenderFrameHost *frameHost,
+ const content::PermissionRequestDescription &requestDescription,
+ base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
+{
+ if (requestDescription.requesting_origin.is_empty()) {
+ std::move(callback).Run(std::vector<content::PermissionStatus>(requestDescription.permissions.size(), blink::mojom::PermissionStatus::DENIED));
+ return;
}
WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt *>(
@@ -249,111 +356,180 @@ int PermissionManagerQt::RequestPermissions(const std::vector<content::Permissio
Q_ASSERT(contentsDelegate);
bool answerable = true;
- std::vector<blink::mojom::PermissionStatus> result;
- result.reserve(permissions.size());
- for (content::PermissionType permission : permissions) {
- const ProfileAdapter::PermissionType permissionType = toQt(permission);
- if (permissionType == ProfileAdapter::UnsupportedPermission)
+ std::vector<content::PermissionStatus> result;
+ result.reserve(requestDescription.permissions.size());
+ for (blink::PermissionType permission : requestDescription.permissions) {
+ const QWebEnginePermission::Feature feature = toQt(permission);
+ if (feature == QWebEnginePermission::Unsupported) {
result.push_back(blink::mojom::PermissionStatus::DENIED);
- else if (permissionType == ProfileAdapter::ClipboardRead) {
- WebEngineSettings *settings = contentsDelegate->webEngineSettings();
- if (settings->testAttribute(QWebEngineSettings::JavascriptCanAccessClipboard)
- && settings->testAttribute(QWebEngineSettings::JavascriptCanPaste))
- result.push_back(blink::mojom::PermissionStatus::GRANTED);
- else
- result.push_back(blink::mojom::PermissionStatus::DENIED);
+ continue;
+ }
+
+ blink::mojom::PermissionStatus permissionStatus = getStatusFromSettings(permission, contentsDelegate->webEngineSettings());
+ if (permissionStatus == blink::mojom::PermissionStatus::ASK) {
+ permissionStatus = GetPermissionStatus(permission, requestDescription.requesting_origin, GURL());
+ if (m_persistence && permissionStatus != blink::mojom::PermissionStatus::ASK) {
+ // Automatically grant/deny without prompt if already asked once
+ result.push_back(permissionStatus);
+ } else {
+ answerable = false;
+ break;
+ }
} else {
- answerable = false;
- break;
+ // Reached when clipboard settings have been set
+ result.push_back(permissionStatus);
}
}
+
if (answerable) {
std::move(callback).Run(result);
- return content::PermissionController::kNoPendingOperation;
+ return;
}
int request_id = ++m_requestIdCount;
- auto requestOrigin = toQt(requesting_origin);
- m_multiRequests.push_back({ request_id, permissions, requestOrigin, std::move(callback) });
- for (content::PermissionType permission : permissions) {
- const ProfileAdapter::PermissionType permissionType = toQt(permission);
- if (canRequestPermissionFor(permissionType))
- contentsDelegate->requestFeaturePermission(permissionType, requestOrigin);
+ auto requestOrigin = toQt(requestDescription.requesting_origin);
+ m_multiRequests.push_back({ request_id, requestDescription.permissions, requestOrigin, std::move(callback) });
+ for (blink::PermissionType permission : requestDescription.permissions) {
+ const QWebEnginePermission::Feature feature = toQt(permission);
+ if (!QWebEnginePermission::isTransient(feature))
+ contentsDelegate->requestFeaturePermission(feature, requestOrigin);
}
- return request_id;
+}
+
+void PermissionManagerQt::RequestPermissionsFromCurrentDocument(content::RenderFrameHost *frameHost,
+ const content::PermissionRequestDescription &requestDescription,
+ base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
+{
+ RequestPermissions(frameHost, requestDescription, std::move(callback));
}
blink::mojom::PermissionStatus PermissionManagerQt::GetPermissionStatus(
- content::PermissionType permission,
+ blink::PermissionType permission,
const GURL& requesting_origin,
const GURL& /*embedding_origin*/)
{
- const ProfileAdapter::PermissionType permissionType = toQt(permission);
- if (permissionType == ProfileAdapter::UnsupportedPermission)
+ const QWebEnginePermission::Feature feature = toQt(permission);
+ if (feature == QWebEnginePermission::Unsupported)
return blink::mojom::PermissionStatus::DENIED;
- QPair<QUrl, ProfileAdapter::PermissionType> key(toQt(requesting_origin), permissionType);
- if (!m_permissions.contains(key))
+ permission = toBlink(toQt(permission)); // Filter out merged/unsupported permissions (e.g. clipboard)
+ auto *pref = m_prefService->FindPreference(featureString(toQt(permission)));
+ if (!pref)
+ return blink::mojom::PermissionStatus::ASK; // Permission type not in database
+
+ const auto *permissions = pref->GetValue()->GetIfDict();
+ Q_ASSERT(permissions);
+
+ auto requestedPermission = permissions->FindBool(requesting_origin.DeprecatedGetOriginAsURL().spec());
+ if (!requestedPermission)
+ return blink::mojom::PermissionStatus::ASK; // Origin is not in the current permission type's database
+
+ // Workaround: local fonts are entirely managed by Chromium, which only calls RequestPermission() _after_
+ // it's checked whether the permission has been granted. By always returning ASK, we force the request to
+ // come through every time.
+ if (permission == blink::PermissionType::LOCAL_FONTS
+ && m_profileAdapter->persistentPermissionsPolicy() == ProfileAdapter::NoPersistentPermissions)
return blink::mojom::PermissionStatus::ASK;
- if (m_permissions[key])
+
+ if (requestedPermission.value())
return blink::mojom::PermissionStatus::GRANTED;
return blink::mojom::PermissionStatus::DENIED;
}
-blink::mojom::PermissionStatus PermissionManagerQt::GetPermissionStatusForFrame(
- content::PermissionType permission,
- content::RenderFrameHost *render_frame_host,
- const GURL &requesting_origin)
+blink::mojom::PermissionStatus PermissionManagerQt::GetPermissionStatusForCurrentDocument(
+ blink::PermissionType permission,
+ content::RenderFrameHost *render_frame_host)
{
- if (permission == content::PermissionType::CLIPBOARD_READ_WRITE ||
- permission == content::PermissionType::CLIPBOARD_SANITIZED_WRITE) {
+ if (permission == blink::PermissionType::CLIPBOARD_READ_WRITE ||
+ permission == blink::PermissionType::CLIPBOARD_SANITIZED_WRITE) {
WebContentsDelegateQt *delegate = static_cast<WebContentsDelegateQt *>(
content::WebContents::FromRenderFrameHost(render_frame_host)->GetDelegate());
- if (!delegate->webEngineSettings()->testAttribute(
- QWebEngineSettings::JavascriptCanAccessClipboard))
- return blink::mojom::PermissionStatus::DENIED;
- if (permission == content::PermissionType::CLIPBOARD_READ_WRITE
- && !delegate->webEngineSettings()->testAttribute(
- QWebEngineSettings::JavascriptCanPaste))
- return blink::mojom::PermissionStatus::DENIED;
- return blink::mojom::PermissionStatus::GRANTED;
+ Q_ASSERT(delegate);
+ auto status = getStatusFromSettings(permission, delegate->webEngineSettings());
+ if (status != blink::mojom::PermissionStatus::ASK)
+ return status;
}
return GetPermissionStatus(
permission,
- requesting_origin,
- content::WebContents::FromRenderFrameHost(render_frame_host)->GetLastCommittedURL().GetOrigin());
+ render_frame_host->GetLastCommittedOrigin().GetURL(),
+ render_frame_host->GetLastCommittedOrigin().GetURL());
+}
+
+blink::mojom::PermissionStatus PermissionManagerQt::GetPermissionStatusForWorker(
+ blink::PermissionType permission,
+ content::RenderProcessHost *render_process_host,
+ const GURL &url)
+{
+ return GetPermissionStatus(permission, url, url);
+}
+
+blink::mojom::PermissionStatus PermissionManagerQt::GetPermissionStatusForEmbeddedRequester(
+ blink::PermissionType permission,
+ content::RenderFrameHost *render_frame_host,
+ const url::Origin &requesting_origin)
+{
+ return GetPermissionStatus(permission, requesting_origin.GetURL(),
+ render_frame_host->GetLastCommittedOrigin().GetURL());
+}
+
+content::PermissionResult PermissionManagerQt::GetPermissionResultForOriginWithoutContext(
+ blink::PermissionType permission,
+ const url::Origin &requesting_origin,
+ const url::Origin &embedding_origin)
+{
+ blink::mojom::PermissionStatus status =
+ GetPermissionStatus(permission, requesting_origin.GetURL(), embedding_origin.GetURL());
+
+ return content::PermissionResult(status, content::PermissionStatusSource::UNSPECIFIED);
}
void PermissionManagerQt::ResetPermission(
- content::PermissionType permission,
+ blink::PermissionType permission,
const GURL& requesting_origin,
const GURL& /*embedding_origin*/)
{
- const ProfileAdapter::PermissionType permissionType = toQt(permission);
- if (permissionType == ProfileAdapter::UnsupportedPermission)
+ const QWebEnginePermission::Feature feature = toQt(permission);
+ if (feature == QWebEnginePermission::Unsupported)
return;
- QPair<QUrl, ProfileAdapter::PermissionType> key(toQt(requesting_origin), permissionType);
- m_permissions.remove(key);
+ ScopedDictPrefUpdate updater(m_prefService.get(), featureString(feature));
+ updater.Get().Remove(requesting_origin.spec());
}
-int PermissionManagerQt::SubscribePermissionStatusChange(
- content::PermissionType permission,
- content::RenderFrameHost * /* render_frame_host */,
- const GURL& requesting_origin,
- base::RepeatingCallback<void(blink::mojom::PermissionStatus)> callback)
+content::PermissionControllerDelegate::SubscriptionId
+PermissionManagerQt::SubscribeToPermissionStatusChange(
+ blink::PermissionType permission, content::RenderProcessHost * /*render_process_host*/,
+ content::RenderFrameHost * /* render_frame_host */, const GURL &requesting_origin,
+ base::RepeatingCallback<void(blink::mojom::PermissionStatus)> callback)
{
- int subscriber_id = ++m_subscriberIdCount;
+ auto subscriber_id = subscription_id_generator_.GenerateNextId();
m_subscribers.insert( { subscriber_id,
Subscription { toQt(permission), toQt(requesting_origin), std::move(callback) } });
return subscriber_id;
}
-void PermissionManagerQt::UnsubscribePermissionStatusChange(int subscription_id)
+void PermissionManagerQt::UnsubscribeFromPermissionStatusChange(
+ content::PermissionControllerDelegate::SubscriptionId subscription_id)
{
if (!m_subscribers.erase(subscription_id))
LOG(WARNING) << "PermissionManagerQt::UnsubscribePermissionStatusChange called on unknown subscription id" << subscription_id;
}
+void PermissionManagerQt::setPermission(
+ blink::PermissionType permission,
+ const GURL& requesting_origin,
+ bool granted)
+{
+ const QWebEnginePermission::Feature feature = toQt(permission);
+ if (feature == QWebEnginePermission::Unsupported)
+ return;
+
+ if (!m_prefService->FindPreference(featureString(feature)))
+ return;
+
+ ScopedDictPrefUpdate updater(m_prefService.get(), featureString(feature));
+ updater.Get().Set(requesting_origin.spec(), granted);
+}
+
} // namespace QtWebEngineCore