43constexpr const char *qtOnContinueMigrationDataPropertyName =
"__io_qt_on_continue_migration_data";
45QOhosSupplier<QByteArray> makeUniqueIdsGenerator()
47 return [sequenceNumber =
std::uint64_t(0)]()
mutable {
48 QByteArray idBytes(32, Qt::Uninitialized);
49 std::memcpy(idBytes.data(), &sequenceNumber,
sizeof(sequenceNumber));
50 QRandomGenerator::global()->generate(idBytes.begin() +
sizeof(sequenceNumber), idBytes.end());
56class QOhosOpenLinkOptionsImpl :
public OpenLinkOptions
59 QOhosOpenLinkOptionsImpl();
61 void setAppLinkingOnly(
bool appLinkingOnly) override;
63 std::optional<
bool> appLinkingOnly()
const;
66 std::optional<
bool> m_appLinkingOnly;
69QOhosOpenLinkOptionsImpl::QOhosOpenLinkOptionsImpl() =
default;
71void QOhosOpenLinkOptionsImpl::setAppLinkingOnly(
bool appLinkingOnly)
73 m_appLinkingOnly = appLinkingOnly;
76std::optional<
bool> QOhosOpenLinkOptionsImpl::appLinkingOnly()
const
78 return m_appLinkingOnly;
81using OnContinueResult = QtOhosHarmonyExtras::enums::ohos::app::ability::AbilityConstant::OnContinueResult;
83enum class AbilityOnContinueResponseStatus
90struct AbilityOnContinueRequest
92 int sourceApplicationVersionCode;
95struct AbilityOnContinueResponse
97 AbilityOnContinueResponseStatus status;
98 QMap<QString, QString> wantObjectParams;
99 std::optional<
bool> exitAppOnSourceDeviceAfterMigration;
102std::optional<OnContinueResult> tryMapAbilityOnContinueResponseStatusToOhos(
103 AbilityOnContinueResponseStatus status)
106 case AbilityOnContinueResponseStatus::Agree:
107 return OnContinueResult::AGREE;
108 case AbilityOnContinueResponseStatus::Reject:
109 return OnContinueResult::REJECT;
110 case AbilityOnContinueResponseStatus::Mismatch:
111 return OnContinueResult::MISMATCH;
116void setOnContinueRequestsHandlerForAbilityInstanceWindow(
117 QObject *windowObject,
118 std::function<
void(AbilityOnContinueRequest, QOhosConsumer<AbilityOnContinueResponse>)> requestsHandler)
120 auto *qWindow = qobject_cast<QWindow *>(windowObject);
121 if (qWindow ==
nullptr)
122 qOhosReportFatalErrorAndAbort(
"%s: windowObject argument is null or not a QWindow", Q_FUNC_INFO);
124 auto qWindowRef = QtOhos::QObjectThreadSafeRef(qWindow);
125 auto sharedRequestsHandler = QtOhos::moveToSharedPtr(std::move(requestsHandler));
127 struct JsResultContext
129 QNapi::Reference<QNapi::Object> wantParamsReference;
130 QOhosConsumer<QOhosJsState &, QNapi::Number> resultConsumer;
133 QOhosJsThreadGateway::runAndWait(
134 [&](QOhosJsState &jsState) {
135 auto optQAbility = jsState.tryGetQAbilityByQWindow(qWindowRef);
138 "%s: no ability for window %s, handler not set",
139 Q_FUNC_INFO, qWindowRef.refName().c_str());
143 jsState.setOnContinueRequestsHandler(
145 [sharedRequestsHandler](QOhosJsState &, QNapi::Object wantParamsObj,
auto resultConsumer) {
146 int sourceVersionCode = wantParamsObj.get<QNapi::Number>(
"version");
147 auto jsResultContext = QtOhos::makeProxyWithJsThreadDeleter(std::make_shared<JsResultContext>());
148 jsResultContext->wantParamsReference = QNapi::Reference<>::makePersistentFrom(wantParamsObj);
149 jsResultContext->resultConsumer = std::move(resultConsumer);
150 QtOhos::invokeInQtThread(
151 [sharedRequestsHandler, sourceVersionCode, jsResultContext]() {
152 (*sharedRequestsHandler)(
153 AbilityOnContinueRequest{
154 .sourceApplicationVersionCode = sourceVersionCode,
156 [jsResultContext](AbilityOnContinueResponse qtResponse) {
157 QOhosJsThreadGateway::invoke(
158 [jsResultContext, qtResponse](QOhosJsState &jsState) {
159 if (qtResponse.status == AbilityOnContinueResponseStatus::Agree) {
160 auto wantParamsObj = jsResultContext->wantParamsReference.Value();
161 auto newWantParamsIter = qtResponse.wantObjectParams.constKeyValueBegin();
162 while (newWantParamsIter != qtResponse.wantObjectParams.constKeyValueEnd()) {
164 newWantParamsIter->first.toStdString(),
165 newWantParamsIter->second.toStdString());
168 if (qtResponse.exitAppOnSourceDeviceAfterMigration.has_value()) {
170 jsState.eval<QNapi::String>(
171 "@ohos.app.ability.wantConstant.Params.SUPPORT_CONTINUE_SOURCE_EXIT_KEY"),
172 qtResponse.exitAppOnSourceDeviceAfterMigration.value());
175 auto optResultEnum = tryMapAbilityOnContinueResponseStatusToOhos(qtResponse.status);
176 if (!optResultEnum) {
178 "%s: got illegal status (%d) from requests handler, rejecting the request",
179 Q_FUNC_INFO,
static_cast<
int>(qtResponse.status));
181 jsResultContext->resultConsumer(
182 jsState, jsState.mapOhosEnumToJs(optResultEnum.value_or(OnContinueResult::REJECT)));
191void setDestroyAllowedFlagForAbilityInstances(
192 std::vector<QObject *> instancesMainWindows,
bool destroyEnabled)
194 std::vector<QtOhos::QObjectThreadSafeRef> instancesMainWindowsRefs;
195 for (
auto *instanceMainWindow : instancesMainWindows)
196 instancesMainWindowsRefs.emplace_back(instanceMainWindow);
198 QOhosJsThreadGateway::runAndWait(
199 [&](QOhosJsState &jsState) {
200 for (
const auto &instanceMainWindowRef : instancesMainWindowsRefs) {
201 auto optQAbility = jsState.tryGetQAbilityByQWindow(instanceMainWindowRef);
203 jsState.setDestroyFromSystemAllowed(optQAbility.value(), destroyEnabled);
209class QOhosOnContinueContextImpl :
public OnContinueContext
212 QOhosOnContinueContextImpl(
int sourceApplicationVersionCode);
214 void sendAgreeResponse(
const QByteArray &responseData)
override;
215 void sendRejectResponse() override;
216 void sendMismatchResponse() override;
218 void setExitAppOnSourceDeviceAfterMigration(
bool exitAfterMigration) override;
220 int sourceApplicationVersionCode()
const override;
222 AbilityOnContinueResponse response()
const;
225 int m_sourceApplicationVersionCode;
226 AbilityOnContinueResponse m_baseResponse;
227 std::optional<
bool> m_exitAppOnSourceDeviceAfterMigration;
230QOhosOnContinueContextImpl::QOhosOnContinueContextImpl(
int sourceApplicationVersionCode)
231 : OnContinueContext()
232 , m_sourceApplicationVersionCode(sourceApplicationVersionCode)
234 sendRejectResponse();
238
239
240
241
242
243
244
245void QOhosOnContinueContextImpl::sendAgreeResponse(
const QByteArray &responseData)
247 m_baseResponse = AbilityOnContinueResponse{
248 .status = AbilityOnContinueResponseStatus::Agree,
249 .wantObjectParams = {
251 QString::fromUtf8(qtOnContinueMigrationDataPropertyName),
252 QString::fromUtf8(responseData.toBase64())
255 .exitAppOnSourceDeviceAfterMigration = {},
260
261
262
263
264
265
266
267
268
269void QOhosOnContinueContextImpl::sendRejectResponse()
271 m_baseResponse = AbilityOnContinueResponse{
272 .status = AbilityOnContinueResponseStatus::Reject,
273 .wantObjectParams = {},
274 .exitAppOnSourceDeviceAfterMigration = {},
279
280
281
282
283
284
285
286
287
288
289void QOhosOnContinueContextImpl::sendMismatchResponse()
291 m_baseResponse = AbilityOnContinueResponse{
292 .status = AbilityOnContinueResponseStatus::Mismatch,
293 .wantObjectParams = {},
294 .exitAppOnSourceDeviceAfterMigration = {},
299
300
301
302
303
304
305
306void QOhosOnContinueContextImpl::setExitAppOnSourceDeviceAfterMigration(
bool exitAfterMigration)
308 m_exitAppOnSourceDeviceAfterMigration = exitAfterMigration;
311AbilityOnContinueResponse QOhosOnContinueContextImpl::response()
const
313 auto response = m_baseResponse;
314 response.exitAppOnSourceDeviceAfterMigration = m_exitAppOnSourceDeviceAfterMigration;
319
320
321
322
323
324
325int QOhosOnContinueContextImpl::sourceApplicationVersionCode()
const
327 return m_sourceApplicationVersionCode;
330std::optional<QtOhosHarmonyExtras::enums::ohos::app::ability::AbilityConstant::WindowMode> tryMapWindowModeToOhosOrLogWarning(
331 QOhosStartOptionsData::WindowMode windowMode)
333 namespace AbilityConstant = QtOhosHarmonyExtras::enums::ohos::app::ability::AbilityConstant;
334 using OptionsData = QOhosStartOptionsData;
336 switch (windowMode) {
337 case OptionsData::WindowMode::WINDOW_MODE_SPLIT_PRIMARY:
338 return std::make_optional(AbilityConstant::WindowMode::WINDOW_MODE_SPLIT_PRIMARY);
339 case OptionsData::WindowMode::WINDOW_MODE_SPLIT_SECONDARY:
340 return std::make_optional(AbilityConstant::WindowMode::WINDOW_MODE_SPLIT_SECONDARY);
341 case OptionsData::WindowMode::WINDOW_MODE_FULLSCREEN:
342 return std::make_optional(AbilityConstant::WindowMode::WINDOW_MODE_FULLSCREEN);
345 qCWarning(QtForOhos,
"%s: got illegal WindowMode: %d", Q_FUNC_INFO,
static_cast<
int>(windowMode));
350std::optional<QtOhosHarmonyExtras::enums::ohos::app::ability::contextConstant::ProcessMode> tryMapProcessModeToOhosOrLogWarning(
351 QOhosStartOptionsData::ProcessMode processMode)
353 namespace contextConstant = QtOhosHarmonyExtras::enums::ohos::app::ability::contextConstant;
354 using OptionsData = QOhosStartOptionsData;
356 switch (processMode) {
357 case OptionsData::ProcessMode::NEW_PROCESS_ATTACH_TO_PARENT:
358 return std::make_optional(contextConstant::ProcessMode::NEW_PROCESS_ATTACH_TO_PARENT);
359 case OptionsData::ProcessMode::NEW_PROCESS_ATTACH_TO_STATUS_BAR_ITEM:
360 return std::make_optional(contextConstant::ProcessMode::NEW_PROCESS_ATTACH_TO_STATUS_BAR_ITEM);
363 qCWarning(QtForOhos,
"%s: got illegal ProcessMode: %d", Q_FUNC_INFO,
static_cast<
int>(processMode));
368std::optional<QtOhosHarmonyExtras::enums::ohos::app::ability::contextConstant::StartupVisibility> tryMapStartupVisibilityToOhosOrLogWarning(
369 QOhosStartOptionsData::StartupVisibility startupVisibility)
371 namespace contextConstant = QtOhosHarmonyExtras::enums::ohos::app::ability::contextConstant;
372 using OptionsData = QOhosStartOptionsData;
374 switch (startupVisibility) {
375 case OptionsData::StartupVisibility::STARTUP_HIDE:
376 return std::make_optional(contextConstant::StartupVisibility::STARTUP_HIDE);
377 case OptionsData::StartupVisibility::STARTUP_SHOW:
378 return std::make_optional(contextConstant::StartupVisibility::STARTUP_SHOW);
381 qCWarning(QtForOhos,
"%s: got illegal StartupVisibility: %d", Q_FUNC_INFO,
static_cast<
int>(startupVisibility));
386std::optional<QtOhosHarmonyExtras::enums::ohos::bundle::bundleManager::SupportWindowMode> tryMapSupportWindowModeToOhosOrLogWarning(
387 QOhosStartOptionsData::SupportWindowMode supportWindowMode)
389 namespace bundleManager = QtOhosHarmonyExtras::enums::ohos::bundle::bundleManager;
390 using OptionsData = QOhosStartOptionsData;
392 switch (supportWindowMode) {
393 case OptionsData::SupportWindowMode::FULL_SCREEN:
394 return std::make_optional(bundleManager::SupportWindowMode::FULL_SCREEN);
395 case OptionsData::SupportWindowMode::SPLIT:
396 return std::make_optional(bundleManager::SupportWindowMode::SPLIT);
397 case OptionsData::SupportWindowMode::FLOATING:
398 return std::make_optional(bundleManager::SupportWindowMode::FLOATING);
401 qCWarning(QtForOhos,
"%s: got illegal SupportWindowMode: %d", Q_FUNC_INFO,
static_cast<
int>(supportWindowMode));
406QNapi::Array mapSupportWindowModesToJsEnumsArray(
407 QOhosJsState &jsState,
const QList<QOhosStartOptionsData::SupportWindowMode> &supportWindowModes)
409 std::vector<QNapi::ValueWrapper> jsSupportWindowModes;
410 for (
auto supportWindowMode : supportWindowModes) {
411 auto optOhosSupportWindowMode = tryMapSupportWindowModeToOhosOrLogWarning(supportWindowMode);
412 if (optOhosSupportWindowMode.has_value())
413 jsSupportWindowModes.push_back(jsState.mapOhosEnumToJs(optOhosSupportWindowMode.value()));
416 return QNapi::makeArray(jsState.env(), jsSupportWindowModes);
419QNapi::Object makeJsCompletionHandler(
420 QOhosJsState &jsState, std::shared_ptr<QOhosConsumer<
bool, QJsonObject, QString>> qtThreadCompletionHandler)
422 auto makeCompletionCallback = [qtThreadCompletionHandler](
bool requestSuccess) {
423 return [qtThreadCompletionHandler, requestSuccess](
const QNapi::CallbackInfo &cbInfo) {
424 QNapi::Object elementNameObj;
425 QNapi::String messageValue;
426 cbInfo.getLeadingArgs(Q_FUNC_INFO, elementNameObj, messageValue);
428 const QJsonObject elementName = QtOhos::mapNapiObjectToJsonObject(elementNameObj);
429 const QString message = QString::fromStdString(messageValue);
431 QtOhos::invokeInQtThread(
432 [qtThreadCompletionHandler, requestSuccess, elementName, message]() {
433 (*qtThreadCompletionHandler)(requestSuccess, elementName, message);
438 return QNapi::makeObject(
441 {
"onRequestSuccess", makeCompletionCallback(
true)},
442 {
"onRequestFailure", makeCompletionCallback(
false)},
446QNapi::Object convertStartOptionsToNapiObject(
447 QOhosJsState &jsState,
const QOhosStartOptionsData &opts)
449 auto *env = jsState.env();
450 auto napiOptions = QNapi::Object::New(env);
452 auto optOhosWindowMode = opts.windowMode.has_value()
453 ? tryMapWindowModeToOhosOrLogWarning(opts.windowMode.value())
455 if (optOhosWindowMode.has_value())
456 napiOptions.set(
"windowMode", jsState.mapOhosEnumToJs(optOhosWindowMode.value()));
457 if (opts.displayId.has_value())
458 napiOptions.set(
"displayId", opts.displayId.value());
459 if (opts.withAnimation.has_value())
460 napiOptions.set(
"withAnimation", opts.withAnimation.value());
461 if (opts.windowLeft.has_value())
462 napiOptions.set(
"windowLeft", opts.windowLeft.value());
463 if (opts.windowTop.has_value())
464 napiOptions.set(
"windowTop", opts.windowTop.value());
465 if (opts.windowWidth.has_value())
466 napiOptions.set(
"windowWidth", opts.windowWidth.value());
467 if (opts.windowHeight.has_value())
468 napiOptions.set(
"windowHeight", opts.windowHeight.value());
469 auto optOhosProcessMode = opts.processMode.has_value()
470 ? tryMapProcessModeToOhosOrLogWarning(opts.processMode.value())
472 if (optOhosProcessMode.has_value())
473 napiOptions.set(
"processMode", jsState.mapOhosEnumToJs(optOhosProcessMode.value()));
474 auto optOhosStartupVisibility = opts.startupVisibility.has_value()
475 ? tryMapStartupVisibilityToOhosOrLogWarning(opts.startupVisibility.value())
477 if (optOhosStartupVisibility.has_value())
478 napiOptions.set(
"startupVisibility", jsState.mapOhosEnumToJs(optOhosStartupVisibility.value()));
479 if (opts.windowIcon.has_value()) {
480 auto windowIcon = opts.windowIcon.value().value<QImage>();
481 if (!windowIcon.isNull())
482 napiOptions.set(
"startWindowIcon", makeOhosNapiPixelMapFromQImage(jsState, windowIcon));
484 if (opts.windowBackgroundColorHex.has_value())
485 napiOptions.set(
"startWindowBackgroundColor", opts.windowBackgroundColorHex.value().toStdString());
486 if (opts.supportWindowModes.has_value()) {
487 auto jsSupportWindowModes = mapSupportWindowModesToJsEnumsArray(jsState, opts.supportWindowModes.value());
488 if (jsSupportWindowModes.Length() != 0)
489 napiOptions.set(
"supportWindowModes", jsSupportWindowModes);
491 qCWarning(QtForOhos,
"%s: OHOS doesn't support empty supportWindowModes, skipping", Q_FUNC_INFO);
493 if (opts.minWindowWidth.has_value())
494 napiOptions.set(
"minWindowWidth", opts.minWindowWidth.value());
495 if (opts.minWindowHeight.has_value())
496 napiOptions.set(
"minWindowHeight", opts.minWindowHeight.value());
497 if (opts.maxWindowWidth.has_value())
498 napiOptions.set(
"maxWindowWidth", opts.maxWindowWidth.value());
499 if (opts.maxWindowHeight.has_value())
500 napiOptions.set(
"maxWindowHeight", opts.maxWindowHeight.value());
501 if (opts.optCompletionHandler)
502 napiOptions.set(
"completionHandler", makeJsCompletionHandler(jsState, opts.optCompletionHandler));
503 if (opts.hideStartWindow.has_value())
504 napiOptions.set(
"hideStartWindow", opts.hideStartWindow.value());
505 if (opts.windowCreateParams.has_value()) {
506 const auto &windowCreateParams = opts.windowCreateParams.value();
507 std::vector<std::pair<std::string, QNapi::ValueWrapper>> windowCreateParamsProps;
508 if (windowCreateParams.setWindowFadeInOutAnimation) {
509 windowCreateParamsProps.emplace_back(
516 jsState.mapOhosEnumToJs(
517 QtOhosHarmonyExtras::enums::ohos::window::AnimationType::FADE_IN_OUT),
521 napiOptions.set(
"windowCreateParams", QNapi::makeObject(env, windowCreateParamsProps));
527void requestStartAbilityForResult(
528 const Want &want, std::optional<QOhosStartOptionsData> options,
529 QWindow *optInstanceMainWindow, QObject *callerContext,
535 QtOhos::QObjectThreadSafeRef resultConsumerQtContextRef;
538 auto context = QtOhos::moveToSharedPtr(
540 .resultCallback = std::move(resultCallback),
541 .resultConsumerQtContextRef = QtOhos::QObjectThreadSafeRef(callerContext),
544 auto resultConsumer = [context](std::optional<QOhosAbilityResult> optAbilityResult) {
545 if (optAbilityResult.has_value()) {
546 auto abilityResult = optAbilityResult.value();
547 auto want = abilityResult.want.has_value()
548 ?
std::optional(convertWantFromJsonObject(abilityResult.want.value()))
552 context->resultCallback(
std::nullopt);
556 auto wantJson = convertWantToJsonObject(want);
557 auto optInstanceMainWindowRef =
558 optInstanceMainWindow !=
nullptr
559 ?
std::make_optional(QtOhos::QObjectThreadSafeRef(optInstanceMainWindow))
562 QOhosJsThreadGateway::invoke(
563 [context, resultConsumer, wantJson, options, optInstanceMainWindowRef](QOhosJsState &jsState) {
564 auto optUiAbility = optInstanceMainWindowRef.has_value()
565 ? jsState.tryGetQAbilityByQWindow(optInstanceMainWindowRef.value())
566 : jsState.defaultQAbility();
567 if (!optUiAbility.has_value()) {
568 context->resultConsumerQtContextRef.visitInQtThreadIfAlive(
569 [resultConsumer](
auto &) {
575 auto arguments = std::vector<QNapi::ValueWrapper>{QtOhos::mapJsonObjectToNapiObject(jsState.env(), wantJson)};
576 if (options.has_value())
577 arguments.push_back(convertStartOptionsToNapiObject(jsState, options.value()));
579 optUiAbility.value().evalToPromiseOrRejectOnThrow(
"context.startAbilityForResult(*)", arguments)
581 [context, resultConsumer](
const QOhosCallbackInfo &cbInfo) {
582 QNapi::Object abilityResult = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
583 int resultCode = abilityResult.get<QNapi::Number>(
"resultCode");
585 auto wantOrEmpty = QNapi::getOptionalPropOrEmpty<QNapi::Object>(abilityResult,
"want");
586 auto jsonWant = !wantOrEmpty.IsEmpty()
587 ? std::optional<QJsonObject>(QtOhos::mapNapiObjectToJsonObject(wantOrEmpty))
590 context->resultConsumerQtContextRef.visitInQtThreadIfAlive(
591 [resultConsumer, resultCode, jsonWant](
auto &) {
592 constexpr int startedAbilityErrorResultCode = -1;
594 resultCode != startedAbilityErrorResultCode
595 ? std::optional<QOhosAbilityResult>({resultCode, jsonWant})
600 [context, resultConsumer](
const QOhosCallbackInfo &cbInfo) {
601 QtOhos::logJsCallbackError(cbInfo,
"Got error from startAbilityForResult()");
602 context->resultConsumerQtContextRef.visitInQtThreadIfAlive(
603 [resultConsumer](
auto &) {
610class QOhosBaseAbilityContextImpl :
public AbilityContext
613 QOhosBaseAbilityContextImpl();
615 QByteArray generateUniqueId();
617 void startAbilityForResultImpl(
618 const Want &want, QWindow *optInstanceMainWindow,
619 std::optional<QOhosStartOptionsData> qpaStartOptions,
622 void shareDataWithShareKitImpl(
623 QWindow *optMainWindow,
const QList<std::shared_ptr<ShareKit::SharedRecord>> &records,
624 std::shared_ptr<ShareKit::ShareControllerOptions> controllerOptions,
626 std::function<
void(std::shared_ptr<ShareKit::ShareOperationResult>)> onShareCompleted,
627 std::function<
void()> onPanelClosed);
630 QOhosSupplier<QByteArray> m_uniqueIdsGenerator;
631 QHash<QByteArray, std::shared_ptr<
void>> m_shareDataRequestsHandles;
634class QOhosDefaultAbilityContextImpl :
public QOhosBaseAbilityContextImpl
637 QOhosDefaultAbilityContextImpl();
639 void setDestroyFromSystemEnabled(
bool destroyEnabled) override;
641 void startAbilityForResult(
642 const Want &want, std::shared_ptr<StartOptions> options, QObject *context,
645 void shareDataWithShareKit(
646 const QList<std::shared_ptr<ShareKit::SharedRecord>> &records,
647 std::shared_ptr<ShareKit::ShareControllerOptions> controllerOptions,
649 std::function<
void(std::shared_ptr<ShareKit::ShareOperationResult>)> onShareCompleted,
650 std::function<
void()> onPanelClosed)
override;
652 bool tryOpenLink(
const QString &link, std::shared_ptr<OpenLinkOptions> options)
override;
654 void setContinuationActive(
bool continuationActive) override;
657Q_GLOBAL_STATIC(QOhosDefaultAbilityContextImpl, s_defaultAbilityContextInstance)
659class QOhosAbilityContextImpl :
public QOhosBaseAbilityContextImpl
662 QOhosAbilityContextImpl(QWindow *instanceMainWindow);
664 void setDestroyFromSystemEnabled(
bool destroyEnabled) override;
666 void startAbilityForResult(
667 const Want &want, std::shared_ptr<StartOptions> options, QObject *context,
670 void shareDataWithShareKit(
671 const QList<std::shared_ptr<ShareKit::SharedRecord>> &records,
672 std::shared_ptr<ShareKit::ShareControllerOptions> controllerOptions,
674 std::function<
void(std::shared_ptr<ShareKit::ShareOperationResult>)> onShareCompleted,
675 std::function<
void()> onPanelClosed)
override;
677 bool tryOpenLink(
const QString &link, std::shared_ptr<OpenLinkOptions> options)
override;
679 void setContinuationActive(
bool continuationActive) override;
682 QPointer<QWindow> m_instanceMainWindow;
685std::map<QWindow *, std::unique_ptr<QOhosAbilityContextImpl>> abilityContextsMap;
687QOhosBaseAbilityContextImpl::QOhosBaseAbilityContextImpl()
688 : m_uniqueIdsGenerator(makeUniqueIdsGenerator())
692QByteArray QOhosBaseAbilityContextImpl::generateUniqueId()
694 return m_uniqueIdsGenerator();
697void QOhosBaseAbilityContextImpl::startAbilityForResultImpl(
698 const Want &want, QWindow *optInstanceMainWindow,
699 std::optional<QOhosStartOptionsData> qpaStartOptions,
702 requestStartAbilityForResult(
703 want,
std::move(qpaStartOptions), optInstanceMainWindow, context,
704 std::move(callback));
707void QOhosBaseAbilityContextImpl::shareDataWithShareKitImpl(
708 QWindow *optMainWindow,
const QList<std::shared_ptr<ShareKit::SharedRecord>> &records,
709 std::shared_ptr<ShareKit::ShareControllerOptions> controllerOptions,
711 std::function<
void(std::shared_ptr<ShareKit::ShareOperationResult>)> onShareCompleted,
712 std::function<
void()> onPanelClosed)
714 auto selfPtr = QPointer<QOhosBaseAbilityContextImpl>(
this);
715 auto contextPtr = QPointer<QObject>(context);
716 auto requestId = generateUniqueId();
717 auto requestHandle = shareData(
718 optMainWindow, records, controllerOptions,
719 [selfPtr, contextPtr, requestId, onPanelClosed]() {
720 if (!selfPtr.isNull())
721 selfPtr->m_shareDataRequestsHandles.remove(requestId);
722 if (!contextPtr.isNull() && onPanelClosed)
725 [contextPtr, onShareCompleted](
auto shareOperationResult) {
726 if (!contextPtr.isNull() && onShareCompleted)
727 onShareCompleted(shareOperationResult);
730 m_shareDataRequestsHandles.insert(requestId, requestHandle);
733QOhosDefaultAbilityContextImpl::QOhosDefaultAbilityContextImpl() =
default;
735void QOhosDefaultAbilityContextImpl::setDestroyFromSystemEnabled(
bool destroyEnabled)
737 qCDebug(QtForOhos,
"%s: setting destroyEnabled=%d for all instances", Q_FUNC_INFO, destroyEnabled);
739 std::vector<QObject *> instancesMainWindows;
740 for (
const auto &contextEntry : abilityContextsMap)
741 instancesMainWindows.push_back(contextEntry.first);
743 setDestroyAllowedFlagForAbilityInstances(instancesMainWindows, destroyEnabled);
746void QOhosDefaultAbilityContextImpl::startAbilityForResult(
747 const Want &want, std::shared_ptr<StartOptions> options, QObject *context,
750 startAbilityForResultImpl(
752 options ? tryConvertStartOptionsToQpaFunctionsStruct(*options) : std::nullopt,
753 context, std::move(callback));
756void QOhosDefaultAbilityContextImpl::shareDataWithShareKit(
757 const QList<std::shared_ptr<ShareKit::SharedRecord>> &records,
758 std::shared_ptr<ShareKit::ShareControllerOptions> controllerOptions,
760 std::function<
void(std::shared_ptr<ShareKit::ShareOperationResult>)> onShareCompleted,
761 std::function<
void()> onPanelClosed)
763 shareDataWithShareKitImpl(
764 nullptr, records, controllerOptions, context,
765 std::move(onShareCompleted), std::move(onPanelClosed));
768bool startAbilityByTypeImpl(
const QString &appType,
const QJsonObject &wantParameters)
772 return QOhosJsThreadGateway::evalWithPromise<
bool>(
773 [&](QOhosJsState &jsState, QOhosTaskPromise<
bool> evalPromise) {
774 auto optQAbility = jsState.defaultQAbility();
775 if (!optQAbility.has_value()) {
780 auto thenCatchPromises = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
781 optQAbility.value().evalToPromiseOrRejectOnThrow(
782 "context.startAbilityByType(*)",
784 appType.toStdString(),
785 QtOhos::mapJsonObjectToNapiObject(jsState.env(), wantParameters),
791 [](
const QOhosCallbackInfo&) {
792 qOhosPrintfDebug(
"startAbilityByType: onResult called");
797 [](
const QOhosCallbackInfo &cbInfo) {
798 QtOhos::logJsCallbackError(cbInfo,
"startAbilityByType: onError called");
804 [thenPromise = std::move(thenCatchPromises.first)](
const QOhosCallbackInfo &) {
808 [catchPromise = std::move(thenCatchPromises.second)](
const QOhosCallbackInfo &cbInfo) {
809 QtOhos::logJsCallbackError(cbInfo,
"startAbilityByType: failed");
816bool tryOpenLinkImpl(QObject *optInstanceMainWindow,
const QString &link,
std::optional<
bool> appLinkingOnly)
818 if (optInstanceMainWindow !=
nullptr && qobject_cast<QWindow *>(optInstanceMainWindow) ==
nullptr)
819 qOhosReportFatalErrorAndAbort(
"%s: the main window argument is not a QWindow", Q_FUNC_INFO);
821 auto optInstanceMainWindowRef = optInstanceMainWindow !=
nullptr
822 ?
std::make_optional(QtOhos::QObjectThreadSafeRef(optInstanceMainWindow))
825 return QOhosJsThreadGateway::evalWithPromise<
bool>(
826 [&](QOhosJsState &jsState, QOhosTaskPromise<
bool> evalPromise) {
827 auto optUiAbility = optInstanceMainWindowRef.has_value()
828 ? jsState.tryGetQAbilityByQWindow(optInstanceMainWindowRef.value())
829 : jsState.defaultQAbility();
830 if (!optUiAbility.has_value()) {
835 std::vector<std::pair<std::string, QNapi::ValueWrapper>> openLinkOptions;
836 if (appLinkingOnly.has_value())
837 openLinkOptions.emplace_back(
"appLinkingOnly", appLinkingOnly.value());
839 auto thenCatchPromises = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
840 optUiAbility.value().evalToPromiseOrRejectOnThrow(
841 "context.openLink(*)",
844 QNapi::makeObject(jsState.env(), openLinkOptions),
847 [thenPromise = std::move(thenCatchPromises.first)](
const QOhosCallbackInfo &) {
851 [catchPromise = std::move(thenCatchPromises.second)](
const QOhosCallbackInfo &cbInfo) {
852 QtOhos::logJsCallbackError(cbInfo,
"Got error from openLink()");
859void setContinuationActiveImpl(QObject *optInstanceMainWindow,
bool continuationActive)
861 using ContinueState = QtOhosHarmonyExtras::enums::ohos::app::ability::AbilityConstant::ContinueState;
863 auto optInstanceMainWindowRef = optInstanceMainWindow !=
nullptr
864 ?
std::make_optional(QtOhos::QObjectThreadSafeRef(optInstanceMainWindow))
867 QOhosJsThreadGateway::invokeAndWaitForContinue(
868 [&](QOhosJsState &jsState, QOhosTaskPromise<> taskPromise) {
869 auto optUiAbility = optInstanceMainWindowRef.has_value()
870 ? jsState.tryGetQAbilityByQWindow(optInstanceMainWindowRef.value())
871 : jsState.defaultQAbility();
872 if (!optUiAbility.has_value()) {
877 auto continueState = continuationActive ? ContinueState::ACTIVE : ContinueState::INACTIVE;
878 optUiAbility.value().evalToPromiseOrRejectOnThrow(
879 "context.setMissionContinueState(*)", {jsState.mapOhosEnumToJs(continueState)})
880 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setMissionContinueState()"))
881 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
886bool QOhosDefaultAbilityContextImpl::tryOpenLink(
const QString &link, std::shared_ptr<OpenLinkOptions> options)
888 return tryOpenLinkImpl(
891 ?
static_cast<
const QOhosOpenLinkOptionsImpl &>(*options).appLinkingOnly()
895void QOhosDefaultAbilityContextImpl::setContinuationActive(
bool continuationActive)
897 setContinuationActiveImpl(
nullptr, continuationActive);
900QOhosAbilityContextImpl::QOhosAbilityContextImpl(QWindow *instanceMainWindow)
901 : m_instanceMainWindow(instanceMainWindow)
903 setOnContinueRequestsHandlerForAbilityInstanceWindow(
905 [self = QPointer<QOhosAbilityContextImpl>(
this)](
auto request,
auto responseConsumer) {
906 auto context =
std::make_shared<QOhosOnContinueContextImpl>(request.sourceApplicationVersionCode);
909 Q_EMIT self->continueRequestReceived(context);
911 context->sendRejectResponse();
913 QtOhos::invokeInQtThread(
914 [response = context->response(), responseConsumer = std::move(responseConsumer)]() {
915 responseConsumer(response);
921
922
923
924
925
926
927
928
929
930
931
932
933
934void QOhosAbilityContextImpl::setDestroyFromSystemEnabled(
bool destroyEnabled)
936 if (m_instanceMainWindow.isNull()) {
937 qCWarning(QtForOhos,
"%s: called on destroyed instance, ignoring", Q_FUNC_INFO);
942 QtForOhos,
"%s: setting destroyEnabled=%d for window %p",
943 Q_FUNC_INFO, destroyEnabled, m_instanceMainWindow.data());
945 setDestroyAllowedFlagForAbilityInstances(
946 {m_instanceMainWindow.data()}, destroyEnabled);
950
951
952
953
954
955
956
957
958
959void QOhosAbilityContextImpl::startAbilityForResult(
960 const Want &want, std::shared_ptr<StartOptions> options, QObject *context,
963 startAbilityForResultImpl(
964 want, m_instanceMainWindow,
965 options ? tryConvertStartOptionsToQpaFunctionsStruct(*options) : std::nullopt,
966 context, std::move(callback));
970
971
972
973
974
975
976
977
978
979
980
981void QOhosAbilityContextImpl::shareDataWithShareKit(
982 const QList<std::shared_ptr<ShareKit::SharedRecord>> &records,
983 std::shared_ptr<ShareKit::ShareControllerOptions> controllerOptions,
985 std::function<
void(std::shared_ptr<ShareKit::ShareOperationResult>)> onShareCompleted,
986 std::function<
void()> onPanelClosed)
988 shareDataWithShareKitImpl(
989 m_instanceMainWindow, records, controllerOptions, context,
990 std::move(onShareCompleted), std::move(onPanelClosed));
994
995
996
997
998
999
1000
1001
1002bool QOhosAbilityContextImpl::tryOpenLink(
const QString &link, std::shared_ptr<OpenLinkOptions> options)
1004 return tryOpenLinkImpl(
1005 m_instanceMainWindow, link,
1007 ?
static_cast<
const QOhosOpenLinkOptionsImpl &>(*options).appLinkingOnly()
1012
1013
1014
1015
1016
1017
1018
1019void QOhosAbilityContextImpl::setContinuationActive(
bool continuationActive)
1021 setContinuationActiveImpl(m_instanceMainWindow, continuationActive);
1024std::shared_ptr<OperationStatus> startAbilityImpl(
1025 const Want &want, std::optional<QOhosStartOptionsData> qpaStartOptions)
1027 auto wantJson = convertWantToJsonObject(want);
1028 bool success = QOhosJsThreadGateway::eval(
1029 [&](QOhosJsState &jsState) {
1030 auto optMainUiAbility = jsState.defaultQAbility();
1031 if (!optMainUiAbility.has_value())
1033 auto mainUiAbility = optMainUiAbility.value();
1034 if (mainUiAbility.IsEmpty())
1037 auto arguments = std::vector<QNapi::ValueWrapper>{QtOhos::mapJsonObjectToNapiObject(jsState.env(), wantJson)};
1038 if (qpaStartOptions.has_value())
1039 arguments.push_back(convertStartOptionsToNapiObject(jsState, qpaStartOptions.value()));
1041 mainUiAbility.eval(
"context.startAbility(*)", arguments);
1049 return createOperationStatus(success);
1052void startAppProcessImpl(
1053 const QString &processId,
const Want &requestWant,
1054 std::optional<QOhosStartOptionsData> qpaStartOptions)
1056 auto requestWantJson = convertWantToJsonObject(requestWant);
1057 QOhosJsThreadGateway::invokeAndWaitForContinue(
1058 [&](QOhosJsState &jsState, QOhosTaskPromise<> taskPromise) {
1059 auto startOptions = qpaStartOptions.has_value()
1060 ? convertStartOptionsToNapiObject(jsState, qpaStartOptions.value())
1063 auto sharedTaskPromise = QtOhos::moveToSharedPtr(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1064 jsState.startAppProcess(
1065 processId.toStdString(),
1066 QtOhos::mapJsonObjectToNapiObject(jsState.env(), requestWantJson),
1068 [sharedTaskPromise](QOhosJsState &) {
1069 (*sharedTaskPromise)();
1078
1079
1080
1081
1082
1083
1084
1087
1088
1089
1090
1091
1092
1095
1096
1097
1098
1099
1100
1101
1102
1103
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1177 return startAbilityImpl(want, options ? tryConvertStartOptionsToQpaFunctionsStruct(*options) : std::nullopt);
1181
1182
1183
1184
1185
1186
1187
1188
1189
1192 bool success = startAbilityByTypeImpl(appType, wantParameters);
1193 return createOperationStatus(success);
1197
1198
1199
1200
1203 instanceWidget->show();
1207
1208
1209
1210
1211
1212void startAppProcess(
const QString &processId,
const Want &requestWant, std::shared_ptr<StartOptions> options)
1214 startAppProcessImpl(processId, requestWant, options ? tryConvertStartOptionsToQpaFunctionsStruct(*options) :
std::nullopt);
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1232 AbilityContext::instanceForMainWindow(instanceWindow)->setDestroyFromSystemEnabled(destroyEnabled);
1236
1237
1238
1239
1240
1241
1242
1245 auto key = QString::fromUtf8(qtOnContinueMigrationDataPropertyName);
1246 if (want.parameters.contains(key)) {
1247 auto base64String = want.parameters.value(key).toString();
1248 auto decodedData = QByteArray::fromBase64(base64String.toUtf8());
1256
1257
1258
1259
1260
1261
1262
1263
1272 return std::make_shared<QOhosOpenLinkOptionsImpl>();