diff --git a/frameworks/js/napi/BUILD.gn b/frameworks/js/napi/BUILD.gn index 24068816149d8bb51050cf42300e1c8e56044b3f..67a17324375d776c23821c1601783892927cddd6 100644 --- a/frameworks/js/napi/BUILD.gn +++ b/frameworks/js/napi/BUILD.gn @@ -54,6 +54,7 @@ group("napi_packages") { "${ability_runtime_napi_path}/inner/napi_common:napi_common", "${ability_runtime_napi_path}/insight_intent/insight_intent:insightintent_napi", "${ability_runtime_napi_path}/insight_intent/insight_intent_driver:insightintentdriver_napi", + "${ability_runtime_napi_path}/insight_intent/insight_intent_executor:insightintentexecutor_napi", "${ability_runtime_napi_path}/insight_intent_context:insightintentcontext_napi", "${ability_runtime_napi_path}/js_child_process:childprocess_napi", "${ability_runtime_napi_path}/js_child_process_manager:childprocessmanager_napi", diff --git a/frameworks/js/napi/inner/napi_common/napi_common_execute_result.cpp b/frameworks/js/napi/inner/napi_common/napi_common_execute_result.cpp index 529a9d005b9537425e1738d75f1a53498afb3e23..25195e7db215c34c770e9ea709bd90c22d3fbd16 100644 --- a/frameworks/js/napi/inner/napi_common/napi_common_execute_result.cpp +++ b/frameworks/js/napi/inner/napi_common/napi_common_execute_result.cpp @@ -29,6 +29,10 @@ bool UnwrapExecuteResult(napi_env env, napi_value param, InsightIntentExecuteRes { HILOG_DEBUG("called."); + if (!IsTypeForNapiValue(env, param, napi_valuetype::napi_object)) { + HILOG_ERROR("UnwrapExecuteResult not object"); + return false; + } int32_t code = 0; if (!UnwrapInt32ByPropertyName(env, param, "code", code)) { HILOG_ERROR("Intent result must contian a code."); diff --git a/frameworks/js/napi/insight_intent/insight_intent_executor/BUILD.gn b/frameworks/js/napi/insight_intent/insight_intent_executor/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..81a7c37edab55a5dc6cf8b09abec2d004ae8c928 --- /dev/null +++ b/frameworks/js/napi/insight_intent/insight_intent_executor/BUILD.gn @@ -0,0 +1,50 @@ +# 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. + +import("//arkcompiler/ets_frontend/es2panda/es2abc_config.gni") +import("//build/ohos.gni") + +es2abc_gen_abc("gen_insight_intent_executor_abc") { + src_js = rebase_path("insight_intent_executor.js") + dst_file = rebase_path(target_out_dir + "/insight_intent_executor.abc") + in_puts = [ "insight_intent_executor.js" ] + out_puts = [ target_out_dir + "/insight_intent_executor.abc" ] + extra_args = [ "--module" ] +} + +gen_js_obj("insight_intent_executor_js") { + input = "insight_intent_executor.js" + output = target_out_dir + "/insight_intent_executor.o" +} + +gen_js_obj("insight_intent_executor_abc") { + input = get_label_info(":gen_insight_intent_executor_abc", "target_out_dir") + + "/insight_intent_executor.abc" + output = target_out_dir + "/insight_intent_executor_abc.o" + dep = ":gen_insight_intent_executor_abc" +} + +ohos_shared_library("insightintentexecutor_napi") { + sources = [ "insight_intent_executor_module.cpp" ] + + deps = [ + ":insight_intent_executor_abc", + ":insight_intent_executor_js", + ] + + external_deps = [ "napi:ace_napi" ] + + relative_install_dir = "module/app/ability" + subsystem_name = "ability" + part_name = "ability_runtime" +} diff --git a/frameworks/js/napi/insight_intent/insight_intent_executor/insight_intent_executor.js b/frameworks/js/napi/insight_intent/insight_intent_executor/insight_intent_executor.js new file mode 100644 index 0000000000000000000000000000000000000000..c9b0966f7b1b6cd1a304a9d9e4b10e0aaec06b49 --- /dev/null +++ b/frameworks/js/napi/insight_intent/insight_intent_executor/insight_intent_executor.js @@ -0,0 +1,34 @@ +/* + * 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. + */ + +class InsightIntentExecutor { + constructor() {} + + onExecuteInUIAbilityForegroundMode(name, param, pageLoader) { + console.log(`onExecuteInUIAbilityForegroundMode $name$`); + return { + 'code': 0 + }; + } + + onExecuteInUIAbilityBackgroundMode(name, param) { + console.log(`onExecuteInUIAbilityForegroundMode $name$`); + return { + 'code': 0 + }; + } +} + +export default InsightIntentExecutor; diff --git a/frameworks/js/napi/insight_intent/insight_intent_executor/insight_intent_executor_module.cpp b/frameworks/js/napi/insight_intent/insight_intent_executor/insight_intent_executor_module.cpp new file mode 100644 index 0000000000000000000000000000000000000000..85e777eeb6c6866eb855f56dcbdd389f1b836974 --- /dev/null +++ b/frameworks/js/napi/insight_intent/insight_intent_executor/insight_intent_executor_module.cpp @@ -0,0 +1,56 @@ +/* + * 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 "native_engine/native_engine.h" + +extern const char _binary_insight_intent_executor_js_start[]; +extern const char _binary_insight_intent_executor_js_end[]; +extern const char _binary_insight_intent_executor_abc_start[]; +extern const char _binary_insight_intent_executor_abc_end[]; + +static napi_module _module = { + .nm_version = 0, + .nm_modname = "app.ability.InsightIntentExecutor", + .nm_filename = "app/ability/insightintentexecutor_napi.so/insight_intent_executor.js", +}; + +extern "C" __attribute__((constructor)) +void NAPI_app_ability_InsightIntentExecutor_AutoRegister() +{ + napi_module_register(&_module); +} + +extern "C" __attribute__((visibility("default"))) +void NAPI_app_ability_InsightIntentExecutor_GetJSCode(const char **buf, int *bufLen) +{ + if (buf != nullptr) { + *buf = _binary_insight_intent_executor_js_start; + } + + if (bufLen != nullptr) { + *bufLen = _binary_insight_intent_executor_js_end - _binary_insight_intent_executor_js_start; + } +} + +extern "C" __attribute__((visibility("default"))) +void NAPI_app_ability_InsightIntentExecutor_GetABCCode(const char **buf, int *buflen) +{ + if (buf != nullptr) { + *buf = _binary_insight_intent_executor_abc_start; + } + if (buflen != nullptr) { + *buflen = _binary_insight_intent_executor_abc_end - _binary_insight_intent_executor_abc_start; + } +} diff --git a/frameworks/native/ability/native/BUILD.gn b/frameworks/native/ability/native/BUILD.gn index a7903b5d59b96f5145e6dd75ed83679f9af314b4..83854f153d5d4f35b70a572364bf1c4d7bd12da7 100644 --- a/frameworks/native/ability/native/BUILD.gn +++ b/frameworks/native/ability/native/BUILD.gn @@ -405,6 +405,43 @@ ohos_shared_library("extensionkit_native") { part_name = "ability_runtime" } +config("insight_intent_executor_public_config") { + visibility = [ ":*" ] + include_dirs = [ "${ability_runtime_path}/interfaces/kits/native/ability/native/insight_intent_executor" ] +} + +ohos_shared_library("insight_intent_executor") { + sources = [ + "${ability_runtime_native_path}/ability/native/insight_intent_executor/insight_intent_executor.cpp", + "${ability_runtime_native_path}/ability/native/insight_intent_executor/js_insight_intent_executor.cpp", + ] + + public_configs = [ ":insight_intent_executor_public_config" ] + + deps = [ + "${ability_runtime_innerkits_path}/ability_manager:ability_manager", + "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_napi_path}/inner/napi_common:napi_common", + "${ability_runtime_native_path}/ability/native:ability_business_error", + ] + + external_deps = [ + "ability_base:want", + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "c_utils:utils", + "eventhandler:libeventhandler", + "hilog:libhilog", + "hitrace:hitrace_meter", + "ipc:ipc_core", + "ipc:ipc_napi_common", + "napi:ace_napi", + ] + + subsystem_name = "ability" + part_name = "ability_runtime" +} + config("uiability_config") { visibility = [ ":*" ] include_dirs = [ diff --git a/frameworks/native/ability/native/insight_intent_executor/insight_intent_executor.cpp b/frameworks/native/ability/native/insight_intent_executor/insight_intent_executor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4ff65c2130fed595466932551de54580e766fd80 --- /dev/null +++ b/frameworks/native/ability/native/insight_intent_executor/insight_intent_executor.cpp @@ -0,0 +1,35 @@ +/* + * 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 "insight_intent_executor.h" +#include "js_insight_intent_executor.h" + +#include "hilog_wrapper.h" +#include "js_runtime.h" +#include "runtime.h" + +namespace OHOS::AbilityRuntime { +std::shared_ptr InsightIntentExecutor::Create(Runtime& runtime) +{ + HILOG_DEBUG("InsightIntentExecutor Create runtime"); + switch (runtime.GetLanguage()) { + case Runtime::Language::JS: + return static_cast>(JsInsightIntentExecutor::Create( + static_cast(runtime))); + default: + return nullptr; + } +} +} // namespace OHOS::AbilityRuntime diff --git a/frameworks/native/ability/native/insight_intent_executor/js_insight_intent_executor.cpp b/frameworks/native/ability/native/insight_intent_executor/js_insight_intent_executor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..73b9a87f6f5f20a31df15f30cb36b5efff27d36e --- /dev/null +++ b/frameworks/native/ability/native/insight_intent_executor/js_insight_intent_executor.cpp @@ -0,0 +1,462 @@ +/* + * 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_insight_intent_executor.h" + +#include + +#include "ability_transaction_callback_info.h" +#include "hilog_wrapper.h" +#include "insight_intent_constant.h" +#include "insight_intent_execute_result.h" +#include "js_runtime.h" +#include "js_runtime_utils.h" +#include "napi_common_execute_result.h" +#include "napi_common_util.h" +#include "napi_common_want.h" +#include "native_reference.h" + +#undef STATE_PATTERN_NAIVE_H +#define STATE_PATTERN_NAIVE_STATE state_ +#include "state_pattern_naive.h" + +#define TMP_NAPI_ANONYMOUS_FUNC "_" + +namespace OHOS::AbilityRuntime { + +std::shared_ptr JsInsightIntentExecutor::Create(JsRuntime& runtime) +{ + std::shared_ptr ptr(new (std::nothrow) JsInsightIntentExecutor(runtime)); + return ptr; +} + +using State = JsInsightIntentExecutor::State; + +JsInsightIntentExecutor::JsInsightIntentExecutor(JsRuntime& runtime) : runtime_(runtime) +{ } + +JsInsightIntentExecutor::~JsInsightIntentExecutor() +{ + state_ = State::DESTROYED; + HILOG_INFO("JsInsightIntentExecutor destructor"); +} + +bool JsInsightIntentExecutor::Init(const InsightIntentExecutorInfo& insightIntentInfo) +{ + HILOG_DEBUG("enter"); + STATE_PATTERN_NAIVE_ACCEPT(State::CREATED, false); + state_ = State::INITIALIZED; + + HandleScope handleScope(runtime_); + jsObj_ = JsInsightIntentExecutor::LoadJsCode(insightIntentInfo, runtime_); + if (jsObj_ == nullptr) { + HILOG_ERROR("LoadJsCode failed."); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + + return true; +} + +bool JsInsightIntentExecutor::HandleExecuteIntent( + InsightIntentExecuteMode mode, + const std::string& name, + const AAFwk::WantParams& param, + const std::shared_ptr& pageLoader, + std::unique_ptr callback, + bool& isAsync) +{ + HILOG_DEBUG("enter"); + STATE_PATTERN_NAIVE_ACCEPT(State::INITIALIZED, false); + state_ = State::EXECUTING; + + if (callback == nullptr || callback->IsEmpty()) { + HILOG_ERROR("HandleExecuteIntent invalid callback."); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + callback_ = std::move(callback); + bool successful = false; + switch (mode) { + case InsightIntentExecuteMode::UIABILITY_FOREGROUND: + if (!JsInsightIntentExecutor::CheckParametersUIAbilityForeground(pageLoader)) { + HILOG_ERROR("CheckParametersUIAbilityForeground error"); + ReplyFailedInner(); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + successful = ExecuteInsightIntentUIAbilityForeground(name, param, pageLoader); + break; + case InsightIntentExecuteMode::UIABILITY_BACKGROUND: + if (!JsInsightIntentExecutor::CheckParametersUIAbilityBackground()) { + HILOG_ERROR("CheckParametersUIAbilityBackground error"); + ReplyFailedInner(); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + successful = ExecuteInsightIntentUIAbilityBackground(name, param); + break; + case InsightIntentExecuteMode::UIEXTENSION_ABILITY: + if (!JsInsightIntentExecutor::CheckParametersUIExtension(pageLoader)) { + HILOG_ERROR("CheckParametersUIAbilityBackground error"); + ReplyFailedInner(); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + successful = ExecuteInsightIntentUIExtension(name, param, pageLoader); + break; + case InsightIntentExecuteMode::SERVICE_EXTENSION_ABILITY: + if (!JsInsightIntentExecutor::CheckParametersServiceExtension()) { + HILOG_ERROR("CheckParametersUIAbilityBackground error"); + ReplyFailedInner(); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + successful = ExecuteInsightIntentServiceExtension(name, param); + break; + default: + HILOG_ERROR("InsightIntentExecuteMode not supported yet"); + ReplyFailedInner(); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + isAsync = isAsync_; + return successful; +} + +std::unique_ptr JsInsightIntentExecutor::LoadJsCode( + const InsightIntentExecutorInfo& info, + JsRuntime& runtime) +{ + HILOG_DEBUG("enter"); + auto executeParam = info.executeParam; + if (executeParam == nullptr) { + HILOG_ERROR("Execute param invalid."); + return std::unique_ptr(); + } + + std::string moduleName(executeParam->moduleName_); + std::string srcPath(executeParam->moduleName_ + "/" + info.srcEntry); + auto pos = srcPath.rfind('.'); + if (pos == std::string::npos) { + return nullptr; + } + srcPath.erase(pos); + srcPath.append(".abc"); + + std::unique_ptr jsCode( + runtime.LoadModule(moduleName, srcPath, info.hapPath, info.esmodule)); + return jsCode; +} + +bool JsInsightIntentExecutor::CallJsFunctionWithResult( + napi_env env, + napi_value obj, + const char* funcName, + size_t argc, + const napi_value* argv, + napi_value& result) +{ + HILOG_DEBUG("enter"); + napi_value method = AppExecFwk::GetPropertyValueByPropertyName( + env, + obj, + funcName, + napi_valuetype::napi_function); + if (method == nullptr) { + HILOG_ERROR("CallJsFunctionWithResult error"); + return false; + } + napi_call_function( + env, + obj, + method, + argc, + argv, + &result); + return true; +} + +bool JsInsightIntentExecutor::CallJsFunctionWithResultInner( + const char* funcName, + size_t argc, + const napi_value* argv, + napi_value& result) +{ + HILOG_DEBUG("enter"); + auto* env = runtime_.GetNapiEnv(); + napi_value obj = jsObj_->GetNapiValue(); + if (!CheckTypeForNapiValue(env, obj, napi_valuetype::napi_object)) { + HILOG_ERROR("CallJsFunctionWithResultInner Type error"); + return false; + } + return JsInsightIntentExecutor::CallJsFunctionWithResult( + env, + obj, + funcName, + argc, + argv, + result); +} + +std::shared_ptr JsInsightIntentExecutor::GetResultFromJs( + napi_env env, napi_value resultJs) +{ + HILOG_DEBUG("enter"); + auto resultCpp = std::make_shared(); + if (!AppExecFwk::UnwrapExecuteResult(env, resultJs, *resultCpp)) { + return nullptr; + } + return resultCpp; +} + +napi_value JsInsightIntentExecutor::ResolveCbCpp(napi_env env, napi_callback_info info) +{ + HILOG_DEBUG("enter"); + constexpr size_t argc = 1; + napi_value argv[argc] = {nullptr}; + size_t actualArgc = argc; + void* data = nullptr; + napi_get_cb_info(env, info, &actualArgc, argv, nullptr, &data); + auto* callback = static_cast(data); + napi_value resultJs = argv[0]; + if (resultJs == nullptr) { + JsInsightIntentExecutor::ReplyFailed(callback); + return nullptr; + } + std::shared_ptr resultCpp = + JsInsightIntentExecutor::GetResultFromJs(env, resultJs); + JsInsightIntentExecutor::ReplySucceeded(callback, resultCpp); + return nullptr; +} + +napi_value JsInsightIntentExecutor::RejectCbCpp(napi_env env, napi_callback_info info) +{ + void* data = nullptr; + napi_get_cb_info(env, info, nullptr, nullptr, nullptr, &data); + auto* callback = static_cast(data); + JsInsightIntentExecutor::ReplyFailed(callback); + return nullptr; +} + +void JsInsightIntentExecutor::ReplyFailed(InsightIntentExecutorAsyncCallback* callback, + InsightIntentInnerErr innerErr) +{ + HILOG_DEBUG("enter"); + if (callback == nullptr) { + return; + } + AAFwk::IntentExecuteResult errorResult{}; + errorResult.innerErr = innerErr; + callback->Call(errorResult); + delete callback; +} + +void JsInsightIntentExecutor::ReplySucceeded(InsightIntentExecutorAsyncCallback* callback, + std::shared_ptr resultCpp) +{ + HILOG_DEBUG("enter"); + if (callback == nullptr) { + return; + } + if (resultCpp == nullptr) { + ReplyFailed(callback); + return; + } + resultCpp->innerErr = InsightIntentInnerErr::INSIGHT_INTENT_ERR_OK; + callback->Call(*resultCpp); + delete callback; +} + +void JsInsightIntentExecutor::ReplyFailedInner(InsightIntentInnerErr innerErr) +{ + HILOG_DEBUG("enter"); + state_ = JsInsightIntentExecutor::State::INVALID; + auto* callback = callback_.release(); + JsInsightIntentExecutor::ReplyFailed(callback, innerErr); +} + +void JsInsightIntentExecutor::ReplySucceededInner(std::shared_ptr resultCpp) +{ + HILOG_DEBUG("enter"); + state_ = JsInsightIntentExecutor::State::EXECUTATION_DONE; + auto* callback = callback_.release(); + JsInsightIntentExecutor::ReplySucceeded(callback, resultCpp); +} + +bool JsInsightIntentExecutor::HandleResultReturnedFromJsFunc(napi_value resultJs) +{ + HILOG_DEBUG("enter"); + auto* env = runtime_.GetNapiEnv(); + if (resultJs == nullptr) { + ReplyFailedInner(); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + bool isPromise = false; + napi_is_promise(env, resultJs, &isPromise); + + isAsync_ = isPromise; + + if (isPromise) { + HILOG_INFO("Is promise"); + auto* callback = callback_.release(); + + napi_value then = nullptr; + napi_get_named_property(env, resultJs, "then", &then); + napi_value resolveCbJs = nullptr; + napi_create_function(env, TMP_NAPI_ANONYMOUS_FUNC, strlen(TMP_NAPI_ANONYMOUS_FUNC), + ResolveCbCpp, callback, &resolveCbJs); + constexpr size_t argcThen = 1; + napi_value argvThen[argcThen] = { resolveCbJs }; + napi_call_function(env, resultJs, then, argcThen, argvThen, nullptr); + + napi_value promiseCatch = nullptr; + napi_get_named_property(env, resultJs, "catch", &promiseCatch); + napi_value rejectCbJs = nullptr; + napi_create_function(env, TMP_NAPI_ANONYMOUS_FUNC, strlen(TMP_NAPI_ANONYMOUS_FUNC), + RejectCbCpp, callback, &rejectCbJs); + constexpr size_t argcCatch = 1; + napi_value argvCatch[argcCatch] = { rejectCbJs }; + napi_call_function(env, resultJs, promiseCatch, argcCatch, argvCatch, nullptr); + } else { + HILOG_INFO("Not promise"); + std::shared_ptr resultCpp = JsInsightIntentExecutor::GetResultFromJs(env, resultJs); + if (resultCpp == nullptr) { + HILOG_ERROR("Result invalid"); + ReplyFailedInner(); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + HILOG_DEBUG("Call succeed"); + ReplySucceededInner(resultCpp); + } + return true; +} + +bool JsInsightIntentExecutor::CheckParametersUIAbilityForeground(const std::shared_ptr& windowStage) +{ + return windowStage != nullptr; +} + +bool JsInsightIntentExecutor::ExecuteInsightIntentUIAbilityForeground( + const std::string& name, + const AAFwk::WantParams& param, + const std::shared_ptr& windowStageJs) +{ + HILOG_DEBUG("enter"); + HandleScope handleScope(runtime_); + + constexpr auto intentMode = static_cast(InsightIntentExecuteMode::UIABILITY_FOREGROUND); + constexpr auto funcName = JsInsightIntentExecutor::JS_FUNC_NAME_FOR_MODE[intentMode]; + constexpr auto argc = JsInsightIntentExecutor::JS_ARGC_FOR_MODE[intentMode]; + + auto* env = runtime_.GetNapiEnv(); + napi_value nameJs = AppExecFwk::WrapStringToJS(env, name); + napi_value paramJs = AppExecFwk::WrapWantParams(env, param); + napi_value argv[argc] = { nameJs, paramJs, windowStageJs->GetNapiValue() }; + napi_value result = nullptr; + + if (!CallJsFunctionWithResultInner(funcName, argc, argv, result)) { + ReplyFailedInner(); + return false; + } + + return HandleResultReturnedFromJsFunc(result); +} + +bool JsInsightIntentExecutor::CheckParametersUIAbilityBackground() +{ + return true; +} + +bool JsInsightIntentExecutor::ExecuteInsightIntentUIAbilityBackground( + const std::string& name, + const AAFwk::WantParams& param) +{ + HILOG_DEBUG("enter"); + HandleScope handleScope(runtime_); + + constexpr auto intentMode = static_cast(InsightIntentExecuteMode::UIABILITY_BACKGROUND); + constexpr auto funcName = JsInsightIntentExecutor::JS_FUNC_NAME_FOR_MODE[intentMode]; + constexpr auto argc = JsInsightIntentExecutor::JS_ARGC_FOR_MODE[intentMode]; + + auto* env = runtime_.GetNapiEnv(); + napi_value nameJs = AppExecFwk::WrapStringToJS(env, name); + napi_value paramJs = AppExecFwk::WrapWantParams(env, param); + napi_value argv[argc] = { nameJs, paramJs }; + napi_value result = nullptr; + + if (!CallJsFunctionWithResultInner(funcName, argc, argv, result)) { + ReplyFailedInner(); + return false; + } + + return HandleResultReturnedFromJsFunc(result); +} + +bool JsInsightIntentExecutor::CheckParametersUIExtension( + const std::shared_ptr& UIExtensionContentSession) +{ + return UIExtensionContentSession != nullptr; +} + +bool JsInsightIntentExecutor::ExecuteInsightIntentUIExtension( + const std::string& name, + const AAFwk::WantParams& param, + const std::shared_ptr& UIExtensionContentSession) +{ + HILOG_DEBUG("enter"); + HandleScope handleScope(runtime_); + + constexpr auto intentMode = static_cast(InsightIntentExecuteMode::UIEXTENSION_ABILITY); + constexpr auto funcName = JsInsightIntentExecutor::JS_FUNC_NAME_FOR_MODE[intentMode]; + constexpr auto argc = JsInsightIntentExecutor::JS_ARGC_FOR_MODE[intentMode]; + + auto* env = runtime_.GetNapiEnv(); + napi_value nameJs = AppExecFwk::WrapStringToJS(env, name); + napi_value paramJs = AppExecFwk::WrapWantParams(env, param); + napi_value argv[argc] = { nameJs, paramJs, UIExtensionContentSession->GetNapiValue() }; + napi_value result = nullptr; + + if (!CallJsFunctionWithResultInner(funcName, argc, argv, result)) { + ReplyFailedInner(); + return false; + } + + return HandleResultReturnedFromJsFunc(result); +} + +bool JsInsightIntentExecutor::CheckParametersServiceExtension() +{ + return true; +} + +bool JsInsightIntentExecutor::ExecuteInsightIntentServiceExtension( + const std::string& name, + const AAFwk::WantParams& param) +{ + HILOG_DEBUG("enter"); + HandleScope handleScope(runtime_); + + constexpr auto intentMode = static_cast(InsightIntentExecuteMode::SERVICE_EXTENSION_ABILITY); + constexpr auto funcName = JsInsightIntentExecutor::JS_FUNC_NAME_FOR_MODE[intentMode]; + constexpr auto argc = JsInsightIntentExecutor::JS_ARGC_FOR_MODE[intentMode]; + + auto* env = runtime_.GetNapiEnv(); + napi_value nameJs = AppExecFwk::WrapStringToJS(env, name); + napi_value paramJs = AppExecFwk::WrapWantParams(env, param); + napi_value argv[argc] = { nameJs, paramJs }; + napi_value result = nullptr; + + if (!CallJsFunctionWithResultInner(funcName, argc, argv, result)) { + ReplyFailedInner(); + return false; + } + + return HandleResultReturnedFromJsFunc(result); +} +} // namespace OHOS::AbilityRuntime diff --git a/interfaces/inner_api/ability_manager/include/insight_intent_constant.h b/interfaces/inner_api/ability_manager/include/insight_intent_constant.h new file mode 100644 index 0000000000000000000000000000000000000000..bdd04fecec8f42018604dceb8c1cfdb5dcf79696 --- /dev/null +++ b/interfaces/inner_api/ability_manager/include/insight_intent_constant.h @@ -0,0 +1,35 @@ +/* + * 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_ABILITY_RUNTIME_INSIGHT_INTENT_CONSTANT_H +#define OHOS_ABILITY_RUNTIME_INSIGHT_INTENT_CONSTANT_H + +namespace OHOS::AbilityRuntime { + enum class InsightIntentExecuteMode { + UIABILITY_FOREGROUND, + UIABILITY_BACKGROUND, + UIEXTENSION_ABILITY, + SERVICE_EXTENSION_ABILITY, + // Use default enum value and keep `Count` as the last element + Count + }; + + enum InsightIntentInnerErr { + INSIGHT_INTENT_ERR_OK, + INSIGHT_INTENT_INTERNAL_ERROR + }; +} // namespace OHOS::AbilityRuntime + +#endif // OHOS_ABILITY_RUNTIME_INSIGHT_INTENT_CONSTANT_H diff --git a/interfaces/inner_api/ability_manager/include/insight_intent_execute_result.h b/interfaces/inner_api/ability_manager/include/insight_intent_execute_result.h index 12553c9ab93193dc817e9d54de2a2a3fb1f8af62..94b026c8dd72e9317d98f76ac329b52ad55aee5e 100644 --- a/interfaces/inner_api/ability_manager/include/insight_intent_execute_result.h +++ b/interfaces/inner_api/ability_manager/include/insight_intent_execute_result.h @@ -16,6 +16,7 @@ #ifndef OHOS_ABILITY_RUNTIME_INSIGHT_INTENT_EXECUTE_RESULT_H #define OHOS_ABILITY_RUNTIME_INSIGHT_INTENT_EXECUTE_RESULT_H +#include "insight_intent_constant.h" #include "parcel.h" #include "want_params.h" @@ -28,14 +29,15 @@ using WantParams = OHOS::AAFwk::WantParams; */ struct InsightIntentExecuteResult : public Parcelable { public: + int32_t innerErr = AbilityRuntime::InsightIntentInnerErr::INSIGHT_INTENT_ERR_OK; + int32_t code = 0; + std::shared_ptr result = nullptr; + bool ReadFromParcel(Parcel &parcel); bool Marshalling(Parcel &parcel) const override; static InsightIntentExecuteResult *Unmarshalling(Parcel &parcel); // Check result returned by intent executor static bool CheckResult(std::shared_ptr result); - - int32_t code = 0; - std::shared_ptr result = nullptr; }; } // namespace AppExecFwk } // namespace OHOS diff --git a/interfaces/inner_api/ability_manager/include/state_pattern_naive.h b/interfaces/inner_api/ability_manager/include/state_pattern_naive.h new file mode 100644 index 0000000000000000000000000000000000000000..539fe1b740d6c570ed09f45618be1521e6041335 --- /dev/null +++ b/interfaces/inner_api/ability_manager/include/state_pattern_naive.h @@ -0,0 +1,66 @@ +/* + * 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 STATE_PATTERN_NAIVE_H +#define STATE_PATTERN_NAIVE_H + +/** + * Highly not recommanded to inlcude this header in a header file. + * When using naive state design pattern, please define `STATE_PATTERN_NAIVE_STATE` + * in the **cpp** file. And then include this header in the **cpp** file. + * If an error log is needed, please define `STATE_PATTERN_NAIVE_LOGGER`. +**/ +#ifdef STATE_PATTERN_NAIVE_STATE + +#define STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(state, returnVal) \ +do { \ + STATE_PATTERN_NAIVE_STATE = state; \ + return returnVal; \ +} while (0) \ + +#define STATE_PATTERN_NAIVE_ACCEPT(state, returnVal) \ +do { \ + if (STATE_PATTERN_NAIVE_STATE != state) { \ + return returnVal; \ + } \ +} while (0) \ + +#define STATE_PATTERN_NAIVE_REJECT(state, returnVal) \ +do { \ + if (STATE_PATTERN_NAIVE_STATE == state) { \ + return returnVal; \ + } \ +} while (0) \ + +#ifdef STATE_PATTERN_NAIVE_LOGGER +#define STATE_PATTERN_NAIVE_ACCEPT_LOG(state, returnVal, ...) \ +do { \ + if (STATE_PATTERN_NAIVE_STATE != state) { \ + STATE_PATTERN_NAIVE_LOGGER(__VA_ARGS__); \ + return returnVal; \ + } \ +} while (0) \ + +#define STATE_PATTERN_NAIVE_REJECT_LOG(state, returnVal, ...) \ +do { \ + if (STATE_PATTERN_NAIVE_STATE == state) { \ + STATE_PATTERN_NAIVE_LOGGER(__VA_ARGS__); \ + return returnVal; \ + } \ +} while (0) \ + +#endif // STATE_PATTERN_NAIVE_LOGGER +#endif // STATE_PATTERN_NAIVE_STATE +#endif // STATE_PATTERN_NAIVE_H diff --git a/interfaces/kits/native/ability/native/ability_transaction_callback_info.h b/interfaces/kits/native/ability/native/ability_transaction_callback_info.h index a6739e1742890b837f7c0467245a2df8180c2bc7..766ee32d7e9fe55c4a2a51fc2a5eaf028e7f8ac9 100644 --- a/interfaces/kits/native/ability/native/ability_transaction_callback_info.h +++ b/interfaces/kits/native/ability/native/ability_transaction_callback_info.h @@ -26,6 +26,9 @@ class AbilityTransactionCallbackInfo { public: using CallbackFunc = std::function; + AbilityTransactionCallbackInfo() = default; + ~AbilityTransactionCallbackInfo() = default; + static AbilityTransactionCallbackInfo *Create() { return new(std::nothrow) AbilityTransactionCallbackInfo(); @@ -50,11 +53,12 @@ public: } } -private: - AbilityTransactionCallbackInfo() = default; - - ~AbilityTransactionCallbackInfo() = default; + bool IsEmpty() const + { + return callbackStack_.empty(); + } +private: std::stack callbackStack_ {}; }; @@ -63,6 +67,9 @@ class AbilityTransactionCallbackInfo { public: using CallbackFunc = std::function; + AbilityTransactionCallbackInfo() = default; + ~AbilityTransactionCallbackInfo() = default; + static AbilityTransactionCallbackInfo *Create() { return new(std::nothrow) AbilityTransactionCallbackInfo(); @@ -87,11 +94,12 @@ public: } } -private: - AbilityTransactionCallbackInfo() = default; - - ~AbilityTransactionCallbackInfo() = default; + bool IsEmpty() const + { + return callbackStack_.empty(); + } +private: std::stack callbackStack_ {}; }; } // namespace AppExecFwk diff --git a/interfaces/kits/native/ability/native/insight_intent_executor/insight_intent_executor.h b/interfaces/kits/native/ability/native/insight_intent_executor/insight_intent_executor.h new file mode 100644 index 0000000000000000000000000000000000000000..70a8976d6ff169482630683077882e1f43c9edf7 --- /dev/null +++ b/interfaces/kits/native/ability/native/insight_intent_executor/insight_intent_executor.h @@ -0,0 +1,73 @@ +/* + * 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_ABILITY_RUNTIME_INSIGHT_INTENT_EXECUTOR_H +#define OHOS_ABILITY_RUNTIME_INSIGHT_INTENT_EXECUTOR_H + +#include +#include +#include +#include "insight_intent_constant.h" +#include "insight_intent_executor_info.h" + +namespace OHOS { +namespace AAFwk { + struct InsightIntentExecuteResult; + class WantParams; +} // namespace AAFwk +namespace AppExecFwk { + template class AbilityTransactionCallbackInfo; +} // namespace AppExecFwk +namespace AbilityRuntime { +class Runtime; +using InsightIntentExecutorAsyncCallback = + AppExecFwk::AbilityTransactionCallbackInfo; +class InsightIntentExecutor { +public: + static std::shared_ptr Create(Runtime& runtime); +protected: + InsightIntentExecutor() = default; +public: + InsightIntentExecutor(const InsightIntentExecutor&) = delete; + InsightIntentExecutor(const InsightIntentExecutor&&) = delete; + InsightIntentExecutor& operator=(const InsightIntentExecutor&) = delete; + InsightIntentExecutor& operator=(const InsightIntentExecutor&&) = delete; + virtual ~InsightIntentExecutor() = default; + + /** + * @brief Init the insight intent executor and insight intent context. + * + * @param + */ + virtual bool Init(const InsightIntentExecutorInfo& intentInfo) = 0; + + /** + * @brief Handling the life cycle execute insight intent. + * + * @param + * + */ + virtual bool HandleExecuteIntent( + InsightIntentExecuteMode mode, + const std::string& name, + const AAFwk::WantParams& params, + const std::shared_ptr& pageLoader, + std::unique_ptr callback, + bool& isAsync) = 0; +}; +} // namespace AbilityRuntime +} // namespace OHOS + +#endif // OHOS_ABILITY_RUNTIME_INSIGHT_INTENT_EXECUTOR_H diff --git a/interfaces/kits/native/ability/native/insight_intent_executor/insight_intent_executor_info.h b/interfaces/kits/native/ability/native/insight_intent_executor/insight_intent_executor_info.h new file mode 100644 index 0000000000000000000000000000000000000000..bdd8700b800dc3c2351e84ac532a256cf7b3d9a7 --- /dev/null +++ b/interfaces/kits/native/ability/native/insight_intent_executor/insight_intent_executor_info.h @@ -0,0 +1,38 @@ +/* + * 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_ABILITY_RUNTIME_INSIGHT_INTENT_EXECUTOR_INFO_H +#define OHOS_ABILITY_RUNTIME_INSIGHT_INTENT_EXECUTOR_INFO_H + +#include + +#include "insight_intent_execute_param.h" +#include "js_runtime.h" + +class NativeReference; + +namespace OHOS::AbilityRuntime { +using InsightIntentExecuteParam = AAFwk::InsightIntentExecuteParam; +struct InsightIntentExecutorInfo { + std::string srcEntry; + std::string hapPath; + bool esmodule = true; + int32_t windowMode = 0; + sptr token = nullptr; + std::shared_ptr pageLoader = nullptr; + std::shared_ptr executeParam = nullptr; +}; +} // namespace OHOS::AbilityRuntime +#endif // OHOS_ABILITY_RUNTIME_INSIGHT_INTENT_EXECUTOR_INFO_H diff --git a/interfaces/kits/native/ability/native/insight_intent_executor/js_insight_intent_executor.h b/interfaces/kits/native/ability/native/insight_intent_executor/js_insight_intent_executor.h new file mode 100644 index 0000000000000000000000000000000000000000..26c8866c56daf1d4f816800173ddeec2f05da5e8 --- /dev/null +++ b/interfaces/kits/native/ability/native/insight_intent_executor/js_insight_intent_executor.h @@ -0,0 +1,155 @@ +/* + * 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_ABILITY_RUNTIME_JS_INSIGHT_INTENT_EXECUTOR_H +#define OHOS_ABILITY_RUNTIME_JS_INSIGHT_INTENT_EXECUTOR_H + +#include "insight_intent_executor.h" + +#include "native_reference.h" + +class NativeReference; + +namespace OHOS { +namespace AAFwk { + struct IntentExecuteResult; +} // namespace AAFwk +namespace AbilityRuntime { +class JsRuntime; + +class JsInsightIntentExecutor final : public InsightIntentExecutor { +public: + static std::shared_ptr Create(JsRuntime& runtime); + enum class State { + INVALID, + CREATED, + INITIALIZED, + EXECUTING, + EXECUTATION_DONE, + DESTROYED + }; +private: + static constexpr std::array(InsightIntentExecuteMode::Count)> JS_FUNC_NAME_FOR_MODE { + "onExecuteInUIAbilityForegroundMode", + "onExecuteInUIAbilityBackgroundMode", + "onExecuteInUIExtensionAbility", + "onExecuteInServiceExtensionAbility" + }; + static constexpr std::array(InsightIntentExecuteMode::Count)> JS_ARGC_FOR_MODE { + 3, 2, 3, 2 }; + + explicit JsInsightIntentExecutor(JsRuntime& runtime); +public: + JsInsightIntentExecutor(const JsInsightIntentExecutor&) = delete; + JsInsightIntentExecutor(const JsInsightIntentExecutor&&) = delete; + JsInsightIntentExecutor& operator=(const JsInsightIntentExecutor&) = delete; + JsInsightIntentExecutor& operator=(const JsInsightIntentExecutor&&) = delete; + ~JsInsightIntentExecutor() override; + + /** + * @brief Init the intent executor and intent context. + * + * @param + */ + bool Init(const InsightIntentExecutorInfo& insightIntentInfo) override; + + /** + * @brief Handling the life cycle execute intent. + * + * @param + * + */ + bool HandleExecuteIntent( + InsightIntentExecuteMode mode, + const std::string& name, + const AAFwk::WantParams& param, + const std::shared_ptr& pageLoader, + std::unique_ptr callback, + bool& isAsync) override; + + inline State GetState() const + { + return state_; + } + +private: + static std::unique_ptr LoadJsCode( + const InsightIntentExecutorInfo& insightIntentInfo, + JsRuntime& runtime); + + static bool CallJsFunctionWithResult( + napi_env env, + napi_value obj, + const char* funcName, + size_t argc, + const napi_value* argv, + napi_value& result + ); + + bool CallJsFunctionWithResultInner( + const char* funcName, + size_t argc, + const napi_value* argv, + napi_value& result + ); + + static std::shared_ptr GetResultFromJs(napi_env env, + napi_value resultJs); + + static napi_value ResolveCbCpp(napi_env env, napi_callback_info info); + static napi_value RejectCbCpp(napi_env env, napi_callback_info info); + + static void ReplyFailed(InsightIntentExecutorAsyncCallback* callback, + InsightIntentInnerErr innerErr = InsightIntentInnerErr::INSIGHT_INTENT_INTERNAL_ERROR); + static void ReplySucceeded(InsightIntentExecutorAsyncCallback* callback, + std::shared_ptr resultCpp); + void ReplyFailedInner(InsightIntentInnerErr innerErr = InsightIntentInnerErr::INSIGHT_INTENT_INTERNAL_ERROR); + void ReplySucceededInner(std::shared_ptr resultCpp); + + bool HandleResultReturnedFromJsFunc(napi_value resultJs); + + static bool CheckParametersUIAbilityForeground(const std::shared_ptr& windowStage); + bool ExecuteInsightIntentUIAbilityForeground( + const std::string& name, + const AAFwk::WantParams& param, + const std::shared_ptr& windowStage); + + static bool CheckParametersUIAbilityBackground(); + bool ExecuteInsightIntentUIAbilityBackground( + const std::string& name, + const AAFwk::WantParams& param); + + static bool CheckParametersUIExtension(const std::shared_ptr& UIExtensionContentSession); + bool ExecuteInsightIntentUIExtension( + const std::string& name, + const AAFwk::WantParams& param, + const std::shared_ptr& UIExtensionContentSession); + + static bool CheckParametersServiceExtension(); + bool ExecuteInsightIntentServiceExtension( + const std::string& name, + const AAFwk::WantParams& param); + + JsRuntime& runtime_; + State state_ = State::CREATED; + std::unique_ptr jsObj_ = nullptr; + std::unique_ptr callback_; + bool isAsync_ = false; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_JS_INSIGHT_INTENT_EXECUTOR_H diff --git a/services/abilitymgr/src/insight_intent_execute_result.cpp b/services/abilitymgr/src/insight_intent_execute_result.cpp index 474df54c9d0fb8b02a555db2a3f2a5e3cccbbac3..73fb80dc79423ba03550c657e5e6b8e2fc4b15ba 100644 --- a/services/abilitymgr/src/insight_intent_execute_result.cpp +++ b/services/abilitymgr/src/insight_intent_execute_result.cpp @@ -20,6 +20,7 @@ namespace AppExecFwk { using WantParams = OHOS::AAFwk::WantParams; bool InsightIntentExecuteResult::ReadFromParcel(Parcel &parcel) { + innerErr = parcel.ReadInt32(); code = parcel.ReadInt32(); result = std::shared_ptr(parcel.ReadParcelable()); return true; @@ -27,6 +28,9 @@ bool InsightIntentExecuteResult::ReadFromParcel(Parcel &parcel) bool InsightIntentExecuteResult::Marshalling(Parcel &parcel) const { + if (!parcel.WriteInt32(innerErr)) { + return false; + } if (!parcel.WriteInt32(code)) { return false; }