From 085b5035425df1b4d61eda88b353bb26e4fb67c6 Mon Sep 17 00:00:00 2001 From: qpzeng Date: Fri, 5 May 2023 19:26:11 +0800 Subject: [PATCH] add js root scene session Signed-off-by: qpzeng Change-Id: Ia38bca3bcd06fb9ee8532f119545a6e4fa961e53 --- window_scene/interfaces/kits/napi/BUILD.gn | 5 +- .../kits/napi/scene_session_manager/BUILD.gn | 1 + .../js_root_scene_session.cpp | 220 ++++++++++++++++++ .../js_root_scene_session.h | 48 ++++ .../js_scene_session_manager.cpp | 28 +++ .../js_scene_session_manager.h | 2 + 6 files changed, 303 insertions(+), 1 deletion(-) create mode 100644 window_scene/interfaces/kits/napi/scene_session_manager/js_root_scene_session.cpp create mode 100644 window_scene/interfaces/kits/napi/scene_session_manager/js_root_scene_session.h diff --git a/window_scene/interfaces/kits/napi/BUILD.gn b/window_scene/interfaces/kits/napi/BUILD.gn index 99a4b4482b..b45a1ef77e 100644 --- a/window_scene/interfaces/kits/napi/BUILD.gn +++ b/window_scene/interfaces/kits/napi/BUILD.gn @@ -14,5 +14,8 @@ import("//build/ohos.gni") group("window_scene_napi_packages") { - public_deps = [ "screen_session_manager:screensessionmanager_napi" ] + public_deps = [ + "scene_session_manager:scenesessionmanager_napi", + "screen_session_manager:screensessionmanager_napi", + ] } diff --git a/window_scene/interfaces/kits/napi/scene_session_manager/BUILD.gn b/window_scene/interfaces/kits/napi/scene_session_manager/BUILD.gn index 882e20fbdf..34db80c797 100644 --- a/window_scene/interfaces/kits/napi/scene_session_manager/BUILD.gn +++ b/window_scene/interfaces/kits/napi/scene_session_manager/BUILD.gn @@ -21,6 +21,7 @@ config("scene_session_manager_napi_public_config") { ohos_shared_library("scenesessionmanager_napi") { sources = [ + "js_root_scene_session.cpp", "js_scene_session.cpp", "js_scene_session_manager.cpp", "js_scene_utils.cpp", diff --git a/window_scene/interfaces/kits/napi/scene_session_manager/js_root_scene_session.cpp b/window_scene/interfaces/kits/napi/scene_session_manager/js_root_scene_session.cpp new file mode 100644 index 0000000000..d0b55facbf --- /dev/null +++ b/window_scene/interfaces/kits/napi/scene_session_manager/js_root_scene_session.cpp @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "js_root_scene_session.h" + +#include "context.h" +#include +#include "window_manager_hilog.h" + +#include "js_scene_utils.h" + +namespace OHOS::Rosen { +using namespace AbilityRuntime; +namespace { +constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "JsRootSceneSession" }; +const std::string PENDING_SCENE_CB = "pendingSceneSessionActivation"; +} // namespace + +JsRootSceneSession::JsRootSceneSession(NativeEngine& engine, const sptr& rootSceneSession) + : engine_(engine), rootSceneSession_(rootSceneSession) +{} + +NativeValue* JsRootSceneSession::Create(NativeEngine& engine, const sptr& rootSceneSession) +{ + NativeValue* objValue = engine.CreateObject(); + NativeObject* object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("[NAPI]Object is null!"); + return engine.CreateUndefined(); + } + + auto jsRootSceneSession = std::make_unique(engine, rootSceneSession); + object->SetNativePointer(jsRootSceneSession.release(), JsRootSceneSession::Finalizer, nullptr); + + const char* moduleName = "JsRootSceneSession"; + BindNativeFunction(engine, *object, "loadContent", moduleName, JsRootSceneSession::LoadContent); + BindNativeFunction(engine, *object, "on", moduleName, JsRootSceneSession::RegisterCallback); + return objValue; +} + +void JsRootSceneSession::Finalizer(NativeEngine* engine, void* data, void* hint) +{ + WLOGD("Finalizer."); + std::unique_ptr(static_cast(data)); +} + +NativeValue* JsRootSceneSession::RegisterCallback(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGD("RegisterCallback."); + JsRootSceneSession* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnRegisterCallback(*engine, *info) : nullptr; +} + +NativeValue* JsRootSceneSession::LoadContent(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGD("LoadContent."); + JsRootSceneSession* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnLoadContent(*engine, *info) : nullptr; +} + +NativeValue* JsRootSceneSession::OnRegisterCallback(NativeEngine& engine, NativeCallbackInfo& info) +{ + if (info.argc < 2) { // 2: params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + engine.Throw(CreateJsError(engine, static_cast(WSErrorCode::WS_ERROR_INVALID_PARAM), + "Input parameter is missing or invalid")); + return engine.CreateUndefined(); + } + std::string cbType; + if (!ConvertFromJsValue(engine, info.argv[0], cbType)) { + WLOGFE("[NAPI]Failed to convert parameter to callbackType"); + engine.Throw(CreateJsError(engine, static_cast(WSErrorCode::WS_ERROR_INVALID_PARAM), + "Input parameter is missing or invalid")); + return engine.CreateUndefined(); + } + NativeValue* value = info.argv[1]; + if (value == nullptr || !value->IsCallable()) { + WLOGFE("[NAPI]Invalid argument"); + engine.Throw(CreateJsError(engine, static_cast(WSErrorCode::WS_ERROR_INVALID_PARAM), + "Input parameter is missing or invalid")); + return engine.CreateUndefined(); + } + if (IsCallbackRegistered(cbType, value)) { + return engine.CreateUndefined(); + } + if (rootSceneSession_ == nullptr) { + WLOGFE("[NAPI]root session is nullptr"); + engine.Throw(CreateJsError( + engine, static_cast(WSErrorCode::WS_ERROR_INVALID_PARAM), "Root scene session is null!")); + return engine.CreateUndefined(); + } + + wptr rootSessionWptr(this); + NotifyPendingSessionActivationFunc func = [rootSessionWptr](const SessionInfo& info) { + auto jsRootSceneSession = rootSessionWptr.promote(); + if (jsRootSceneSession == nullptr) { + WLOGFE("[NAPI]this scene session"); + return; + } + jsRootSceneSession->PendingSessionActivation(info); + }; + rootSceneSession_->SetPendingSessionActivationEventListener(func); + std::shared_ptr callbackRef; + callbackRef.reset(engine.CreateReference(value, 1)); + jsCbMap_[cbType] = callbackRef; + WLOGFI("[NAPI]Register end, type = %{public}s, callback = %{public}p", cbType.c_str(), value); + return engine.CreateUndefined(); +} + +NativeValue* JsRootSceneSession::OnLoadContent(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGD("[NAPI]OnLoadContent"); + if (info.argc < 2) { // 2: params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + engine.Throw(CreateJsError(engine, static_cast(WSErrorCode::WS_ERROR_INVALID_PARAM), + "Input parameter is missing or invalid")); + return engine.CreateUndefined(); + } + std::string contentUrl; + NativeValue* context = info.argv[1]; + NativeValue* storage = info.argc < 3 ? nullptr : info.argv[2]; + if (!ConvertFromJsValue(engine, info.argv[0], contentUrl)) { + WLOGFE("[NAPI]Failed to convert parameter to content url"); + engine.Throw(CreateJsError(engine, static_cast(WSErrorCode::WS_ERROR_INVALID_PARAM), + "Input parameter is missing or invalid")); + return engine.CreateUndefined(); + } + auto contextObj = ConvertNativeValueTo(context); + if (contextObj == nullptr) { + WLOGFE("[NAPI]Failed to get context object"); + engine.Throw(CreateJsError(engine, static_cast(WSErrorCode::WS_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } + auto contextNativePointer = static_cast*>(contextObj->GetNativePointer()); + if (contextNativePointer == nullptr) { + WLOGFE("[NAPI]Failed to get context pointer from js object"); + engine.Throw(CreateJsError(engine, static_cast(WSErrorCode::WS_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } + auto contextWeakPtr = *contextNativePointer; + + std::shared_ptr contentStorage = + (storage == nullptr) ? nullptr : std::shared_ptr(engine.CreateReference(storage, 1)); + NativeValue* nativeStorage = contentStorage ? contentStorage->Get() : nullptr; + AsyncTask::CompleteCallback complete = [rootSceneSession = rootSceneSession_, contentUrl, contextWeakPtr, + nativeStorage](NativeEngine& engine, AsyncTask& task, int32_t status) { + if (rootSceneSession == nullptr) { + WLOGFE("[NAPI]rootSceneSession is nullptr"); + task.Reject(engine, CreateJsError(engine, static_cast(WSErrorCode::WS_ERROR_STATE_ABNORMALLY))); + return; + } + rootSceneSession->LoadContent(contentUrl, &engine, nativeStorage, contextWeakPtr.lock().get()); + }; + NativeValue* lastParam = nullptr; + NativeValue* result = nullptr; + AsyncTask::Schedule("JsRootSceneSession::OnLoadContent", engine, + CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +bool JsRootSceneSession::IsCallbackRegistered(std::string type, NativeValue* jsListenerObject) +{ + if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) { + WLOGFI("[NAPI]Method %{public}s has not been registered", type.c_str()); + return false; + } + + for (auto iter = jsCbMap_.begin(); iter != jsCbMap_.end(); ++iter) { + if (jsListenerObject->StrictEquals(iter->second->Get())) { + WLOGFE("[NAPI]Method %{public}s has already been registered", type.c_str()); + return true; + } + } + return false; +} + +void JsRootSceneSession::PendingSessionActivation(const SessionInfo& info) +{ + WLOGI("[NAPI]pending session activation: bundleName = %{public}s, id = %{public}s", info.bundleName_.c_str(), + info.abilityName_.c_str()); + auto iter = jsCbMap_.find(PENDING_SCENE_CB); + if (iter == jsCbMap_.end()) { + return; + } + + wptr rootSessionWptr(this); + auto jsCallBack = iter->second; + auto complete = std::make_unique( + [rootSessionWptr, info, jsCallBack](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto jsRootSceneSession = rootSessionWptr.promote(); + if (jsRootSceneSession == nullptr) { + WLOGFE("[NAPI]root session or target session or engine is nullptr"); + return; + } + NativeValue* jsSessionInfo = CreateJsSessionInfo(engine, info); + if (jsSessionInfo == nullptr) { + WLOGFE("[NAPI]this target session info is nullptr"); + } + NativeValue* argv[] = { jsSessionInfo }; + engine.CallFunction(engine.CreateUndefined(), jsCallBack->Get(), argv, ArraySize(argv)); + }); + + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule("JsSceneSession::PendingSessionActivation", engine_, + std::make_unique(callback, std::move(execute), std::move(complete))); +} +} // namespace OHOS::Rosen diff --git a/window_scene/interfaces/kits/napi/scene_session_manager/js_root_scene_session.h b/window_scene/interfaces/kits/napi/scene_session_manager/js_root_scene_session.h new file mode 100644 index 0000000000..5025f730ef --- /dev/null +++ b/window_scene/interfaces/kits/napi/scene_session_manager/js_root_scene_session.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_WINDOW_SCENE_JS_ROOT_SCENE_SESSION_H +#define OHOS_WINDOW_SCENE_JS_ROOT_SCENE_SESSION_H + +#include +#include +#include +#include "session/host/include/root_scene_session.h" + +namespace OHOS::Rosen { +class JsRootSceneSession : public RefBase { +public: + JsRootSceneSession(NativeEngine& engine, const sptr& rootSceneSession); + ~JsRootSceneSession() = default; + + static NativeValue* Create(NativeEngine& engine, const sptr& rootSceneSession); + static void Finalizer(NativeEngine* engine, void* data, void* hint); + + static NativeValue* RegisterCallback(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* LoadContent(NativeEngine* engine, NativeCallbackInfo* info); + +private: + NativeValue* OnRegisterCallback(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnLoadContent(NativeEngine& engine, NativeCallbackInfo& info); + bool IsCallbackRegistered(std::string type, NativeValue* jsListenerObject); + void PendingSessionActivation(const SessionInfo& info); + + NativeEngine& engine_; + std::map> jsCbMap_; + sptr rootSceneSession_; +}; +} // namespace OHOS::Rosen + +#endif // OHOS_WINDOW_SCENE_JS_ROOT_SCENE_SESSION_H diff --git a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session_manager.cpp b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session_manager.cpp index c9126a74cf..61f02062e6 100644 --- a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session_manager.cpp +++ b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session_manager.cpp @@ -20,6 +20,7 @@ #include "session_manager/include/scene_session_manager.h" #include "window_manager_hilog.h" +#include "js_root_scene_session.h" #include "js_scene_session.h" #include "js_scene_utils.h" @@ -47,6 +48,7 @@ NativeValue* JsSceneSessionManager::Init(NativeEngine* engine, NativeValue* expo object->SetNativePointer(jsSceneSessionManager.release(), JsSceneSessionManager::Finalizer, nullptr); const char* moduleName = "JsSceneSessionManager"; + BindNativeFunction(*engine, *object, "getRootSceneSession", moduleName, JsSceneSessionManager::GetRootSceneSession); BindNativeFunction(*engine, *object, "requestSceneSession", moduleName, JsSceneSessionManager::RequestSceneSession); BindNativeFunction(*engine, *object, "requestSceneSessionActivation", moduleName, JsSceneSessionManager::RequestSceneSessionActivation); @@ -63,6 +65,13 @@ void JsSceneSessionManager::Finalizer(NativeEngine* engine, void* data, void* hi std::unique_ptr(static_cast(data)); } +NativeValue* JsSceneSessionManager::GetRootSceneSession(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGI("[NAPI]GetRootSceneSession"); + JsSceneSessionManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnGetRootSceneSession(*engine, *info) : nullptr; +} + NativeValue* JsSceneSessionManager::RequestSceneSession(NativeEngine* engine, NativeCallbackInfo* info) { WLOGI("[NAPI]RequestSceneSession"); @@ -91,6 +100,25 @@ NativeValue* JsSceneSessionManager::RequestSceneSessionDestruction(NativeEngine* return (me != nullptr) ? me->OnRequestSceneSessionDestruction(*engine, *info) : nullptr; } +NativeValue* JsSceneSessionManager::OnGetRootSceneSession(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFI("[NAPI]OnGetRootSceneSession"); + sptr rootSceneSession = SceneSessionManager::GetInstance().GetRootSceneSession(); + if (rootSceneSession == nullptr) { + engine.Throw( + CreateJsError(engine, static_cast(WSErrorCode::WS_ERROR_STATE_ABNORMALLY), "System is abnormal")); + return engine.CreateUndefined(); + } else { + NativeValue* jsRootSceneSessionObj = JsRootSceneSession::Create(engine, rootSceneSession); + if (jsRootSceneSessionObj == nullptr) { + WLOGFE("[NAPI]jsRootSceneSessionObj is nullptr"); + engine.Throw(CreateJsError( + engine, static_cast(WSErrorCode::WS_ERROR_STATE_ABNORMALLY), "System is abnormal")); + } + return jsRootSceneSessionObj; + } +} + NativeValue* JsSceneSessionManager::OnRequestSceneSession(NativeEngine& engine, NativeCallbackInfo& info) { WLOGI("[NAPI]OnRequestSceneSession"); diff --git a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session_manager.h b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session_manager.h index f7eb5f7998..a3c9e67802 100644 --- a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session_manager.h +++ b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session_manager.h @@ -28,12 +28,14 @@ public: static NativeValue* Init(NativeEngine* engine, NativeValue* exportObj); static void Finalizer(NativeEngine* engine, void* data, void* hint); + static NativeValue* GetRootSceneSession(NativeEngine* engine, NativeCallbackInfo* info); static NativeValue* RequestSceneSession(NativeEngine* engine, NativeCallbackInfo* info); static NativeValue* RequestSceneSessionActivation(NativeEngine* engine, NativeCallbackInfo* info); static NativeValue* RequestSceneSessionBackground(NativeEngine* engine, NativeCallbackInfo* info); static NativeValue* RequestSceneSessionDestruction(NativeEngine* engine, NativeCallbackInfo* info); private: + NativeValue* OnGetRootSceneSession(NativeEngine& engine, NativeCallbackInfo& info); NativeValue* OnRequestSceneSession(NativeEngine& engine, NativeCallbackInfo& info); NativeValue* OnRequestSceneSessionActivation(NativeEngine& engine, NativeCallbackInfo& info); NativeValue* OnRequestSceneSessionBackground(NativeEngine& engine, NativeCallbackInfo& info);