summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/api/qwebenginepage.cpp79
-rw-r--r--src/core/api/qwebenginepage_p.h6
-rw-r--r--src/core/api/qwebenginepermission.cpp39
-rw-r--r--src/core/api/qwebenginepermission_p.h6
-rw-r--r--src/core/api/qwebengineprofile.cpp2
-rw-r--r--src/core/media_capture_devices_dispatcher.cpp30
-rw-r--r--src/core/permission_manager_qt.cpp435
-rw-r--r--src/core/permission_manager_qt.h37
-rw-r--r--src/core/profile_adapter.cpp24
-rw-r--r--src/core/profile_adapter.h5
-rw-r--r--src/core/web_contents_adapter.cpp158
-rw-r--r--src/core/web_contents_adapter.h12
-rw-r--r--src/core/web_contents_adapter_client.h7
-rw-r--r--src/core/web_contents_delegate_qt.cpp48
-rw-r--r--src/core/web_contents_delegate_qt.h3
-rw-r--r--src/webenginequick/api/qquickwebengineprofile.cpp2
-rw-r--r--src/webenginequick/api/qquickwebengineview.cpp82
-rw-r--r--src/webenginequick/api/qquickwebengineview_p_p.h6
18 files changed, 554 insertions, 427 deletions
diff --git a/src/core/api/qwebenginepage.cpp b/src/core/api/qwebenginepage.cpp
index bfa184e5c..8d73723f6 100644
--- a/src/core/api/qwebenginepage.cpp
+++ b/src/core/api/qwebenginepage.cpp
@@ -590,49 +590,6 @@ void QWebEnginePagePrivate::showColorDialog(QSharedPointer<ColorChooserControlle
view->showColorDialog(controller);
}
-void QWebEnginePagePrivate::runMediaAccessPermissionRequest(const QUrl &securityOrigin, WebContentsAdapterClient::MediaRequestFlags requestFlags)
-{
- Q_Q(QWebEnginePage);
- QWebEnginePermission::PermissionType permissionType;
-
- if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture)
- && requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture))
- permissionType = QWebEnginePermission::PermissionType::MediaAudioVideoCapture;
- else if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture))
- permissionType = QWebEnginePermission::PermissionType::MediaAudioCapture;
- else if (requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture))
- permissionType = QWebEnginePermission::PermissionType::MediaVideoCapture;
- else if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopAudioCapture)
- && requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture))
- permissionType = QWebEnginePermission::PermissionType::DesktopAudioVideoCapture;
- else // if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture))
- permissionType = QWebEnginePermission::PermissionType::DesktopVideoCapture;
-
- Q_EMIT q->permissionRequested(createFeaturePermissionObject(securityOrigin, permissionType));
-
-#if QT_DEPRECATED_SINCE(6, 8)
- QT_WARNING_PUSH
- QT_WARNING_DISABLE_DEPRECATED
- QWebEnginePage::Feature deprecatedFeature;
-
- if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture)
- && requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture))
- deprecatedFeature = QWebEnginePage::MediaAudioVideoCapture;
- else if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture))
- deprecatedFeature = QWebEnginePage::MediaAudioCapture;
- else if (requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture))
- deprecatedFeature = QWebEnginePage::MediaVideoCapture;
- else if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopAudioCapture)
- && requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture))
- deprecatedFeature = QWebEnginePage::DesktopAudioVideoCapture;
- else // if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture))
- deprecatedFeature = QWebEnginePage::DesktopVideoCapture;
-
- Q_EMIT q->featurePermissionRequested(securityOrigin, deprecatedFeature);
- QT_WARNING_POP
-#endif // QT_DEPRECATED_SINCE(6, 8)
-}
-
#if QT_DEPRECATED_SINCE(6, 8)
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
@@ -668,33 +625,19 @@ static QWebEnginePage::Feature toDeprecatedFeature(QWebEnginePermission::Permiss
QT_WARNING_POP
#endif // QT_DEPRECATED_SINCE(6, 8)
-void QWebEnginePagePrivate::runFeaturePermissionRequest(QWebEnginePermission::PermissionType permissionType, const QUrl &securityOrigin)
+void QWebEnginePagePrivate::runFeaturePermissionRequest(
+ QWebEnginePermission::PermissionType permissionType,
+ const QUrl &securityOrigin,
+ int childId, const std::string &serializedToken)
{
Q_Q(QWebEnginePage);
- if (QWebEnginePermission::isPersistent(permissionType)) {
- Q_EMIT q->permissionRequested(createFeaturePermissionObject(securityOrigin, permissionType));
-#if QT_DEPRECATED_SINCE(6, 8)
- QT_WARNING_PUSH
- QT_WARNING_DISABLE_DEPRECATED
- Q_EMIT q->featurePermissionRequested(securityOrigin, toDeprecatedFeature(permissionType));
- QT_WARNING_POP
-#endif // QT_DEPRECATED_SINCE(6, 8)
- return;
- }
-
- Q_UNREACHABLE();
-}
-
-void QWebEnginePagePrivate::runMouseLockPermissionRequest(const QUrl &securityOrigin)
-{
- Q_Q(QWebEnginePage);
- Q_EMIT q->permissionRequested(createFeaturePermissionObject(securityOrigin, QWebEnginePermission::PermissionType::MouseLock));
-
+ Q_EMIT q->permissionRequested(QWebEnginePermission(
+ new QWebEnginePermissionPrivate(securityOrigin, permissionType, profileAdapter(), childId, serializedToken)));
#if QT_DEPRECATED_SINCE(6, 8)
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
- Q_EMIT q->featurePermissionRequested(securityOrigin, QWebEnginePage::MouseLock);
+ Q_EMIT q->featurePermissionRequested(securityOrigin, toDeprecatedFeature(permissionType));
QT_WARNING_POP
#endif // QT_DEPRECATED_SINCE(6, 8)
}
@@ -885,12 +828,6 @@ void QWebEnginePagePrivate::showWebAuthDialog(QWebEngineWebAuthUxRequest *reques
Q_EMIT q->webAuthUxRequested(request);
}
-QWebEnginePermission QWebEnginePagePrivate::createFeaturePermissionObject(const QUrl &securityOrigin, QWebEnginePermission::PermissionType feature)
-{
- auto *returnPrivate = new QWebEnginePermissionPrivate(securityOrigin, feature, adapter, profileAdapter());
- return QWebEnginePermission(returnPrivate);
-}
-
QWebEnginePage::QWebEnginePage(QObject* parent)
: QObject(parent)
, d_ptr(new QWebEnginePagePrivate())
@@ -1918,7 +1855,7 @@ void QWebEnginePage::setFeaturePermission(const QUrl &securityOrigin, QWebEngine
Q_UNREACHABLE();
}
- d->adapter->setPermission(securityOrigin, f, s);
+ d->adapter->setPermission(securityOrigin, f, s, {});
}
QT_WARNING_POP
#endif // QT_DEPRECATED_SINCE(6, 8)
diff --git a/src/core/api/qwebenginepage_p.h b/src/core/api/qwebenginepage_p.h
index 76b4a4d9d..ba1fbc6d5 100644
--- a/src/core/api/qwebenginepage_p.h
+++ b/src/core/api/qwebenginepage_p.h
@@ -148,9 +148,8 @@ public:
void authenticationRequired(
QSharedPointer<QtWebEngineCore::AuthenticationDialogController>) override;
void releaseProfile() override;
- void runMediaAccessPermissionRequest(const QUrl &securityOrigin, MediaRequestFlags requestFlags) override;
- void runFeaturePermissionRequest(QWebEnginePermission::PermissionType permissionType, const QUrl &securityOrigin) override;
- void runMouseLockPermissionRequest(const QUrl &securityOrigin) override;
+ void runFeaturePermissionRequest(QWebEnginePermission::PermissionType permissionType, const QUrl &securityOrigin,
+ int childId, const std::string &serializedToken) override;
void runRegisterProtocolHandlerRequest(QWebEngineRegisterProtocolHandlerRequest) override;
void runFileSystemAccessRequest(QWebEngineFileSystemAccessRequest) override;
QObject *accessibilityParentObject() override;
@@ -181,7 +180,6 @@ public:
const QRect &bounds, bool autoselectFirstSuggestion) override;
void hideAutofillPopup() override;
void showWebAuthDialog(QWebEngineWebAuthUxRequest *controller) override;
- QWebEnginePermission createFeaturePermissionObject(const QUrl &securityOrigin, QWebEnginePermission::PermissionType permissionType) override;
QtWebEngineCore::ProfileAdapter *profileAdapter() override;
QtWebEngineCore::WebContentsAdapter *webContentsAdapter() override;
diff --git a/src/core/api/qwebenginepermission.cpp b/src/core/api/qwebenginepermission.cpp
index ec62f0e4c..1d1b12b7e 100644
--- a/src/core/api/qwebenginepermission.cpp
+++ b/src/core/api/qwebenginepermission.cpp
@@ -20,11 +20,12 @@ QWebEnginePermissionPrivate::QWebEnginePermissionPrivate()
/*! \internal */
QWebEnginePermissionPrivate::QWebEnginePermissionPrivate(const QUrl &origin_, QWebEnginePermission::PermissionType permissionType_,
- QSharedPointer<QtWebEngineCore::WebContentsAdapter> webContentsAdapter_, QtWebEngineCore::ProfileAdapter *profileAdapter_)
+ QtWebEngineCore::ProfileAdapter *profileAdapter_, int childId_, const std::string &serializedToken_)
: QSharedData()
, origin(origin_)
, permissionType(permissionType_)
- , webContentsAdapter(webContentsAdapter_)
+ , childId(childId_)
+ , serializedToken(serializedToken_)
, profileAdapter(profileAdapter_)
{
}
@@ -114,15 +115,12 @@ bool QWebEnginePermission::equals(const QWebEnginePermission &other) const
return false;
if (!isPersistent(d_ptr->permissionType)) {
- if (d_ptr->webContentsAdapter != other.d_ptr->webContentsAdapter)
+ if (d_ptr->childId != other.d_ptr->childId
+ && d_ptr->serializedToken != other.d_ptr->serializedToken)
return false;
} else {
- QtWebEngineCore::ProfileAdapter *thisProfile = d_ptr->webContentsAdapter
- ? d_ptr->webContentsAdapter.toStrongRef()->profileAdapter()
- : d_ptr->profileAdapter.get();
- QtWebEngineCore::ProfileAdapter *otherProfile = d_ptr->webContentsAdapter
- ? other.d_ptr->webContentsAdapter.toStrongRef()->profileAdapter()
- : other.d_ptr->profileAdapter.get();
+ QtWebEngineCore::ProfileAdapter *thisProfile = d_ptr->profileAdapter.get();
+ QtWebEngineCore::ProfileAdapter *otherProfile = other.d_ptr->profileAdapter.get();
if (thisProfile != otherProfile)
return false;
@@ -201,11 +199,7 @@ QWebEnginePermission::State QWebEnginePermission::state() const
{
if (!isValid())
return State::Invalid;
- if (d_ptr->webContentsAdapter)
- return d_ptr->webContentsAdapter.toStrongRef()->getPermissionState(origin(), permissionType());
- if (d_ptr->profileAdapter)
- return d_ptr->profileAdapter->getPermissionState(origin(), permissionType());
- Q_UNREACHABLE_RETURN(State::Ask);
+ return d_ptr->profileAdapter->getPermissionState(origin(), permissionType(), d_ptr->childId, d_ptr->serializedToken);
}
/*!
@@ -227,7 +221,7 @@ bool QWebEnginePermission::isValid() const
return false;
if (permissionType() == PermissionType::Unsupported)
return false;
- if (!d_ptr->profileAdapter && !d_ptr->webContentsAdapter)
+ if (!d_ptr->profileAdapter)
return false;
if (!d_ptr->origin.isValid())
return false;
@@ -243,10 +237,7 @@ void QWebEnginePermission::grant() const
{
if (!isValid())
return;
- if (d_ptr->webContentsAdapter)
- d_ptr->webContentsAdapter.toStrongRef()->setPermission(origin(), permissionType(), State::Granted);
- else if (d_ptr->profileAdapter)
- d_ptr->profileAdapter->setPermission(origin(), permissionType(), State::Granted);
+ d_ptr->profileAdapter->setPermission(origin(), permissionType(), State::Granted, d_ptr->childId, d_ptr->serializedToken);
}
/*!
@@ -258,10 +249,7 @@ void QWebEnginePermission::deny() const
{
if (!isValid())
return;
- if (d_ptr->webContentsAdapter)
- d_ptr->webContentsAdapter.toStrongRef()->setPermission(origin(), permissionType(), State::Denied);
- else if (d_ptr->profileAdapter)
- d_ptr->profileAdapter->setPermission(origin(), permissionType(), State::Denied);
+ d_ptr->profileAdapter->setPermission(origin(), permissionType(), State::Denied, d_ptr->childId, d_ptr->serializedToken);
}
/*!
@@ -279,10 +267,7 @@ void QWebEnginePermission::reset() const
{
if (!isValid())
return;
- if (d_ptr->webContentsAdapter)
- d_ptr->webContentsAdapter.toStrongRef()->setPermission(origin(), permissionType(), State::Ask);
- else if (d_ptr->profileAdapter)
- d_ptr->profileAdapter->setPermission(origin(), permissionType(), State::Ask);
+ d_ptr->profileAdapter->setPermission(origin(), permissionType(), State::Ask, d_ptr->childId, d_ptr->serializedToken);
}
/*!
diff --git a/src/core/api/qwebenginepermission_p.h b/src/core/api/qwebenginepermission_p.h
index c6b525b31..aabb5c4b9 100644
--- a/src/core/api/qwebenginepermission_p.h
+++ b/src/core/api/qwebenginepermission_p.h
@@ -33,12 +33,14 @@ struct QWebEnginePermissionPrivate : public QSharedData
{
Q_WEBENGINECORE_EXPORT QWebEnginePermissionPrivate();
Q_WEBENGINECORE_EXPORT QWebEnginePermissionPrivate(const QUrl &, QWebEnginePermission::PermissionType,
- QSharedPointer<QtWebEngineCore::WebContentsAdapter>, QtWebEngineCore::ProfileAdapter *);
+ QtWebEngineCore::ProfileAdapter *, int = -1, const std::string & = std::string());
QUrl origin;
QWebEnginePermission::PermissionType permissionType;
- QWeakPointer<QtWebEngineCore::WebContentsAdapter> webContentsAdapter;
+ int childId = -1;
+ std::string serializedToken;
+
QPointer<QtWebEngineCore::ProfileAdapter> profileAdapter;
};
diff --git a/src/core/api/qwebengineprofile.cpp b/src/core/api/qwebengineprofile.cpp
index 55ac939ad..842b0b106 100644
--- a/src/core/api/qwebengineprofile.cpp
+++ b/src/core/api/qwebengineprofile.cpp
@@ -1015,7 +1015,7 @@ QWebEnginePermission QWebEngineProfile::queryPermission(const QUrl &securityOrig
return QWebEnginePermission(new QWebEnginePermissionPrivate());
}
- auto *pvt = new QWebEnginePermissionPrivate(securityOrigin, permissionType, nullptr, d->profileAdapter());
+ auto *pvt = new QWebEnginePermissionPrivate(securityOrigin, permissionType, d->profileAdapter());
return QWebEnginePermission(pvt);
}
diff --git a/src/core/media_capture_devices_dispatcher.cpp b/src/core/media_capture_devices_dispatcher.cpp
index 848a92986..d691c65ea 100644
--- a/src/core/media_capture_devices_dispatcher.cpp
+++ b/src/core/media_capture_devices_dispatcher.cpp
@@ -11,6 +11,8 @@
#include "web_contents_delegate_qt.h"
#include "web_contents_view_qt.h"
#include "web_engine_settings.h"
+#include "permission_manager_qt.h"
+#include "type_conversion.h"
#include "base/strings/strcat.h"
#include "blink/public/common/page/page_zoom.h"
@@ -21,6 +23,8 @@
#include "content/public/browser/desktop_streams_registry.h"
#include "content/public/browser/host_zoom_map.h"
#include "content/public/browser/media_capture_devices.h"
+#include "content/public/browser/permission_controller_delegate.h"
+#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "media/audio/audio_device_description.h"
#include "media/audio/audio_manager_base.h"
@@ -493,8 +497,17 @@ void MediaCaptureDevicesDispatcher::processMediaAccessRequest(
}
enqueueMediaAccessRequest(webContents, request, std::move(callback), id);
- // We might not require this approval for pepper requests.
- adapterClient->runMediaAccessPermissionRequest(toQt(request.security_origin), flags);
+
+ PermissionManagerQt *permissionManager = static_cast<PermissionManagerQt *>(
+ webContents->GetBrowserContext()->GetPermissionControllerDelegate());
+ permissionManager->requestMediaPermissions(
+ content::RenderFrameHost::FromID(request.render_process_id, request.render_frame_id),
+ flags,
+ base::BindOnce(
+ &MediaCaptureDevicesDispatcher::handleMediaAccessPermissionResponse,
+ base::Unretained(this),
+ webContents,
+ toQt(request.url_origin)));
}
void MediaCaptureDevicesDispatcher::processDesktopCaptureAccessRequest(content::WebContents *webContents, const content::MediaStreamRequest &request, content::MediaResponseCallback callback)
@@ -558,9 +571,18 @@ void MediaCaptureDevicesDispatcher::ProcessQueuedAccessRequest(content::WebConte
RequestsQueue &queue(it->second);
content::MediaStreamRequest &request = queue.front()->request;
+ WebContentsAdapterClient::MediaRequestFlags flags = mediaRequestFlagsForRequest(request);
- WebContentsAdapterClient *adapterClient = WebContentsViewQt::from(static_cast<content::WebContentsImpl *>(webContents)->GetView())->client();
- adapterClient->runMediaAccessPermissionRequest(toQt(request.security_origin), mediaRequestFlagsForRequest(request));
+ PermissionManagerQt *permissionManager = static_cast<PermissionManagerQt *>(
+ webContents->GetBrowserContext()->GetPermissionControllerDelegate());
+ permissionManager->requestMediaPermissions(
+ content::RenderFrameHost::FromID(request.render_process_id, request.render_frame_id),
+ flags,
+ base::BindOnce(
+ &MediaCaptureDevicesDispatcher::handleMediaAccessPermissionResponse,
+ base::Unretained(this),
+ webContents,
+ toQt(request.url_origin)));
}
void MediaCaptureDevicesDispatcher::getDefaultDevices(const std::string &audioDeviceId, const std::string &videoDeviceId,
diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp
index 5258f15cf..eae98b350 100644
--- a/src/core/permission_manager_qt.cpp
+++ b/src/core/permission_manager_qt.cpp
@@ -40,7 +40,7 @@ static QWebEnginePermission::PermissionType toQt(blink::PermissionType type)
case blink::PermissionType::VIDEO_CAPTURE:
return QWebEnginePermission::PermissionType::MediaVideoCapture;
case blink::PermissionType::DISPLAY_CAPTURE:
- return QWebEnginePermission::PermissionType::DesktopAudioVideoCapture;
+ return QWebEnginePermission::PermissionType::DesktopVideoCapture;
// We treat these both as read/write since we do not currently have a
// ClipboardSanitizedWrite permission type.
case blink::PermissionType::CLIPBOARD_READ_WRITE:
@@ -56,6 +56,8 @@ static QWebEnginePermission::PermissionType toQt(blink::PermissionType type)
case blink::PermissionType::WINDOW_MANAGEMENT:
case blink::PermissionType::BACKGROUND_SYNC:
case blink::PermissionType::NUM:
+ case blink::PermissionType::TOP_LEVEL_STORAGE_ACCESS:
+ case blink::PermissionType::SPEAKER_SELECTION:
return QWebEnginePermission::PermissionType::Unsupported;
case blink::PermissionType::MIDI_SYSEX:
case blink::PermissionType::PROTECTED_MEDIA_IDENTIFIER:
@@ -72,16 +74,13 @@ static QWebEnginePermission::PermissionType toQt(blink::PermissionType type)
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::SPEAKER_SELECTION:
case blink::PermissionType::KEYBOARD_LOCK:
case blink::PermissionType::AUTOMATIC_FULLSCREEN:
case blink::PermissionType::HAND_TRACKING:
case blink::PermissionType::WEB_APP_INSTALLATION:
- LOG(INFO) << "Unexpected unsupported Blink permission type: " << static_cast<int>(type);
break;
}
return QWebEnginePermission::PermissionType::Unsupported;
@@ -107,16 +106,50 @@ static blink::PermissionType toBlink(QWebEnginePermission::PermissionType permis
return blink::PermissionType::LOCAL_FONTS;
case QWebEnginePermission::PermissionType::MouseLock:
return blink::PermissionType::POINTER_LOCK;
- case QWebEnginePermission::PermissionType::MediaAudioVideoCapture:
- LOG(INFO) << "Unexpected unsupported WebEngine permission type: " << static_cast<int>(permissionType);
- Q_FALLTHROUGH();
case QWebEnginePermission::PermissionType::Unsupported:
return blink::PermissionType::NUM;
+ case QWebEnginePermission::PermissionType::MediaAudioVideoCapture:
+ break;
}
Q_UNREACHABLE_RETURN(blink::PermissionType::NUM);
}
+static std::vector<QWebEnginePermission::PermissionType> toQt(
+ const std::vector<blink::PermissionType> &blinkPermissions)
+{
+ // This function handles the edge case differences between our permission types and Blink's;
+ // namely, MediaAudioVideoCapture and DesktopAudioVideoCapture
+ std::vector<QWebEnginePermission::PermissionType> permissions;
+ for (auto &p : blinkPermissions) {
+ permissions.push_back(toQt(p));
+ }
+
+ for (auto i1 = permissions.begin(); i1 != permissions.end(); ++i1) {
+ if (*i1 == QWebEnginePermission::PermissionType::MediaAudioCapture) {
+ for (auto i2 = permissions.begin(); i2 != permissions.end(); ++i2) {
+ if (*i2 == QWebEnginePermission::PermissionType::MediaVideoCapture) {
+ // Merge MediaAudioCapture and MediaVideoCapture into MediaAudioVideoCapture
+ *i1 = QWebEnginePermission::PermissionType::MediaAudioVideoCapture;
+ permissions.erase(i2);
+ break;
+ }
+ }
+ } else if (*i1 == QWebEnginePermission::PermissionType::DesktopVideoCapture) {
+ for (auto i2 = i1 + 1; i2 != permissions.end(); ++i2) {
+ if (*i2 == QWebEnginePermission::PermissionType::DesktopVideoCapture) {
+ // Double DesktopVideoCapture means we actually need DesktopAudioVideoCapture
+ *i2 = QWebEnginePermission::PermissionType::DesktopAudioVideoCapture;
+ i1 = permissions.erase(i1);
+ break;
+ }
+ }
+ }
+ }
+
+ return permissions;
+}
+
static QWebEnginePermission::State toQt(blink::mojom::PermissionStatus state)
{
switch (state) {
@@ -154,6 +187,8 @@ std::string permissionTypeString(QWebEnginePermission::PermissionType permission
return "MediaVideoCapture";
case QWebEnginePermission::PermissionType::DesktopAudioVideoCapture:
return "DesktopAudioVideoCapture";
+ case QWebEnginePermission::PermissionType::DesktopVideoCapture:
+ return "DesktopVideoCapture";
case QWebEnginePermission::PermissionType::MouseLock:
return "MouseLock";
case QWebEnginePermission::PermissionType::Notifications:
@@ -213,6 +248,8 @@ PermissionManagerQt::PermissionManagerQt(ProfileAdapter *profileAdapter)
m_permissionTypes.push_back(QWebEnginePermission::PermissionType::MediaAudioCapture);
m_permissionTypes.push_back(QWebEnginePermission::PermissionType::MediaVideoCapture);
+ m_permissionTypes.push_back(QWebEnginePermission::PermissionType::DesktopAudioVideoCapture);
+ m_permissionTypes.push_back(QWebEnginePermission::PermissionType::DesktopVideoCapture);
m_permissionTypes.push_back(QWebEnginePermission::PermissionType::MouseLock);
m_permissionTypes.push_back(QWebEnginePermission::PermissionType::Notifications);
m_permissionTypes.push_back(QWebEnginePermission::PermissionType::Geolocation);
@@ -239,38 +276,83 @@ PermissionManagerQt::~PermissionManagerQt()
commit();
}
+// static
+content::GlobalRenderFrameHostToken PermissionManagerQt::deserializeToken(int childId, const std::string &serializedToken)
+{
+ auto maybeToken = base::UnguessableToken::DeserializeFromString(serializedToken);
+ if (maybeToken)
+ return content::GlobalRenderFrameHostToken(childId, blink::LocalFrameToken(maybeToken.value()));
+
+ return content::GlobalRenderFrameHostToken();
+}
+
void PermissionManagerQt::setPermission(
const QUrl &url,
- QWebEnginePermission::PermissionType permissionType,
- QWebEnginePermission::State state,
- content::RenderFrameHost *rfh)
+ const QWebEnginePermission::PermissionType permissionType,
+ const QWebEnginePermission::State state,
+ const content::GlobalRenderFrameHostToken &token)
+{
+ if (permissionType == QWebEnginePermission::PermissionType::MediaAudioVideoCapture) {
+ setPermissionImpl(url, QWebEnginePermission::PermissionType::MediaAudioCapture, state, token);
+ setPermissionImpl(url, QWebEnginePermission::PermissionType::MediaVideoCapture, state, token);
+ return;
+ }
+
+ setPermissionImpl(url, permissionType, state, token);
+}
+
+void PermissionManagerQt::setPermission(
+ const QUrl &url,
+ const QWebEnginePermission::PermissionType permissionType,
+ const QWebEnginePermission::State state,
+ int childId, const std::string &serializedToken)
+{
+ content::GlobalRenderFrameHostToken token;
+ auto maybeToken = base::UnguessableToken::DeserializeFromString(serializedToken);
+ if (maybeToken)
+ token = content::GlobalRenderFrameHostToken(childId, blink::LocalFrameToken(maybeToken.value()));
+
+ setPermission(url, permissionType, state, token);
+}
+
+void PermissionManagerQt::setPermissionImpl(
+ const QUrl &url,
+ const QWebEnginePermission::PermissionType permissionTypeQt,
+ const QWebEnginePermission::State permissionStateQt,
+ const content::GlobalRenderFrameHostToken &frameToken)
{
+ const blink::PermissionType permissionTypeBlink = toBlink(permissionTypeQt);
+ const blink::mojom::PermissionStatus permissionStateBlink = toBlink(permissionStateQt);
+
// 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;
- // Send eligible permissions with an associated rfh to the transient store. When pre-granting
+ // Send eligible permissions with an associated frameToken to the transient store. When pre-granting
// a non-persistent permission (or pre-granting any permission in AskEveryTime mode), it is allowed
// to pass through the persistent store. It will be moved to the transient store and associated
- // with a rfh the next time its status is requested.
- bool inTransientStore = rfh && (!QWebEnginePermission::isPersistent(permissionType) || !m_persistence);
+ // with a frameToken the next time its status is requested.
+ bool inTransientStore = frameToken.child_id != content::kInvalidChildProcessUniqueId
+ && (!QWebEnginePermission::isPersistent(permissionTypeQt) || !m_persistence);
- blink::mojom::PermissionStatus blinkStatus = toBlink(state);
- if (state == QWebEnginePermission::State::Ask) {
+ blink::mojom::PermissionStatus blinkStatus = permissionStateBlink;
+ if (permissionStateQt == QWebEnginePermission::State::Ask) {
if (inTransientStore)
- resetTransientPermission(toBlink(permissionType), gorigin, rfh->GetGlobalFrameToken());
+ resetTransientPermission(permissionTypeBlink, gorigin, frameToken);
else
- ResetPermission(toBlink(permissionType), gorigin, gorigin);
+ ResetPermission(permissionTypeBlink, gorigin, gorigin);
} else {
if (inTransientStore)
- setTransientPermission(toBlink(permissionType), gorigin, state == QWebEnginePermission::State::Granted, rfh->GetGlobalFrameToken());
+ setTransientPermission(permissionTypeBlink, gorigin,
+ permissionStateQt == QWebEnginePermission::State::Granted, frameToken);
else
- setPersistentPermission(toBlink(permissionType), gorigin, state == QWebEnginePermission::State::Granted);
+ setPersistentPermission(permissionTypeBlink,
+ gorigin, permissionStateQt == QWebEnginePermission::State::Granted);
auto it = m_requests.begin();
while (it != m_requests.end()) {
- if (it->origin == origin && it->type == permissionType) {
+ if (it->origin == origin && it->type == permissionTypeQt) {
std::move(it->callback).Run(blinkStatus);
it = m_requests.erase(it);
} else
@@ -292,10 +374,10 @@ void PermissionManagerQt::setPermission(
if (subscription->embedding_origin != gorigin)
continue;
- if (subscription->permission != toBlink(permissionType))
+ if (subscription->permission != permissionTypeBlink)
continue;
- if ((!QWebEnginePermission::isPersistent(permissionType) || !m_persistence)
- && targetRfh && targetRfh != rfh)
+ if ((!QWebEnginePermission::isPersistent(permissionTypeQt) || !m_persistence)
+ && targetRfh && targetRfh != content::RenderFrameHost::FromFrameToken(frameToken))
continue;
// Behavior in callbacks may differ depending on the denial reason. Until we have
@@ -312,7 +394,7 @@ void PermissionManagerQt::setPermission(
std::move(callback).Run();
}
- if (state == QWebEnginePermission::State::Ask)
+ if (permissionStateQt == QWebEnginePermission::State::Ask)
return;
auto it = m_multiRequests.begin();
@@ -321,32 +403,37 @@ void PermissionManagerQt::setPermission(
bool answerable = true;
std::vector<blink::mojom::PermissionStatus> result;
result.reserve(it->types.size());
- for (blink::PermissionType permission : it->types) {
- if (toQt(permission) == QWebEnginePermission::PermissionType::Unsupported) {
+ for (blink::PermissionType currentPermissionType : it->types) {
+ if (toQt(currentPermissionType) == QWebEnginePermission::PermissionType::Unsupported) {
result.push_back(blink::mojom::PermissionStatus::DENIED);
continue;
}
blink::mojom::PermissionStatus permissionStatus;
if (inTransientStore)
- permissionStatus = toBlink(getPermissionState(url, permissionType, rfh));
+ permissionStatus = toBlink(getPermissionState(url, toQt(currentPermissionType), frameToken));
else
- permissionStatus = GetPermissionStatus(permission, gorigin, GURL());
+ permissionStatus = GetPermissionStatus(currentPermissionType, gorigin, GURL());
- if (permissionStatus == toBlink(state)) {
+ if (permissionStatus == permissionStateBlink) {
if (permissionStatus == blink::mojom::PermissionStatus::ASK) {
answerable = false;
break;
}
result.push_back(permissionStatus);
- } else {
+ } else if (!m_persistence) {
// Reached when the PersistentPermissionsPolicy is set to AskEveryTime
- result.push_back(toBlink(state));
+ result.push_back(permissionStateBlink);
+ } else {
+ // Not all of the permissions in this request have been set yet, bail and wait for the next setPermission() call
+ answerable = false;
+ break;
}
}
if (answerable) {
- std::move(it->callback).Run(result);
+ if (!it->callback.is_null())
+ std::move(it->callback).Run(result);
it = m_multiRequests.erase(it);
continue;
}
@@ -355,23 +442,44 @@ void PermissionManagerQt::setPermission(
}
}
-QWebEnginePermission::State PermissionManagerQt::getPermissionState(const QUrl &origin, QWebEnginePermission::PermissionType permissionType,
- content::RenderFrameHost *rfh)
+QWebEnginePermission::State PermissionManagerQt::getPermissionState(
+ const QUrl &origin,
+ const QWebEnginePermission::PermissionType permissionType,
+ const content::GlobalRenderFrameHostToken &frameToken)
{
- if (rfh) {
- // Ignore the origin parameter
- return toQt(GetPermissionStatusForCurrentDocument(toBlink(permissionType), rfh, false));
+ std::vector<QWebEnginePermission::PermissionType> types;
+ if (permissionType == QWebEnginePermission::PermissionType::MediaAudioVideoCapture) {
+ types.push_back(QWebEnginePermission::PermissionType::MediaAudioCapture);
+ types.push_back(QWebEnginePermission::PermissionType::MediaVideoCapture);
+ } else {
+ types.push_back(permissionType);
+ }
+
+ auto *rfh = content::RenderFrameHost::FromFrameToken(frameToken);
+ QWebEnginePermission::State returnState = QWebEnginePermission::State::Invalid;
+ for (auto type : types) {
+ QWebEnginePermission::State state = rfh
+ ? toQt(GetPermissionStatusForCurrentDocument(toBlink(type), rfh, false))
+ : toQt(GetPermissionStatus(toBlink(type), toGurl(origin), GURL()));
+
+ if (returnState == QWebEnginePermission::State::Invalid)
+ returnState = state;
+ else if (returnState != state)
+ returnState = QWebEnginePermission::State::Ask;
}
- return toQt(GetPermissionStatus(toBlink(permissionType), toGurl(origin), GURL()));
+ return returnState;
}
-QList<QWebEnginePermission> PermissionManagerQt::listPermissions(const QUrl &origin, QWebEnginePermission::PermissionType permissionType)
+QList<QWebEnginePermission> PermissionManagerQt::listPermissions(
+ const QUrl &origin,
+ const QWebEnginePermission::PermissionType permissionType)
{
Q_ASSERT(origin.isEmpty() || permissionType == QWebEnginePermission::PermissionType::Unsupported);
+
QList<QWebEnginePermission> returnList;
- GURL gorigin = toGurl(origin).DeprecatedGetOriginAsURL();
- std::string originSpec = gorigin.spec();
+ const GURL gorigin = toGurl(origin).DeprecatedGetOriginAsURL();
+ const std::string originSpec = gorigin.spec();
if (!origin.isEmpty() && !gorigin.is_valid())
return returnList;
@@ -382,7 +490,7 @@ QList<QWebEnginePermission> PermissionManagerQt::listPermissions(const QUrl &ori
else
types.push_back(permissionType);
- for (auto &type : types) {
+ for (const 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::isPersistent(type))
@@ -399,7 +507,8 @@ QList<QWebEnginePermission> PermissionManagerQt::listPermissions(const QUrl &ori
if (!originSpec.empty() && entry.first != originSpec)
continue;
- auto *pvt = new QWebEnginePermissionPrivate(toQt(GURL(std::string_view(entry.first))), type, nullptr, m_profileAdapter.get());
+ auto *pvt = new QWebEnginePermissionPrivate(
+ toQt(GURL(std::string_view(entry.first))), type, m_profileAdapter.get());
returnList.push_back(QWebEnginePermission(pvt));
}
}
@@ -407,6 +516,78 @@ QList<QWebEnginePermission> PermissionManagerQt::listPermissions(const QUrl &ori
return returnList;
}
+void PermissionManagerQt::requestMediaPermissions(
+ content::RenderFrameHost *render_frame_host,
+ const WebContentsAdapterClient::MediaRequestFlags flags,
+ base::OnceCallback<void(WebContentsAdapterClient::MediaRequestFlags authorizationFlags)> callback)
+{
+ std::vector<blink::PermissionType> permissionTypesBlink;
+ if (flags.testFlag(WebContentsAdapterClient::MediaAudioCapture))
+ permissionTypesBlink.push_back(blink::PermissionType::AUDIO_CAPTURE);
+ if (flags.testFlag(WebContentsAdapterClient::MediaVideoCapture))
+ permissionTypesBlink.push_back(blink::PermissionType::VIDEO_CAPTURE);
+ if (flags.testFlag(WebContentsAdapterClient::MediaDesktopAudioCapture)
+ || flags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture)) {
+ permissionTypesBlink.push_back(blink::PermissionType::DISPLAY_CAPTURE);
+ if (flags.testFlag(WebContentsAdapterClient::MediaDesktopAudioCapture)) {
+ // Inject a second copy of the permission type into the request,
+ // so we can distinguish between DesktopVideoCapture and DesktopAudioVideoCapture.
+ permissionTypesBlink.push_back(blink::PermissionType::DISPLAY_CAPTURE);
+ }
+ }
+
+ content::PermissionRequestDescription description(permissionTypesBlink, false, render_frame_host->GetLastCommittedOrigin().GetURL());
+
+ RequestPermissions(render_frame_host, description, base::BindOnce([](
+ std::vector<blink::PermissionType> permissionTypesBlink,
+ base::OnceCallback<void(WebContentsAdapterClient::MediaRequestFlags authorizationFlags)> callback,
+ const std::vector<blink::mojom::PermissionStatus> &statuses)
+ {
+ // This callback converts the Blink permission types to MediaRequestFlags,
+ // and then runs the callback initially passed to requestMediaPermissions().
+ DCHECK(permissionTypesBlink.size() == statuses.size());
+ WebContentsAdapterClient::MediaRequestFlags flags = WebContentsAdapterClient::MediaRequestFlag::MediaNone;
+ for (uint i = 0; i < statuses.size(); ++i) {
+ if (statuses[i] == blink::mojom::PermissionStatus::GRANTED) {
+ switch (permissionTypesBlink[i]) {
+ case blink::PermissionType::AUDIO_CAPTURE:
+ flags.setFlag(WebContentsAdapterClient::MediaRequestFlag::MediaAudioCapture);
+ break;
+ case blink::PermissionType::VIDEO_CAPTURE:
+ flags.setFlag(WebContentsAdapterClient::MediaRequestFlag::MediaVideoCapture);
+ break;
+ case blink::PermissionType::DISPLAY_CAPTURE:
+ flags.setFlag(WebContentsAdapterClient::MediaRequestFlag::MediaDesktopAudioCapture);
+ flags.setFlag(WebContentsAdapterClient::MediaRequestFlag::MediaDesktopVideoCapture);
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ }
+ }
+ std::move(callback).Run(flags);
+ }, permissionTypesBlink, std::move(callback)));
+}
+
+// Needed for the rare cases where a RenderFrameHost remains the same even after
+// a cross-origin navigation (e.g. inside an iframe). Needs to be called every
+// time transient permissions are accessed.
+void PermissionManagerQt::onCrossOriginNavigation(content::RenderFrameHost *render_frame_host)
+{
+ if (!render_frame_host)
+ return;
+
+ auto frameToken = render_frame_host->GetGlobalFrameToken();
+ auto &permissionsForToken = m_transientPermissions[frameToken];
+ if (!permissionsForToken.size())
+ return;
+
+ GURL savedOrigin = get<0>(permissionsForToken[0]);
+ if (render_frame_host->GetLastCommittedOrigin().GetURL() != savedOrigin)
+ m_transientPermissions.erase(frameToken);
+}
+
void PermissionManagerQt::commit()
{
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -414,15 +595,18 @@ void PermissionManagerQt::commit()
m_prefService->CommitPendingWrite();
}
-void PermissionManagerQt::RequestPermissions(content::RenderFrameHost *frameHost,
- const content::PermissionRequestDescription &requestDescription,
- base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
+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));
+ std::move(callback).Run(std::vector<content::PermissionStatus>(requestDescription.permissions.size(),
+ blink::mojom::PermissionStatus::DENIED));
return;
}
+ const auto frameToken = frameHost->GetGlobalFrameToken();
WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt *>(
content::WebContents::FromRenderFrameHost(frameHost)->GetDelegate());
Q_ASSERT(contentsDelegate);
@@ -430,53 +614,54 @@ void PermissionManagerQt::RequestPermissions(content::RenderFrameHost *frameHost
bool answerable = true;
std::vector<content::PermissionStatus> result;
result.reserve(requestDescription.permissions.size());
- for (blink::PermissionType permission : requestDescription.permissions) {
- const QWebEnginePermission::PermissionType permissionType = toQt(permission);
- if (permissionType == QWebEnginePermission::PermissionType::Unsupported) {
+ for (const blink::PermissionType permissionTypeBlink : requestDescription.permissions) {
+ const QWebEnginePermission::PermissionType permissionTypeQt = toQt(permissionTypeBlink);
+ if (permissionTypeQt == QWebEnginePermission::PermissionType::Unsupported) {
result.push_back(blink::mojom::PermissionStatus::DENIED);
continue;
}
- blink::mojom::PermissionStatus permissionStatus = getStatusFromSettings(permission, contentsDelegate->webEngineSettings());
- if (permissionStatus == blink::mojom::PermissionStatus::ASK) {
+ blink::mojom::PermissionStatus permissionStatusBlink = getStatusFromSettings(
+ permissionTypeBlink, contentsDelegate->webEngineSettings());
+ if (permissionStatusBlink == blink::mojom::PermissionStatus::ASK) {
const GURL &rorigin = requestDescription.requesting_origin;
+ bool maybePreGranted = false;
if (!m_persistence) {
- answerable = false;
- break;
+ maybePreGranted = true;
}
- bool inTransientStore = !QWebEnginePermission::isPersistent(toQt(permission));
+ bool inTransientStore = !QWebEnginePermission::isPersistent(permissionTypeQt) || maybePreGranted;
if (inTransientStore) {
- permissionStatus = getTransientPermissionStatus(permission, rorigin, frameHost->GetGlobalFrameToken());
+ permissionStatusBlink = getTransientPermissionStatus(permissionTypeBlink, rorigin, frameToken);
- if (permissionStatus != blink::mojom::PermissionStatus::ASK) {
- result.push_back(permissionStatus);
+ if (permissionStatusBlink != blink::mojom::PermissionStatus::ASK) {
+ result.push_back(permissionStatusBlink);
continue;
}
// Fall through to check if permission was pre-granted (and thus landed in the permanent store)
}
- permissionStatus = GetPermissionStatus(permission, rorigin, rorigin);
+ permissionStatusBlink = GetPermissionStatus(permissionTypeBlink, rorigin, rorigin);
- if (inTransientStore && permissionStatus != blink::mojom::PermissionStatus::ASK) {
- // Move the pre-granted permission to the transient store and associate it with the rfh
- ResetPermission(permission, rorigin, rorigin);
- setTransientPermission(permission, rorigin, permissionStatus == blink::mojom::PermissionStatus::GRANTED,
- frameHost->GetGlobalFrameToken());
+ if (inTransientStore && permissionStatusBlink != blink::mojom::PermissionStatus::ASK) {
+ // Move the pre-granted permission to the transient store and associate it with a frame token
+ ResetPermission(permissionTypeBlink, rorigin, rorigin);
+ setTransientPermission(permissionTypeBlink, rorigin,
+ permissionStatusBlink == blink::mojom::PermissionStatus::GRANTED, frameToken);
}
- if (permissionStatus != blink::mojom::PermissionStatus::ASK) {
+ if (permissionStatusBlink != blink::mojom::PermissionStatus::ASK) {
// Automatically grant/deny without prompt if already asked once
- result.push_back(permissionStatus);
+ result.push_back(permissionStatusBlink);
} else {
answerable = false;
break;
}
} else {
// Reached when clipboard settings have been set
- result.push_back(permissionStatus);
+ result.push_back(permissionStatusBlink);
}
}
@@ -486,80 +671,75 @@ void PermissionManagerQt::RequestPermissions(content::RenderFrameHost *frameHost
}
int request_id = ++m_requestIdCount;
- auto requestOrigin = toQt(requestDescription.requesting_origin);
+ const 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::PermissionType permissionType = toQt(permission);
- if (QWebEnginePermission::isPersistent(permissionType))
- contentsDelegate->requestFeaturePermission(permissionType, requestOrigin);
+ auto qtPermissions = toQt(requestDescription.permissions);
+ for (const QWebEnginePermission::PermissionType permissionTypeQt : qtPermissions) {
+ contentsDelegate->requestFeaturePermission(permissionTypeQt, requestOrigin, frameToken);
}
}
-void PermissionManagerQt::RequestPermissionsFromCurrentDocument(content::RenderFrameHost *frameHost,
- const content::PermissionRequestDescription &requestDescription,
- base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
+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(
- blink::PermissionType permission,
+ blink::PermissionType permissionTypeBlink,
const GURL& requesting_origin,
const GURL& /*embedding_origin*/)
{
- const QWebEnginePermission::PermissionType permissionType = toQt(permission);
- if (permissionType == QWebEnginePermission::PermissionType::Unsupported)
+ const QWebEnginePermission::PermissionType permissionTypeQt = toQt(permissionTypeBlink);
+ if (permissionTypeQt == QWebEnginePermission::PermissionType::Unsupported)
return blink::mojom::PermissionStatus::DENIED;
- permission = toBlink(toQt(permission)); // Filter out merged/unsupported permissions (e.g. clipboard)
- auto *pref = m_prefService->FindPreference(permissionTypeString(toQt(permission)));
+ permissionTypeBlink = toBlink(toQt(permissionTypeBlink)); // Filter out merged/unsupported permissions (e.g. clipboard)
+ auto *pref = m_prefService->FindPreference(permissionTypeString(permissionTypeQt));
if (!pref)
return blink::mojom::PermissionStatus::ASK; // Permission type not in database
- const auto *permissions = pref->GetValue()->GetIfDict();
- Q_ASSERT(permissions);
+ const auto *permissionsDict = pref->GetValue()->GetIfDict();
+ Q_ASSERT(permissionsDict);
- auto requestedPermission = permissions->FindBool(requesting_origin.DeprecatedGetOriginAsURL().spec());
+ const auto requestedPermission = permissionsDict->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_persistence)
- return blink::mojom::PermissionStatus::ASK;
-
if (requestedPermission.value())
return blink::mojom::PermissionStatus::GRANTED;
return blink::mojom::PermissionStatus::DENIED;
}
blink::mojom::PermissionStatus PermissionManagerQt::GetPermissionStatusForCurrentDocument(
- blink::PermissionType permission,
+ blink::PermissionType permissionTypeBlink,
content::RenderFrameHost *render_frame_host, bool)
{
Q_ASSERT(render_frame_host);
- if (permission == blink::PermissionType::CLIPBOARD_READ_WRITE ||
- permission == blink::PermissionType::CLIPBOARD_SANITIZED_WRITE) {
+ if (permissionTypeBlink == blink::PermissionType::CLIPBOARD_READ_WRITE ||
+ permissionTypeBlink == blink::PermissionType::CLIPBOARD_SANITIZED_WRITE) {
WebContentsDelegateQt *delegate = static_cast<WebContentsDelegateQt *>(
content::WebContents::FromRenderFrameHost(render_frame_host)->GetDelegate());
Q_ASSERT(delegate);
- auto status = getStatusFromSettings(permission, delegate->webEngineSettings());
+ auto status = getStatusFromSettings(permissionTypeBlink, delegate->webEngineSettings());
if (status != blink::mojom::PermissionStatus::ASK)
return status;
}
- permission = toBlink(toQt(permission)); // Filter out merged/unsupported permissions (e.g. clipboard)
- if (toQt(permission) == QWebEnginePermission::PermissionType::Unsupported)
+ permissionTypeBlink = toBlink(toQt(permissionTypeBlink)); // Filter out merged/unsupported permissions (e.g. clipboard)
+ QWebEnginePermission::PermissionType permissionTypeQt = toQt(permissionTypeBlink);
+ if (permissionTypeQt == QWebEnginePermission::PermissionType::Unsupported)
return blink::mojom::PermissionStatus::DENIED;
GURL origin = render_frame_host->GetLastCommittedOrigin().GetURL();
auto status = blink::mojom::PermissionStatus::ASK;
- bool inTransientStore = !QWebEnginePermission::isPersistent(toQt(permission)) || !m_persistence;
+ const bool inTransientStore = !QWebEnginePermission::isPersistent(permissionTypeQt) || !m_persistence;
if (inTransientStore) {
- status = getTransientPermissionStatus(permission, origin, render_frame_host->GetGlobalFrameToken());
+ status = getTransientPermissionStatus(permissionTypeBlink, origin, render_frame_host->GetGlobalFrameToken());
if (status != blink::mojom::PermissionStatus::ASK) {
return status;
@@ -568,12 +748,12 @@ blink::mojom::PermissionStatus PermissionManagerQt::GetPermissionStatusForCurren
// Fall through to check if permission was pre-granted (and thus landed in the permanent store)
}
- status = GetPermissionStatus(permission, origin, origin);
+ status = GetPermissionStatus(permissionTypeBlink, origin, origin);
if (inTransientStore && status != blink::mojom::PermissionStatus::ASK) {
// Move the pre-granted permission to the transient store and associate it with the rfh
- ResetPermission(permission, origin, origin);
- setTransientPermission(permission, origin, status == blink::mojom::PermissionStatus::GRANTED,
+ ResetPermission(permissionTypeBlink, origin, origin);
+ setTransientPermission(permissionTypeBlink, origin, status == blink::mojom::PermissionStatus::GRANTED,
render_frame_host->GetGlobalFrameToken());
}
@@ -610,9 +790,9 @@ content::PermissionResult PermissionManagerQt::GetPermissionResultForOriginWitho
}
void PermissionManagerQt::ResetPermission(
- blink::PermissionType permission,
- const GURL& requesting_origin,
- const GURL& /*embedding_origin*/)
+ blink::PermissionType permission,
+ const GURL& requesting_origin,
+ const GURL& /*embedding_origin*/)
{
const QWebEnginePermission::PermissionType permissionType = toQt(permission);
if (permissionType == QWebEnginePermission::PermissionType::Unsupported)
@@ -622,12 +802,12 @@ void PermissionManagerQt::ResetPermission(
updater.Get().Remove(requesting_origin.spec());
}
-blink::mojom::PermissionStatus PermissionManagerQt::getTransientPermissionStatus(blink::PermissionType permission,
+blink::mojom::PermissionStatus PermissionManagerQt::getTransientPermissionStatus(
+ blink::PermissionType permissionTypeBlink,
const GURL& requesting_origin,
content::GlobalRenderFrameHostToken token)
{
- const QWebEnginePermission::PermissionType permissionType = toQt(permission);
- if (permissionType == QWebEnginePermission::PermissionType::Unsupported)
+ if (toQt(permissionTypeBlink) == QWebEnginePermission::PermissionType::Unsupported)
return blink::mojom::PermissionStatus::DENIED;
if (!m_transientPermissions.contains(token))
@@ -635,8 +815,10 @@ blink::mojom::PermissionStatus PermissionManagerQt::getTransientPermissionStatus
auto &permissionsForToken = m_transientPermissions[token];
for (auto p = permissionsForToken.begin(); p != permissionsForToken.end(); ++p) {
- if (get<0>(*p) == requesting_origin && get<1>(*p) == permission) {
- return get<2>(*p) ? blink::mojom::PermissionStatus::GRANTED : blink::mojom::PermissionStatus::DENIED;
+ if (get<0>(*p) == requesting_origin && get<1>(*p) == permissionTypeBlink) {
+ return get<2>(*p)
+ ? blink::mojom::PermissionStatus::GRANTED
+ : blink::mojom::PermissionStatus::DENIED;
}
}
@@ -644,47 +826,49 @@ blink::mojom::PermissionStatus PermissionManagerQt::getTransientPermissionStatus
}
void PermissionManagerQt::setPersistentPermission(
- blink::PermissionType permission,
- const GURL& requesting_origin,
- bool granted)
+ blink::PermissionType permissionTypeBlink,
+ const GURL& requesting_origin,
+ bool granted)
{
- const QWebEnginePermission::PermissionType permissionType = toQt(permission);
- if (permissionType == QWebEnginePermission::PermissionType::Unsupported)
+ const QWebEnginePermission::PermissionType permissionTypeQt = toQt(permissionTypeBlink);
+ if (permissionTypeQt == QWebEnginePermission::PermissionType::Unsupported)
return;
- if (!m_prefService->FindPreference(permissionTypeString(permissionType)))
+ if (!m_prefService->FindPreference(permissionTypeString(permissionTypeQt)))
return;
- ScopedDictPrefUpdate updater(m_prefService.get(), permissionTypeString(permissionType));
+ ScopedDictPrefUpdate updater(m_prefService.get(), permissionTypeString(permissionTypeQt));
updater.Get().Set(requesting_origin.spec(), granted);
m_prefService->SchedulePendingLossyWrites();
}
-void PermissionManagerQt::setTransientPermission(blink::PermissionType permission,
+void PermissionManagerQt::setTransientPermission(
+ blink::PermissionType permissionTypeBlink,
const GURL& requesting_origin,
bool granted,
content::GlobalRenderFrameHostToken token)
{
- const QWebEnginePermission::PermissionType permissionType = toQt(permission);
- if (permissionType == QWebEnginePermission::PermissionType::Unsupported)
+ const QWebEnginePermission::PermissionType permissionTypeQt = toQt(permissionTypeBlink);
+ if (permissionTypeQt == QWebEnginePermission::PermissionType::Unsupported)
return;
auto &permissionsForToken = m_transientPermissions[token];
for (auto &p : permissionsForToken) {
- if (get<0>(p) == requesting_origin && get<1>(p) == permission) {
+ if (get<0>(p) == requesting_origin && get<1>(p) == permissionTypeBlink) {
get<2>(p) = granted;
return;
}
}
- permissionsForToken.push_back({requesting_origin, permission, granted});
+ permissionsForToken.push_back({requesting_origin, permissionTypeBlink, granted});
// Render frame hosts get discarded often, so the map will eventualy fill up with junk unless
// periodically cleaned. The number 25 was chosen arbitrarily.
if (++m_transientWriteCount > 25) {
content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE,
- base::BindOnce([](PermissionManagerQt *p){
+ base::BindOnce([](PermissionManagerQt *p)
+ {
for (auto i = p->m_transientPermissions.begin(); i != p->m_transientPermissions.end(); ++i) {
if (content::RenderFrameHost::FromFrameToken(i->first) == nullptr) {
i = p->m_transientPermissions.erase(i);
@@ -695,17 +879,18 @@ void PermissionManagerQt::setTransientPermission(blink::PermissionType permissio
}
}
-void PermissionManagerQt::resetTransientPermission(blink::PermissionType permission,
+void PermissionManagerQt::resetTransientPermission(
+ blink::PermissionType permissionTypeBlink,
const GURL& requesting_origin,
content::GlobalRenderFrameHostToken token)
{
- const QWebEnginePermission::PermissionType permissionType = toQt(permission);
- if (permissionType == QWebEnginePermission::PermissionType::Unsupported)
+ const QWebEnginePermission::PermissionType permissionTypeQt = toQt(permissionTypeBlink);
+ if (permissionTypeQt == QWebEnginePermission::PermissionType::Unsupported)
return;
auto &permissionsForToken = m_transientPermissions[token];
for (auto i = permissionsForToken.begin(); i != permissionsForToken.end(); ++i) {
- if (get<0>(*i) == requesting_origin && get<1>(*i) == permission) {
+ if (get<0>(*i) == requesting_origin && get<1>(*i) == permissionTypeBlink) {
permissionsForToken.erase(i);
return;
}
diff --git a/src/core/permission_manager_qt.h b/src/core/permission_manager_qt.h
index 7468e9861..d8474d1e1 100644
--- a/src/core/permission_manager_qt.h
+++ b/src/core/permission_manager_qt.h
@@ -6,11 +6,13 @@
#include "base/functional/callback.h"
#include "content/public/browser/global_routing_id.h"
+#include "content/public/browser/media_stream_request.h"
#include "content/public/browser/permission_controller_delegate.h"
#include "content/public/browser/render_frame_host.h"
#include <QtWebEngineCore/qwebenginepermission.h>
#include "profile_adapter.h"
+#include "web_contents_adapter_client.h"
#include <map>
#include <tuple>
@@ -25,14 +27,30 @@ public:
PermissionManagerQt(ProfileAdapter *adapter);
~PermissionManagerQt();
+ static content::GlobalRenderFrameHostToken deserializeToken(int childId, const std::string &serializedToken);
+
+ void setPermission(
+ const QUrl &origin,
+ const QWebEnginePermission::PermissionType permissionType,
+ const QWebEnginePermission::State state,
+ const content::GlobalRenderFrameHostToken &frameToken);
+
void setPermission(
const QUrl &origin,
- QWebEnginePermission::PermissionType permissionType,
- QWebEnginePermission::State state,
- content::RenderFrameHost *rfh = nullptr);
- QWebEnginePermission::State getPermissionState(const QUrl &origin, QWebEnginePermission::PermissionType permissionType,
- content::RenderFrameHost *rfh = nullptr);
- QList<QWebEnginePermission> listPermissions(const QUrl &origin, QWebEnginePermission::PermissionType permissionType);
+ const QWebEnginePermission::PermissionType permissionType,
+ const QWebEnginePermission::State state,
+ int childId, const std::string &serializedToken);
+
+ QWebEnginePermission::State getPermissionState(const QUrl &origin, const QWebEnginePermission::PermissionType permissionType,
+ const content::GlobalRenderFrameHostToken &frameToken);
+ QList<QWebEnginePermission> listPermissions(const QUrl &origin, const QWebEnginePermission::PermissionType permissionType);
+
+ void requestMediaPermissions(
+ content::RenderFrameHost *render_frame_host,
+ const WebContentsAdapterClient::MediaRequestFlags flags,
+ base::OnceCallback<void(WebContentsAdapterClient::MediaRequestFlags authorizationFlags)> callback);
+
+ void onCrossOriginNavigation(content::RenderFrameHost *render_frame_host);
void commit();
@@ -42,7 +60,6 @@ public:
const GURL& requesting_origin,
const GURL& embedding_origin) override;
-
content::PermissionStatus GetPermissionStatusForCurrentDocument(blink::PermissionType, content::RenderFrameHost*, bool) override;
blink::mojom::PermissionStatus GetPermissionStatusForWorker(blink::PermissionType, content::RenderProcessHost *, const GURL &) override;
@@ -85,6 +102,12 @@ private:
base::RepeatingCallback<void(blink::mojom::PermissionStatus)> callback;
};
+ void setPermissionImpl(
+ const QUrl &origin,
+ const QWebEnginePermission::PermissionType permissionType,
+ const QWebEnginePermission::State state,
+ const content::GlobalRenderFrameHostToken &frameToken);
+
blink::mojom::PermissionStatus getTransientPermissionStatus(blink::PermissionType permission,
const GURL& requesting_origin,
content::GlobalRenderFrameHostToken token);
diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp
index f0cabc088..1e07f95f3 100644
--- a/src/core/profile_adapter.cpp
+++ b/src/core/profile_adapter.cpp
@@ -33,7 +33,9 @@
#include "renderer_host/user_resource_controller_host.h"
#include "type_conversion.h"
#include "visited_links_manager_qt.h"
+#include "web_contents_adapter.h"
#include "web_contents_adapter_client.h"
+#include "web_contents_delegate_qt.h"
#include "web_engine_context.h"
#include <QCoreApplication>
@@ -627,15 +629,29 @@ UserResourceControllerHost *ProfileAdapter::userResourceController()
}
void ProfileAdapter::setPermission(const QUrl &origin, QWebEnginePermission::PermissionType permissionType,
- QWebEnginePermission::State state, content::RenderFrameHost *rfh)
+ QWebEnginePermission::State state, int childId, const std::string &serializedToken)
{
- static_cast<PermissionManagerQt*>(profile()->GetPermissionControllerDelegate())->setPermission(origin, permissionType, state, rfh);
+ auto token = PermissionManagerQt::deserializeToken(childId, serializedToken);
+
+ // Check if the frame token is valid, and defer to WebContentsAdapter if so
+ auto *rfh = content::RenderFrameHost::FromFrameToken(token);
+ if (rfh) {
+ static_cast<WebContentsDelegateQt *>(content::WebContents::FromRenderFrameHost(rfh)->GetDelegate())
+ ->webContentsAdapter()
+ ->setPermission(origin, permissionType, state, childId, serializedToken);
+ return;
+ }
+
+ // Otherwise, set the permission directly
+ static_cast<PermissionManagerQt *>(profile()->GetPermissionControllerDelegate())
+ ->setPermission(origin, permissionType, state, token);
}
QWebEnginePermission::State ProfileAdapter::getPermissionState(const QUrl &origin, QWebEnginePermission::PermissionType permissionType,
- content::RenderFrameHost *rfh)
+ int childId, const std::string &serializedToken)
{
- return static_cast<PermissionManagerQt*>(profile()->GetPermissionControllerDelegate())->getPermissionState(origin, permissionType, rfh);
+ return static_cast<PermissionManagerQt*>(profile()->GetPermissionControllerDelegate())
+ ->getPermissionState(origin, permissionType, PermissionManagerQt::deserializeToken(childId, serializedToken));
}
QList<QWebEnginePermission> ProfileAdapter::listPermissions(const QUrl &origin, QWebEnginePermission::PermissionType permissionType)
diff --git a/src/core/profile_adapter.h b/src/core/profile_adapter.h
index b6357ce1c..142ad9aff 100644
--- a/src/core/profile_adapter.h
+++ b/src/core/profile_adapter.h
@@ -16,6 +16,7 @@
#define PROFILE_ADAPTER_H
#include <QtWebEngineCore/private/qtwebenginecoreglobal_p.h>
+#include <QtWebEngineCore/private/qwebenginepermission_p.h>
#include <QHash>
#include <QList>
@@ -186,9 +187,9 @@ public:
UserResourceControllerHost *userResourceController();
void setPermission(const QUrl &origin, QWebEnginePermission::PermissionType permissionType,
- QWebEnginePermission::State state, content::RenderFrameHost *rfh = nullptr);
+ QWebEnginePermission::State state, int childId = -1, const std::string &serializedToken = std::string());
QWebEnginePermission::State getPermissionState(const QUrl &origin, QWebEnginePermission::PermissionType permissionType,
- content::RenderFrameHost *rfh = nullptr);
+ int childId = -1, const std::string &serializedToken = std::string());
QList<QWebEnginePermission> listPermissions(const QUrl &origin = QUrl(),
QWebEnginePermission::PermissionType permissionType = QWebEnginePermission::PermissionType::Unsupported);
diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp
index 8c4d01e58..685b2acfe 100644
--- a/src/core/web_contents_adapter.cpp
+++ b/src/core/web_contents_adapter.cpp
@@ -16,6 +16,7 @@
#include "find_text_helper.h"
#include "media_capture_devices_dispatcher.h"
#include "pdf_util_qt.h"
+#include "permission_manager_qt.h"
#include "profile_adapter.h"
#include "profile_qt.h"
#include "qwebengineloadinginfo.h"
@@ -1417,17 +1418,18 @@ QSizeF WebContentsAdapter::lastContentsSize() const
return QSizeF();
}
-void WebContentsAdapter::setPermission(const QUrl &origin, QWebEnginePermission::PermissionType permissionType, QWebEnginePermission::State state)
+void WebContentsAdapter::setPermission(
+ const QUrl &origin,
+ QWebEnginePermission::PermissionType permissionType,
+ QWebEnginePermission::State state,
+ int childId, const std::string &serializedToken)
{
+ auto *manager = static_cast<PermissionManagerQt*>(m_profileAdapter->profile()->GetPermissionControllerDelegate());
+
if (QWebEnginePermission::isPersistent(permissionType)) {
// Do not check for initialization in this path so permissions can be set before first navigation
Q_ASSERT(m_profileAdapter);
- if (!isInitialized()) {
- m_profileAdapter->setPermission(origin, permissionType, state);
- } else {
- m_profileAdapter->setPermission(origin, permissionType, state, m_webContents.get()->GetPrimaryMainFrame());
- }
-
+ manager->setPermission(origin, permissionType, state, childId, serializedToken);
return;
}
@@ -1440,115 +1442,87 @@ void WebContentsAdapter::setPermission(const QUrl &origin, QWebEnginePermission:
// Do nothing
break;
case QWebEnginePermission::State::Denied:
- grantMouseLockPermission(origin, false);
+ grantMouseLockPermission(origin, childId, serializedToken, false);
break;
case QWebEnginePermission::State::Granted:
- grantMouseLockPermission(origin, true);
+ grantMouseLockPermission(origin, childId, serializedToken, true);
break;
}
return;
}
- const WebContentsAdapterClient::MediaRequestFlags audioVideoCaptureFlags(
- WebContentsAdapterClient::MediaVideoCapture |
- WebContentsAdapterClient::MediaAudioCapture);
- const WebContentsAdapterClient::MediaRequestFlags desktopAudioVideoCaptureFlags(
- WebContentsAdapterClient::MediaDesktopVideoCapture |
- WebContentsAdapterClient::MediaDesktopAudioCapture);
-
- switch (state) {
- case QWebEnginePermission::State::Invalid:
- case QWebEnginePermission::State::Ask:
- // Do nothing
- return;
- case QWebEnginePermission::State::Denied:
- // Deny all media access
- grantMediaAccessPermission(origin, WebContentsAdapterClient::MediaNone);
- return;
- case QWebEnginePermission::State::Granted:
- // Enable only the requested capture type
- break;
- }
+ // If we reach this, we must be handling media access permissions
+ manager->setPermission(origin, permissionType, state, childId, serializedToken);
- switch (permissionType) {
- case QWebEnginePermission::PermissionType::MediaAudioVideoCapture:
- grantMediaAccessPermission(origin, audioVideoCaptureFlags);
- break;
- case QWebEnginePermission::PermissionType::MediaAudioCapture:
- grantMediaAccessPermission(origin, WebContentsAdapterClient::MediaAudioCapture);
- break;
- case QWebEnginePermission::PermissionType::MediaVideoCapture:
- grantMediaAccessPermission(origin, WebContentsAdapterClient::MediaVideoCapture);
- break;
- case QWebEnginePermission::PermissionType::DesktopAudioVideoCapture:
- grantMediaAccessPermission(origin, desktopAudioVideoCaptureFlags);
- break;
- case QWebEnginePermission::PermissionType::DesktopVideoCapture:
- grantMediaAccessPermission(origin, WebContentsAdapterClient::MediaDesktopVideoCapture);
- break;
- default:
- Q_UNREACHABLE();
- break;
+ WebContentsAdapterClient::MediaRequestFlags flags = WebContentsAdapterClient::MediaNone;
+ if (state == QWebEnginePermission::State::Granted) {
+ switch (permissionType) {
+ case QWebEnginePermission::PermissionType::MediaAudioCapture:
+ flags.setFlag(WebContentsAdapterClient::MediaAudioCapture);
+ break;
+ case QWebEnginePermission::PermissionType::MediaVideoCapture:
+ flags.setFlag(WebContentsAdapterClient::MediaVideoCapture);
+ break;
+ case QWebEnginePermission::PermissionType::MediaAudioVideoCapture:
+ flags.setFlag(WebContentsAdapterClient::MediaAudioCapture);
+ flags.setFlag(WebContentsAdapterClient::MediaVideoCapture);
+ break;
+ case QWebEnginePermission::PermissionType::DesktopVideoCapture:
+ flags.setFlag(WebContentsAdapterClient::MediaDesktopVideoCapture);
+ break;
+ case QWebEnginePermission::PermissionType::DesktopAudioVideoCapture:
+ flags.setFlag(WebContentsAdapterClient::MediaDesktopAudioCapture);
+ flags.setFlag(WebContentsAdapterClient::MediaDesktopVideoCapture);
+ break;
+ default:
+ break;
+ }
}
-}
-QWebEnginePermission::State WebContentsAdapter::getPermissionState(const QUrl &origin, QWebEnginePermission::PermissionType permissionType)
-{
- return m_profileAdapter->getPermissionState(origin, permissionType, m_webContents.get()->GetPrimaryMainFrame());
-}
-
-void WebContentsAdapter::grantMediaAccessPermission(const QUrl &origin, WebContentsAdapterClient::MediaRequestFlags flags)
-{
- CHECK_INITIALIZED();
- // Let the permission manager remember the reply.
- if (flags & WebContentsAdapterClient::MediaAudioCapture)
- m_profileAdapter->setPermission(origin,
- QWebEnginePermission::PermissionType::MediaAudioCapture,
- QWebEnginePermission::State::Granted,
- m_webContents.get()->GetPrimaryMainFrame());
- if (flags & WebContentsAdapterClient::MediaVideoCapture)
- m_profileAdapter->setPermission(origin,
- QWebEnginePermission::PermissionType::MediaVideoCapture,
- QWebEnginePermission::State::Granted,
- m_webContents.get()->GetPrimaryMainFrame());
MediaCaptureDevicesDispatcher::GetInstance()->handleMediaAccessPermissionResponse(m_webContents.get(), origin, flags);
}
-void WebContentsAdapter::grantMouseLockPermission(const QUrl &securityOrigin, bool granted)
+void WebContentsAdapter::grantMouseLockPermission(const QUrl &securityOrigin, int childId,
+ const std::string &serializedToken, bool granted)
{
CHECK_INITIALIZED();
- if (securityOrigin != toQt(m_webContents->GetLastCommittedURL().DeprecatedGetOriginAsURL()))
- return;
- if (granted) {
- if (RenderWidgetHostViewQt *rwhv = static_cast<RenderWidgetHostViewQt *>(m_webContents->GetRenderWidgetHostView())) {
- rwhv->Focus();
- if (!rwhv->HasFocus()) {
- // We tried to activate our RWHVQtDelegate, but we failed. This probably means that
- // the permission was granted from a modal dialog and the windowing system is not ready
- // to set focus on the originating view. Since pointer lock strongly requires it, we just
- // wait until the next FocusIn event.
- m_pendingMouseLockPermissions.insert(securityOrigin, granted);
- return;
- }
- } else
- granted = false;
+ bool focused = false;
+ if (RenderWidgetHostViewQt *rwhv = static_cast<RenderWidgetHostViewQt *>(m_webContents->GetRenderWidgetHostView())) {
+ rwhv->Focus();
+ if (rwhv->HasFocus()) {
+ focused = true;
+ }
+ } else {
+ granted = false;
}
- m_webContents->GotResponseToPointerLockRequest(granted ? blink::mojom::PointerLockResult::kSuccess
- : blink::mojom::PointerLockResult::kPermissionDenied);
+ m_pendingMouseLockPermissions.enqueue({ securityOrigin, granted, childId, serializedToken });
+
+ if (focused) {
+ handlePendingMouseLockPermission();
+ }
}
void WebContentsAdapter::handlePendingMouseLockPermission()
{
CHECK_INITIALIZED();
- auto it = m_pendingMouseLockPermissions.find(toQt(m_webContents->GetLastCommittedURL().DeprecatedGetOriginAsURL()));
- if (it != m_pendingMouseLockPermissions.end()) {
- m_webContents->GotResponseToPointerLockRequest(it.value() ? blink::mojom::PointerLockResult::kSuccess
- : blink::mojom::PointerLockResult::kPermissionDenied);
- m_pendingMouseLockPermissions.erase(it);
- }
+ if (!m_pendingMouseLockPermissions.size())
+ return;
+
+ auto pending = m_pendingMouseLockPermissions.dequeue();
+
+ // Simply set the permission in the manager. The callback from WebContentsDelegateQt::RequestPointerLock()
+ // will ensure WebContents receives the response
+ auto *manager = static_cast<PermissionManagerQt*>(m_profileAdapter->profile()->GetPermissionControllerDelegate());
+ manager->setPermission(
+ get<0>(pending), // origin
+ QWebEnginePermission::PermissionType::MouseLock,
+ get<1>(pending) // granted
+ ? QWebEnginePermission::State::Granted : QWebEnginePermission::State::Denied,
+ get<2>(pending), // childId
+ get<3>(pending)); // serializedToken
}
void WebContentsAdapter::setBackgroundColor(const QColor &color)
diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h
index 3bb639b1b..212411109 100644
--- a/src/core/web_contents_adapter.h
+++ b/src/core/web_contents_adapter.h
@@ -21,6 +21,7 @@
#include <QtCore/QUrl>
#include <QtCore/QVariant>
#include <QtCore/QPointer>
+#include <QtCore/QQueue>
#include <QtGui/qtgui-config.h>
#include <QtWebEngineCore/private/qtwebenginecoreglobal_p.h>
#include <QtWebEngineCore/qwebenginecontextmenurequest.h>
@@ -48,6 +49,7 @@ namespace content {
class WebContents;
class SiteInstance;
class RenderFrameHost;
+struct GlobalRenderFrameHostToken;
}
QT_BEGIN_NAMESPACE
@@ -179,11 +181,9 @@ public:
void devToolsFrontendDestroyed(DevToolsFrontendQt *frontend);
QString devToolsId();
- void setPermission(const QUrl &origin, QWebEnginePermission::PermissionType permissionType, QWebEnginePermission::State state);
- QWebEnginePermission::State getPermissionState(const QUrl &origin, QWebEnginePermission::PermissionType permissionType);
-
- void grantMediaAccessPermission(const QUrl &origin, WebContentsAdapterClient::MediaRequestFlags flags);
- void grantMouseLockPermission(const QUrl &origin, bool granted);
+ void setPermission(const QUrl &origin, QWebEnginePermission::PermissionType permissionType,
+ QWebEnginePermission::State state, int childId = -1, const std::string &serializedToken = std::string());
+ void grantMouseLockPermission(const QUrl &origin, int childId, const std::string &serializedToken, bool granted);
void handlePendingMouseLockPermission();
void setBackgroundColor(const QColor &color);
@@ -272,7 +272,7 @@ private:
#endif
WebContentsAdapterClient *m_adapterClient;
quint64 m_nextRequestId;
- QMap<QUrl, bool> m_pendingMouseLockPermissions;
+ QQueue<std::tuple<QUrl, bool, int, std::string>> m_pendingMouseLockPermissions;
QMap<quint64, std::function<void(const QVariant &)>> m_javaScriptCallbacks;
std::map<quint64, std::function<void(QSharedPointer<QByteArray>)>> m_printCallbacks;
std::unique_ptr<content::DropData> m_currentDropData;
diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h
index 9ce5bebfc..2f93d4783 100644
--- a/src/core/web_contents_adapter_client.h
+++ b/src/core/web_contents_adapter_client.h
@@ -16,6 +16,7 @@
#define WEB_CONTENTS_ADAPTER_CLIENT_H
#include <QtWebEngineCore/private/qtwebenginecoreglobal_p.h>
+#include <QtWebEngineCore/private/qwebenginepermission_p.h>
#include <QtWebEngineCore/qwebenginepermission.h>
#include "profile_adapter.h"
@@ -195,9 +196,8 @@ public:
virtual QObject *accessibilityParentObject() = 0;
virtual void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) = 0;
virtual void authenticationRequired(QSharedPointer<AuthenticationDialogController>) = 0;
- virtual void runFeaturePermissionRequest(QWebEnginePermission::PermissionType, const QUrl &securityOrigin) = 0;
- virtual void runMediaAccessPermissionRequest(const QUrl &securityOrigin, MediaRequestFlags requestFlags) = 0;
- virtual void runMouseLockPermissionRequest(const QUrl &securityOrigin) = 0;
+ virtual void runFeaturePermissionRequest(QWebEnginePermission::PermissionType, const QUrl &securityOrigin,
+ int childId, const std::string &serializedToken) = 0;
virtual void runRegisterProtocolHandlerRequest(QWebEngineRegisterProtocolHandlerRequest) = 0;
virtual void runFileSystemAccessRequest(QWebEngineFileSystemAccessRequest) = 0;
virtual QWebEngineSettings *webEngineSettings() const = 0;
@@ -229,7 +229,6 @@ public:
virtual WebContentsAdapter* webContentsAdapter() = 0;
virtual void releaseProfile() = 0;
virtual void showWebAuthDialog(QWebEngineWebAuthUxRequest *request) = 0;
- virtual QWebEnginePermission createFeaturePermissionObject(const QUrl &securityOrigin, QWebEnginePermission::PermissionType permissionType) = 0;
};
} // namespace QtWebEngineCore
diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp
index 89a0a6582..77ba5ec91 100644
--- a/src/core/web_contents_delegate_qt.cpp
+++ b/src/core/web_contents_delegate_qt.cpp
@@ -19,6 +19,7 @@
#include "javascript_dialog_manager_qt.h"
#include "media_capture_devices_dispatcher.h"
#include "native_web_keyboard_event_qt.h"
+#include "permission_manager_qt.h"
#include "profile_adapter.h"
#include "profile_qt.h"
#include "qwebengineloadinginfo.h"
@@ -418,6 +419,12 @@ void WebContentsDelegateQt::emitLoadCommitted()
void WebContentsDelegateQt::DidFinishNavigation(content::NavigationHandle *navigation_handle)
{
+ if (navigation_handle->HasCommitted() && !navigation_handle->IsSameOrigin()) {
+ PermissionManagerQt *permissionManager = static_cast<PermissionManagerQt *>(
+ navigation_handle->GetWebContents()->GetBrowserContext()->GetPermissionControllerDelegate());
+ permissionManager->onCrossOriginNavigation(navigation_handle->GetRenderFrameHost());
+ }
+
if (!navigation_handle->IsInMainFrame())
return;
@@ -731,14 +738,32 @@ void WebContentsDelegateQt::ActivateContents(content::WebContents* contents)
void WebContentsDelegateQt::RequestPointerLock(content::WebContents *web_contents, bool user_gesture, bool last_unlocked_by_target)
{
- Q_UNUSED(user_gesture);
-
if (last_unlocked_by_target)
web_contents->GotResponseToPointerLockRequest(blink::mojom::PointerLockResult::kSuccess);
- else
- m_viewClient->runMouseLockPermissionRequest(toQt(web_contents->GetLastCommittedURL().DeprecatedGetOriginAsURL()));
+ else {
+ PermissionManagerQt *permissionManager = static_cast<PermissionManagerQt *>(
+ web_contents->GetBrowserContext()->GetPermissionControllerDelegate());
+
+ auto *rfh = web_contents->GetFocusedFrame();
+ if (!rfh)
+ rfh = web_contents->GetPrimaryMainFrame();
+
+ permissionManager->RequestPermissions(
+ rfh,
+ content::PermissionRequestDescription(blink::PermissionType::POINTER_LOCK, user_gesture, rfh->GetLastCommittedOrigin().GetURL()),
+ base::BindOnce([](content::WebContents *web_contents, PermissionManagerQt *manager, const std::vector<blink::mojom::PermissionStatus> &status)
+ {
+ Q_ASSERT(status.size() == 1);
+
+ web_contents->GotResponseToPointerLockRequest(status[0] == blink::mojom::PermissionStatus::GRANTED
+ ? blink::mojom::PointerLockResult::kSuccess
+ : blink::mojom::PointerLockResult::kPermissionDenied);
+ }, web_contents, permissionManager)
+ );
+ }
}
+
void WebContentsDelegateQt::overrideWebPreferences(content::WebContents *webContents, blink::web_pref::WebPreferences *webPreferences)
{
WebEngineSettings::get(m_viewClient->webEngineSettings())->overrideWebPreferences(webContents, webPreferences);
@@ -773,9 +798,12 @@ void WebContentsDelegateQt::selectClientCert(const QSharedPointer<ClientCertSele
m_viewClient->selectClientCert(selectController);
}
-void WebContentsDelegateQt::requestFeaturePermission(QWebEnginePermission::PermissionType permissionType, const QUrl &requestingOrigin)
+void WebContentsDelegateQt::requestFeaturePermission(
+ QWebEnginePermission::PermissionType permissionType,
+ const QUrl &requestingOrigin,
+ const content::GlobalRenderFrameHostToken &frameToken)
{
- m_viewClient->runFeaturePermissionRequest(permissionType, requestingOrigin);
+ m_viewClient->runFeaturePermissionRequest(permissionType, requestingOrigin, frameToken.child_id, frameToken.frame_token.ToString());
}
extern WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::PageTransition transition);
@@ -834,18 +862,22 @@ bool WebContentsDelegateQt::CheckMediaAccessPermission(content::RenderFrameHost
blink::mojom::MediaStreamType type)
{
Q_ASSERT(rfh);
+
+ auto token = rfh->GetGlobalFrameToken();
+ std::string serializedToken = token.frame_token.ToString();
+
switch (type) {
case blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE:
return m_viewClient->profileAdapter()->getPermissionState(
toQt(security_origin),
QWebEnginePermission::PermissionType::MediaAudioCapture,
- rfh)
+ token.child_id, serializedToken)
== QWebEnginePermission::State::Granted;
case blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE:
return m_viewClient->profileAdapter()->getPermissionState(
toQt(security_origin),
QWebEnginePermission::PermissionType::MediaVideoCapture,
- rfh)
+ token.child_id, serializedToken)
== QWebEnginePermission::State::Granted;
default:
LOG(INFO) << "WebContentsDelegateQt::CheckMediaAccessPermission: "
diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h
index 099d8280b..383803c4d 100644
--- a/src/core/web_contents_delegate_qt.h
+++ b/src/core/web_contents_delegate_qt.h
@@ -25,6 +25,7 @@ class ColorChooser;
class JavaScriptDialogManager;
class WebContents;
struct MediaStreamRequest;
+struct GlobalRenderFrameHostToken;
}
namespace QtWebEngineCore {
@@ -144,7 +145,7 @@ public:
void overrideWebPreferences(content::WebContents *, blink::web_pref::WebPreferences*);
void allowCertificateError(const QSharedPointer<CertificateErrorController> &);
void selectClientCert(const QSharedPointer<ClientCertSelectController> &);
- void requestFeaturePermission(QWebEnginePermission::PermissionType permissionType, const QUrl &requestingOrigin);
+ void requestFeaturePermission(QWebEnginePermission::PermissionType permissionType, const QUrl &requestingOrigin, const content::GlobalRenderFrameHostToken &frameToken);
void launchExternalURL(const QUrl &url, ui::PageTransition page_transition, bool is_main_frame, bool has_user_gesture);
FindTextHelper *findTextHelper();
diff --git a/src/webenginequick/api/qquickwebengineprofile.cpp b/src/webenginequick/api/qquickwebengineprofile.cpp
index 6aebc18a1..6eb58515c 100644
--- a/src/webenginequick/api/qquickwebengineprofile.cpp
+++ b/src/webenginequick/api/qquickwebengineprofile.cpp
@@ -1223,7 +1223,7 @@ QWebEnginePermission QQuickWebEngineProfile::queryPermission(const QUrl &securit
return QWebEnginePermission(new QWebEnginePermissionPrivate());
}
- auto *pvt = new QWebEnginePermissionPrivate(securityOrigin, permissionType, nullptr, d->profileAdapter());
+ auto *pvt = new QWebEnginePermissionPrivate(securityOrigin, permissionType, d->profileAdapter());
return QWebEnginePermission(pvt);
}
diff --git a/src/webenginequick/api/qquickwebengineview.cpp b/src/webenginequick/api/qquickwebengineview.cpp
index ade8b451c..619cbaef6 100644
--- a/src/webenginequick/api/qquickwebengineview.cpp
+++ b/src/webenginequick/api/qquickwebengineview.cpp
@@ -521,22 +521,30 @@ static QQuickWebEngineView::Feature toDeprecatedFeature(QWebEnginePermission::Pe
QT_WARNING_POP
#endif // QT_DEPRECATED_SINCE(6, 8)
-void QQuickWebEngineViewPrivate::runFeaturePermissionRequest(QWebEnginePermission::PermissionType permissionType, const QUrl &securityOrigin)
+void QQuickWebEngineViewPrivate::runFeaturePermissionRequest(
+ QWebEnginePermission::PermissionType permissionType,
+ const QUrl &securityOrigin,
+ int childId, const std::string &serializedToken)
{
Q_Q(QQuickWebEngineView);
- if (QWebEnginePermission::isPersistent(permissionType)) {
- Q_EMIT q->permissionRequested(createFeaturePermissionObject(securityOrigin, permissionType));
-#if QT_DEPRECATED_SINCE(6, 8)
- QT_WARNING_PUSH
- QT_WARNING_DISABLE_DEPRECATED
- Q_EMIT q->featurePermissionRequested(securityOrigin, toDeprecatedFeature(permissionType));
- QT_WARNING_POP
-#endif // QT_DEPRECATED_SINCE(6, 8)
+ if (permissionType == QWebEnginePermission::PermissionType::MouseLock) {
+ // Not supported in Qt Quick
+ auto permission = QWebEnginePermission(
+ new QWebEnginePermissionPrivate(securityOrigin, permissionType, profileAdapter(), childId, serializedToken));
+ permission.deny();
return;
}
- Q_UNREACHABLE();
+ Q_EMIT q->permissionRequested(QWebEnginePermission(
+ new QWebEnginePermissionPrivate(securityOrigin, permissionType, profileAdapter(), childId, serializedToken)));
+#if QT_DEPRECATED_SINCE(6, 8)
+ QT_WARNING_PUSH
+ QT_WARNING_DISABLE_DEPRECATED
+ Q_EMIT q->featurePermissionRequested(securityOrigin, toDeprecatedFeature(permissionType));
+ QT_WARNING_POP
+#endif // QT_DEPRECATED_SINCE(6, 8)
+ return;
}
void QQuickWebEngineViewPrivate::showColorDialog(QSharedPointer<ColorChooserController> controller)
@@ -809,54 +817,6 @@ void QQuickWebEngineViewPrivate::authenticationRequired(QSharedPointer<Authentic
ui()->showDialog(controller);
}
-void QQuickWebEngineViewPrivate::runMediaAccessPermissionRequest(const QUrl &securityOrigin, WebContentsAdapterClient::MediaRequestFlags requestFlags)
-{
- Q_Q(QQuickWebEngineView);
- if (!requestFlags)
- return;
- QWebEnginePermission::PermissionType permissionType;
- if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture) && requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture))
- permissionType = QWebEnginePermission::PermissionType::MediaAudioVideoCapture;
- else if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture))
- permissionType = QWebEnginePermission::PermissionType::MediaAudioCapture;
- else if (requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture))
- permissionType = QWebEnginePermission::PermissionType::MediaVideoCapture;
- else if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopAudioCapture) &&
- requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture))
- permissionType = QWebEnginePermission::PermissionType::DesktopAudioVideoCapture;
- else // if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture))
- permissionType = QWebEnginePermission::PermissionType::DesktopVideoCapture;
- Q_EMIT q->permissionRequested(createFeaturePermissionObject(securityOrigin, permissionType));
-
-#if QT_DEPRECATED_SINCE(6, 8)
- QT_WARNING_PUSH
- QT_WARNING_DISABLE_DEPRECATED
- QQuickWebEngineView::Feature deprecatedFeature;
-
- if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture)
- && requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture))
- deprecatedFeature = QQuickWebEngineView::MediaAudioVideoCapture;
- else if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture))
- deprecatedFeature = QQuickWebEngineView::MediaAudioCapture;
- else if (requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture))
- deprecatedFeature = QQuickWebEngineView::MediaVideoCapture;
- else if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopAudioCapture)
- && requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture))
- deprecatedFeature = QQuickWebEngineView::DesktopAudioVideoCapture;
- else // if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture))
- deprecatedFeature = QQuickWebEngineView::DesktopVideoCapture;
-
- Q_EMIT q->featurePermissionRequested(securityOrigin, deprecatedFeature);
- QT_WARNING_POP
-#endif // QT_DEPRECATED_SINCE(6, 8)
-}
-
-void QQuickWebEngineViewPrivate::runMouseLockPermissionRequest(const QUrl &securityOrigin)
-{
- // TODO: Add mouse lock support
- adapter->grantMouseLockPermission(securityOrigin, false);
-}
-
void QQuickWebEngineViewPrivate::runRegisterProtocolHandlerRequest(QWebEngineRegisterProtocolHandlerRequest request)
{
Q_Q(QQuickWebEngineView);
@@ -1523,12 +1483,6 @@ void QQuickWebEngineViewPrivate::showWebAuthDialog(QWebEngineWebAuthUxRequest *r
Q_EMIT q->webAuthUxRequested(request);
}
-QWebEnginePermission QQuickWebEngineViewPrivate::createFeaturePermissionObject(const QUrl &securityOrigin, QWebEnginePermission::PermissionType permissionType)
-{
- auto *returnPrivate = new QWebEnginePermissionPrivate(securityOrigin, permissionType, adapter, profileAdapter());
- return QWebEnginePermission(returnPrivate);
-}
-
bool QQuickWebEngineView::isLoading() const
{
Q_D(const QQuickWebEngineView);
diff --git a/src/webenginequick/api/qquickwebengineview_p_p.h b/src/webenginequick/api/qquickwebengineview_p_p.h
index d78157597..8fe98145b 100644
--- a/src/webenginequick/api/qquickwebengineview_p_p.h
+++ b/src/webenginequick/api/qquickwebengineview_p_p.h
@@ -105,8 +105,6 @@ public:
bool passOnFocus(bool reverse) override;
void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) override;
void authenticationRequired(QSharedPointer<QtWebEngineCore::AuthenticationDialogController>) override;
- void runMediaAccessPermissionRequest(const QUrl &securityOrigin, MediaRequestFlags requestFlags) override;
- void runMouseLockPermissionRequest(const QUrl &securityOrigin) override;
void runRegisterProtocolHandlerRequest(QWebEngineRegisterProtocolHandlerRequest) override;
void runFileSystemAccessRequest(QWebEngineFileSystemAccessRequest) override;
QObject *accessibilityParentObject() override;
@@ -114,7 +112,8 @@ public:
void allowCertificateError(const QWebEngineCertificateError &error) override;
void selectClientCert(const QSharedPointer<QtWebEngineCore::ClientCertSelectController>
&selectController) override;
- void runFeaturePermissionRequest(QWebEnginePermission::PermissionType permissionType, const QUrl &securityOrigin) override;
+ void runFeaturePermissionRequest(QWebEnginePermission::PermissionType permissionType, const QUrl &securityOrigin,
+ int childId, const std::string &serializedToken) override;
void renderProcessTerminated(RenderProcessTerminationStatus terminationStatus, int exitCode) override;
void requestGeometryChange(const QRect &geometry, const QRect &frameGeometry) override;
void updateScrollPosition(const QPointF &position) override;
@@ -139,7 +138,6 @@ public:
const QRect &bounds, bool autoselectFirstSuggestion) override;
void hideAutofillPopup() override;
void showWebAuthDialog(QWebEngineWebAuthUxRequest *request) override;
- QWebEnginePermission createFeaturePermissionObject(const QUrl &securityOrigin, QWebEnginePermission::PermissionType permissionType) override;
void updateAction(QQuickWebEngineView::WebAction) const;
bool adoptWebContents(QtWebEngineCore::WebContentsAdapter *webContents);