5#include <QtCore/private/qnapi_p.h>
6#include <qohosjsenv_p.h>
7#include <QtCore/private/qohoslogger_p.h>
8#include <QtCore/qcryptographichash.h>
9#include <QtGui/qwindow.h>
14#include <qohosdeviceinfo_p.h>
15#include <qohosjsutils.h>
16#include <qohosplatformwindow.h>
17#include <render/qohosview.h>
25using namespace std::chrono_literals;
31const auto qtInternalRequestIdWantParamKey =
"io.qt.private.internalRequestId";
32const auto qAbilityInstanceIdWantParamKey =
"io.qt.private.abilityInstanceId";
33const auto callerAbilityNameWantParamKey =
"ohos.aafwk.param.callerAbilityName";
34const auto callerBundleNameWantParamKey =
"ohos.aafwk.param.callerBundleName";
35const auto callerPidWantParamKey =
"ohos.aafwk.param.callerPid";
37std::string getUtf8QtInternalRequestIdForThisProcess()
39 static const auto internalRequestIdCommonData =
40 QByteArray::fromHex(
"eba08604c86e45ae3690621757b3f4e9");
42 std::int32_t thisProcessPid = ::getpid();
44 QCryptographicHash hash{QCryptographicHash::Sha1};
45 hash.addData(internalRequestIdCommonData);
46 hash.addData(QByteArray::number(thisProcessPid));
48 return hash.result().toHex().toStdString();
51QNapi::Symbol getAbilityLaunchParamPropSymbol(
JsState &jsState)
57 return jsState.getJsSymbolForType<SymbolTag>();
60void sendWantToSelfQAbility(
62 QNapi::Object baseQAbility, QNapi::Object optStartOptions,
const std::string &instanceId,
65 auto qAbilityInfo = abilityEngine->readAbilityInfo(baseQAbility);
67 std::vector<QNapi::ValueWrapper> startAbilityArgs = {
71 {
"bundleName", qAbilityInfo.bundleName},
72 {
"moduleName", qAbilityInfo.moduleName},
73 {
"abilityName", qAbilityInfo.name},
79 {qtInternalRequestIdWantParamKey, getUtf8QtInternalRequestIdForThisProcess()},
80 {qAbilityInstanceIdWantParamKey, instanceId},
86 if (!optStartOptions.IsEmpty())
87 startAbilityArgs.push_back(optStartOptions);
89 baseQAbility.evalToPromiseOrRejectOnThrow(
"context.startAbility(*)", startAbilityArgs)
92 logJsCallbackError(cbInfo,
"context.startAbility()");
93 qOhosReportFatalErrorAndAbort(
"Failed to start the Ability with instance id: %s", instanceId.c_str());
96 [continueFunc = std::move(continueFunc)](
const CallbackInfo &cbInfo) {
101QOhosSupplier<std::string> makeAbilityInstanceIdsGenerator()
103 return [idsCounter =
std::uint64_t(0)]()
mutable {
104 auto instanceId =
std::to_string(idsCounter);
115 std::string instanceId, QObjectThreadSafeRef qwindow,
116 QNapi::Object uiAbility);
118 ~QAbilityPeerImpl() =
default;
120 std::string instanceId()
final;
121 QNapi::Object qAbility()
final;
122 QObjectThreadSafeRef qWindowRef()
final;
123 std::optional<QNapi::Promise> qWindowDestroyPromise()
final;
124 void forceResolveQWindowDestroyPromiseIfPresent(Napi::Env env)
final;
125 std::shared_ptr<
std::atomic_bool> destroyAllowedFlag()
final;
127 void setQWindow(Napi::Env env, QObjectThreadSafeRef qwindow)
final;
130 struct QWindowDestroyPromiseData
132 std::optional<QNapi::Promise::Deferred> deferred;
133 QNapi::Reference<QNapi::Promise> promise;
137 std::string m_instanceId;
138 QObjectThreadSafeRef m_qwindow;
139 std::shared_ptr<QWindowDestroyPromiseData> m_optQWindowDestroyPromiseData;
140 std::shared_ptr<
std::atomic_bool> m_destroyAllowedFlag;
141 QNapi::Reference<QNapi::Object> m_uiAbility;
144QAbilityPeerImpl::QAbilityPeerImpl(
146 std::string instanceId, QObjectThreadSafeRef qwindow,
147 QNapi::Object uiAbility)
148 : m_abilityEngine(abilityEngine)
149 , m_instanceId(
std::move(instanceId))
150 , m_destroyAllowedFlag(std::make_shared<std::atomic_bool>(
false))
151 , m_uiAbility(Napi::Persistent(uiAbility))
153 setQWindow(uiAbility.Env(), qwindow);
156std::string QAbilityPeerImpl::instanceId()
161QNapi::Object QAbilityPeerImpl::qAbility()
163 return m_uiAbility.Value();
166QObjectThreadSafeRef QAbilityPeerImpl::qWindowRef()
171std::optional<QNapi::Promise> QAbilityPeerImpl::qWindowDestroyPromise()
173 if (!m_optQWindowDestroyPromiseData || m_optQWindowDestroyPromiseData->promise.IsEmpty())
176 auto promiseValue = m_optQWindowDestroyPromiseData->promise.Value();
177 m_optQWindowDestroyPromiseData->promise.Reset();
182void QAbilityPeerImpl::forceResolveQWindowDestroyPromiseIfPresent(Napi::Env env)
184 if (!m_optQWindowDestroyPromiseData || !m_optQWindowDestroyPromiseData->deferred)
188 "%s: force-resolving QWindow destroy Promise for id='%s'",
189 Q_FUNC_INFO, m_instanceId.c_str());
190 std::exchange(m_optQWindowDestroyPromiseData->deferred, std::nullopt)->Resolve(env.Undefined());
193std::shared_ptr<
std::atomic_bool> QAbilityPeerImpl::destroyAllowedFlag()
195 return m_destroyAllowedFlag;
198void QAbilityPeerImpl::setQWindow(Napi::Env env, QObjectThreadSafeRef qwindow)
200 if (qwindow == m_qwindow)
204 "%s: setting QAbilityPeer's QWindow: %s / %s",
205 Q_FUNC_INFO, m_instanceId.c_str(), m_qwindow.refName().c_str());
207 if (m_qwindow != QObjectThreadSafeRef()) {
208 qOhosReportFatalErrorAndAbort(
209 "QAbilityPeerImpl: overwriting previously set qwindow: %s => %s",
210 m_qwindow.refName().c_str(), qwindow.refName().c_str());
215 auto qWindowDestroyPromiseDeferred = QNapi::Promise::Deferred::New(env);
216 m_optQWindowDestroyPromiseData = std::make_shared<QWindowDestroyPromiseData>(
217 QWindowDestroyPromiseData{
218 .deferred = qWindowDestroyPromiseDeferred,
219 .promise = QNapi::Reference<QNapi::Promise>::makePersistentFrom(
220 qWindowDestroyPromiseDeferred.Promise()),
223 auto resolveQWindowDestroyPromiseFunc =
224 [qWindowRef = qwindow, weakPromiseData = QtOhos::makeWeakPtr(m_optQWindowDestroyPromiseData)]() {
226 "%s: sending request to resolve QWindow destroy notify Promise if needed: %s",
227 Q_FUNC_INFO, qWindowRef.refName().c_str());
229 [qWindowRef, weakPromiseData](
JsState &jsState) {
230 auto promiseData = weakPromiseData.lock();
231 if (promiseData && promiseData->deferred) {
233 "%s: resolving QWindow destroy notify Promise: %s",
234 Q_FUNC_INFO, qWindowRef.refName().c_str());
235 auto napiUndefined = Napi::Env(jsState.env()).Undefined();
236 std::exchange(promiseData->deferred, std::nullopt)->Resolve(napiUndefined);
239 "%s: QAbilityPeer already removed on QWindow's destroy notification: %s",
240 Q_FUNC_INFO, qWindowRef.refName().c_str());
245 QtOhos::invokeInQtThread(
246 [qWindowRef = qwindow, resolveQWindowDestroyPromiseFunc]() {
247 auto *qWindow =
static_cast<QWindow *>(qWindowRef.data().data());
248 auto *platformWindow = qWindow !=
nullptr ? QOhosPlatformWindow::fromQWindowOrNull(qWindow) :
nullptr;
249 auto *view = platformWindow !=
nullptr ? platformWindow->ownedViewOrNull() :
nullptr;
251 if (view !=
nullptr) {
253 QtForOhos,
"%s: connecting to QOhosView's 'destroyed', win: %s",
254 Q_FUNC_INFO, qWindowRef.refName().c_str());
256 view, &QObject::destroyed,
257 [qWindowRef, resolveQWindowDestroyPromiseFunc](QObject *) {
259 QtForOhos,
"%s: got QOhosView's 'destroyed' signal, win: %s",
260 Q_FUNC_INFO, qWindowRef.refName().c_str());
261 resolveQWindowDestroyPromiseFunc();
265 QtForOhos,
"%s: QOhosView already destroyed, win: %s",
266 Q_FUNC_INFO, qWindowRef.refName().c_str());
267 resolveQWindowDestroyPromiseFunc();
277 std::string instanceId, QObjectThreadSafeRef qwindow,
278 QNapi::Object uiAbility, QNapi::Object windowStage);
280 QNapi::Object uiContext()
override;
281 QNapi::Object launchWant()
override;
282 QNapi::Object launchParam()
override;
283 QNapi::Object windowStage()
override;
284 QNapi::Object window()
override;
285 bool isTerminating()
override;
287 QNapi::Promise handleCloseRequestFromSystem(
289 std::function<QNapi::Value(JsState &, CloseAbilityRequestResolution)> promiseValueFactory)
override;
291 void handleOnContinueRequestFromSystem(
292 JsState &jsState, QNapi::Object wantParamsObj,
293 QOhosConsumer<JsState &, QOhosAbilityOnContinueResult> resultConsumer)
override;
295 void setOnContinueRequestsHandler(
296 std::function<
void(
JsState &, QNapi::Object, QOhosConsumer<JsState &, QOhosAbilityOnContinueResult>)> requestsHandler)
override;
299 QNapi::Reference<QNapi::Object> m_windowStage;
300 QNapi::Reference<QNapi::Object> m_window;
301 QNapi::Reference<QNapi::Object> m_launchParam;
302 std::shared_ptr<
void> m_windowWillCloseCallbackHandle;
303 std::function<
void(
JsState &, QNapi::Object, QOhosConsumer<JsState &, QOhosAbilityOnContinueResult>)> m_onContinueRequestsHandler;
306QUiAbilityPeerImpl::QUiAbilityPeerImpl(
308 std::string instanceId, QObjectThreadSafeRef qwindow,
309 QNapi::Object uiAbility, QNapi::Object windowStage)
310 : QAbilityPeerImpl(jsState, abilityEngine, instanceId, qwindow, uiAbility)
311 , m_windowStage(Napi::Persistent(windowStage))
312 , m_window(Napi::Persistent(windowStage.eval<QNapi::Object>(
"getMainWindowSync()")))
314 auto optLaunchParam = QNapi::getOptionalPropOrEmpty<QNapi::Object>(
315 uiAbility, getAbilityLaunchParamPropSymbol(jsState));
316 if (optLaunchParam.IsEmpty()) {
317 qOhosReportFatalErrorAndAbort(
318 "Ability with instanceId='%s' doesn't have 'launchParam' set. It shouldn't happen!",
321 m_launchParam = QNapi::Reference<>::makePersistentFrom(optLaunchParam);
323 m_windowWillCloseCallbackHandle = registerQOhosOnOffMethodsBasedEventHandler(
324 window(),
"windowWillClose",
325 [
this](
const CallbackInfo &cbInfo) {
326 JsState &jsState = cbInfo.jsState();
327 return handleCloseRequestFromSystem(
328 jsState,
"Window.windowWillClose",
329 CloseAbilityRequestSource::WindowWillClose,
330 [](JsState &jsState, CloseAbilityRequestResolution ohosRequestResolution) {
331 return QNapi::Boolean::New(
333 ohosRequestResolution == CloseAbilityRequestResolution::DontClose);
337 .optEventSourceAliveCheckFunc =
338 [qAbilityWeakRef = moveToSharedPtr(Napi::Weak(uiAbility))](QNapi::Object window) {
339 bool isWindowClosing = evalInJsThread(
341 return JsWindowsTracker::isWindowClosing(window);
344 auto qAbilityValue = qAbilityWeakRef->Value();
347 && qAbilityValue.IsObject()
348 && !QNapi::checkedCast<QNapi::Object>(qAbilityValue).eval<QNapi::Boolean>(
"context.isTerminating()");
352 .optOnCallExceptionHandler = [](
const Napi::Error &error) {
353 constexpr auto capabilityNotSupportedErrorCode = 801;
354 QtOhos::rethrowUnlessJsBusinessErrorIs(
355 error, capabilityNotSupportedErrorCode,
"on('windowWillClose')");
360QNapi::Object QUiAbilityPeerImpl::uiContext()
362 return window().eval<QNapi::Object>(
"getUIContext()");
365QNapi::Object QUiAbilityPeerImpl::launchWant()
367 return qAbility().get<QNapi::Object>(
"launchWant");
370QNapi::Object QUiAbilityPeerImpl::launchParam()
372 return m_launchParam.Value();
375QNapi::Object QUiAbilityPeerImpl::windowStage()
377 return m_windowStage.Value();
380QNapi::Object QUiAbilityPeerImpl::window()
382 return m_window.Value();
385bool QUiAbilityPeerImpl::isTerminating()
387 return qAbility().eval<QNapi::Boolean>(
"context.isTerminating()");
390QOhosCloseEventContext::CloseRootCause mapCloseAbilityRequestSourceToRootCause(
394 using CloseRootCause = QOhosCloseEventContext::CloseRootCause;
396 switch (requestSource) {
398 return CloseRootCause::OnPrepareToTerminate;
400 return CloseRootCause::WindowStageClose;
403 qOhosReportFatalErrorAndAbort(
"Unsupported CloseAbilityRequestSource: %d",
static_cast<
int>(requestSource));
406QNapi::Promise QUiAbilityPeerImpl::handleCloseRequestFromSystem(
408 std::function<QNapi::Value(JsState &, CloseAbilityRequestResolution)> promiseValueFactory)
410 auto instanceId =
this->instanceId();
413 "%s: got close request from source %d, id: '%s'",
414 logContextStr.c_str(),
static_cast<
int>(requestSource), instanceId.c_str());
416 if (destroyAllowedFlag()->load()) {
418 "%s: resolving immediately with 'false', id: '%s'",
419 Q_FUNC_INFO, instanceId.c_str());
420 JsWindowsTracker::tagWindowAsClosing(
421 window(), printfToString(
"%s => false", logContextStr.c_str()).c_str());
422 return makeResolvedPromise(
423 promiseValueFactory(jsState, CloseAbilityRequestResolution::Close));
426 struct PromiseResolveFuncContext
428 std::string logContextStr;
430 std::shared_ptr<QNapi::Promise::Deferred> promiseDeferred;
431 std::string instanceId;
432 std::function<QNapi::Value(JsState &, CloseAbilityRequestResolution)> promiseValueFactory;
435 auto promiseResolveFuncContext = moveToSharedPtr(
436 PromiseResolveFuncContext{
437 .logContextStr = logContextStr,
438 .weakQAbilityPeer = makeWeakPtr(shared_from_this()),
439 .promiseDeferred = std::make_shared<QNapi::Promise::Deferred>(jsState.env()),
440 .instanceId = instanceId,
441 .promiseValueFactory = std::move(promiseValueFactory),
444 auto promiseResolveFunc = moveToSharedPtr(
447 auto qAbilityPeer = context->weakQAbilityPeer.lock();
449 JsWindowsTracker::tagWindowAsClosing(
450 qAbilityPeer->window(), printfToString(
"%s => false", context->logContextStr.c_str()).c_str());
452 context->promiseDeferred->Resolve(
453 context->promiseValueFactory(jsState, ohosRequestResolution));
455 "%s: promise resolved as %d, id: '%s'",
456 context->logContextStr.c_str(),
static_cast<
int>(ohosRequestResolution), context->instanceId.c_str());
459 constexpr auto promiseAutoresolveTimeout = 9s;
462 [logContextStr, promiseResolveFunc, instanceId](
const CallbackInfo &cbInfo) {
465 "%s: promise resolved by timeout, id: '%s'",
466 logContextStr.c_str(), instanceId.c_str());
469 promiseAutoresolveTimeout);
471 qWindowRef().visitInQtThreadIfAlive(
472 [logContextStr, requestSource, promiseResolveFunc, instanceId](
auto &qWindowObj) {
474 "%s: calling close(), id: '%s'",
475 logContextStr.c_str(), instanceId.c_str());
476 QOhosCloseEventContext::runWithCloseRootCauseAndCloseResolutionConsumerSet(
477 mapCloseAbilityRequestSourceToRootCause(requestSource),
478 [logContextStr, promiseResolveFunc, instanceId](QOhosCloseEventContext::CloseResolution closeResolution) {
479 auto ohosRequestResolution =
480 closeResolution == QOhosCloseEventContext::CloseResolution::Close
481 ? CloseAbilityRequestResolution::Close
482 : CloseAbilityRequestResolution::DontClose;
484 "%s: requesting promise resolve to %d from Qt thread, id: '%s'",
485 logContextStr.c_str(),
static_cast<
int>(ohosRequestResolution), instanceId.c_str());
486 QtOhos::invokeInJsThread(
487 [logContextStr, promiseResolveFunc, ohosRequestResolution, instanceId](JsState &jsState) {
488 bool resolveCalled = (*promiseResolveFunc)(jsState, ohosRequestResolution);
490 "%s: promise resolve to %d, called: %s, id: '%s'",
491 logContextStr.c_str(),
static_cast<
int>(ohosRequestResolution),
492 mapBoolToTrueFalseStr(resolveCalled), instanceId.c_str());
496 static_cast<QWindow &>(qWindowObj).close();
500 qOhosPrintfInfo(
"%s: returning Promise, id: '%s'", logContextStr.c_str(), instanceId.c_str());
502 return promiseResolveFuncContext->promiseDeferred->Promise();
505void QUiAbilityPeerImpl::handleOnContinueRequestFromSystem(
506 JsState &jsState, QNapi::Object wantParamsObj, QOhosConsumer<JsState &, QOhosAbilityOnContinueResult> resultConsumer)
508 if (m_onContinueRequestsHandler) {
509 m_onContinueRequestsHandler(jsState, wantParamsObj, std::move(resultConsumer));
511 qOhosPrintfDebug(
"%s: no handler set, rejecting", Q_FUNC_INFO);
513 [resultConsumer = std::move(resultConsumer)](
JsState &jsState) {
514 resultConsumer(jsState, QOhosAbilityOnContinueResult::REJECT);
519void QUiAbilityPeerImpl::setOnContinueRequestsHandler(
520 std::function<
void(
JsState &, QNapi::Object, QOhosConsumer<JsState &, QOhosAbilityOnContinueResult>)> requestsHandler)
522 if (m_onContinueRequestsHandler) {
523 qOhosReportFatalErrorAndAbort(
524 "%s: overwriting previously set requests handler, id='%s'",
525 Q_FUNC_INFO, instanceId().c_str());
528 m_onContinueRequestsHandler = std::move(requestsHandler);
534 explicit QAbilityInstancesManagerImpl(
540 bool isWantFromThisApp(QNapi::Object appQAbility, QNapi::Object want)
const override;
542 std::optional<
std::string> tryGetQAbilityInstanceIdFromWant(QNapi::Object appQAbility, QNapi::Object want)
const override;
543 std::string getQAbilityInstanceIdOrPendingAutoStartedId(QNapi::Object qAbility)
const override;
545 std::optional<
std::string> pendingAutoStartedInstanceId()
const override;
547 void registerPendingAutoStartedInstance()
override;
549 void startNewInstance(
550 QNapi::Object baseQAbility, QObjectThreadSafeRef qwindow,
551 QNapi::Object optStartOptions,
554 void handleStartedUiInstance(
JsState &jsState, QNapi::Object qAbility, QNapi::Object windowStage)
override;
559 struct InstanceStartParams
561 QObjectThreadSafeRef qwindow;
565 void handleStartedInstance(
566 JsState &jsState,
const std::string &abilityInstanceId,
567 const std::function<
std::shared_ptr<
QAbilityPeer>(
const std::string &,
const InstanceStartParams &)> &qAbilityPeerFactory);
571 std::shared_ptr<std::map<QUiAbilityPeer *, std::weak_ptr<QUiAbilityPeerImpl>>> m_ownedUiAbilityPeers;
572 QOhosSupplier<std::string> m_abilityInstanceIdsGenerator;
573 std::map<std::string, InstanceStartParams> m_pendingInstancesStartParams;
574 std::optional<
std::string> m_pendingAutoStartedInstanceId;
577QAbilityInstancesManagerImpl::QAbilityInstancesManagerImpl(
580 : m_abilityEngine(abilityEngine)
581 , m_autoStartedInstanceStartupNotifyFunc(moveToSharedPtr(std::move(autoStartedInstanceStartupNotifyFunc)))
582 , m_ownedUiAbilityPeers(std::make_shared<std::map<QUiAbilityPeer *, std::weak_ptr<QUiAbilityPeerImpl>>>())
583 , m_abilityInstanceIdsGenerator(makeAbilityInstanceIdsGenerator())
585 registerPendingAutoStartedInstance();
588std::optional<
std::string> QAbilityInstancesManagerImpl::tryGetQAbilityInstanceIdFromWant(
589 QNapi::Object appQAbility, QNapi::Object want)
const
591 auto wantParameters = QNapi::getPropOrUndefined(want,
"parameters");
592 if (wantParameters.IsUndefined())
595 auto instanceIdParam = QNapi::getPropOrUndefined(wantParameters, qAbilityInstanceIdWantParamKey);
597 bool validInstanceId = isWantFromThisApp(appQAbility, want) && instanceIdParam.IsString();
599 return validInstanceId
600 ? std::optional(QNapi::checkedCast<QNapi::String>(instanceIdParam).Utf8Value())
604std::string QAbilityInstancesManagerImpl::getQAbilityInstanceIdOrPendingAutoStartedId(QNapi::Object qAbility)
const
606 auto optInstanceId = tryGetQAbilityInstanceIdFromWant(
607 qAbility, qAbility.get<QNapi::Object>(
"launchWant"));
609 if (!optInstanceId.has_value() && !m_pendingAutoStartedInstanceId.has_value()) {
610 qOhosReportFatalErrorAndAbort(
611 "Got Ability without '%s' param and no pending auto-started instance",
612 qAbilityInstanceIdWantParamKey);
615 return optInstanceId.has_value()
616 ? optInstanceId.value()
617 : m_pendingAutoStartedInstanceId.value();
622 return m_abilityEngine;
625bool QAbilityInstancesManagerImpl::isWantFromThisApp(QNapi::Object appQAbility, QNapi::Object want)
const
627 auto wantParameters = QNapi::getPropOrUndefined(want,
"parameters");
628 if (wantParameters.IsUndefined())
631 auto callerAbilityNameParam = QNapi::getPropOrUndefined(wantParameters, callerAbilityNameWantParamKey);
632 auto callerBundleNameParam = QNapi::getPropOrUndefined(wantParameters, callerBundleNameWantParamKey);
634 auto appAbilityInfo = m_abilityEngine->readAbilityInfo(appQAbility);
637 callerAbilityNameParam.IsString()
638 && QNapi::checkedCast<QNapi::String>(callerAbilityNameParam).Utf8Value() == appAbilityInfo.name
639 && callerBundleNameParam.IsString()
640 && QNapi::checkedCast<QNapi::String>(callerBundleNameParam).Utf8Value() == appAbilityInfo.bundleName;
643std::optional<
std::string> QAbilityInstancesManagerImpl::pendingAutoStartedInstanceId()
const
645 return m_pendingAutoStartedInstanceId;
648void QAbilityInstancesManagerImpl::registerPendingAutoStartedInstance()
650 if (m_pendingAutoStartedInstanceId.has_value()) {
651 qOhosReportFatalErrorAndAbort(
652 "%s: pending auto-started instance already registered (id='%s')",
653 Q_FUNC_INFO, m_pendingAutoStartedInstanceId.value().c_str());
656 m_pendingAutoStartedInstanceId = m_abilityInstanceIdsGenerator();
659 "Registered pending auto-started Ability instance, id='%s'",
660 m_pendingAutoStartedInstanceId.value().c_str());
663void QAbilityInstancesManagerImpl::startNewInstance(
664 QNapi::Object baseQAbility, QObjectThreadSafeRef qwindow,
665 QNapi::Object optStartOptions,
671 bool sendWantFinished =
false;
674 void callNotifyIfReady(
JsState &jsState)
677 "%s: sendWantFinished=%s, startedAbilityPeer=%s",
679 if (sendWantFinished && optAbilityPeer)
680 startupNotifyFunc(jsState, optAbilityPeer);
684 auto context =
std::make_shared<Context>();
685 context->startupNotifyFunc =
std::move(startupNotifyFunc);
687 auto instanceId = m_abilityInstanceIdsGenerator();
689 InstanceStartParams startParams;
690 startParams.qwindow = qwindow;
692 context->optAbilityPeer = abilityPeer;
693 context->callNotifyIfReady(jsState);
695 m_pendingInstancesStartParams.emplace(instanceId, std::move(startParams));
697 sendWantToSelfQAbility(
698 m_abilityEngine, baseQAbility, optStartOptions, instanceId,
700 context->sendWantFinished =
true;
701 context->callNotifyIfReady(jsState);
705void QAbilityInstancesManagerImpl::handleStartedUiInstance(
706 JsState &jsState, QNapi::Object qAbility, QNapi::Object windowStage)
708 handleStartedInstance(
709 jsState, getQAbilityInstanceIdOrPendingAutoStartedId(qAbility),
710 [&](
const std::string &instanceId,
const InstanceStartParams &startParams) {
711 auto uiAbilityPeer =
std::make_shared<QUiAbilityPeerImpl>(
712 jsState, m_abilityEngine, instanceId, startParams.qwindow, qAbility, windowStage);
714 m_ownedUiAbilityPeers->emplace(uiAbilityPeerKey, uiAbilityPeer);
715 return makeSharedPtrWithAttachedExtraData(
718 [ownedUiAbilityPeers = m_ownedUiAbilityPeers, uiAbilityPeerKey]() {
719 ownedUiAbilityPeers->erase(uiAbilityPeerKey);
727 auto ownedPeerEntryIter = m_ownedUiAbilityPeers->find(uiAbilityPeer.get());
729 ownedPeerEntryIter != m_ownedUiAbilityPeers->end()
730 ? ownedPeerEntryIter->second.lock()
733 if (!ownedPeerImpl) {
734 qOhosReportFatalErrorAndAbort(
735 "%s: got unknown QUiAbilityPeer %p with id='%s'",
736 Q_FUNC_INFO, uiAbilityPeer.get(), uiAbilityPeer->instanceId().c_str());
739 return ownedPeerImpl;
742void QAbilityInstancesManagerImpl::handleStartedInstance(
743 JsState &jsState,
const std::string &abilityInstanceId,
744 const std::function<
std::shared_ptr<
QAbilityPeer>(
const std::string &,
const InstanceStartParams &)> &qAbilityPeerFactory)
746 auto startParamsIter = m_pendingInstancesStartParams.find(abilityInstanceId);
747 if (startParamsIter != m_pendingInstancesStartParams.end()) {
748 auto startParams =
std::move(startParamsIter->second);
749 m_pendingInstancesStartParams.erase(startParamsIter);
751 auto qAbilityPeer = qAbilityPeerFactory(abilityInstanceId, startParams);
753 startParams.startupNotifyFunc(jsState, qAbilityPeer);
754 }
else if (abilityInstanceId == m_pendingAutoStartedInstanceId) {
755 m_pendingAutoStartedInstanceId.reset();
757 InstanceStartParams startParams = {
758 .qwindow = QObjectThreadSafeRef(),
759 .startupNotifyFunc = [startupNotifyFunc = m_autoStartedInstanceStartupNotifyFunc](
JsState &jsState,
std::shared_ptr<
QAbilityPeer> qAbilityPeer) {
760 (*startupNotifyFunc)(jsState, qAbilityPeer);
763 auto qAbilityPeer = qAbilityPeerFactory(abilityInstanceId, startParams);
765 startParams.startupNotifyFunc(jsState, qAbilityPeer);
768 "%s: got unexpected started instance notification with id='%s', ignoring",
769 Q_FUNC_INFO, abilityInstanceId.c_str());
783 auto optWantParameters = QNapi::getOptionalPropOrEmpty<QNapi::Object>(want,
"parameters");
785 auto optCallerPid = QNapi::getOptionalPropOrEmpty<QNapi::Number>(
786 optWantParameters, callerPidWantParamKey);
787 auto optQtInternalRequestId = QNapi::getOptionalPropOrEmpty<QNapi::String>(
788 optWantParameters, qtInternalRequestIdWantParamKey);
790 std::int32_t thisProcessPid = ::getpid();
793 !optCallerPid.IsEmpty() && optCallerPid.Int32Value() == thisProcessPid
794 && !optQtInternalRequestId.IsEmpty()
795 && optQtInternalRequestId.Utf8Value() == getUtf8QtInternalRequestIdForThisProcess();
799 JsState &jsState, QNapi::Object ability, QNapi::Object launchParam)
801 ability.set(getAbilityLaunchParamPropSymbol(jsState), launchParam);
808 return std::make_shared<QAbilityInstancesManagerImpl>(abilityEngine,
std::move(autoStartedInstanceStartupNotifyFunc));
JsState & jsState() const
CloseAbilityRequestSource
CloseAbilityRequestResolution
std::string const char * mapBoolToTrueFalseStr(bool value)
void invokeInJsThread(std::function< void(JsState &)> task)
std::shared_ptr< QAbilityInstancesManager > makeQAbilityInstancesManager(std::shared_ptr< QAbilityEngine > abilityEngine, std::function< void(JsState &, std::shared_ptr< QAbilityPeer >)> autoStartedInstanceStartupNotifyFunc)
void addJsQAbilityPeer(std::shared_ptr< QAbilityPeer > qAbilityPeer)
QAbilityInstancesManager()
virtual ~QAbilityInstancesManager()