42constexpr const char *qtOnContinueMigrationDataPropertyName =
"__io_qt_on_continue_migration_data";
44QOhosSupplier<QByteArray> makeUniqueIdsGenerator()
46 return [sequenceNumber =
std::uint64_t(0)]()
mutable {
47 QByteArray idBytes(32, Qt::Uninitialized);
48 std::memcpy(idBytes.data(), &sequenceNumber,
sizeof(sequenceNumber));
49 QRandomGenerator::global()->generate(idBytes.begin() +
sizeof(sequenceNumber), idBytes.end());
55class QOhosOpenLinkOptionsImpl :
public OpenLinkOptions
58 QOhosOpenLinkOptionsImpl();
60 void setAppLinkingOnly(
bool appLinkingOnly) override;
62 std::optional<
bool> appLinkingOnly()
const;
65 std::optional<
bool> m_appLinkingOnly;
68QOhosOpenLinkOptionsImpl::QOhosOpenLinkOptionsImpl() =
default;
70void QOhosOpenLinkOptionsImpl::setAppLinkingOnly(
bool appLinkingOnly)
72 m_appLinkingOnly = appLinkingOnly;
75std::optional<
bool> QOhosOpenLinkOptionsImpl::appLinkingOnly()
const
77 return m_appLinkingOnly;
80using OnContinueResult = QtOhos::enums::ohos::app::ability::AbilityConstant::OnContinueResult;
82enum class AbilityOnContinueResponseStatus
89struct AbilityOnContinueRequest
91 int sourceApplicationVersionCode;
94struct AbilityOnContinueResponse
96 AbilityOnContinueResponseStatus status;
97 QMap<QString, QString> wantObjectParams;
98 std::optional<
bool> exitAppOnSourceDeviceAfterMigration;
101std::optional<OnContinueResult> tryMapAbilityOnContinueResponseStatusToOhos(
102 AbilityOnContinueResponseStatus status)
105 case AbilityOnContinueResponseStatus::Agree:
106 return OnContinueResult::AGREE;
107 case AbilityOnContinueResponseStatus::Reject:
108 return OnContinueResult::REJECT;
109 case AbilityOnContinueResponseStatus::Mismatch:
110 return OnContinueResult::MISMATCH;
115void setOnContinueRequestsHandlerForAbilityInstanceWindow(
116 QObject *windowObject,
117 std::function<
void(AbilityOnContinueRequest, QOhosConsumer<AbilityOnContinueResponse>)> requestsHandler)
119 auto *qWindow = qobject_cast<QWindow *>(windowObject);
120 if (qWindow ==
nullptr)
121 qOhosReportFatalErrorAndAbort(
"%s: windowObject argument is null or not a QWindow", Q_FUNC_INFO);
123 auto qWindowRef = QtOhos::QObjectThreadSafeRef(qWindow);
124 auto sharedRequestsHandler = QtOhos::moveToSharedPtr(std::move(requestsHandler));
126 struct JsResultContext
128 QNapi::Reference<QNapi::Object> wantParamsReference;
129 QOhosConsumer<QOhosJsState &, QNapi::Number> resultConsumer;
132 QOhosJsThreadGateway::runAndWait(
133 [&](QOhosJsState &jsState) {
134 auto optQAbility = jsState.tryGetQAbilityByQWindow(qWindowRef);
137 "%s: no ability for window %s, handler not set",
138 Q_FUNC_INFO, qWindowRef.refName().c_str());
142 jsState.setOnContinueRequestsHandler(
144 [sharedRequestsHandler](QOhosJsState &, QNapi::Object wantParamsObj,
auto resultConsumer) {
145 int sourceVersionCode = wantParamsObj.get<QNapi::Number>(
"version");
146 auto jsResultContext = QtOhos::makeProxyWithJsThreadDeleter(std::make_shared<JsResultContext>());
147 jsResultContext->wantParamsReference = QNapi::Reference<>::makePersistentFrom(wantParamsObj);
148 jsResultContext->resultConsumer = std::move(resultConsumer);
149 QtOhos::invokeInQtThread(
150 [sharedRequestsHandler, sourceVersionCode, jsResultContext]() {
151 (*sharedRequestsHandler)(
152 AbilityOnContinueRequest{
153 .sourceApplicationVersionCode = sourceVersionCode,
155 [jsResultContext](AbilityOnContinueResponse qtResponse) {
156 QOhosJsThreadGateway::invoke(
157 [jsResultContext, qtResponse](QOhosJsState &jsState) {
158 if (qtResponse.status == AbilityOnContinueResponseStatus::Agree) {
159 auto wantParamsObj = jsResultContext->wantParamsReference.Value();
160 auto newWantParamsIter = qtResponse.wantObjectParams.constKeyValueBegin();
161 while (newWantParamsIter != qtResponse.wantObjectParams.constKeyValueEnd()) {
163 newWantParamsIter->first.toStdString(),
164 newWantParamsIter->second.toStdString());
167 if (qtResponse.exitAppOnSourceDeviceAfterMigration.has_value()) {
169 jsState.eval<QNapi::String>(
170 "@ohos.app.ability.wantConstant.Params.SUPPORT_CONTINUE_SOURCE_EXIT_KEY"),
171 qtResponse.exitAppOnSourceDeviceAfterMigration.value());
174 auto optResultEnum = tryMapAbilityOnContinueResponseStatusToOhos(qtResponse.status);
175 if (!optResultEnum) {
177 "%s: got illegal status (%d) from requests handler, rejecting the request",
178 Q_FUNC_INFO,
static_cast<
int>(qtResponse.status));
180 jsResultContext->resultConsumer(
181 jsState, jsState.mapOhosEnumToJs(optResultEnum.value_or(OnContinueResult::REJECT)));
190void setDestroyAllowedFlagForAbilityInstances(
191 std::vector<QObject *> instancesMainWindows,
bool destroyEnabled)
193 std::vector<QtOhos::QObjectThreadSafeRef> instancesMainWindowsRefs;
194 for (
auto *instanceMainWindow : instancesMainWindows)
195 instancesMainWindowsRefs.emplace_back(instanceMainWindow);
197 QOhosJsThreadGateway::runAndWait(
198 [&](QOhosJsState &jsState) {
199 for (
const auto &instanceMainWindowRef : instancesMainWindowsRefs) {
200 auto optQAbility = jsState.tryGetQAbilityByQWindow(instanceMainWindowRef);
202 jsState.setDestroyFromSystemAllowed(optQAbility.value(), destroyEnabled);
208class QOhosOnContinueContextImpl :
public OnContinueContext
211 QOhosOnContinueContextImpl(
int sourceApplicationVersionCode);
213 void sendAgreeResponse(
const QByteArray &responseData)
override;
214 void sendRejectResponse() override;
215 void sendMismatchResponse() override;
217 void setExitAppOnSourceDeviceAfterMigration(
bool exitAfterMigration) override;
219 int sourceApplicationVersionCode()
const override;
221 AbilityOnContinueResponse response()
const;
224 int m_sourceApplicationVersionCode;
225 AbilityOnContinueResponse m_baseResponse;
226 std::optional<
bool> m_exitAppOnSourceDeviceAfterMigration;
229QOhosOnContinueContextImpl::QOhosOnContinueContextImpl(
int sourceApplicationVersionCode)
230 : OnContinueContext()
231 , m_sourceApplicationVersionCode(sourceApplicationVersionCode)
233 sendRejectResponse();
237
238
239
240
241
242
243
244void QOhosOnContinueContextImpl::sendAgreeResponse(
const QByteArray &responseData)
246 m_baseResponse = AbilityOnContinueResponse{
247 .status = AbilityOnContinueResponseStatus::Agree,
248 .wantObjectParams = {
250 QString::fromUtf8(qtOnContinueMigrationDataPropertyName),
251 QString::fromUtf8(responseData.toBase64())
254 .exitAppOnSourceDeviceAfterMigration = {},
259
260
261
262
263
264
265
266
267
268void QOhosOnContinueContextImpl::sendRejectResponse()
270 m_baseResponse = AbilityOnContinueResponse{
271 .status = AbilityOnContinueResponseStatus::Reject,
272 .wantObjectParams = {},
273 .exitAppOnSourceDeviceAfterMigration = {},
278
279
280
281
282
283
284
285
286
287
288void QOhosOnContinueContextImpl::sendMismatchResponse()
290 m_baseResponse = AbilityOnContinueResponse{
291 .status = AbilityOnContinueResponseStatus::Mismatch,
292 .wantObjectParams = {},
293 .exitAppOnSourceDeviceAfterMigration = {},
298
299
300
301
302
303
304
305void QOhosOnContinueContextImpl::setExitAppOnSourceDeviceAfterMigration(
bool exitAfterMigration)
307 m_exitAppOnSourceDeviceAfterMigration = exitAfterMigration;
310AbilityOnContinueResponse QOhosOnContinueContextImpl::response()
const
312 auto response = m_baseResponse;
313 response.exitAppOnSourceDeviceAfterMigration = m_exitAppOnSourceDeviceAfterMigration;
318
319
320
321
322
323
324int QOhosOnContinueContextImpl::sourceApplicationVersionCode()
const
326 return m_sourceApplicationVersionCode;
329std::optional<QtOhos::enums::ohos::app::ability::AbilityConstant::WindowMode> tryMapWindowModeToOhosOrLogWarning(
330 QOhosStartOptionsData::WindowMode windowMode)
332 namespace AbilityConstant = QtOhos::enums::ohos::app::ability::AbilityConstant;
333 using OptionsData = QOhosStartOptionsData;
335 switch (windowMode) {
336 case OptionsData::WindowMode::WINDOW_MODE_SPLIT_PRIMARY:
337 return std::make_optional(AbilityConstant::WindowMode::WINDOW_MODE_SPLIT_PRIMARY);
338 case OptionsData::WindowMode::WINDOW_MODE_SPLIT_SECONDARY:
339 return std::make_optional(AbilityConstant::WindowMode::WINDOW_MODE_SPLIT_SECONDARY);
340 case OptionsData::WindowMode::WINDOW_MODE_FULLSCREEN:
341 return std::make_optional(AbilityConstant::WindowMode::WINDOW_MODE_FULLSCREEN);
344 qCWarning(QtForOhos,
"%s: got illegal WindowMode: %d", Q_FUNC_INFO,
static_cast<
int>(windowMode));
349std::optional<QtOhos::enums::ohos::app::ability::contextConstant::ProcessMode> tryMapProcessModeToOhosOrLogWarning(
350 QOhosStartOptionsData::ProcessMode processMode)
352 namespace contextConstant = QtOhos::enums::ohos::app::ability::contextConstant;
353 using OptionsData = QOhosStartOptionsData;
355 switch (processMode) {
356 case OptionsData::ProcessMode::NEW_PROCESS_ATTACH_TO_PARENT:
357 return std::make_optional(contextConstant::ProcessMode::NEW_PROCESS_ATTACH_TO_PARENT);
358 case OptionsData::ProcessMode::NEW_PROCESS_ATTACH_TO_STATUS_BAR_ITEM:
359 return std::make_optional(contextConstant::ProcessMode::NEW_PROCESS_ATTACH_TO_STATUS_BAR_ITEM);
362 qCWarning(QtForOhos,
"%s: got illegal ProcessMode: %d", Q_FUNC_INFO,
static_cast<
int>(processMode));
367std::optional<QtOhos::enums::ohos::app::ability::contextConstant::StartupVisibility> tryMapStartupVisibilityToOhosOrLogWarning(
368 QOhosStartOptionsData::StartupVisibility startupVisibility)
370 namespace contextConstant = QtOhos::enums::ohos::app::ability::contextConstant;
371 using OptionsData = QOhosStartOptionsData;
373 switch (startupVisibility) {
374 case OptionsData::StartupVisibility::STARTUP_HIDE:
375 return std::make_optional(contextConstant::StartupVisibility::STARTUP_HIDE);
376 case OptionsData::StartupVisibility::STARTUP_SHOW:
377 return std::make_optional(contextConstant::StartupVisibility::STARTUP_SHOW);
380 qCWarning(QtForOhos,
"%s: got illegal StartupVisibility: %d", Q_FUNC_INFO,
static_cast<
int>(startupVisibility));
385std::optional<QtOhos::enums::ohos::bundle::bundleManager::SupportWindowMode> tryMapSupportWindowModeToOhosOrLogWarning(
386 QOhosStartOptionsData::SupportWindowMode supportWindowMode)
388 namespace bundleManager = QtOhos::enums::ohos::bundle::bundleManager;
389 using OptionsData = QOhosStartOptionsData;
391 switch (supportWindowMode) {
392 case OptionsData::SupportWindowMode::FULL_SCREEN:
393 return std::make_optional(bundleManager::SupportWindowMode::FULL_SCREEN);
394 case OptionsData::SupportWindowMode::SPLIT:
395 return std::make_optional(bundleManager::SupportWindowMode::SPLIT);
396 case OptionsData::SupportWindowMode::FLOATING:
397 return std::make_optional(bundleManager::SupportWindowMode::FLOATING);
400 qCWarning(QtForOhos,
"%s: got illegal SupportWindowMode: %d", Q_FUNC_INFO,
static_cast<
int>(supportWindowMode));
405QNapi::Array mapSupportWindowModesToJsEnumsArray(
406 QOhosJsState &jsState,
const QList<QOhosStartOptionsData::SupportWindowMode> &supportWindowModes)
408 std::vector<QNapi::ValueWrapper> jsSupportWindowModes;
409 for (
auto supportWindowMode : supportWindowModes) {
410 auto optOhosSupportWindowMode = tryMapSupportWindowModeToOhosOrLogWarning(supportWindowMode);
411 if (optOhosSupportWindowMode.has_value())
412 jsSupportWindowModes.push_back(jsState.mapOhosEnumToJs(optOhosSupportWindowMode.value()));
415 return QNapi::makeArray(jsState.env(), jsSupportWindowModes);
418QNapi::Object makeJsCompletionHandler(
419 QOhosJsState &jsState, std::shared_ptr<QOhosConsumer<
bool, QJsonObject, QString>> qtThreadCompletionHandler)
421 auto makeCompletionCallback = [qtThreadCompletionHandler](
bool requestSuccess) {
422 return [qtThreadCompletionHandler, requestSuccess](
const QNapi::CallbackInfo &cbInfo) {
423 QNapi::Object elementNameObj;
424 QNapi::String messageValue;
425 cbInfo.getLeadingArgs(Q_FUNC_INFO, elementNameObj, messageValue);
427 const QJsonObject elementName = QOhosJsEnv::fromNapiValue<QJsonObject>(elementNameObj);
428 const QString message = QString::fromStdString(messageValue);
430 QtOhos::invokeInQtThread(
431 [qtThreadCompletionHandler, requestSuccess, elementName, message]() {
432 (*qtThreadCompletionHandler)(requestSuccess, elementName, message);
437 return QNapi::makeObject(
440 {
"onRequestSuccess", makeCompletionCallback(
true)},
441 {
"onRequestFailure", makeCompletionCallback(
false)},
445QNapi::Object convertStartOptionsToNapiObject(
446 QOhosJsState &jsState,
const QOhosStartOptionsData &opts)
448 auto *env = jsState.env();
449 auto napiOptions = QNapi::Object::New(env);
451 auto optOhosWindowMode = opts.windowMode.has_value()
452 ? tryMapWindowModeToOhosOrLogWarning(opts.windowMode.value())
454 if (optOhosWindowMode.has_value())
455 napiOptions.set(
"windowMode", jsState.mapOhosEnumToJs(optOhosWindowMode.value()));
456 if (opts.displayId.has_value())
457 napiOptions.set(
"displayId", opts.displayId.value());
458 if (opts.withAnimation.has_value())
459 napiOptions.set(
"withAnimation", opts.withAnimation.value());
460 if (opts.windowLeft.has_value())
461 napiOptions.set(
"windowLeft", opts.windowLeft.value());
462 if (opts.windowTop.has_value())
463 napiOptions.set(
"windowTop", opts.windowTop.value());
464 if (opts.windowWidth.has_value())
465 napiOptions.set(
"windowWidth", opts.windowWidth.value());
466 if (opts.windowHeight.has_value())
467 napiOptions.set(
"windowHeight", opts.windowHeight.value());
468 auto optOhosProcessMode = opts.processMode.has_value()
469 ? tryMapProcessModeToOhosOrLogWarning(opts.processMode.value())
471 if (optOhosProcessMode.has_value())
472 napiOptions.set(
"processMode", jsState.mapOhosEnumToJs(optOhosProcessMode.value()));
473 auto optOhosStartupVisibility = opts.startupVisibility.has_value()
474 ? tryMapStartupVisibilityToOhosOrLogWarning(opts.startupVisibility.value())
476 if (optOhosStartupVisibility.has_value())
477 napiOptions.set(
"startupVisibility", jsState.mapOhosEnumToJs(optOhosStartupVisibility.value()));
478 if (opts.windowIcon.has_value()) {
479 auto windowIcon = opts.windowIcon.value().value<QImage>();
480 if (!windowIcon.isNull())
481 napiOptions.set(
"startWindowIcon", makeOhosNapiPixelMapFromQImage(jsState, windowIcon));
483 if (opts.windowBackgroundColorHex.has_value())
484 napiOptions.set(
"startWindowBackgroundColor", opts.windowBackgroundColorHex.value().toStdString());
485 if (opts.supportWindowModes.has_value()) {
486 auto jsSupportWindowModes = mapSupportWindowModesToJsEnumsArray(jsState, opts.supportWindowModes.value());
487 if (jsSupportWindowModes.Length() != 0)
488 napiOptions.set(
"supportWindowModes", jsSupportWindowModes);
490 qCWarning(QtForOhos,
"%s: OHOS doesn't support empty supportWindowModes, skipping", Q_FUNC_INFO);
492 if (opts.minWindowWidth.has_value())
493 napiOptions.set(
"minWindowWidth", opts.minWindowWidth.value());
494 if (opts.minWindowHeight.has_value())
495 napiOptions.set(
"minWindowHeight", opts.minWindowHeight.value());
496 if (opts.maxWindowWidth.has_value())
497 napiOptions.set(
"maxWindowWidth", opts.maxWindowWidth.value());
498 if (opts.maxWindowHeight.has_value())
499 napiOptions.set(
"maxWindowHeight", opts.maxWindowHeight.value());
500 if (opts.optCompletionHandler)
501 napiOptions.set(
"completionHandler", makeJsCompletionHandler(jsState, opts.optCompletionHandler));
502 if (opts.hideStartWindow.has_value())
503 napiOptions.set(
"hideStartWindow", opts.hideStartWindow.value());
504 if (opts.windowCreateParams.has_value()) {
505 const auto &windowCreateParams = opts.windowCreateParams.value();
506 std::vector<std::pair<std::string, QNapi::ValueWrapper>> windowCreateParamsProps;
507 if (windowCreateParams.setWindowFadeInOutAnimation) {
508 windowCreateParamsProps.emplace_back(
515 jsState.mapOhosEnumToJs(
516 QtOhos::enums::ohos::window::AnimationType::FADE_IN_OUT),
520 napiOptions.set(
"windowCreateParams", QNapi::makeObject(env, windowCreateParamsProps));
526void requestStartAbilityForResult(
527 const Want &want, std::optional<QOhosStartOptionsData> options,
528 QWindow *optInstanceMainWindow, QObject *callerContext,
534 QtOhos::QObjectThreadSafeRef resultConsumerQtContextRef;
537 auto context = QtOhos::moveToSharedPtr(
539 .resultCallback = std::move(resultCallback),
540 .resultConsumerQtContextRef = QtOhos::QObjectThreadSafeRef(callerContext),
543 auto resultConsumer = [context](std::optional<QOhosAbilityResult> optAbilityResult) {
544 if (optAbilityResult.has_value()) {
545 auto abilityResult = optAbilityResult.value();
546 auto want = abilityResult.want.has_value()
547 ?
std::optional(convertWantFromJsonObject(abilityResult.want.value()))
551 context->resultCallback(
std::nullopt);
555 auto wantJson = convertWantToJsonObject(want);
556 auto optInstanceMainWindowRef =
557 optInstanceMainWindow !=
nullptr
558 ?
std::make_optional(QtOhos::QObjectThreadSafeRef(optInstanceMainWindow))
561 QOhosJsThreadGateway::invoke(
562 [context, resultConsumer, wantJson, options, optInstanceMainWindowRef](QOhosJsState &jsState) {
563 auto optUiAbility = optInstanceMainWindowRef.has_value()
564 ? jsState.tryGetQAbilityByQWindow(optInstanceMainWindowRef.value())
565 : jsState.defaultQAbility();
566 if (!optUiAbility.has_value()) {
567 context->resultConsumerQtContextRef.visitInQtThreadIfAlive(
568 [resultConsumer](
auto &) {
574 auto arguments = std::vector<QNapi::ValueWrapper>{QOhosJsEnv::toNapiValue(jsState.env(), wantJson)};
575 if (options.has_value())
576 arguments.push_back(convertStartOptionsToNapiObject(jsState, options.value()));
578 optUiAbility.value().evalToPromiseOrRejectOnThrow(
"context.startAbilityForResult(*)", arguments)
580 [context, resultConsumer](
const QOhosCallbackInfo &cbInfo) {
581 QNapi::Object abilityResult = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
582 int resultCode = abilityResult.get<QNapi::Number>(
"resultCode");
584 auto wantOrEmpty = QNapi::getOptionalPropOrEmpty<QNapi::Object>(abilityResult,
"want");
585 auto jsonWant = !wantOrEmpty.IsEmpty()
586 ? std::optional<QJsonObject>(QOhosJsEnv::fromNapiValue<QJsonObject>(wantOrEmpty))
589 context->resultConsumerQtContextRef.visitInQtThreadIfAlive(
590 [resultConsumer, resultCode, jsonWant](
auto &) {
591 constexpr int startedAbilityErrorResultCode = -1;
593 resultCode != startedAbilityErrorResultCode
594 ? std::optional<QOhosAbilityResult>({resultCode, jsonWant})
599 [context, resultConsumer](
const QOhosCallbackInfo &cbInfo) {
600 QtOhos::logJsCallbackError(cbInfo,
"Got error from startAbilityForResult()");
601 context->resultConsumerQtContextRef.visitInQtThreadIfAlive(
602 [resultConsumer](
auto &) {
609class QOhosBaseAbilityContextImpl :
public AbilityContext
612 QOhosBaseAbilityContextImpl();
614 QByteArray generateUniqueId();
616 void startAbilityForResultImpl(
617 const Want &want, QWindow *optInstanceMainWindow,
618 std::optional<QOhosStartOptionsData> qpaStartOptions,
621 void shareDataWithShareKitImpl(
622 QWindow *optMainWindow,
const QList<std::shared_ptr<ShareKit::SharedRecord>> &records,
623 std::shared_ptr<ShareKit::ShareControllerOptions> controllerOptions,
625 std::function<
void(std::shared_ptr<ShareKit::ShareOperationResult>)> onShareCompleted,
626 std::function<
void()> onPanelClosed);
629 QOhosSupplier<QByteArray> m_uniqueIdsGenerator;
630 QHash<QByteArray, std::shared_ptr<
void>> m_shareDataRequestsHandles;
633class QOhosDefaultAbilityContextImpl :
public QOhosBaseAbilityContextImpl
636 QOhosDefaultAbilityContextImpl();
638 void setDestroyFromSystemEnabled(
bool destroyEnabled) override;
640 void startAbilityForResult(
641 const Want &want, std::shared_ptr<StartOptions> options, QObject *context,
644 void shareDataWithShareKit(
645 const QList<std::shared_ptr<ShareKit::SharedRecord>> &records,
646 std::shared_ptr<ShareKit::ShareControllerOptions> controllerOptions,
648 std::function<
void(std::shared_ptr<ShareKit::ShareOperationResult>)> onShareCompleted,
649 std::function<
void()> onPanelClosed)
override;
651 bool tryOpenLink(
const QString &link, std::shared_ptr<OpenLinkOptions> options)
override;
653 void setContinuationActive(
bool continuationActive) override;
656class QOhosAbilityContextImpl :
public QOhosBaseAbilityContextImpl
659 QOhosAbilityContextImpl(QWindow *instanceMainWindow);
661 void setDestroyFromSystemEnabled(
bool destroyEnabled) override;
663 void startAbilityForResult(
664 const Want &want, std::shared_ptr<StartOptions> options, QObject *context,
667 void shareDataWithShareKit(
668 const QList<std::shared_ptr<ShareKit::SharedRecord>> &records,
669 std::shared_ptr<ShareKit::ShareControllerOptions> controllerOptions,
671 std::function<
void(std::shared_ptr<ShareKit::ShareOperationResult>)> onShareCompleted,
672 std::function<
void()> onPanelClosed)
override;
674 bool tryOpenLink(
const QString &link, std::shared_ptr<OpenLinkOptions> options)
override;
676 void setContinuationActive(
bool continuationActive) override;
679 QPointer<QWindow> m_instanceMainWindow;
682std::map<QWindow *, std::unique_ptr<QOhosAbilityContextImpl>> abilityContextsMap;
684QOhosBaseAbilityContextImpl::QOhosBaseAbilityContextImpl()
685 : m_uniqueIdsGenerator(makeUniqueIdsGenerator())
689QByteArray QOhosBaseAbilityContextImpl::generateUniqueId()
691 return m_uniqueIdsGenerator();
694void QOhosBaseAbilityContextImpl::startAbilityForResultImpl(
695 const Want &want, QWindow *optInstanceMainWindow,
696 std::optional<QOhosStartOptionsData> qpaStartOptions,
699 requestStartAbilityForResult(
700 want,
std::move(qpaStartOptions), optInstanceMainWindow, context,
701 std::move(callback));
704void QOhosBaseAbilityContextImpl::shareDataWithShareKitImpl(
705 QWindow *optMainWindow,
const QList<std::shared_ptr<ShareKit::SharedRecord>> &records,
706 std::shared_ptr<ShareKit::ShareControllerOptions> controllerOptions,
708 std::function<
void(std::shared_ptr<ShareKit::ShareOperationResult>)> onShareCompleted,
709 std::function<
void()> onPanelClosed)
711 auto selfPtr = QPointer<QOhosBaseAbilityContextImpl>(
this);
712 auto contextPtr = QPointer<QObject>(context);
713 auto requestId = generateUniqueId();
714 auto requestHandle = shareData(
715 optMainWindow, records, controllerOptions,
716 [selfPtr, contextPtr, requestId, onPanelClosed]() {
717 if (!selfPtr.isNull())
718 selfPtr->m_shareDataRequestsHandles.remove(requestId);
719 if (!contextPtr.isNull() && onPanelClosed)
722 [contextPtr, onShareCompleted](
auto shareOperationResult) {
723 if (!contextPtr.isNull() && onShareCompleted)
724 onShareCompleted(shareOperationResult);
727 m_shareDataRequestsHandles.insert(requestId, requestHandle);
730QOhosDefaultAbilityContextImpl::QOhosDefaultAbilityContextImpl() =
default;
732void QOhosDefaultAbilityContextImpl::setDestroyFromSystemEnabled(
bool destroyEnabled)
734 qCDebug(QtForOhos,
"%s: setting destroyEnabled=%d for all instances", Q_FUNC_INFO, destroyEnabled);
736 std::vector<QObject *> instancesMainWindows;
737 for (
const auto &contextEntry : abilityContextsMap)
738 instancesMainWindows.push_back(contextEntry.first);
740 setDestroyAllowedFlagForAbilityInstances(instancesMainWindows, destroyEnabled);
743void QOhosDefaultAbilityContextImpl::startAbilityForResult(
744 const Want &want, std::shared_ptr<StartOptions> options, QObject *context,
747 startAbilityForResultImpl(
749 options ? tryConvertStartOptionsToQpaFunctionsStruct(*options) : std::nullopt,
750 context, std::move(callback));
753void QOhosDefaultAbilityContextImpl::shareDataWithShareKit(
754 const QList<std::shared_ptr<ShareKit::SharedRecord>> &records,
755 std::shared_ptr<ShareKit::ShareControllerOptions> controllerOptions,
757 std::function<
void(std::shared_ptr<ShareKit::ShareOperationResult>)> onShareCompleted,
758 std::function<
void()> onPanelClosed)
760 shareDataWithShareKitImpl(
761 nullptr, records, controllerOptions, context,
762 std::move(onShareCompleted), std::move(onPanelClosed));
765bool startAbilityByTypeImpl(
const QString &appType,
const QJsonObject &wantParameters)
769 return QOhosJsThreadGateway::evalWithPromise<
bool>(
770 [&](QOhosJsState &jsState, QOhosTaskPromise<
bool> evalPromise) {
771 auto optQAbility = jsState.defaultQAbility();
772 if (!optQAbility.has_value()) {
777 auto thenCatchPromises = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
778 optQAbility.value().evalToPromiseOrRejectOnThrow(
779 "context.startAbilityByType(*)",
781 appType.toStdString(),
782 QOhosJsEnv::toNapiValue(jsState.env(), wantParameters),
788 [](
const QOhosCallbackInfo&) {
789 qOhosPrintfDebug(
"startAbilityByType: onResult called");
794 [](
const QOhosCallbackInfo &cbInfo) {
795 QtOhos::logJsCallbackError(cbInfo,
"startAbilityByType: onError called");
801 [thenPromise = std::move(thenCatchPromises.first)](
const QOhosCallbackInfo &) {
805 [catchPromise = std::move(thenCatchPromises.second)](
const QOhosCallbackInfo &cbInfo) {
806 QtOhos::logJsCallbackError(cbInfo,
"startAbilityByType: failed");
813bool tryOpenLinkImpl(QObject *optInstanceMainWindow,
const QString &link,
std::optional<
bool> appLinkingOnly)
815 if (optInstanceMainWindow !=
nullptr && qobject_cast<QWindow *>(optInstanceMainWindow) ==
nullptr)
816 qOhosReportFatalErrorAndAbort(
"%s: the main window argument is not a QWindow", Q_FUNC_INFO);
818 auto optInstanceMainWindowRef = optInstanceMainWindow !=
nullptr
819 ?
std::make_optional(QtOhos::QObjectThreadSafeRef(optInstanceMainWindow))
822 return QOhosJsThreadGateway::evalWithPromise<
bool>(
823 [&](QOhosJsState &jsState, QOhosTaskPromise<
bool> evalPromise) {
824 auto optUiAbility = optInstanceMainWindowRef.has_value()
825 ? jsState.tryGetQAbilityByQWindow(optInstanceMainWindowRef.value())
826 : jsState.defaultQAbility();
827 if (!optUiAbility.has_value()) {
832 std::vector<std::pair<std::string, QNapi::ValueWrapper>> openLinkOptions;
833 if (appLinkingOnly.has_value())
834 openLinkOptions.emplace_back(
"appLinkingOnly", appLinkingOnly.value());
836 auto thenCatchPromises = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
837 optUiAbility.value().evalToPromiseOrRejectOnThrow(
838 "context.openLink(*)",
841 QNapi::makeObject(jsState.env(), openLinkOptions),
844 [thenPromise = std::move(thenCatchPromises.first)](
const QOhosCallbackInfo &) {
848 [catchPromise = std::move(thenCatchPromises.second)](
const QOhosCallbackInfo &cbInfo) {
849 QtOhos::logJsCallbackError(cbInfo,
"Got error from openLink()");
856void setContinuationActiveImpl(QObject *optInstanceMainWindow,
bool continuationActive)
858 using ContinueState = QtOhos::enums::ohos::app::ability::AbilityConstant::ContinueState;
860 auto optInstanceMainWindowRef = optInstanceMainWindow !=
nullptr
861 ?
std::make_optional(QtOhos::QObjectThreadSafeRef(optInstanceMainWindow))
864 QOhosJsThreadGateway::invokeAndWaitForContinue(
865 [&](QOhosJsState &jsState, QOhosTaskPromise<> taskPromise) {
866 auto optUiAbility = optInstanceMainWindowRef.has_value()
867 ? jsState.tryGetQAbilityByQWindow(optInstanceMainWindowRef.value())
868 : jsState.defaultQAbility();
869 if (!optUiAbility.has_value()) {
874 auto continueState = continuationActive ? ContinueState::ACTIVE : ContinueState::INACTIVE;
875 optUiAbility.value().evalToPromiseOrRejectOnThrow(
876 "context.setMissionContinueState(*)", {jsState.mapOhosEnumToJs(continueState)})
877 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setMissionContinueState()"))
878 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
883bool QOhosDefaultAbilityContextImpl::tryOpenLink(
const QString &link, std::shared_ptr<OpenLinkOptions> options)
885 return tryOpenLinkImpl(
888 ?
static_cast<
const QOhosOpenLinkOptionsImpl &>(*options).appLinkingOnly()
892void QOhosDefaultAbilityContextImpl::setContinuationActive(
bool continuationActive)
894 setContinuationActiveImpl(
nullptr, continuationActive);
897QOhosAbilityContextImpl::QOhosAbilityContextImpl(QWindow *instanceMainWindow)
898 : m_instanceMainWindow(instanceMainWindow)
900 setOnContinueRequestsHandlerForAbilityInstanceWindow(
902 [self = QPointer<QOhosAbilityContextImpl>(
this)](
auto request,
auto responseConsumer) {
903 auto context =
std::make_shared<QOhosOnContinueContextImpl>(request.sourceApplicationVersionCode);
906 Q_EMIT self->continueRequestReceived(context);
908 context->sendRejectResponse();
910 QtOhos::invokeInQtThread(
911 [response = context->response(), responseConsumer = std::move(responseConsumer)]() {
912 responseConsumer(response);
918
919
920
921
922
923
924
925
926
927
928
929
930
931void QOhosAbilityContextImpl::setDestroyFromSystemEnabled(
bool destroyEnabled)
933 if (m_instanceMainWindow.isNull()) {
934 qCWarning(QtForOhos,
"%s: called on destroyed instance, ignoring", Q_FUNC_INFO);
939 QtForOhos,
"%s: setting destroyEnabled=%d for window %p",
940 Q_FUNC_INFO, destroyEnabled, m_instanceMainWindow.data());
942 setDestroyAllowedFlagForAbilityInstances(
943 {m_instanceMainWindow.data()}, destroyEnabled);
947
948
949
950
951
952
953
954
955
956void QOhosAbilityContextImpl::startAbilityForResult(
957 const Want &want, std::shared_ptr<StartOptions> options, QObject *context,
960 startAbilityForResultImpl(
961 want, m_instanceMainWindow,
962 options ? tryConvertStartOptionsToQpaFunctionsStruct(*options) : std::nullopt,
963 context, std::move(callback));
967
968
969
970
971
972
973
974
975
976
977
978void QOhosAbilityContextImpl::shareDataWithShareKit(
979 const QList<std::shared_ptr<ShareKit::SharedRecord>> &records,
980 std::shared_ptr<ShareKit::ShareControllerOptions> controllerOptions,
982 std::function<
void(std::shared_ptr<ShareKit::ShareOperationResult>)> onShareCompleted,
983 std::function<
void()> onPanelClosed)
985 shareDataWithShareKitImpl(
986 m_instanceMainWindow, records, controllerOptions, context,
987 std::move(onShareCompleted), std::move(onPanelClosed));
991
992
993
994
995
996
997
998
999bool QOhosAbilityContextImpl::tryOpenLink(
const QString &link, std::shared_ptr<OpenLinkOptions> options)
1001 return tryOpenLinkImpl(
1002 m_instanceMainWindow, link,
1004 ?
static_cast<
const QOhosOpenLinkOptionsImpl &>(*options).appLinkingOnly()
1009
1010
1011
1012
1013
1014
1015
1016void QOhosAbilityContextImpl::setContinuationActive(
bool continuationActive)
1018 setContinuationActiveImpl(m_instanceMainWindow, continuationActive);
1021std::shared_ptr<OperationStatus> startAbilityImpl(
1022 const Want &want, std::optional<QOhosStartOptionsData> qpaStartOptions)
1024 auto wantJson = convertWantToJsonObject(want);
1025 bool success = QOhosJsThreadGateway::eval(
1026 [&](QOhosJsState &jsState) {
1027 auto optMainUiAbility = jsState.defaultQAbility();
1028 if (!optMainUiAbility.has_value())
1030 auto mainUiAbility = optMainUiAbility.value();
1031 if (mainUiAbility.IsEmpty())
1034 auto arguments = std::vector<QNapi::ValueWrapper>{QOhosJsEnv::toNapiValue(jsState.env(), wantJson)};
1035 if (qpaStartOptions.has_value())
1036 arguments.push_back(convertStartOptionsToNapiObject(jsState, qpaStartOptions.value()));
1038 mainUiAbility.eval(
"context.startAbility(*)", arguments);
1046 return createOperationStatus(success);
1049void startAppProcessImpl(
1050 const QString &processId,
const Want &requestWant,
1051 std::optional<QOhosStartOptionsData> qpaStartOptions)
1053 auto requestWantJson = convertWantToJsonObject(requestWant);
1054 QOhosJsThreadGateway::invokeAndWaitForContinue(
1055 [&](QOhosJsState &jsState, QOhosTaskPromise<> taskPromise) {
1056 auto startOptions = qpaStartOptions.has_value()
1057 ? convertStartOptionsToNapiObject(jsState, qpaStartOptions.value())
1060 auto sharedTaskPromise = QtOhos::moveToSharedPtr(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1061 jsState.startAppProcess(
1062 processId.toStdString(),
1063 QNapi::checkedCast<QNapi::Object>(
1064 QOhosJsEnv::toNapiValue(jsState.env(), requestWantJson)),
1066 [sharedTaskPromise](QOhosJsState &) {
1067 (*sharedTaskPromise)();
1076
1077
1078
1079
1080
1081
1082
1085
1086
1087
1088
1089
1090
1093
1094
1095
1096
1097
1098
1099
1100
1101
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1176 return startAbilityImpl(want, options ? tryConvertStartOptionsToQpaFunctionsStruct(*options) : std::nullopt);
1180
1181
1182
1183
1184
1185
1186
1187
1188
1191 bool success = startAbilityByTypeImpl(appType, wantParameters);
1192 return createOperationStatus(success);
1196
1197
1198
1199
1202 instanceWidget->show();
1206
1207
1208
1209
1210
1211void startAppProcess(
const QString &processId,
const Want &requestWant, std::shared_ptr<StartOptions> options)
1213 startAppProcessImpl(processId, requestWant, options ? tryConvertStartOptionsToQpaFunctionsStruct(*options) :
std::nullopt);
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1231 AbilityContext::instanceForMainWindow(instanceWindow)->setDestroyFromSystemEnabled(destroyEnabled);
1235
1236
1237
1238
1239
1240
1241
1244 auto key = QString::fromUtf8(qtOnContinueMigrationDataPropertyName);
1245 if (want.parameters.contains(key)) {
1246 auto base64String = want.parameters.value(key).toString();
1247 auto decodedData = QByteArray::fromBase64(base64String.toUtf8());
1255
1256
1257
1258
1259
1260
1261
1262
1271 return std::make_shared<QOhosOpenLinkOptionsImpl>();