1 /*
2 * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "js_insight_intent_driver.h"
17
18 #include "ability_business_error.h"
19 #include "ability_manager_client.h"
20 #include "event_handler.h"
21 #include "event_runner.h"
22 #include "hilog_tag_wrapper.h"
23 #include "insight_intent_callback_interface.h"
24 #include "insight_intent_host_client.h"
25 #include "insight_intent_execute_result.h"
26 #include "js_error_utils.h"
27 #include "js_insight_intent_driver_utils.h"
28 #include "js_runtime_utils.h"
29 #include "napi_common_execute_param.h"
30 #include "napi_common_util.h"
31 #include "native_engine/native_value.h"
32
33 #include <mutex>
34
35 namespace OHOS {
36 namespace AbilityRuntime {
37 using namespace OHOS::AppExecFwk;
38 namespace {
39 constexpr int32_t INDEX_ZERO = 0;
40 constexpr int32_t INDEX_ONE = 1;
41 constexpr size_t ARGC_ONE = 1;
42 }
43 class JsInsightIntentExecuteCallbackClient : public InsightIntentExecuteCallbackInterface,
44 public std::enable_shared_from_this<JsInsightIntentExecuteCallbackClient> {
45 public:
JsInsightIntentExecuteCallbackClient(napi_env env,napi_deferred nativeDeferred,napi_ref callbackRef)46 JsInsightIntentExecuteCallbackClient(napi_env env, napi_deferred nativeDeferred, napi_ref callbackRef)
47 : env_(env), nativeDeferred_(nativeDeferred), callbackRef_(callbackRef) {}
48
49 virtual ~JsInsightIntentExecuteCallbackClient() = default;
50
ProcessInsightIntentExecute(int32_t resultCode,AppExecFwk::InsightIntentExecuteResult executeResult)51 void ProcessInsightIntentExecute(int32_t resultCode,
52 AppExecFwk::InsightIntentExecuteResult executeResult) override
53 {
54 NapiAsyncTask::CompleteCallback complete = [resultCode = resultCode, executeResult = executeResult]
55 (napi_env env, NapiAsyncTask &task, int32_t status) {
56 if (resultCode != 0) {
57 task.Reject(env, CreateJsError(env, GetJsErrorCodeByNativeError(resultCode)));
58 } else {
59 task.ResolveWithNoError(env, CreateJsExecuteResult(env, executeResult));
60 }
61 };
62 std::unique_ptr<NapiAsyncTask> asyncTask = nullptr;
63 if (nativeDeferred_) {
64 asyncTask = std::make_unique<NapiAsyncTask>(nativeDeferred_, nullptr,
65 std::make_unique<NapiAsyncTask::CompleteCallback>(std::move(complete)));
66 } else {
67 asyncTask = std::make_unique<NapiAsyncTask>(callbackRef_, nullptr,
68 std::make_unique<NapiAsyncTask::CompleteCallback>(std::move(complete)));
69 }
70 NapiAsyncTask::Schedule("JsInsightIntentDriver::OnExecute", env_, std::move(asyncTask));
71 }
72 private:
73 napi_env env_;
74 napi_deferred nativeDeferred_ = nullptr;
75 napi_ref callbackRef_ = nullptr;
76 };
77
78 class JsInsightIntentDriver {
79 public:
80 JsInsightIntentDriver() = default;
81 ~JsInsightIntentDriver() = default;
82
Finalizer(napi_env env,void * data,void * hint)83 static void Finalizer(napi_env env, void *data, void *hint)
84 {
85 TAG_LOGI(AAFwkTag::INTENT, "called");
86 std::unique_ptr<JsInsightIntentDriver>(static_cast<JsInsightIntentDriver*>(data));
87 }
88
Execute(napi_env env,napi_callback_info info)89 static napi_value Execute(napi_env env, napi_callback_info info)
90 {
91 GET_NAPI_INFO_AND_CALL(env, info, JsInsightIntentDriver, OnExecute);
92 }
93
94 private:
OnExecute(napi_env env,NapiCallbackInfo & info)95 napi_value OnExecute(napi_env env, NapiCallbackInfo& info)
96 {
97 TAG_LOGD(AAFwkTag::INTENT, "called");
98 if (info.argc < ARGC_ONE) {
99 TAG_LOGE(AAFwkTag::INTENT, "invalid argc");
100 ThrowTooFewParametersError(env);
101 return CreateJsUndefined(env);
102 }
103
104 InsightIntentExecuteParam param;
105 if (!UnwrapExecuteParam(env, info.argv[INDEX_ZERO], param)) {
106 TAG_LOGE(AAFwkTag::INTENT, "CheckOnOffType, Parse on off type failed");
107 ThrowInvalidParamError(env, "Parameter error: Parse param failed, param must be a ExecuteParam.");
108 return CreateJsUndefined(env);
109 }
110
111 napi_value lastParam = (info.argc == 1) ? nullptr : info.argv[INDEX_ONE];
112 napi_valuetype type = napi_undefined;
113 napi_typeof(env, lastParam, &type);
114
115 napi_value result = nullptr;
116 napi_deferred nativeDeferred = nullptr;
117 napi_ref callbackRef = nullptr;
118 std::unique_ptr<NapiAsyncTask> asyncTask = nullptr;
119 if (lastParam == nullptr || type != napi_function) {
120 napi_create_promise(env, &nativeDeferred, &result);
121 asyncTask = std::make_unique<NapiAsyncTask>(nativeDeferred, nullptr, nullptr);
122 } else {
123 napi_get_undefined(env, &result);
124 napi_create_reference(env, lastParam, 1, &callbackRef);
125 asyncTask = std::make_unique<NapiAsyncTask>(callbackRef, nullptr, nullptr);
126 }
127
128 if (asyncTask == nullptr) {
129 TAG_LOGE(AAFwkTag::INTENT, "asyncTask is nullptr");
130 return CreateJsUndefined(env);
131 }
132 auto client = std::make_shared<JsInsightIntentExecuteCallbackClient>(env, nativeDeferred, callbackRef);
133 uint64_t key = InsightIntentHostClient::GetInstance()->AddInsightIntentExecute(client);
134 auto err = AbilityManagerClient::GetInstance()->ExecuteIntent(key,
135 InsightIntentHostClient::GetInstance(), param);
136 if (err != 0) {
137 asyncTask->Reject(env, CreateJsError(env, GetJsErrorCodeByNativeError(err)));
138 InsightIntentHostClient::GetInstance()->RemoveInsightIntentExecute(key);
139 }
140 return result;
141 }
142 };
143
JsInsightIntentDriverInit(napi_env env,napi_value exportObj)144 napi_value JsInsightIntentDriverInit(napi_env env, napi_value exportObj)
145 {
146 TAG_LOGD(AAFwkTag::INTENT, "called");
147 if (env == nullptr || exportObj == nullptr) {
148 TAG_LOGE(AAFwkTag::INTENT, "Invalid input parameters");
149 return nullptr;
150 }
151
152 std::unique_ptr<JsInsightIntentDriver> jsIntentDriver = std::make_unique<JsInsightIntentDriver>();
153 napi_wrap(env, exportObj, jsIntentDriver.release(), JsInsightIntentDriver::Finalizer, nullptr, nullptr);
154
155 const char *moduleName = "JsInsightIntentDriver";
156 BindNativeFunction(env, exportObj, "execute", moduleName, JsInsightIntentDriver::Execute);
157 return CreateJsUndefined(env);
158 }
159 } // namespace AbilityRuntime
160 } // namespace OHOS
161