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#include <utility>
13
15
16namespace QtOhos {
17
18namespace {
19
20QWindow *getFocusedWindowOrNull()
21{
22 auto focusedWindows = QWindowProxyRegistry::instance().queryWindowsWithSystemWindowAndFocus();
23 return !focusedWindows.empty() ? focusedWindows.front() : nullptr;
24}
25
26std::optional<Qt::PermissionStatus> tryMapPermissionStatusFromOhos(
27 QtOhos::enums::ohos::abilityAccessCtrl::PermissionStatus ohosPermissionStatus)
28{
29 using OhosPermissionStatus = QtOhos::enums::ohos::abilityAccessCtrl::PermissionStatus;
30
31 switch (ohosPermissionStatus) {
32 case OhosPermissionStatus::GRANTED:
33 return Qt::PermissionStatus::Granted;
34 case OhosPermissionStatus::NOT_DETERMINED:
35 return Qt::PermissionStatus::Undetermined;
36 case OhosPermissionStatus::DENIED:
37 case OhosPermissionStatus::INVALID:
38 case OhosPermissionStatus::RESTRICTED:
39 return Qt::PermissionStatus::Denied;
40 }
41
42 return {};
43}
44
45std::optional<QtOhos::enums::ohos::abilityAccessCtrl::PermissionStatus> tryGetSelfPermissionStatus(
46 QtOhos::JsState &jsState, const std::string &permissionName)
47{
48 using OhosPermissionStatus = QtOhos::enums::ohos::abilityAccessCtrl::PermissionStatus;
49
50 std::optional<QNapi::Number> optJsPermissionStatusValue;
51 try {
52 optJsPermissionStatusValue = jsState.eval<QNapi::Number>(
53 "@ohos.abilityAccessCtrl.createAtManager().getSelfPermissionStatus(*)",
54 {permissionName});
55 } catch (const Napi::Error &error) {
56 qOhosPrintfError("%s: getSelfPermissionStatus() failed: %s", Q_FUNC_INFO, error.what());
57 }
58
59 return qAndThen(
60 optJsPermissionStatusValue,
61 [&](auto jsPermissionStatusValue) {
62 return jsState.tryMapOhosEnumFromJs<OhosPermissionStatus>(jsPermissionStatusValue);
63 });
64}
65
66class QOhosPermissionsHelperImpl : public QOhosPermissionsHelper
67{
68public:
69 QList<Qt::PermissionStatus> checkStatusesOfPermissions(const QStringList &permissionNames) const override;
70
71 void requestPermissionsFromUserIfNeeded(
72 const QStringList &permissionNames, QObject *resultConsumerContext,
73 QOhosConsumer<QList<QOhosPermissionsHelper::PermissionRequestResult>> resultConsumer) override;
74
75 void requestPermissionsOnSettingIfNeeded(
76 const QStringList &permissionNames, QObject *resultConsumerContext,
77 QOhosConsumer<QList<bool>> resultConsumer) override;
78};
79
80QList<Qt::PermissionStatus> QOhosPermissionsHelperImpl::checkStatusesOfPermissions(
81 const QStringList &permissionNames) const
82{
83 if (permissionNames.isEmpty())
84 return {};
85
86 return QtOhos::evalInJsThread(
87 [&](QtOhos::JsState &jsState) {
88 QList<Qt::PermissionStatus> statuses;
89 for (const auto &permissionName : permissionNames) {
90 auto optPermissionStatus = qAndThen(
91 tryGetSelfPermissionStatus(jsState, permissionName.toStdString()),
92 &tryMapPermissionStatusFromOhos);
93 statuses.append(optPermissionStatus.value_or(Qt::PermissionStatus::Denied));
94 }
95 return statuses;
96 });
97}
98
99void QOhosPermissionsHelperImpl::requestPermissionsFromUserIfNeeded(
100 const QStringList &qPermissionNames, QObject *resultConsumerContext,
101 QOhosConsumer<QList<QOhosPermissionsHelper::PermissionRequestResult>> resultConsumer)
102{
103 std::vector<std::string> permissionNames(qPermissionNames.size());
104 std::transform(
105 qPermissionNames.constBegin(), qPermissionNames.constEnd(),
106 permissionNames.begin(), [](const QString &str) { return str.toStdString(); });
107
108 struct Context {
109 QtOhos::QObjectThreadSafeRef resultConsumerQtContextRef;
110 QOhosConsumer<QList<PermissionRequestResult>> resultConsumer;
111 };
112
113 QOhosConsumer<QList<QOhosPermissionsHelper::PermissionRequestResult>> qResultConsumer =
114 [resultConsumer = std::move(resultConsumer)](const auto &inputResult) {
115 QList<QOhosPermissionsHelper::PermissionRequestResult> result;
116 for (const auto &inputEntry : inputResult) {
117 result.append(
118 QOhosPermissionsHelper::PermissionRequestResult{
119 .permissionGranted = inputEntry.permissionGranted,
120 .dialogShown = inputEntry.dialogShown,
121 });
122 resultConsumer(std::move(result));
123 }
124 };
125
126 auto context = QtOhos::moveToSharedPtr(
127 Context{
128 .resultConsumerQtContextRef = QtOhos::QObjectThreadSafeRef(resultConsumerContext),
129 .resultConsumer = std::move(qResultConsumer),
130 });
131
132 QObject *optInstanceMainWindow = getFocusedWindowOrNull();
133 auto optInstanceMainWindowRef =
134 optInstanceMainWindow != nullptr
135 ? makeQOhosOptional(QtOhos::QObjectThreadSafeRef(optInstanceMainWindow))
137
139 [context, permissionNames, optInstanceMainWindowRef](QtOhos::JsState &jsState) {
140 auto optAbilityPeer = QtOhos::tryMapOptMainWindowToAbilityPeer(jsState, optInstanceMainWindowRef);
141 if (!optAbilityPeer) {
142 context->resultConsumerQtContextRef.visitInQtThreadIfAlive(
143 [context, permissionNames](auto &) {
144 const size_t totalPermissions = permissionNames.size();
145 QList<PermissionRequestResult> appPermissionResults(
146 totalPermissions,
147 PermissionRequestResult {
148 .permissionGranted = false,
149 .dialogShown = false,
150 });
151 context->resultConsumer(appPermissionResults);
152 });
153 return;
154 }
156 jsState, optAbilityPeer, permissionNames,
157 [context](QtOhos::JsState &, std::vector<QOhosPermissionsHelper::PermissionRequestResult> result) {
158 context->resultConsumerQtContextRef.visitInQtThreadIfAlive(
159 [context, appPermissionResults = result](auto &) {
160 QList<PermissionRequestResult> appPermResults;
161 for (const auto &appPermResult: appPermissionResults)
162 appPermResults.push_back(
163 PermissionRequestResult {
164 .permissionGranted = appPermResult.permissionGranted,
165 .dialogShown = appPermResult.dialogShown,
166 });
167 context->resultConsumer(appPermResults);
168 });
169 });
170 });
171}
172
173void QOhosPermissionsHelperImpl::requestPermissionsOnSettingIfNeeded(
174 const QStringList &qPermissionNames, QObject *resultConsumerContext,
175 QOhosConsumer<QList<bool>> resultConsumer)
176{
177 std::vector<std::string> permissionNames(qPermissionNames.size());
178 std::transform(
179 qPermissionNames.constBegin(), qPermissionNames.constEnd(),
180 permissionNames.begin(), [](const QString &str) { return str.toStdString(); });
181
182 struct Context {
183 QtOhos::QObjectThreadSafeRef resultConsumerQtContextRef;
184 QOhosConsumer<QList<bool>> resultConsumer;
185 };
186
187 auto context = QtOhos::moveToSharedPtr(
188 Context{
189 .resultConsumerQtContextRef = QtOhos::QObjectThreadSafeRef(resultConsumerContext),
190 .resultConsumer = std::move(resultConsumer),
191 });
192
193 QObject *optInstanceMainWindow = getFocusedWindowOrNull();
194 auto optInstanceMainWindowRef =
195 optInstanceMainWindow != nullptr
196 ? makeQOhosOptional(QtOhos::QObjectThreadSafeRef(optInstanceMainWindow))
198
200 [context, permissionNames, optInstanceMainWindowRef](auto &jsState) {
201 auto optAbilityPeer = QtOhos::tryMapOptMainWindowToAbilityPeer(jsState, optInstanceMainWindowRef);
202 if (!optAbilityPeer) {
203 context->resultConsumerQtContextRef.visitInQtThreadIfAlive(
204 [context, permissionNames](auto &) {
205 QList<bool> settingPermissionResults(permissionNames.size(), false);
206 context->resultConsumer(settingPermissionResults);
207 });
208 return;
209 }
211 jsState, optAbilityPeer ? optAbilityPeer : jsState.defaultQAbilityPeer(),
212 permissionNames,
213 [context](QtOhos::JsState &, std::vector<bool> permissionsGranted) {
214 context->resultConsumerQtContextRef.visitInQtThreadIfAlive(
215 [context, permissionsGranted](auto &) {
216 QList<bool> qPermissionsGranted(
217 permissionsGranted.begin(), permissionsGranted.end());
218 context->resultConsumer(qPermissionsGranted);
219 });
220 });
221 });
222 }
223}
224
226{
227 static QOhosPermissionsHelperImpl permissionsHelperImpl;
228 return &permissionsHelperImpl;
229}
230
231}
232
233QT_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()
std::nullopt_t makeEmptyQOhosOptional()