39constexpr const char *qtOnContinueMigrationDataPropertyName =
"__io_qt_on_continue_migration_data";
41QOhosSupplier<QByteArray> makeUniqueIdsGenerator()
43 return [sequenceNumber =
std::uint64_t(0)]()
mutable {
44 QByteArray idBytes(32, Qt::Uninitialized);
45 std::memcpy(idBytes.data(), &sequenceNumber,
sizeof(sequenceNumber));
46 QRandomGenerator::global()->generate(idBytes.begin() +
sizeof(sequenceNumber), idBytes.end());
52class QOhosOpenLinkOptionsImpl :
public OpenLinkOptions
55 QOhosOpenLinkOptionsImpl();
57 void setAppLinkingOnly(
bool appLinkingOnly) override;
59 std::optional<
bool> appLinkingOnly()
const;
62 std::optional<
bool> m_appLinkingOnly;
65QOhosOpenLinkOptionsImpl::QOhosOpenLinkOptionsImpl() =
default;
67void QOhosOpenLinkOptionsImpl::setAppLinkingOnly(
bool appLinkingOnly)
69 m_appLinkingOnly = appLinkingOnly;
72std::optional<
bool> QOhosOpenLinkOptionsImpl::appLinkingOnly()
const
74 return m_appLinkingOnly;
79enum class AbilityOnContinueResponseStatus
86struct AbilityOnContinueRequest
88 int sourceApplicationVersionCode;
91struct AbilityOnContinueResponse
93 AbilityOnContinueResponseStatus status;
94 QMap<QString, QString> wantObjectParams;
95 std::optional<
bool> exitAppOnSourceDeviceAfterMigration;
98std::optional<OnContinueResult> tryMapAbilityOnContinueResponseStatusToOhos(
99 AbilityOnContinueResponseStatus status)
102 case AbilityOnContinueResponseStatus::Agree:
103 return OnContinueResult
::AGREE;
104 case AbilityOnContinueResponseStatus::Reject:
106 case AbilityOnContinueResponseStatus::Mismatch:
112void setOnContinueRequestsHandlerForAbilityInstanceWindow(
113 QObject *windowObject,
114 std::function<
void(AbilityOnContinueRequest, QOhosConsumer<AbilityOnContinueResponse>)> requestsHandler)
116 auto *qWindow = qobject_cast<QWindow *>(windowObject);
117 if (qWindow ==
nullptr)
118 qOhosReportFatalErrorAndAbort(
"%s: windowObject argument is null or not a QWindow", Q_FUNC_INFO);
120 auto qWindowRef = QtOhos::QObjectThreadSafeRef(qWindow);
121 auto sharedRequestsHandler = QtOhos::moveToSharedPtr(std::move(requestsHandler));
123 struct JsResultContext
125 QNapi::Reference<QNapi::Object> wantParamsReference;
126 QOhosConsumer<QOhosJsState &, QNapi::Number> resultConsumer;
129 QOhosJsThreadGateway::runAndWait(
130 [&](QOhosJsState &jsState) {
131 auto optQAbility = jsState.tryGetQAbilityByQWindow(qWindowRef);
134 "%s: no ability for window %s, handler not set",
135 Q_FUNC_INFO, qWindowRef.refName().c_str());
139 jsState.setOnContinueRequestsHandler(
141 [sharedRequestsHandler](QOhosJsState &, QNapi::Object wantParamsObj,
auto resultConsumer) {
142 int sourceVersionCode = wantParamsObj.get<QNapi::Number>(
"version");
143 auto jsResultContext = QtOhos::makeProxyWithJsThreadDeleter(std::make_shared<JsResultContext>());
144 jsResultContext->wantParamsReference = QNapi::Reference<>::makePersistentFrom(wantParamsObj);
145 jsResultContext->resultConsumer = std::move(resultConsumer);
146 QtOhos::invokeInQtThread(
147 [sharedRequestsHandler, sourceVersionCode, jsResultContext]() {
148 (*sharedRequestsHandler)(
149 AbilityOnContinueRequest{
150 .sourceApplicationVersionCode = sourceVersionCode,
152 [jsResultContext](AbilityOnContinueResponse qtResponse) {
153 QOhosJsThreadGateway::invoke(
154 [jsResultContext, qtResponse](QOhosJsState &jsState) {
155 if (qtResponse.status == AbilityOnContinueResponseStatus::Agree) {
156 auto wantParamsObj = jsResultContext->wantParamsReference.Value();
157 auto newWantParamsIter = qtResponse.wantObjectParams.constKeyValueBegin();
158 while (newWantParamsIter != qtResponse.wantObjectParams.constKeyValueEnd()) {
160 newWantParamsIter->first.toStdString(),
161 newWantParamsIter->second.toStdString());
164 if (qtResponse.exitAppOnSourceDeviceAfterMigration.has_value()) {
166 jsState.eval<QNapi::String>(
167 "@ohos.app.ability.wantConstant.Params.SUPPORT_CONTINUE_SOURCE_EXIT_KEY"),
168 qtResponse.exitAppOnSourceDeviceAfterMigration.value());
171 auto optResultEnum = tryMapAbilityOnContinueResponseStatusToOhos(qtResponse.status);
172 if (!optResultEnum) {
174 "%s: got illegal status (%d) from requests handler, rejecting the request",
175 Q_FUNC_INFO,
static_cast<
int>(qtResponse.status));
177 jsResultContext->resultConsumer(
178 jsState, jsState.mapOhosEnumToJs(optResultEnum.value_or(OnContinueResult::REJECT)));
187void setDestroyAllowedFlagForAbilityInstances(
188 std::vector<QObject *> instancesMainWindows,
bool destroyEnabled)
190 std::vector<QtOhos::QObjectThreadSafeRef> instancesMainWindowsRefs;
191 for (
auto *instanceMainWindow : instancesMainWindows)
192 instancesMainWindowsRefs.emplace_back(instanceMainWindow);
194 QOhosJsThreadGateway::runAndWait(
195 [&](QOhosJsState &jsState) {
196 for (
const auto &instanceMainWindowRef : instancesMainWindowsRefs) {
197 auto optQAbility = jsState.tryGetQAbilityByQWindow(instanceMainWindowRef);
199 jsState.setDestroyFromSystemAllowed(optQAbility.value(), destroyEnabled);
205class QOhosOnContinueContextImpl :
public OnContinueContext
208 QOhosOnContinueContextImpl(
int sourceApplicationVersionCode);
210 void setAgreeResponse(
const QByteArray &responseData)
override;
211 void setRejectResponse() override;
212 void setMismatchResponse() override;
214 void setExitAppOnSourceDeviceAfterMigration(
bool exitAfterMigration) override;
216 int sourceApplicationVersionCode()
const override;
218 AbilityOnContinueResponse response()
const;
221 int m_sourceApplicationVersionCode;
222 AbilityOnContinueResponse m_baseResponse;
223 std::optional<
bool> m_exitAppOnSourceDeviceAfterMigration;
226QOhosOnContinueContextImpl::QOhosOnContinueContextImpl(
int sourceApplicationVersionCode)
227 : OnContinueContext()
228 , m_sourceApplicationVersionCode(sourceApplicationVersionCode)
234
235
236
237
238
239
240
241void QOhosOnContinueContextImpl::setAgreeResponse(
const QByteArray &responseData)
243 m_baseResponse = AbilityOnContinueResponse{
244 .status = AbilityOnContinueResponseStatus::Agree,
245 .wantObjectParams = {
247 QString::fromUtf8(qtOnContinueMigrationDataPropertyName),
248 QString::fromUtf8(responseData.toBase64())
255
256
257
258
259
260
261
262
263
264void QOhosOnContinueContextImpl::setRejectResponse()
266 m_baseResponse = AbilityOnContinueResponse{
267 .status = AbilityOnContinueResponseStatus::Reject,
268 .wantObjectParams = {},
273
274
275
276
277
278
279
280
281
282
283void QOhosOnContinueContextImpl::setMismatchResponse()
285 m_baseResponse = AbilityOnContinueResponse{
286 .status = AbilityOnContinueResponseStatus::Mismatch,
287 .wantObjectParams = {},
292
293
294
295
296
297
298
299void QOhosOnContinueContextImpl::setExitAppOnSourceDeviceAfterMigration(
bool exitAfterMigration)
301 m_exitAppOnSourceDeviceAfterMigration = exitAfterMigration;
304AbilityOnContinueResponse QOhosOnContinueContextImpl::response()
const
306 auto response = m_baseResponse;
307 response.exitAppOnSourceDeviceAfterMigration = m_exitAppOnSourceDeviceAfterMigration;
312
313
314
315
316
317
318int QOhosOnContinueContextImpl::sourceApplicationVersionCode()
const
320 return m_sourceApplicationVersionCode;
324 QOhosStartOptionsData::WindowMode windowMode)
327 using OptionsData = QOhosStartOptionsData;
329 switch (windowMode) {
330 case OptionsData::WindowMode::WINDOW_MODE_SPLIT_PRIMARY:
332 case OptionsData::WindowMode::WINDOW_MODE_SPLIT_SECONDARY:
334 case OptionsData::WindowMode::WINDOW_MODE_FULLSCREEN:
338 qCWarning(QtForOhos,
"%s: got illegal WindowMode: %d", Q_FUNC_INFO,
static_cast<
int>(windowMode));
344 QOhosStartOptionsData::ProcessMode processMode)
347 using OptionsData = QOhosStartOptionsData;
349 switch (processMode) {
350 case OptionsData::ProcessMode::NEW_PROCESS_ATTACH_TO_PARENT:
352 case OptionsData::ProcessMode::NEW_PROCESS_ATTACH_TO_STATUS_BAR_ITEM:
356 qCWarning(QtForOhos,
"%s: got illegal ProcessMode: %d", Q_FUNC_INFO,
static_cast<
int>(processMode));
362 QOhosStartOptionsData::StartupVisibility startupVisibility)
365 using OptionsData = QOhosStartOptionsData;
367 switch (startupVisibility) {
368 case OptionsData::StartupVisibility::STARTUP_HIDE:
370 case OptionsData::StartupVisibility::STARTUP_SHOW:
374 qCWarning(QtForOhos,
"%s: got illegal StartupVisibility: %d", Q_FUNC_INFO,
static_cast<
int>(startupVisibility));
380 QOhosStartOptionsData::SupportWindowMode supportWindowMode)
383 using OptionsData = QOhosStartOptionsData;
385 switch (supportWindowMode) {
386 case OptionsData::SupportWindowMode::FULL_SCREEN:
388 case OptionsData::SupportWindowMode::SPLIT:
390 case OptionsData::SupportWindowMode::FLOATING:
394 qCWarning(QtForOhos,
"%s: got illegal SupportWindowMode: %d", Q_FUNC_INFO,
static_cast<
int>(supportWindowMode));
399QNapi::Array mapSupportWindowModesToJsEnumsArray(
400 QOhosJsState &jsState,
const QList<QOhosStartOptionsData::SupportWindowMode> &supportWindowModes)
402 std::vector<QNapi::ValueWrapper> jsSupportWindowModes;
403 for (
auto supportWindowMode : supportWindowModes) {
404 auto optOhosSupportWindowMode = tryMapSupportWindowModeToOhosOrLogWarning(supportWindowMode);
405 if (optOhosSupportWindowMode.has_value())
406 jsSupportWindowModes.push_back(jsState.mapOhosEnumToJs(optOhosSupportWindowMode.value()));
409 return QNapi::makeArray(jsState.env(), jsSupportWindowModes);
412QNapi::Object makeJsCompletionHandler(
413 QOhosJsState &jsState, std::shared_ptr<QOhosConsumer<
bool, QJsonObject, QString>> qtThreadCompletionHandler)
415 auto makeCompletionCallback = [qtThreadCompletionHandler](
bool requestSuccess) {
416 return [qtThreadCompletionHandler, requestSuccess](
const QNapi::CallbackInfo &cbInfo) {
417 QNapi::Object elementNameObj;
418 QNapi::String messageValue;
419 cbInfo.getLeadingArgs(Q_FUNC_INFO, elementNameObj, messageValue);
421 const QJsonObject elementName = QOhosJsEnv::fromNapiValue<QJsonObject>(elementNameObj);
422 const QString message = QString::fromStdString(messageValue);
424 QtOhos::invokeInQtThread(
425 [qtThreadCompletionHandler, requestSuccess, elementName, message]() {
426 (*qtThreadCompletionHandler)(requestSuccess, elementName, message);
431 return QNapi::makeObject(
434 {
"onRequestSuccess", makeCompletionCallback(
true)},
435 {
"onRequestFailure", makeCompletionCallback(
false)},
439QNapi::Object convertStartOptionsToNapiObject(
440 QOhosJsState &jsState,
const QOhosStartOptionsData &opts)
442 auto *env = jsState.env();
443 auto napiOptions = QNapi::Object::New(env);
445 auto optOhosWindowMode = opts.windowMode.has_value()
446 ? tryMapWindowModeToOhosOrLogWarning(opts.windowMode.value())
448 if (optOhosWindowMode.has_value())
449 napiOptions.set(
"windowMode", jsState.mapOhosEnumToJs(optOhosWindowMode.value()));
450 if (opts.displayId.has_value())
451 napiOptions.set(
"displayId", opts.displayId.value());
452 if (opts.withAnimation.has_value())
453 napiOptions.set(
"withAnimation", opts.withAnimation.value());
454 if (opts.windowLeft.has_value())
455 napiOptions.set(
"windowLeft", opts.windowLeft.value());
456 if (opts.windowTop.has_value())
457 napiOptions.set(
"windowTop", opts.windowTop.value());
458 if (opts.windowWidth.has_value())
459 napiOptions.set(
"windowWidth", opts.windowWidth.value());
460 if (opts.windowHeight.has_value())
461 napiOptions.set(
"windowHeight", opts.windowHeight.value());
462 auto optOhosProcessMode = opts.processMode.has_value()
463 ? tryMapProcessModeToOhosOrLogWarning(opts.processMode.value())
465 if (optOhosProcessMode.has_value())
466 napiOptions.set(
"processMode", jsState.mapOhosEnumToJs(optOhosProcessMode.value()));
467 auto optOhosStartupVisibility = opts.startupVisibility.has_value()
468 ? tryMapStartupVisibilityToOhosOrLogWarning(opts.startupVisibility.value())
470 if (optOhosStartupVisibility.has_value())
471 napiOptions.set(
"startupVisibility", jsState.mapOhosEnumToJs(optOhosStartupVisibility.value()));
472 if (opts.windowIcon.has_value()) {
473 auto windowIcon = opts.windowIcon.value().value<QImage>();
474 if (!windowIcon.isNull())
475 napiOptions.set(
"startWindowIcon", makeOhosNapiPixelMapFromQImage(jsState, windowIcon));
477 if (opts.windowBackgroundColorHex.has_value())
478 napiOptions.set(
"startWindowBackgroundColor", opts.windowBackgroundColorHex.value().toStdString());
479 if (opts.supportWindowModes.has_value()) {
480 auto jsSupportWindowModes = mapSupportWindowModesToJsEnumsArray(jsState, opts.supportWindowModes.value());
481 if (jsSupportWindowModes.Length() != 0)
482 napiOptions.set(
"supportWindowModes", jsSupportWindowModes);
484 qCWarning(QtForOhos,
"%s: OHOS doesn't support empty supportWindowModes, skipping", Q_FUNC_INFO);
486 if (opts.minWindowWidth.has_value())
487 napiOptions.set(
"minWindowWidth", opts.minWindowWidth.value());
488 if (opts.minWindowHeight.has_value())
489 napiOptions.set(
"minWindowHeight", opts.minWindowHeight.value());
490 if (opts.maxWindowWidth.has_value())
491 napiOptions.set(
"maxWindowWidth", opts.maxWindowWidth.value());
492 if (opts.maxWindowHeight.has_value())
493 napiOptions.set(
"maxWindowHeight", opts.maxWindowHeight.value());
494 if (opts.optCompletionHandler)
495 napiOptions.set(
"completionHandler", makeJsCompletionHandler(jsState, opts.optCompletionHandler));
496 if (opts.hideStartWindow.has_value())
497 napiOptions.set(
"hideStartWindow", opts.hideStartWindow.value());
498 if (opts.windowCreateParams.has_value()) {
499 const auto &windowCreateParams = opts.windowCreateParams.value();
500 std::vector<std::pair<std::string, QNapi::ValueWrapper>> windowCreateParamsProps;
501 if (windowCreateParams.setWindowFadeInOutAnimation) {
502 windowCreateParamsProps.emplace_back(
509 jsState.mapOhosEnumToJs(
510 QtOhos::enums::ohos::window::AnimationType::FADE_IN_OUT),
514 napiOptions.set(
"windowCreateParams", QNapi::makeObject(env, windowCreateParamsProps));
520void requestStartAbilityForResult(
521 const Want &want, std::optional<QOhosStartOptionsData> options,
522 QWindow *optInstanceMainWindow, QObject *callerContext,
528 QtOhos::QObjectThreadSafeRef resultConsumerQtContextRef;
531 auto context = QtOhos::moveToSharedPtr(
533 .resultCallback = std::move(resultCallback),
534 .resultConsumerQtContextRef = QtOhos::QObjectThreadSafeRef(callerContext),
537 auto resultConsumer = [context](std::optional<QOhosAbilityResult> optAbilityResult) {
538 if (optAbilityResult.has_value()) {
539 auto abilityResult = optAbilityResult.value();
540 auto want = abilityResult.want.has_value()
541 ? std::optional(convertWantFromJsonObject(abilityResult.want.value()))
545 context->resultCallback(
std::nullopt);
549 auto wantJson = convertWantToJsonObject(want);
550 auto optInstanceMainWindowRef =
551 optInstanceMainWindow !=
nullptr
552 ?
std::make_optional(QtOhos::QObjectThreadSafeRef(optInstanceMainWindow))
555 QOhosJsThreadGateway::invoke(
556 [context, resultConsumer, wantJson, options, optInstanceMainWindowRef](QOhosJsState &jsState) {
557 auto optUiAbility = optInstanceMainWindowRef.has_value()
558 ? jsState.tryGetQAbilityByQWindow(optInstanceMainWindowRef.value())
559 : jsState.defaultQAbility();
560 if (!optUiAbility.has_value()) {
561 context->resultConsumerQtContextRef.visitInQtThreadIfAlive(
562 [resultConsumer](
auto &) {
568 auto arguments = std::vector<QNapi::ValueWrapper>{QOhosJsEnv::toNapiValue(jsState.env(), wantJson)};
569 if (options.has_value())
570 arguments.push_back(convertStartOptionsToNapiObject(jsState, options.value()));
572 optUiAbility.value().evalToPromiseOrRejectOnThrow(
"context.startAbilityForResult(*)", arguments)
574 [context, resultConsumer](
const QOhosCallbackInfo &cbInfo) {
575 QNapi::Object abilityResult = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
576 int resultCode = abilityResult.get<QNapi::Number>(
"resultCode");
578 auto wantOrEmpty = QNapi::getOptionalPropOrEmpty<QNapi::Object>(abilityResult,
"want");
579 auto jsonWant = !wantOrEmpty.IsEmpty()
580 ? std::optional<QJsonObject>(QOhosJsEnv::fromNapiValue<QJsonObject>(wantOrEmpty))
583 context->resultConsumerQtContextRef.visitInQtThreadIfAlive(
584 [resultConsumer, resultCode, jsonWant](
auto &) {
585 constexpr int startedAbilityErrorResultCode = -1;
587 resultCode != startedAbilityErrorResultCode
588 ? std::optional<QOhosAbilityResult>({resultCode, jsonWant})
593 [context, resultConsumer](
const QOhosCallbackInfo &cbInfo) {
594 QtOhos::logJsCallbackError(cbInfo,
"Got error from startAbilityForResult()");
595 context->resultConsumerQtContextRef.visitInQtThreadIfAlive(
596 [resultConsumer](
auto &) {
603class QOhosBaseAbilityContextImpl :
public AbilityContext
606 QOhosBaseAbilityContextImpl();
608 QByteArray generateUniqueId();
610 void startAbilityForResultImpl(
611 const Want &want, QWindow *optInstanceMainWindow,
612 std::optional<QOhosStartOptionsData> qpaStartOptions,
615 void shareDataWithShareKitImpl(
616 QWindow *optMainWindow,
const QList<std::shared_ptr<ShareKit::SharedRecord>> &records,
617 std::shared_ptr<ShareKit::ShareControllerOptions> controllerOptions,
619 std::function<
void(std::shared_ptr<ShareKit::ShareOperationResult>)> onShareCompleted,
620 std::function<
void()> onPanelClosed);
623 QOhosSupplier<QByteArray> m_uniqueIdsGenerator;
624 QHash<QByteArray, std::shared_ptr<
void>> m_shareDataRequestsHandles;
627class QOhosDefaultAbilityContextImpl :
public QOhosBaseAbilityContextImpl
630 QOhosDefaultAbilityContextImpl();
632 void setDestroyFromSystemEnabled(
bool destroyEnabled) override;
634 void startAbilityForResult(
635 const Want &want, std::shared_ptr<StartOptions> options, QObject *context,
638 void shareDataWithShareKit(
639 const QList<std::shared_ptr<ShareKit::SharedRecord>> &records,
640 std::shared_ptr<ShareKit::ShareControllerOptions> controllerOptions,
642 std::function<
void(std::shared_ptr<ShareKit::ShareOperationResult>)> onShareCompleted,
643 std::function<
void()> onPanelClosed)
override;
645 bool tryOpenLink(
const QString &link, std::shared_ptr<OpenLinkOptions> options)
override;
647 void setContinuationActive(
bool continuationActive) override;
650class QOhosAbilityContextImpl :
public QOhosBaseAbilityContextImpl
653 QOhosAbilityContextImpl(QWindow *instanceMainWindow);
655 void setDestroyFromSystemEnabled(
bool destroyEnabled) override;
657 void startAbilityForResult(
658 const Want &want, std::shared_ptr<StartOptions> options, QObject *context,
661 void shareDataWithShareKit(
662 const QList<std::shared_ptr<ShareKit::SharedRecord>> &records,
663 std::shared_ptr<ShareKit::ShareControllerOptions> controllerOptions,
665 std::function<
void(std::shared_ptr<ShareKit::ShareOperationResult>)> onShareCompleted,
666 std::function<
void()> onPanelClosed)
override;
668 bool tryOpenLink(
const QString &link, std::shared_ptr<OpenLinkOptions> options)
override;
670 void setContinuationActive(
bool continuationActive) override;
673 QPointer<QWindow> m_instanceMainWindow;
676std::map<QWindow *, std::shared_ptr<QOhosAbilityContextImpl>> abilityContextsMap;
678QOhosBaseAbilityContextImpl::QOhosBaseAbilityContextImpl()
679 : m_uniqueIdsGenerator(makeUniqueIdsGenerator())
683QByteArray QOhosBaseAbilityContextImpl::generateUniqueId()
685 return m_uniqueIdsGenerator();
688void QOhosBaseAbilityContextImpl::startAbilityForResultImpl(
689 const Want &want, QWindow *optInstanceMainWindow,
690 std::optional<QOhosStartOptionsData> qpaStartOptions,
693 requestStartAbilityForResult(
694 want,
std::move(qpaStartOptions), optInstanceMainWindow, context,
695 std::move(callback));
698void QOhosBaseAbilityContextImpl::shareDataWithShareKitImpl(
699 QWindow *optMainWindow,
const QList<std::shared_ptr<ShareKit::SharedRecord>> &records,
700 std::shared_ptr<ShareKit::ShareControllerOptions> controllerOptions,
702 std::function<
void(std::shared_ptr<ShareKit::ShareOperationResult>)> onShareCompleted,
703 std::function<
void()> onPanelClosed)
705 auto selfPtr = QPointer<QOhosBaseAbilityContextImpl>(
this);
706 auto contextPtr = QPointer<QObject>(context);
707 auto requestId = generateUniqueId();
708 auto requestHandle = shareData(
709 optMainWindow, records, controllerOptions,
710 [selfPtr, contextPtr, requestId, onPanelClosed]() {
711 if (!selfPtr.isNull())
712 selfPtr->m_shareDataRequestsHandles.remove(requestId);
713 if (!contextPtr.isNull() && onPanelClosed)
716 [contextPtr, onShareCompleted](
auto shareOperationResult) {
717 if (!contextPtr.isNull() && onShareCompleted)
718 onShareCompleted(shareOperationResult);
721 m_shareDataRequestsHandles.insert(requestId, requestHandle);
724QOhosDefaultAbilityContextImpl::QOhosDefaultAbilityContextImpl() =
default;
726void QOhosDefaultAbilityContextImpl::setDestroyFromSystemEnabled(
bool destroyEnabled)
728 qCDebug(QtForOhos,
"%s: setting destroyEnabled=%d for all instances", Q_FUNC_INFO, destroyEnabled);
730 std::vector<QObject *> instancesMainWindows;
731 for (
const auto &contextEntry : abilityContextsMap)
732 instancesMainWindows.push_back(contextEntry.first);
734 setDestroyAllowedFlagForAbilityInstances(instancesMainWindows, destroyEnabled);
737void QOhosDefaultAbilityContextImpl::startAbilityForResult(
738 const Want &want, std::shared_ptr<StartOptions> options, QObject *context,
741 startAbilityForResultImpl(
743 options ? tryConvertStartOptionsToQpaFunctionsStruct(*options) : std::nullopt,
744 context, std::move(callback));
747void QOhosDefaultAbilityContextImpl::shareDataWithShareKit(
748 const QList<std::shared_ptr<ShareKit::SharedRecord>> &records,
749 std::shared_ptr<ShareKit::ShareControllerOptions> controllerOptions,
751 std::function<
void(std::shared_ptr<ShareKit::ShareOperationResult>)> onShareCompleted,
752 std::function<
void()> onPanelClosed)
754 shareDataWithShareKitImpl(
755 nullptr, records, controllerOptions, context,
756 std::move(onShareCompleted), std::move(onPanelClosed));
759bool startAbilityByTypeImpl(
const QString &appType,
const QJsonObject &wantParameters)
763 return QOhosJsThreadGateway::evalWithPromise<
bool>(
764 [&](QOhosJsState &jsState, QOhosTaskPromise<
bool> evalPromise) {
765 auto optQAbility = jsState.defaultQAbility();
766 if (!optQAbility.has_value()) {
771 auto thenCatchPromises = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
772 optQAbility.value().evalToPromiseOrRejectOnThrow(
773 "context.startAbilityByType(*)",
775 appType.toStdString(),
776 QOhosJsEnv::toNapiValue(jsState.env(), wantParameters),
782 [](
const QOhosCallbackInfo&) {
783 qOhosPrintfDebug(
"startAbilityByType: onResult called");
788 [](
const QOhosCallbackInfo &cbInfo) {
789 QtOhos::logJsCallbackError(cbInfo,
"startAbilityByType: onError called");
795 [thenPromise = std::move(thenCatchPromises.first)](
const QOhosCallbackInfo &) {
799 [catchPromise = std::move(thenCatchPromises.second)](
const QOhosCallbackInfo &cbInfo) {
800 QtOhos::logJsCallbackError(cbInfo,
"startAbilityByType: failed");
807bool tryOpenLinkImpl(QObject *optInstanceMainWindow,
const QString &link,
std::optional<
bool> appLinkingOnly)
809 if (optInstanceMainWindow !=
nullptr && qobject_cast<QWindow *>(optInstanceMainWindow) ==
nullptr)
810 qOhosReportFatalErrorAndAbort(
"%s: the main window argument is not a QWindow", Q_FUNC_INFO);
812 auto optInstanceMainWindowRef = optInstanceMainWindow !=
nullptr
813 ?
std::make_optional(QtOhos::QObjectThreadSafeRef(optInstanceMainWindow))
816 return QOhosJsThreadGateway::evalWithPromise<
bool>(
817 [&](QOhosJsState &jsState, QOhosTaskPromise<
bool> evalPromise) {
818 auto optUiAbility = optInstanceMainWindowRef.has_value()
819 ? jsState.tryGetQAbilityByQWindow(optInstanceMainWindowRef.value())
820 : jsState.defaultQAbility();
821 if (!optUiAbility.has_value()) {
826 std::vector<std::pair<std::string, QNapi::ValueWrapper>> openLinkOptions;
827 if (appLinkingOnly.has_value())
828 openLinkOptions.emplace_back(
"appLinkingOnly", appLinkingOnly.value());
830 auto thenCatchPromises = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
831 optUiAbility.value().evalToPromiseOrRejectOnThrow(
832 "context.openLink(*)",
835 QNapi::makeObject(jsState.env(), openLinkOptions),
838 [thenPromise = std::move(thenCatchPromises.first)](
const QOhosCallbackInfo &) {
842 [catchPromise = std::move(thenCatchPromises.second)](
const QOhosCallbackInfo &cbInfo) {
843 QtOhos::logJsCallbackError(cbInfo,
"Got error from openLink()");
850void setContinuationActiveImpl(QObject *optInstanceMainWindow,
bool continuationActive)
854 auto optInstanceMainWindowRef = optInstanceMainWindow !=
nullptr
855 ?
std::make_optional(QtOhos::QObjectThreadSafeRef(optInstanceMainWindow))
858 QOhosJsThreadGateway::invokeAndWaitForContinue(
859 [&](QOhosJsState &jsState, QOhosTaskPromise<> taskPromise) {
860 auto optUiAbility = optInstanceMainWindowRef.has_value()
861 ? jsState.tryGetQAbilityByQWindow(optInstanceMainWindowRef.value())
862 : jsState.defaultQAbility();
863 if (!optUiAbility.has_value()) {
868 auto continueState = continuationActive ? ContinueState::ACTIVE : ContinueState::INACTIVE;
869 optUiAbility.value().evalToPromiseOrRejectOnThrow(
870 "context.setMissionContinueState(*)", {jsState.mapOhosEnumToJs(continueState)})
871 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setMissionContinueState()"))
872 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
877bool QOhosDefaultAbilityContextImpl::tryOpenLink(
const QString &link, std::shared_ptr<OpenLinkOptions> options)
879 return tryOpenLinkImpl(
882 ?
static_cast<
const QOhosOpenLinkOptionsImpl &>(*options).appLinkingOnly()
886void QOhosDefaultAbilityContextImpl::setContinuationActive(
bool continuationActive)
888 setContinuationActiveImpl(
nullptr, continuationActive);
891QOhosAbilityContextImpl::QOhosAbilityContextImpl(QWindow *instanceMainWindow)
892 : m_instanceMainWindow(instanceMainWindow)
894 setOnContinueRequestsHandlerForAbilityInstanceWindow(
896 [self = QPointer<QOhosAbilityContextImpl>(
this)](
auto request,
auto responseConsumer) {
897 auto context =
std::make_shared<QOhosOnContinueContextImpl>(request.sourceApplicationVersionCode);
900 Q_EMIT self->continueRequestReceived(context);
902 context->setRejectResponse();
904 QtOhos::invokeInQtThread(
905 [response = context->response(), responseConsumer = std::move(responseConsumer)]() {
906 responseConsumer(response);
912
913
914
915
916
917
918
919
920
921
922
923
924
925void QOhosAbilityContextImpl::setDestroyFromSystemEnabled(
bool destroyEnabled)
927 if (m_instanceMainWindow.isNull()) {
928 qCWarning(QtForOhos,
"%s: called on destroyed instance, ignoring", Q_FUNC_INFO);
933 QtForOhos,
"%s: setting destroyEnabled=%d for window %p",
934 Q_FUNC_INFO, destroyEnabled, m_instanceMainWindow.data());
936 setDestroyAllowedFlagForAbilityInstances(
937 {m_instanceMainWindow.data()}, destroyEnabled);
941
942
943
944
945
946
947
948
949
950void QOhosAbilityContextImpl::startAbilityForResult(
951 const Want &want, std::shared_ptr<StartOptions> options, QObject *context,
954 startAbilityForResultImpl(
955 want, m_instanceMainWindow,
956 options ? tryConvertStartOptionsToQpaFunctionsStruct(*options) : std::nullopt,
957 context, std::move(callback));
961
962
963
964
965
966
967
968
969
970
971
972void QOhosAbilityContextImpl::shareDataWithShareKit(
973 const QList<std::shared_ptr<ShareKit::SharedRecord>> &records,
974 std::shared_ptr<ShareKit::ShareControllerOptions> controllerOptions,
976 std::function<
void(std::shared_ptr<ShareKit::ShareOperationResult>)> onShareCompleted,
977 std::function<
void()> onPanelClosed)
979 shareDataWithShareKitImpl(
980 m_instanceMainWindow, records, controllerOptions, context,
981 std::move(onShareCompleted), std::move(onPanelClosed));
985
986
987
988
989
990
991
992
993bool QOhosAbilityContextImpl::tryOpenLink(
const QString &link, std::shared_ptr<OpenLinkOptions> options)
995 return tryOpenLinkImpl(
996 m_instanceMainWindow, link,
998 ?
static_cast<
const QOhosOpenLinkOptionsImpl &>(*options).appLinkingOnly()
1003
1004
1005
1006
1007
1008
1009
1010void QOhosAbilityContextImpl::setContinuationActive(
bool continuationActive)
1012 setContinuationActiveImpl(m_instanceMainWindow, continuationActive);
1015std::shared_ptr<OperationStatus> startAbilityImpl(
1016 const Want &want, std::optional<QOhosStartOptionsData> qpaStartOptions)
1018 auto wantJson = convertWantToJsonObject(want);
1019 bool success = QOhosJsThreadGateway::eval(
1020 [&](QOhosJsState &jsState) {
1021 auto optMainUiAbility = jsState.defaultQAbility();
1022 if (!optMainUiAbility.has_value())
1024 auto mainUiAbility = optMainUiAbility.value();
1025 if (mainUiAbility.IsEmpty())
1028 auto arguments = std::vector<QNapi::ValueWrapper>{QOhosJsEnv::toNapiValue(jsState.env(), wantJson)};
1029 if (qpaStartOptions.has_value())
1030 arguments.push_back(convertStartOptionsToNapiObject(jsState, qpaStartOptions.value()));
1032 mainUiAbility.eval(
"context.startAbility(*)", arguments);
1040 return createOperationStatus(success);
1043void startAppProcessImpl(
1044 const QString &processId,
const Want &requestWant,
1045 std::optional<QOhosStartOptionsData> qpaStartOptions)
1047 auto requestWantJson = convertWantToJsonObject(requestWant);
1048 QOhosJsThreadGateway::invokeAndWaitForContinue(
1049 [&](QOhosJsState &jsState, QOhosTaskPromise<> taskPromise) {
1050 auto startOptions = qpaStartOptions.has_value()
1051 ? convertStartOptionsToNapiObject(jsState, qpaStartOptions.value())
1054 auto sharedTaskPromise = QtOhos::moveToSharedPtr(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1055 jsState.startAppProcess(
1056 processId.toStdString(),
1057 QNapi::checkedCast<QNapi::Object>(
1058 QOhosJsEnv::toNapiValue(jsState.env(), requestWantJson)),
1060 [sharedTaskPromise](QOhosJsState &) {
1061 (*sharedTaskPromise)();
1070
1071
1072
1073
1074
1075
1076
1079
1080
1081
1082
1083
1084
1087
1088
1089
1090
1091
1092
1093
1094
1095
1107
1108
1109
1110
1111
1112
1113
1114
1115
1123
1124
1125
1126
1127
1128
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1163 return startAbilityImpl(want, options ? tryConvertStartOptionsToQpaFunctionsStruct(*options) : std::nullopt);
1167
1168
1169
1170
1171
1172
1173
1174
1175
1178 bool success = startAbilityByTypeImpl(appType, wantParameters);
1179 return createOperationStatus(success);
1183
1184
1185
1186
1189 instanceWidget->show();
1193
1194
1195
1196
1197
1198void startAppProcess(
const QString &processId,
const Want &requestWant, std::shared_ptr<StartOptions> options)
1200 startAppProcessImpl(processId, requestWant, options ? tryConvertStartOptionsToQpaFunctionsStruct(*options) :
std::nullopt);
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1218 AbilityContext::instanceForMainWindow(instanceWindow)->setDestroyFromSystemEnabled(destroyEnabled);
1222
1223
1224
1225
1226
1227
1228
1231 auto key = QString::fromUtf8(qtOnContinueMigrationDataPropertyName);
1232 if (want.parameters.contains(key)) {
1233 auto base64String = want.parameters.value(key).toString();
1234 auto decodedData = QByteArray::fromBase64(base64String.toUtf8());
1242
1243
1244
1245
1246
1247
1248
1249
1258 return std::make_shared<QOhosOpenLinkOptionsImpl>();