Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qohospermissionshelperimpl.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <QtCore/private/qohoslogger_p.h>
7#include <optional>
8#include <qohosapppermissions_p.h>
9#include <qohosenums.h>
10#include <qohosutils.h>
11#include <render/qwindowproxyregistry.h>
12
14
15namespace QtOhos {
16
17namespace {
18
19QWindow *getFocusedWindowOrNull()
20{
21 auto focusedWindows = QWindowProxyRegistry::instance().queryWindowsWithSystemWindowAndFocus();
22 return !focusedWindows.empty() ? focusedWindows.front() : nullptr;
23}
24
25std::optional<Qt::PermissionStatus> tryMapPermissionStatusFromOhos(
26 QtOhos::enums::ohos::abilityAccessCtrl::PermissionStatus ohosPermissionStatus)
27{
28 using OhosPermissionStatus = QtOhos::enums::ohos::abilityAccessCtrl::PermissionStatus;
29
30 switch (ohosPermissionStatus) {
31 case OhosPermissionStatus::GRANTED:
32 return Qt::PermissionStatus::Granted;
33 case OhosPermissionStatus::NOT_DETERMINED:
34 return Qt::PermissionStatus::Undetermined;
35 case OhosPermissionStatus::DENIED:
36 case OhosPermissionStatus::INVALID:
37 case OhosPermissionStatus::RESTRICTED:
38 return Qt::PermissionStatus::Denied;
39 }
40
41 return {};
42}
43
44std::optional<QtOhos::enums::ohos::abilityAccessCtrl::PermissionStatus> tryGetSelfPermissionStatus(
45 QtOhos::JsState &jsState, const std::string &permissionName)
46{
47 using OhosPermissionStatus = QtOhos::enums::ohos::abilityAccessCtrl::PermissionStatus;
48
49 std::optional<QNapi::Number> optJsPermissionStatusValue;
50 try {
51 optJsPermissionStatusValue = jsState.eval<QNapi::Number>(
52 "@ohos.abilityAccessCtrl.createAtManager().getSelfPermissionStatus(*)",
53 {permissionName});
54 } catch (const Napi::Error &error) {
55 qOhosPrintfError("%s: getSelfPermissionStatus() failed: %s", Q_FUNC_INFO, error.what());
56 }
57
58 return qAndThen(
59 optJsPermissionStatusValue,
60 [&](auto jsPermissionStatusValue) {
61 return jsState.tryMapOhosEnumFromJs<OhosPermissionStatus>(jsPermissionStatusValue);
62 });
63}
64
65class QOhosPermissionsHelperImpl : public QOhosPermissionsHelper
66{
67public:
68 QList<Qt::PermissionStatus> checkStatusesOfPermissions(const QStringList &permissionNames) const override;
69
70 void requestPermissionsFromUserIfNeeded(
71 const QStringList &permissionNames, QObject *resultConsumerContext,
72 QOhosConsumer<QList<QOhosPermissionsHelper::PermissionRequestResult>> resultConsumer) override;
73
74 void requestPermissionsOnSettingIfNeeded(
75 const QStringList &permissionNames, QObject *resultConsumerContext,
76 QOhosConsumer<QList<bool>> resultConsumer) override;
77};
78
79QList<Qt::PermissionStatus> QOhosPermissionsHelperImpl::checkStatusesOfPermissions(
80 const QStringList &permissionNames) const
81{
82 if (permissionNames.isEmpty())
83 return {};
84
85 return QtOhos::evalInJsThread(
86 [&](QtOhos::JsState &jsState) {
87 QList<Qt::PermissionStatus> statuses;
88 for (const auto &permissionName : permissionNames) {
89 auto optPermissionStatus = qAndThen(
90 tryGetSelfPermissionStatus(jsState, permissionName.toStdString()),
91 &tryMapPermissionStatusFromOhos);
92 statuses.append(optPermissionStatus.value_or(Qt::PermissionStatus::Denied));
93 }
94 return statuses;
95 });
96}
97
98void QOhosPermissionsHelperImpl::requestPermissionsFromUserIfNeeded(
99 const QStringList &qPermissionNames, QObject *resultConsumerContext,
100 QOhosConsumer<QList<QOhosPermissionsHelper::PermissionRequestResult>> resultConsumer)
101{
102 std::vector<std::string> permissionNames(qPermissionNames.size());
103 std::transform(
104 qPermissionNames.constBegin(), qPermissionNames.constEnd(),
105 permissionNames.begin(), [](const QString &str) { return str.toStdString(); });
106
107 struct Context {
108 QtOhos::QObjectThreadSafeRef resultConsumerQtContextRef;
109 QOhosConsumer<QList<PermissionRequestResult>> resultConsumer;
110 };
111
112 QOhosConsumer<QList<QOhosPermissionsHelper::PermissionRequestResult>> qResultConsumer =
113 [resultConsumer = std::move(resultConsumer)](const auto &inputResult) {
114 QList<QOhosPermissionsHelper::PermissionRequestResult> result;
115 for (const auto &inputEntry : inputResult) {
116 result.append(
117 QOhosPermissionsHelper::PermissionRequestResult{
118 .permissionGranted = inputEntry.permissionGranted,
119 .dialogShown = inputEntry.dialogShown,
120 });
121 resultConsumer(std::move(result));
122 }
123 };
124
125 auto context = QtOhos::moveToSharedPtr(
126 Context{
127 .resultConsumerQtContextRef = QtOhos::QObjectThreadSafeRef(resultConsumerContext),
128 .resultConsumer = std::move(qResultConsumer),
129 });
130
131 QObject *optInstanceMainWindow = getFocusedWindowOrNull();
132 auto optInstanceMainWindowRef =
133 optInstanceMainWindow != nullptr
134 ? std::optional(QtOhos::QObjectThreadSafeRef(optInstanceMainWindow))
135 : std::nullopt;
136
138 [context, permissionNames, optInstanceMainWindowRef](QtOhos::JsState &jsState) {
139 auto optAbilityPeer = QtOhos::tryMapOptMainWindowToAbilityPeer(jsState, optInstanceMainWindowRef);
140 if (!optAbilityPeer) {
141 context->resultConsumerQtContextRef.visitInQtThreadIfAlive(
142 [context, permissionNames](auto &) {
143 const size_t totalPermissions = permissionNames.size();
144 QList<PermissionRequestResult> appPermissionResults(
145 totalPermissions,
146 PermissionRequestResult {
147 .permissionGranted = false,
148 .dialogShown = false,
149 });
150 context->resultConsumer(appPermissionResults);
151 });
152 return;
153 }
155 jsState, optAbilityPeer, permissionNames,
156 [context](QtOhos::JsState &, std::vector<QOhosPermissionsHelper::PermissionRequestResult> result) {
157 context->resultConsumerQtContextRef.visitInQtThreadIfAlive(
158 [context, appPermissionResults = result](auto &) {
159 QList<PermissionRequestResult> appPermResults;
160 for (const auto &appPermResult: appPermissionResults)
161 appPermResults.push_back(
162 PermissionRequestResult {
163 .permissionGranted = appPermResult.permissionGranted,
164 .dialogShown = appPermResult.dialogShown,
165 });
166 context->resultConsumer(appPermResults);
167 });
168 });
169 });
170}
171
172void QOhosPermissionsHelperImpl::requestPermissionsOnSettingIfNeeded(
173 const QStringList &qPermissionNames, QObject *resultConsumerContext,
174 QOhosConsumer<QList<bool>> resultConsumer)
175{
176 std::vector<std::string> permissionNames(qPermissionNames.size());
177 std::transform(
178 qPermissionNames.constBegin(), qPermissionNames.constEnd(),
179 permissionNames.begin(), [](const QString &str) { return str.toStdString(); });
180
181 struct Context {
182 QtOhos::QObjectThreadSafeRef resultConsumerQtContextRef;
183 QOhosConsumer<QList<bool>> resultConsumer;
184 };
185
186 auto context = QtOhos::moveToSharedPtr(
187 Context{
188 .resultConsumerQtContextRef = QtOhos::QObjectThreadSafeRef(resultConsumerContext),
189 .resultConsumer = std::move(resultConsumer),
190 });
191
192 QObject *optInstanceMainWindow = getFocusedWindowOrNull();
193 auto optInstanceMainWindowRef =
194 optInstanceMainWindow != nullptr
195 ? std::optional(QtOhos::QObjectThreadSafeRef(optInstanceMainWindow))
196 : std::nullopt;
197
199 [context, permissionNames, optInstanceMainWindowRef](auto &jsState) {
200 auto optAbilityPeer = QtOhos::tryMapOptMainWindowToAbilityPeer(jsState, optInstanceMainWindowRef);
201 if (!optAbilityPeer) {
202 context->resultConsumerQtContextRef.visitInQtThreadIfAlive(
203 [context, permissionNames](auto &) {
204 QList<bool> settingPermissionResults(permissionNames.size(), false);
205 context->resultConsumer(settingPermissionResults);
206 });
207 return;
208 }
210 jsState, optAbilityPeer ? optAbilityPeer : jsState.defaultQAbilityPeer(),
211 permissionNames,
212 [context](QtOhos::JsState &, std::vector<bool> permissionsGranted) {
213 context->resultConsumerQtContextRef.visitInQtThreadIfAlive(
214 [context, permissionsGranted](auto &) {
215 QList<bool> qPermissionsGranted(
216 permissionsGranted.begin(), permissionsGranted.end());
217 context->resultConsumer(qPermissionsGranted);
218 });
219 });
220 });
221 }
222}
223
225{
226 static QOhosPermissionsHelperImpl permissionsHelperImpl;
227 return &permissionsHelperImpl;
228}
229
230}
231
232QT_END_NAMESPACE
static QWindowProxyRegistry & instance()
void requestAppPermissionsOnSetting(QtOhos::JsState &jsState, std::shared_ptr< QtOhos::QAbilityPeer > abilityPeer, const std::vector< std::string > &permissionNames, QOhosConsumer< QtOhos::JsState &, std::vector< bool > > resultConsumer)
void requestAppPermissionsFromUserWithResult(QtOhos::JsState &jsState, std::shared_ptr< QtOhos::QAbilityPeer > abilityPeer, const std::vector< std::string > &permissionNames, QOhosConsumer< QtOhos::JsState &, std::vector< AppPermissionResult > > resultConsumer)
Combined button and popup list for selecting options.
void invokeInJsThread(std::function< void(JsState &)> task)
QOhosPermissionsHelper * getQOhosPermissionsHelperImpl()