diff options
author | Kaloyan Chehlarski <kaloyan.chehlarski@qt.io> | 2024-01-23 15:42:15 +0100 |
---|---|---|
committer | Kaloyan Chehlarski <kaloyan.chehlarski@qt.io> | 2024-03-15 11:53:36 +0100 |
commit | 9392144a5a47206fb80f1828ab73c48a47ba1283 (patch) | |
tree | f0958cc42a5ee49e956df29065b5987495274f51 | |
parent | 11e58879960f7f0dce38649642bebf7eb2e24973 (diff) |
Add support for local font access notifications
Accessing local fonts on the user's machine has been available in
Chromium since v103, via a (draft) API descrived here:
https://developer.chrome.com/docs/capabilities/web-apis/local-fonts
This change adds support for the relevant notification types,
effectively exposing the API to WebEngine applications.
Task-number: QTBUG-121320
Change-Id: I42c5261dc689c3d7bb4aa3c58c6300421220a36a
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
-rw-r--r-- | src/core/api/qwebenginepage.cpp | 11 | ||||
-rw-r--r-- | src/core/api/qwebenginepage.h | 1 | ||||
-rw-r--r-- | src/core/doc/src/qwebenginepage_lgpl.qdoc | 2 | ||||
-rw-r--r-- | src/core/permission_manager_qt.cpp | 4 | ||||
-rw-r--r-- | src/core/profile_adapter.h | 1 | ||||
-rw-r--r-- | tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp | 63 |
6 files changed, 81 insertions, 1 deletions
diff --git a/src/core/api/qwebenginepage.cpp b/src/core/api/qwebenginepage.cpp index 0dcc56393..ac645c430 100644 --- a/src/core/api/qwebenginepage.cpp +++ b/src/core/api/qwebenginepage.cpp @@ -597,6 +597,8 @@ static QWebEnginePage::Feature toFeature(QtWebEngineCore::ProfileAdapter::Permis return QWebEnginePage::Geolocation; case QtWebEngineCore::ProfileAdapter::ClipboardReadWrite: return QWebEnginePage::ClipboardReadWrite; + case QtWebEngineCore::ProfileAdapter::LocalFontsPermission: + return QWebEnginePage::LocalFontsAccess; default: break; } @@ -1756,6 +1758,9 @@ void QWebEnginePage::setFeaturePermission(const QUrl &securityOrigin, QWebEngine d->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::ClipboardReadWrite, ProfileAdapter::AskPermission); break; + case LocalFontsAccess: + d->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::LocalFontsPermission, ProfileAdapter::AskPermission); + break; } return; } @@ -1797,6 +1802,9 @@ void QWebEnginePage::setFeaturePermission(const QUrl &securityOrigin, QWebEngine d->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::ClipboardReadWrite, ProfileAdapter::AllowedPermission); break; + case LocalFontsAccess: + d->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::LocalFontsPermission, ProfileAdapter::AllowedPermission); + break; } } else { // if (policy == PermissionDeniedByUser) switch (feature) { @@ -1820,6 +1828,9 @@ void QWebEnginePage::setFeaturePermission(const QUrl &securityOrigin, QWebEngine d->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::ClipboardReadWrite, ProfileAdapter::DeniedPermission); break; + case LocalFontsAccess: + d->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::LocalFontsPermission, ProfileAdapter::DeniedPermission); + break; } } } diff --git a/src/core/api/qwebenginepage.h b/src/core/api/qwebenginepage.h index 2fc6e422d..621dacdc8 100644 --- a/src/core/api/qwebenginepage.h +++ b/src/core/api/qwebenginepage.h @@ -174,6 +174,7 @@ public: DesktopVideoCapture, DesktopAudioVideoCapture, ClipboardReadWrite, + LocalFontsAccess, }; Q_ENUM(Feature) diff --git a/src/core/doc/src/qwebenginepage_lgpl.qdoc b/src/core/doc/src/qwebenginepage_lgpl.qdoc index 458359628..c2515cd13 100644 --- a/src/core/doc/src/qwebenginepage_lgpl.qdoc +++ b/src/core/doc/src/qwebenginepage_lgpl.qdoc @@ -300,6 +300,8 @@ {JavascriptCanPaste} and \l{QWebEngineSettings::JavascriptCanAccessClipboard} {JavascriptCanAccessClipboard} settings are enabled, this permission will always be granted automatically and no feature requests will be made. + \value [since 6.8] LocalFontsAccess + Access to the fonts installed on the user's machine. Only available on desktop platforms. \sa featurePermissionRequested(), featurePermissionRequestCanceled(), setFeaturePermission(), PermissionPolicy diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp index ef235e718..b6e727ef8 100644 --- a/src/core/permission_manager_qt.cpp +++ b/src/core/permission_manager_qt.cpp @@ -32,6 +32,8 @@ static ProfileAdapter::PermissionType toQt(blink::PermissionType type) return ProfileAdapter::ClipboardReadWrite; case blink::PermissionType::NOTIFICATIONS: return ProfileAdapter::NotificationPermission; + case blink::PermissionType::LOCAL_FONTS: + return ProfileAdapter::LocalFontsPermission; case blink::PermissionType::ACCESSIBILITY_EVENTS: case blink::PermissionType::CAMERA_PAN_TILT_ZOOM: case blink::PermissionType::WINDOW_MANAGEMENT: @@ -52,7 +54,6 @@ static ProfileAdapter::PermissionType toQt(blink::PermissionType type) case blink::PermissionType::AR: case blink::PermissionType::VR: case blink::PermissionType::STORAGE_ACCESS_GRANT: - case blink::PermissionType::LOCAL_FONTS: case blink::PermissionType::DISPLAY_CAPTURE: case blink::PermissionType::TOP_LEVEL_STORAGE_ACCESS: case blink::PermissionType::NUM: @@ -68,6 +69,7 @@ static bool canRequestPermissionFor(ProfileAdapter::PermissionType type) case ProfileAdapter::GeolocationPermission: case ProfileAdapter::NotificationPermission: case ProfileAdapter::ClipboardReadWrite: + case ProfileAdapter::LocalFontsPermission: return true; default: break; diff --git a/src/core/profile_adapter.h b/src/core/profile_adapter.h index 018ca5a00..4be0ea51e 100644 --- a/src/core/profile_adapter.h +++ b/src/core/profile_adapter.h @@ -134,6 +134,7 @@ public: AudioCapturePermission = 3, VideoCapturePermission = 4, ClipboardReadWrite = 5, + LocalFontsPermission = 6, }; enum PermissionState { diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index a40b2a93d..d55240abe 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -239,6 +239,8 @@ private Q_SLOTS: void clipboardReadWritePermission_data(); void clipboardReadWritePermission(); void contentsSize(); + void localFontAccessPermission_data(); + void localFontAccessPermission(); void setLifecycleState(); void setVisible(); @@ -4063,6 +4065,67 @@ void tst_QWebEnginePage::contentsSize() QCOMPARE(m_page->contentsSize().height(), 1216); } +void tst_QWebEnginePage::localFontAccessPermission_data() +{ + QTest::addColumn<QWebEnginePage::PermissionPolicy>("policy"); + QTest::addColumn<bool>("ignore"); + QTest::addColumn<bool>("shouldBeEmpty"); + + QTest::newRow("ignore") << QWebEnginePage::PermissionDeniedByUser << true << true; + QTest::newRow("setDeny") << QWebEnginePage::PermissionDeniedByUser << false << true; + QTest::newRow("setGrant") << QWebEnginePage::PermissionGrantedByUser << false << false; +} + +void tst_QWebEnginePage::localFontAccessPermission() { + QFETCH(QWebEnginePage::PermissionPolicy, policy); + QFETCH(bool, ignore); + QFETCH(bool, shouldBeEmpty); + + QWebEngineView view; + QWebEnginePage page(&view); + view.setPage(&page); + + connect(&page, &QWebEnginePage::featurePermissionRequested, &page, [&] (const QUrl &o, QWebEnginePage::Feature f) { + if (f != QWebEnginePage::LocalFontsAccess) + return; + + if (!ignore) + page.setFeaturePermission(o, f, policy); + }); + + QSignalSpy spy(&page, &QWebEnginePage::loadFinished); + page.setHtml(QString("<html><body>Test</body></html>"), QUrl("qrc://secure/origin")); + QTRY_COMPARE(spy.size(), 1); + + // Font access is only enabled for visible WebContents. + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + if (evaluateJavaScriptSync(&page, QStringLiteral("!window.queryLocalFonts")).toBool()) + W_QSKIP("Local fonts access is not supported.", SkipSingle); + + // Access to the API requires recent user interaction + QTest::mouseMove(view.windowHandle(), QPoint(10, 10)); + QTest::mouseClick(view.windowHandle(), Qt::LeftButton); + + auto js = QStringLiteral("var done = false; var fonts; window.queryLocalFonts().then(f => { fonts = f; done = true; });"); + evaluateJavaScriptSync(&page, js); + + if (ignore) { + QTRY_COMPARE_NE_WITH_TIMEOUT(evaluateJavaScriptSync(&page, QStringLiteral("done")).toBool(), true, 1000); + } else { + QTRY_VERIFY_WITH_TIMEOUT(evaluateJavaScriptSync(&page, QStringLiteral("done")).toBool() == true, 1000); + QVERIFY((evaluateJavaScriptSync(&page, QStringLiteral("fonts.length")).toInt() == 0) == shouldBeEmpty); + } + + // Move mouse to make sure subsequent runs' transient activation will fire + QTest::mouseMove(view.windowHandle(), QPoint(1, 10)); + QTest::mouseClick(view.windowHandle(), Qt::LeftButton); + + // Reset permission, since otherwise it will be stored between runs + page.setFeaturePermission(QUrl("qrc://secure/origin"), QWebEnginePage::LocalFontsAccess, QWebEnginePage::PermissionUnknown); +} + void tst_QWebEnginePage::setLifecycleState() { qRegisterMetaType<QWebEnginePage::LifecycleState>("LifecycleState"); |