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())
258
259
260
261
262
263
264
265
266
267void QOhosOnContinueContextImpl::sendRejectResponse()
269 m_baseResponse = AbilityOnContinueResponse{
270 .status = AbilityOnContinueResponseStatus::Reject,
271 .wantObjectParams = {},
276
277
278
279
280
281
282
283
284
285
286void QOhosOnContinueContextImpl::sendMismatchResponse()
288 m_baseResponse = AbilityOnContinueResponse{
289 .status = AbilityOnContinueResponseStatus::Mismatch,
290 .wantObjectParams = {},
295
296
297
298
299
300
301
302void QOhosOnContinueContextImpl::setExitAppOnSourceDeviceAfterMigration(
bool exitAfterMigration)
304 m_exitAppOnSourceDeviceAfterMigration = exitAfterMigration;
307AbilityOnContinueResponse QOhosOnContinueContextImpl::response()
const
309 auto response = m_baseResponse;
310 response.exitAppOnSourceDeviceAfterMigration = m_exitAppOnSourceDeviceAfterMigration;
315
316
317
318
319
320
321int QOhosOnContinueContextImpl::sourceApplicationVersionCode()
const
323 return m_sourceApplicationVersionCode;
326std::optional<QtOhos::enums::ohos::app::ability::AbilityConstant::WindowMode> tryMapWindowModeToOhosOrLogWarning(
327 QOhosStartOptionsData::WindowMode windowMode)
329 namespace AbilityConstant = QtOhos::enums::ohos::app::ability::AbilityConstant;
330 using OptionsData = QOhosStartOptionsData;
332 switch (windowMode) {
333 case OptionsData::WindowMode::WINDOW_MODE_SPLIT_PRIMARY:
334 return std::make_optional(AbilityConstant::WindowMode::WINDOW_MODE_SPLIT_PRIMARY);
335 case OptionsData::WindowMode::WINDOW_MODE_SPLIT_SECONDARY:
336 return std::make_optional(AbilityConstant::WindowMode::WINDOW_MODE_SPLIT_SECONDARY);
337 case OptionsData::WindowMode::WINDOW_MODE_FULLSCREEN:
338 return std::make_optional(AbilityConstant::WindowMode::WINDOW_MODE_FULLSCREEN);
341 qCWarning(QtForOhos,
"%s: got illegal WindowMode: %d", Q_FUNC_INFO,
static_cast<
int>(windowMode));
346std::optional<QtOhos::enums::ohos::app::ability::contextConstant::ProcessMode> tryMapProcessModeToOhosOrLogWarning(
347 QOhosStartOptionsData::ProcessMode processMode)
349 namespace contextConstant = QtOhos::enums::ohos::app::ability::contextConstant;
350 using OptionsData = QOhosStartOptionsData;
352 switch (processMode) {
353 case OptionsData::ProcessMode::NEW_PROCESS_ATTACH_TO_PARENT:
354 return std::make_optional(contextConstant::ProcessMode::NEW_PROCESS_ATTACH_TO_PARENT);
355 case OptionsData::ProcessMode::NEW_PROCESS_ATTACH_TO_STATUS_BAR_ITEM:
356 return std::make_optional(contextConstant::ProcessMode::NEW_PROCESS_ATTACH_TO_STATUS_BAR_ITEM);
359 qCWarning(QtForOhos,
"%s: got illegal ProcessMode: %d", Q_FUNC_INFO,
static_cast<
int>(processMode));
364std::optional<QtOhos::enums::ohos::app::ability::contextConstant::StartupVisibility> tryMapStartupVisibilityToOhosOrLogWarning(
365 QOhosStartOptionsData::StartupVisibility startupVisibility)
367 namespace contextConstant = QtOhos::enums::ohos::app::ability::contextConstant;
368 using OptionsData = QOhosStartOptionsData;
370 switch (startupVisibility) {
371 case OptionsData::StartupVisibility::STARTUP_HIDE:
372 return std::make_optional(contextConstant::StartupVisibility::STARTUP_HIDE);
373 case OptionsData::StartupVisibility::STARTUP_SHOW:
374 return std::make_optional(contextConstant::StartupVisibility::STARTUP_SHOW);
377 qCWarning(QtForOhos,
"%s: got illegal StartupVisibility: %d", Q_FUNC_INFO,
static_cast<
int>(startupVisibility));
382std::optional<QtOhos::enums::ohos::bundle::bundleManager::SupportWindowMode> tryMapSupportWindowModeToOhosOrLogWarning(
383 QOhosStartOptionsData::SupportWindowMode supportWindowMode)
385 namespace bundleManager = QtOhos::enums::ohos::bundle::bundleManager;
386 using OptionsData = QOhosStartOptionsData;
388 switch (supportWindowMode) {
389 case OptionsData::SupportWindowMode::FULL_SCREEN:
390 return std::make_optional(bundleManager::SupportWindowMode::FULL_SCREEN);
391 case OptionsData::SupportWindowMode::SPLIT:
392 return std::make_optional(bundleManager::SupportWindowMode::SPLIT);
393 case OptionsData::SupportWindowMode::FLOATING:
394 return std::make_optional(bundleManager::SupportWindowMode::FLOATING);
397 qCWarning(QtForOhos,
"%s: got illegal SupportWindowMode: %d", Q_FUNC_INFO,
static_cast<
int>(supportWindowMode));
402QNapi::Array mapSupportWindowModesToJsEnumsArray(
403 QOhosJsState &jsState,
const QList<QOhosStartOptionsData::SupportWindowMode> &supportWindowModes)
405 std::vector<QNapi::ValueWrapper> jsSupportWindowModes;
406 for (
auto supportWindowMode : supportWindowModes) {
407 auto optOhosSupportWindowMode = tryMapSupportWindowModeToOhosOrLogWarning(supportWindowMode);
408 if (optOhosSupportWindowMode.has_value())
409 jsSupportWindowModes.push_back(jsState.mapOhosEnumToJs(optOhosSupportWindowMode.value()));
412 return QNapi::makeArray(jsState.env(), jsSupportWindowModes);
415QNapi::Object makeJsCompletionHandler(
416 QOhosJsState &jsState, std::shared_ptr<QOhosConsumer<
bool, QJsonObject, QString>> qtThreadCompletionHandler)
418 auto makeCompletionCallback = [qtThreadCompletionHandler](
bool requestSuccess) {
419 return [qtThreadCompletionHandler, requestSuccess](
const QNapi::CallbackInfo &cbInfo) {
420 QNapi::Object elementNameObj;
421 QNapi::String messageValue;
422 cbInfo.getLeadingArgs(Q_FUNC_INFO, elementNameObj, messageValue);
424 const QJsonObject elementName = QOhosJsEnv::fromNapiValue<QJsonObject>(elementNameObj);
425 const QString message = QString::fromStdString(messageValue);
427 QtOhos::invokeInQtThread(
428 [qtThreadCompletionHandler, requestSuccess, elementName, message]() {
429 (*qtThreadCompletionHandler)(requestSuccess, elementName, message);
434 return QNapi::makeObject(
437 {
"onRequestSuccess", makeCompletionCallback(
true)},
438 {
"onRequestFailure", makeCompletionCallback(
false)},
442QNapi::Object convertStartOptionsToNapiObject(
443 QOhosJsState &jsState,
const QOhosStartOptionsData &opts)
445 auto *env = jsState.env();
446 auto napiOptions = QNapi::Object::New(env);
448 auto optOhosWindowMode = opts.windowMode.has_value()
449 ? tryMapWindowModeToOhosOrLogWarning(opts.windowMode.value())
451 if (optOhosWindowMode.has_value())
452 napiOptions.set(
"windowMode", jsState.mapOhosEnumToJs(optOhosWindowMode.value()));
453 if (opts.displayId.has_value())
454 napiOptions.set(
"displayId", opts.displayId.value());
455 if (opts.withAnimation.has_value())
456 napiOptions.set(
"withAnimation", opts.withAnimation.value());
457 if (opts.windowLeft.has_value())
458 napiOptions.set(
"windowLeft", opts.windowLeft.value());
459 if (opts.windowTop.has_value())
460 napiOptions.set(
"windowTop", opts.windowTop.value());
461 if (opts.windowWidth.has_value())
462 napiOptions.set(
"windowWidth", opts.windowWidth.value());
463 if (opts.windowHeight.has_value())
464 napiOptions.set(
"windowHeight", opts.windowHeight.value());
465 auto optOhosProcessMode = opts.processMode.has_value()
466 ? tryMapProcessModeToOhosOrLogWarning(opts.processMode.value())
468 if (optOhosProcessMode.has_value())
469 napiOptions.set(
"processMode", jsState.mapOhosEnumToJs(optOhosProcessMode.value()));
470 auto optOhosStartupVisibility = opts.startupVisibility.has_value()
471 ? tryMapStartupVisibilityToOhosOrLogWarning(opts.startupVisibility.value())
473 if (optOhosStartupVisibility.has_value())
474 napiOptions.set(
"startupVisibility", jsState.mapOhosEnumToJs(optOhosStartupVisibility.value()));
475 if (opts.windowIcon.has_value()) {
476 auto windowIcon = opts.windowIcon.value().value<QImage>();
477 if (!windowIcon.isNull())
478 napiOptions.set(
"startWindowIcon", makeOhosNapiPixelMapFromQImage(jsState, windowIcon));
480 if (opts.windowBackgroundColorHex.has_value())
481 napiOptions.set(
"startWindowBackgroundColor", opts.windowBackgroundColorHex.value().toStdString());
482 if (opts.supportWindowModes.has_value()) {
483 auto jsSupportWindowModes = mapSupportWindowModesToJsEnumsArray(jsState, opts.supportWindowModes.value());
484 if (jsSupportWindowModes.Length() != 0)
485 napiOptions.set(
"supportWindowModes", jsSupportWindowModes);
487 qCWarning(QtForOhos,
"%s: OHOS doesn't support empty supportWindowModes, skipping", Q_FUNC_INFO);
489 if (opts.minWindowWidth.has_value())
490 napiOptions.set(
"minWindowWidth", opts.minWindowWidth.value());
491 if (opts.minWindowHeight.has_value())
492 napiOptions.set(
"minWindowHeight", opts.minWindowHeight.value());
493 if (opts.maxWindowWidth.has_value())
494 napiOptions.set(
"maxWindowWidth", opts.maxWindowWidth.value());
495 if (opts.maxWindowHeight.has_value())
496 napiOptions.set(
"maxWindowHeight", opts.maxWindowHeight.value());
497 if (opts.optCompletionHandler)
498 napiOptions.set(
"completionHandler", makeJsCompletionHandler(jsState, opts.optCompletionHandler));
499 if (opts.hideStartWindow.has_value())
500 napiOptions.set(
"hideStartWindow", opts.hideStartWindow.value());
501 if (opts.windowCreateParams.has_value()) {
502 const auto &windowCreateParams = opts.windowCreateParams.value();
503 std::vector<std::pair<std::string, QNapi::ValueWrapper>> windowCreateParamsProps;
504 if (windowCreateParams.setWindowFadeInOutAnimation) {
505 windowCreateParamsProps.emplace_back(
512 jsState.mapOhosEnumToJs(
513 QtOhos::enums::ohos::window::AnimationType::FADE_IN_OUT),
517 napiOptions.set(
"windowCreateParams", QNapi::makeObject(env, windowCreateParamsProps));
523void requestStartAbilityForResult(
524 const Want &want, std::optional<QOhosStartOptionsData> options,
525 QWindow *optInstanceMainWindow, QObject *callerContext,
531 QtOhos::QObjectThreadSafeRef resultConsumerQtContextRef;
534 auto context = QtOhos::moveToSharedPtr(
536 .resultCallback = std::move(resultCallback),
537 .resultConsumerQtContextRef = QtOhos::QObjectThreadSafeRef(callerContext),
540 auto resultConsumer = [context](std::optional<QOhosAbilityResult> optAbilityResult) {
541 if (optAbilityResult.has_value()) {
542 auto abilityResult = optAbilityResult.value();
543 auto want = abilityResult.want.has_value()
544 ?
std::optional(convertWantFromJsonObject(abilityResult.want.value()))
548 context->resultCallback(
std::nullopt);
552 auto wantJson = convertWantToJsonObject(want);
553 auto optInstanceMainWindowRef =
554 optInstanceMainWindow !=
nullptr
555 ?
std::make_optional(QtOhos::QObjectThreadSafeRef(optInstanceMainWindow))
558 QOhosJsThreadGateway::invoke(
559 [context, resultConsumer, wantJson, options, optInstanceMainWindowRef](QOhosJsState &jsState) {
560 auto optUiAbility = optInstanceMainWindowRef.has_value()
561 ? jsState.tryGetQAbilityByQWindow(optInstanceMainWindowRef.value())
562 : jsState.defaultQAbility();
563 if (!optUiAbility.has_value()) {
564 context->resultConsumerQtContextRef.visitInQtThreadIfAlive(
565 [resultConsumer](
auto &) {
571 auto arguments = std::vector<QNapi::ValueWrapper>{QOhosJsEnv::toNapiValue(jsState.env(), wantJson)};
572 if (options.has_value())
573 arguments.push_back(convertStartOptionsToNapiObject(jsState, options.value()));
575 optUiAbility.value().evalToPromiseOrRejectOnThrow(
"context.startAbilityForResult(*)", arguments)
577 [context, resultConsumer](
const QOhosCallbackInfo &cbInfo) {
578 QNapi::Object abilityResult = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
579 int resultCode = abilityResult.get<QNapi::Number>(
"resultCode");
581 auto wantOrEmpty = QNapi::getOptionalPropOrEmpty<QNapi::Object>(abilityResult,
"want");
582 auto jsonWant = !wantOrEmpty.IsEmpty()
583 ? std::optional<QJsonObject>(QOhosJsEnv::fromNapiValue<QJsonObject>(wantOrEmpty))
586 context->resultConsumerQtContextRef.visitInQtThreadIfAlive(
587 [resultConsumer, resultCode, jsonWant](
auto &) {
588 constexpr int startedAbilityErrorResultCode = -1;
590 resultCode != startedAbilityErrorResultCode
591 ? std::optional<QOhosAbilityResult>({resultCode, jsonWant})
596 [context, resultConsumer](
const QOhosCallbackInfo &cbInfo) {
597 QtOhos::logJsCallbackError(cbInfo,
"Got error from startAbilityForResult()");
598 context->resultConsumerQtContextRef.visitInQtThreadIfAlive(
599 [resultConsumer](
auto &) {
606class QOhosBaseAbilityContextImpl :
public AbilityContext
609 QOhosBaseAbilityContextImpl();
611 QByteArray generateUniqueId();
613 void startAbilityForResultImpl(
614 const Want &want, QWindow *optInstanceMainWindow,
615 std::optional<QOhosStartOptionsData> qpaStartOptions,
618 void shareDataWithShareKitImpl(
619 QWindow *optMainWindow,
const QList<std::shared_ptr<ShareKit::SharedRecord>> &records,
620 std::shared_ptr<ShareKit::ShareControllerOptions> controllerOptions,
622 std::function<
void(std::shared_ptr<ShareKit::ShareOperationResult>)> onShareCompleted,
623 std::function<
void()> onPanelClosed);
626 QOhosSupplier<QByteArray> m_uniqueIdsGenerator;
627 QHash<QByteArray, std::shared_ptr<
void>> m_shareDataRequestsHandles;
630class QOhosDefaultAbilityContextImpl :
public QOhosBaseAbilityContextImpl
633 QOhosDefaultAbilityContextImpl();
635 void setDestroyFromSystemEnabled(
bool destroyEnabled) override;
637 void startAbilityForResult(
638 const Want &want, std::shared_ptr<StartOptions> options, QObject *context,
641 void shareDataWithShareKit(
642 const QList<std::shared_ptr<ShareKit::SharedRecord>> &records,
643 std::shared_ptr<ShareKit::ShareControllerOptions> controllerOptions,
645 std::function<
void(std::shared_ptr<ShareKit::ShareOperationResult>)> onShareCompleted,
646 std::function<
void()> onPanelClosed)
override;
648 bool tryOpenLink(
const QString &link, std::shared_ptr<OpenLinkOptions> options)
override;
650 void setContinuationActive(
bool continuationActive) override;
653class QOhosAbilityContextImpl :
public QOhosBaseAbilityContextImpl
656 QOhosAbilityContextImpl(QWindow *instanceMainWindow);
658 void setDestroyFromSystemEnabled(
bool destroyEnabled) override;
660 void startAbilityForResult(
661 const Want &want, std::shared_ptr<StartOptions> options, QObject *context,
664 void shareDataWithShareKit(
665 const QList<std::shared_ptr<ShareKit::SharedRecord>> &records,
666 std::shared_ptr<ShareKit::ShareControllerOptions> controllerOptions,
668 std::function<
void(std::shared_ptr<ShareKit::ShareOperationResult>)> onShareCompleted,
669 std::function<
void()> onPanelClosed)
override;
671 bool tryOpenLink(
const QString &link, std::shared_ptr<OpenLinkOptions> options)
override;
673 void setContinuationActive(
bool continuationActive) override;
676 QPointer<QWindow> m_instanceMainWindow;
679std::map<QWindow *, std::unique_ptr<QOhosAbilityContextImpl>> abilityContextsMap;
681QOhosBaseAbilityContextImpl::QOhosBaseAbilityContextImpl()
682 : m_uniqueIdsGenerator(makeUniqueIdsGenerator())
686QByteArray QOhosBaseAbilityContextImpl::generateUniqueId()
688 return m_uniqueIdsGenerator();
691void QOhosBaseAbilityContextImpl::startAbilityForResultImpl(
692 const Want &want, QWindow *optInstanceMainWindow,
693 std::optional<QOhosStartOptionsData> qpaStartOptions,
696 requestStartAbilityForResult(
697 want,
std::move(qpaStartOptions), optInstanceMainWindow, context,
698 std::move(callback));
701void QOhosBaseAbilityContextImpl::shareDataWithShareKitImpl(
702 QWindow *optMainWindow,
const QList<std::shared_ptr<ShareKit::SharedRecord>> &records,
703 std::shared_ptr<ShareKit::ShareControllerOptions> controllerOptions,
705 std::function<
void(std::shared_ptr<ShareKit::ShareOperationResult>)> onShareCompleted,
706 std::function<
void()> onPanelClosed)
708 auto selfPtr = QPointer<QOhosBaseAbilityContextImpl>(
this);
709 auto contextPtr = QPointer<QObject>(context);
710 auto requestId = generateUniqueId();
711 auto requestHandle = shareData(
712 optMainWindow, records, controllerOptions,
713 [selfPtr, contextPtr, requestId, onPanelClosed]() {
714 if (!selfPtr.isNull())
715 selfPtr->m_shareDataRequestsHandles.remove(requestId);
716 if (!contextPtr.isNull() && onPanelClosed)
719 [contextPtr, onShareCompleted](
auto shareOperationResult) {
720 if (!contextPtr.isNull() && onShareCompleted)
721 onShareCompleted(shareOperationResult);
724 m_shareDataRequestsHandles.insert(requestId, requestHandle);
727QOhosDefaultAbilityContextImpl::QOhosDefaultAbilityContextImpl() =
default;
729void QOhosDefaultAbilityContextImpl::setDestroyFromSystemEnabled(
bool destroyEnabled)
731 qCDebug(QtForOhos,
"%s: setting destroyEnabled=%d for all instances", Q_FUNC_INFO, destroyEnabled);
733 std::vector<QObject *> instancesMainWindows;
734 for (
const auto &contextEntry : abilityContextsMap)
735 instancesMainWindows.push_back(contextEntry.first);
737 setDestroyAllowedFlagForAbilityInstances(instancesMainWindows, destroyEnabled);
740void QOhosDefaultAbilityContextImpl::startAbilityForResult(
741 const Want &want, std::shared_ptr<StartOptions> options, QObject *context,
744 startAbilityForResultImpl(
746 options ? tryConvertStartOptionsToQpaFunctionsStruct(*options) : std::nullopt,
747 context, std::move(callback));
750void QOhosDefaultAbilityContextImpl::shareDataWithShareKit(
751 const QList<std::shared_ptr<ShareKit::SharedRecord>> &records,
752 std::shared_ptr<ShareKit::ShareControllerOptions> controllerOptions,
754 std::function<
void(std::shared_ptr<ShareKit::ShareOperationResult>)> onShareCompleted,
755 std::function<
void()> onPanelClosed)
757 shareDataWithShareKitImpl(
758 nullptr, records, controllerOptions, context,
759 std::move(onShareCompleted), std::move(onPanelClosed));
762bool startAbilityByTypeImpl(
const QString &appType,
const QJsonObject &wantParameters)
766 return QOhosJsThreadGateway::evalWithPromise<
bool>(
767 [&](QOhosJsState &jsState, QOhosTaskPromise<
bool> evalPromise) {
768 auto optQAbility = jsState.defaultQAbility();
769 if (!optQAbility.has_value()) {
774 auto thenCatchPromises = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
775 optQAbility.value().evalToPromiseOrRejectOnThrow(
776 "context.startAbilityByType(*)",
778 appType.toStdString(),
779 QOhosJsEnv::toNapiValue(jsState.env(), wantParameters),
785 [](
const QOhosCallbackInfo&) {
786 qOhosPrintfDebug(
"startAbilityByType: onResult called");
791 [](
const QOhosCallbackInfo &cbInfo) {
792 QtOhos::logJsCallbackError(cbInfo,
"startAbilityByType: onError called");
798 [thenPromise = std::move(thenCatchPromises.first)](
const QOhosCallbackInfo &) {
802 [catchPromise = std::move(thenCatchPromises.second)](
const QOhosCallbackInfo &cbInfo) {
803 QtOhos::logJsCallbackError(cbInfo,
"startAbilityByType: failed");
810bool tryOpenLinkImpl(QObject *optInstanceMainWindow,
const QString &link,
std::optional<
bool> appLinkingOnly)
812 if (optInstanceMainWindow !=
nullptr && qobject_cast<QWindow *>(optInstanceMainWindow) ==
nullptr)
813 qOhosReportFatalErrorAndAbort(
"%s: the main window argument is not a QWindow", Q_FUNC_INFO);
815 auto optInstanceMainWindowRef = optInstanceMainWindow !=
nullptr
816 ?
std::make_optional(QtOhos::QObjectThreadSafeRef(optInstanceMainWindow))
819 return QOhosJsThreadGateway::evalWithPromise<
bool>(
820 [&](QOhosJsState &jsState, QOhosTaskPromise<
bool> evalPromise) {
821 auto optUiAbility = optInstanceMainWindowRef.has_value()
822 ? jsState.tryGetQAbilityByQWindow(optInstanceMainWindowRef.value())
823 : jsState.defaultQAbility();
824 if (!optUiAbility.has_value()) {
829 std::vector<std::pair<std::string, QNapi::ValueWrapper>> openLinkOptions;
830 if (appLinkingOnly.has_value())
831 openLinkOptions.emplace_back(
"appLinkingOnly", appLinkingOnly.value());
833 auto thenCatchPromises = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
834 optUiAbility.value().evalToPromiseOrRejectOnThrow(
835 "context.openLink(*)",
838 QNapi::makeObject(jsState.env(), openLinkOptions),
841 [thenPromise = std::move(thenCatchPromises.first)](
const QOhosCallbackInfo &) {
845 [catchPromise = std::move(thenCatchPromises.second)](
const QOhosCallbackInfo &cbInfo) {
846 QtOhos::logJsCallbackError(cbInfo,
"Got error from openLink()");
853void setContinuationActiveImpl(QObject *optInstanceMainWindow,
bool continuationActive)
855 using ContinueState = QtOhos::enums::ohos::app::ability::AbilityConstant::ContinueState;
857 auto optInstanceMainWindowRef = optInstanceMainWindow !=
nullptr
858 ?
std::make_optional(QtOhos::QObjectThreadSafeRef(optInstanceMainWindow))
861 QOhosJsThreadGateway::invokeAndWaitForContinue(
862 [&](QOhosJsState &jsState, QOhosTaskPromise<> taskPromise) {
863 auto optUiAbility = optInstanceMainWindowRef.has_value()
864 ? jsState.tryGetQAbilityByQWindow(optInstanceMainWindowRef.value())
865 : jsState.defaultQAbility();
866 if (!optUiAbility.has_value()) {
871 auto continueState = continuationActive ? ContinueState::ACTIVE : ContinueState::INACTIVE;
872 optUiAbility.value().evalToPromiseOrRejectOnThrow(
873 "context.setMissionContinueState(*)", {jsState.mapOhosEnumToJs(continueState)})
874 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setMissionContinueState()"))
875 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
880bool QOhosDefaultAbilityContextImpl::tryOpenLink(
const QString &link, std::shared_ptr<OpenLinkOptions> options)
882 return tryOpenLinkImpl(
885 ?
static_cast<
const QOhosOpenLinkOptionsImpl &>(*options).appLinkingOnly()
889void QOhosDefaultAbilityContextImpl::setContinuationActive(
bool continuationActive)
891 setContinuationActiveImpl(
nullptr, continuationActive);
894QOhosAbilityContextImpl::QOhosAbilityContextImpl(QWindow *instanceMainWindow)
895 : m_instanceMainWindow(instanceMainWindow)
897 setOnContinueRequestsHandlerForAbilityInstanceWindow(
899 [self = QPointer<QOhosAbilityContextImpl>(
this)](
auto request,
auto responseConsumer) {
900 auto context =
std::make_shared<QOhosOnContinueContextImpl>(request.sourceApplicationVersionCode);
903 Q_EMIT self->continueRequestReceived(context);
905 context->sendRejectResponse();
907 QtOhos::invokeInQtThread(
908 [response = context->response(), responseConsumer = std::move(responseConsumer)]() {
909 responseConsumer(response);
915
916
917
918
919
920
921
922
923
924
925
926
927
928void QOhosAbilityContextImpl::setDestroyFromSystemEnabled(
bool destroyEnabled)
930 if (m_instanceMainWindow.isNull()) {
931 qCWarning(QtForOhos,
"%s: called on destroyed instance, ignoring", Q_FUNC_INFO);
936 QtForOhos,
"%s: setting destroyEnabled=%d for window %p",
937 Q_FUNC_INFO, destroyEnabled, m_instanceMainWindow.data());
939 setDestroyAllowedFlagForAbilityInstances(
940 {m_instanceMainWindow.data()}, destroyEnabled);
944
945
946
947
948
949
950
951
952
953void QOhosAbilityContextImpl::startAbilityForResult(
954 const Want &want, std::shared_ptr<StartOptions> options, QObject *context,
957 startAbilityForResultImpl(
958 want, m_instanceMainWindow,
959 options ? tryConvertStartOptionsToQpaFunctionsStruct(*options) : std::nullopt,
960 context, std::move(callback));
964
965
966
967
968
969
970
971
972
973
974
975void QOhosAbilityContextImpl::shareDataWithShareKit(
976 const QList<std::shared_ptr<ShareKit::SharedRecord>> &records,
977 std::shared_ptr<ShareKit::ShareControllerOptions> controllerOptions,
979 std::function<
void(std::shared_ptr<ShareKit::ShareOperationResult>)> onShareCompleted,
980 std::function<
void()> onPanelClosed)
982 shareDataWithShareKitImpl(
983 m_instanceMainWindow, records, controllerOptions, context,
984 std::move(onShareCompleted), std::move(onPanelClosed));
988
989
990
991
992
993
994
995
996bool QOhosAbilityContextImpl::tryOpenLink(
const QString &link, std::shared_ptr<OpenLinkOptions> options)
998 return tryOpenLinkImpl(
999 m_instanceMainWindow, link,
1001 ?
static_cast<
const QOhosOpenLinkOptionsImpl &>(*options).appLinkingOnly()
1006
1007
1008
1009
1010
1011
1012
1013void QOhosAbilityContextImpl::setContinuationActive(
bool continuationActive)
1015 setContinuationActiveImpl(m_instanceMainWindow, continuationActive);
1018std::shared_ptr<OperationStatus> startAbilityImpl(
1019 const Want &want, std::optional<QOhosStartOptionsData> qpaStartOptions)
1021 auto wantJson = convertWantToJsonObject(want);
1022 bool success = QOhosJsThreadGateway::eval(
1023 [&](QOhosJsState &jsState) {
1024 auto optMainUiAbility = jsState.defaultQAbility();
1025 if (!optMainUiAbility.has_value())
1027 auto mainUiAbility = optMainUiAbility.value();
1028 if (mainUiAbility.IsEmpty())
1031 auto arguments = std::vector<QNapi::ValueWrapper>{QOhosJsEnv::toNapiValue(jsState.env(), wantJson)};
1032 if (qpaStartOptions.has_value())
1033 arguments.push_back(convertStartOptionsToNapiObject(jsState, qpaStartOptions.value()));
1035 mainUiAbility.eval(
"context.startAbility(*)", arguments);
1043 return createOperationStatus(success);
1046void startAppProcessImpl(
1047 const QString &processId,
const Want &requestWant,
1048 std::optional<QOhosStartOptionsData> qpaStartOptions)
1050 auto requestWantJson = convertWantToJsonObject(requestWant);
1051 QOhosJsThreadGateway::invokeAndWaitForContinue(
1052 [&](QOhosJsState &jsState, QOhosTaskPromise<> taskPromise) {
1053 auto startOptions = qpaStartOptions.has_value()
1054 ? convertStartOptionsToNapiObject(jsState, qpaStartOptions.value())
1057 auto sharedTaskPromise = QtOhos::moveToSharedPtr(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1058 jsState.startAppProcess(
1059 processId.toStdString(),
1060 QNapi::checkedCast<QNapi::Object>(
1061 QOhosJsEnv::toNapiValue(jsState.env(), requestWantJson)),
1063 [sharedTaskPromise](QOhosJsState &) {
1064 (*sharedTaskPromise)();
1073
1074
1075
1076
1077
1078
1079
1082
1083
1084
1085
1086
1087
1090
1091
1092
1093
1094
1095
1096
1097
1098
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1173 return startAbilityImpl(want, options ? tryConvertStartOptionsToQpaFunctionsStruct(*options) : std::nullopt);
1177
1178
1179
1180
1181
1182
1183
1184
1185
1188 bool success = startAbilityByTypeImpl(appType, wantParameters);
1189 return createOperationStatus(success);
1193
1194
1195
1196
1199 instanceWidget->show();
1203
1204
1205
1206
1207
1208void startAppProcess(
const QString &processId,
const Want &requestWant, std::shared_ptr<StartOptions> options)
1210 startAppProcessImpl(processId, requestWant, options ? tryConvertStartOptionsToQpaFunctionsStruct(*options) :
std::nullopt);
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1228 AbilityContext::instanceForMainWindow(instanceWindow)->setDestroyFromSystemEnabled(destroyEnabled);
1232
1233
1234
1235
1236
1237
1238
1241 auto key = QString::fromUtf8(qtOnContinueMigrationDataPropertyName);
1242 if (want.parameters.contains(key)) {
1243 auto base64String = want.parameters.value(key).toString();
1244 auto decodedData = QByteArray::fromBase64(base64String.toUtf8());
1252
1253
1254
1255
1256
1257
1258
1259
1268 return std::make_shared<QOhosOpenLinkOptionsImpl>();