1 /*
2 * Copyright (c) 2021 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 #include <uv.h>
16
17 #include "app_log_wrapper.h"
18 #include "bundle_status_callback.h"
19
20 #include "napi/native_common.h"
21
BundleStatusCallback(napi_env env, napi_ref addedCallback, napi_ref updatedCallback, napi_ref removeCallback)22 BundleStatusCallback::BundleStatusCallback(napi_env env, napi_ref addedCallback,
23 napi_ref updatedCallback,
24 napi_ref removeCallback)
25 : env_(env), addedCallback_(addedCallback),
26 updatedCallback_(updatedCallback), removeCallback_(removeCallback) {}
27
~BundleStatusCallback()28 BundleStatusCallback::~BundleStatusCallback()
29 {
30 uv_loop_s* loop = nullptr;
31 napi_get_uv_event_loop(env_, &loop);
32 uv_work_t* work = new (std::nothrow) uv_work_t;
33 if (work == nullptr) {
34 return;
35 }
36 DelRefCallbackInfo* delRefCallbackInfo = new (std::nothrow) DelRefCallbackInfo {
37 .env_ = env_,
38 .addedCallback_ = addedCallback_,
39 .updatedCallback_ = updatedCallback_,
40 .removeCallback_ = removeCallback_,
41 };
42 if (delRefCallbackInfo == nullptr) {
43 delete work;
44 return;
45 }
46 work->data = reinterpret_cast<void*>(delRefCallbackInfo);
47 int ret = uv_queue_work(
48 loop, work, [](uv_work_t* work) { APP_LOGI("~BundleStatusCallback asyn work done"); },
49 [](uv_work_t* work, int status) {
50 // JS Thread
51 DelRefCallbackInfo* delRefCallbackInfo = reinterpret_cast<DelRefCallbackInfo*>(work->data);
52 if (delRefCallbackInfo == nullptr) {
53 return;
54 }
55 napi_delete_reference(delRefCallbackInfo->env_, delRefCallbackInfo->addedCallback_);
56 napi_delete_reference(delRefCallbackInfo->env_, delRefCallbackInfo->updatedCallback_);
57 napi_delete_reference(delRefCallbackInfo->env_, delRefCallbackInfo->removeCallback_);
58 delete delRefCallbackInfo;
59 delRefCallbackInfo = nullptr;
60 delete work;
61 work = nullptr;
62 });
63 if (ret != 0) {
64 delete delRefCallbackInfo;
65 delete work;
66 }
67 }
68
OnBundleAdded(const std::string& bundleName, const int userId)69 void BundleStatusCallback::OnBundleAdded(const std::string& bundleName, const int userId)
70 {
71 uv_loop_s* loop = nullptr;
72 napi_get_uv_event_loop(env_, &loop);
73 uv_work_t* work = new (std::nothrow) uv_work_t;
74 if (work == nullptr) {
75 APP_LOGW("BundleStatusCallback OnBundleAdded work is nullptr bundleName : %{public}s", bundleName.c_str());
76 return;
77 }
78 AsyncCallbackInfo* asyncCallbackInfo = new (std::nothrow)AsyncCallbackInfo {
79 .env_ = env_,
80 .callback_ = addedCallback_,
81 .bundleName_ = bundleName,
82 .userId_ = userId,
83 };
84 if (asyncCallbackInfo == nullptr) {
85 APP_LOGW("BundleStatusCallback OnBundleAdded asyncCallbackInfo is nullptr bundleName : %{public}s",
86 bundleName.c_str());
87 delete work;
88 return;
89 }
90 work->data = reinterpret_cast<void*>(asyncCallbackInfo);
91 if (loop == nullptr) {
92 APP_LOGW("BundleStatusCallback OnBundleAdded loop is nullptr bundleName : %{public}s", bundleName.c_str());
93 delete work;
94 return;
95 }
96 int ret = uv_queue_work(
97 loop, work, [](uv_work_t* work) { APP_LOGI("BundleStatusCallback OnBundleAdded asyn work done"); },
98 [](uv_work_t* work, int status) {
99 // JS Thread
100 APP_LOGI("BundleStatusCallback OnBundleAdded in JS Thread");
101 AsyncCallbackInfo* asyncCallbackInfo = reinterpret_cast<AsyncCallbackInfo*>(work->data);
102 if (asyncCallbackInfo == nullptr) {
103 APP_LOGE("asyncCallbackInfo is null");
104 return;
105 }
106 std::unique_ptr<AsyncCallbackInfo> callbackPtr {asyncCallbackInfo};
107 napi_handle_scope scope = nullptr;
108 napi_open_handle_scope(asyncCallbackInfo->env_, &scope);
109 if (scope == nullptr) {
110 APP_LOGE("scope is null");
111 return;
112 }
113 napi_value callback = nullptr;
114 napi_value placeHolder = nullptr;
115 napi_value result[2] = { 0 };
116 napi_get_reference_value(asyncCallbackInfo->env_, asyncCallbackInfo->callback_, &callback);
117 napi_create_string_utf8(
118 asyncCallbackInfo->env_, asyncCallbackInfo->bundleName_.c_str(), NAPI_AUTO_LENGTH, &result[0]);
119 napi_create_uint32(asyncCallbackInfo->env_, asyncCallbackInfo->userId_, &result[1]);
120 napi_call_function(
121 asyncCallbackInfo->env_, nullptr, callback, sizeof(result) / sizeof(result[0]), result, &placeHolder);
122 napi_close_handle_scope(asyncCallbackInfo->env_, scope);
123 if (work != nullptr) {
124 delete work;
125 work = nullptr;
126 }
127 });
128 if (ret != 0) {
129 APP_LOGE("OnBundleAdded failed due to call uv_queue_work failed");
130 delete asyncCallbackInfo;
131 delete work;
132 }
133 }
134
OnBundleUpdated(const std::string& bundleName, const int userId)135 void BundleStatusCallback::OnBundleUpdated(const std::string& bundleName, const int userId)
136 {
137 uv_loop_s* loop = nullptr;
138 napi_get_uv_event_loop(env_, &loop);
139 uv_work_t* work = new (std::nothrow) uv_work_t;
140 if (work == nullptr) {
141 APP_LOGW("BundleStatusCallback OnBundleUpdated work is nullptr bundleName : %{public}s", bundleName.c_str());
142 return;
143 }
144 AsyncCallbackInfo* asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo {
145 .env_ = env_,
146 .callback_ = updatedCallback_,
147 .bundleName_ = bundleName,
148 .userId_ = userId,
149 };
150 if (asyncCallbackInfo == nullptr) {
151 APP_LOGW("BundleStatusCallback OnBundleUpdated asyncCallbackInfo is nullptr bundleName : %{public}s",
152 bundleName.c_str());
153 delete work;
154 return;
155 }
156 work->data = reinterpret_cast<void*>(asyncCallbackInfo);
157 if (loop == nullptr) {
158 APP_LOGW("BundleStatusCallback OnBundleUpdated loop is nullptr bundleName : %{public}s", bundleName.c_str());
159 delete work;
160 return;
161 }
162 int ret = uv_queue_work(
163 loop, work, [](uv_work_t* work) { APP_LOGI("BundleStatusCallback OnBundleUpdated asyn work done"); },
164 [](uv_work_t* work, int status) {
165 APP_LOGI("BundleStatusCallback OnBundleUpdated in JS Thread");
166 AsyncCallbackInfo* asyncCallbackInfo = reinterpret_cast<AsyncCallbackInfo*>(work->data);
167 if (asyncCallbackInfo == nullptr) {
168 APP_LOGE("asyncCallbackInfo is null");
169 return;
170 }
171 std::unique_ptr<AsyncCallbackInfo> callbackPtr {asyncCallbackInfo};
172 napi_handle_scope scope = nullptr;
173 napi_open_handle_scope(asyncCallbackInfo->env_, &scope);
174 if (scope == nullptr) {
175 APP_LOGE("scope is null");
176 return;
177 }
178 napi_value callback = nullptr;
179 napi_value placeHolder = nullptr;
180 napi_value result[2] = { 0 };
181 napi_get_reference_value(asyncCallbackInfo->env_, asyncCallbackInfo->callback_, &callback);
182 napi_create_string_utf8(
183 asyncCallbackInfo->env_, asyncCallbackInfo->bundleName_.c_str(), NAPI_AUTO_LENGTH, &result[0]);
184 napi_create_uint32(asyncCallbackInfo->env_, asyncCallbackInfo->userId_, &result[1]);
185 napi_call_function(
186 asyncCallbackInfo->env_, nullptr, callback, sizeof(result) / sizeof(result[0]), result, &placeHolder);
187 napi_close_handle_scope(asyncCallbackInfo->env_, scope);
188 if (work != nullptr) {
189 delete work;
190 work = nullptr;
191 }
192 });
193 if (ret != 0) {
194 APP_LOGE("OnBundleUpdated failed due to call uv_queue_work failed");
195 if (asyncCallbackInfo != nullptr) {
196 delete asyncCallbackInfo;
197 }
198 if (work != nullptr) {
199 delete work;
200 }
201 }
202 }
203
OnBundleRemoved(const std::string& bundleName, const int userId)204 void BundleStatusCallback::OnBundleRemoved(const std::string& bundleName, const int userId)
205 {
206 uv_loop_s* loop = nullptr;
207 napi_get_uv_event_loop(env_, &loop);
208 uv_work_t* work = new (std::nothrow) uv_work_t;
209 if (work == nullptr) {
210 APP_LOGW("BundleStatusCallback OnBundleRemoved work is nullptr bundleName : %{public}s", bundleName.c_str());
211 return;
212 }
213 AsyncCallbackInfo* asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo {
214 .env_ = env_,
215 .callback_ = removeCallback_,
216 .bundleName_ = bundleName,
217 .userId_ = userId,
218 };
219 if (asyncCallbackInfo == nullptr) {
220 APP_LOGW("BundleStatusCallback OnBundleUpdated asyncCallbackInfo is nullptr bundleName : %{public}s",
221 bundleName.c_str());
222 delete work;
223 return;
224 }
225 work->data = reinterpret_cast<void*>(asyncCallbackInfo);
226 if (loop == nullptr) {
227 APP_LOGW("BundleStatusCallback OnBundleRemoved loop is nullptr bundleName : %{public}s", bundleName.c_str());
228 delete work;
229 return;
230 }
231 int ret = uv_queue_work(
232 loop, work, [](uv_work_t* work) { APP_LOGI("BundleStatusCallback OnBundleRemoved asyn work done"); },
233 [](uv_work_t* work, int status) {
234 APP_LOGI("BundleStatusCallback OnBundleRemoved in JS Thread");
235 // JS Thread
236 AsyncCallbackInfo* asyncCallbackInfo = reinterpret_cast<AsyncCallbackInfo*>(work->data);
237 if (asyncCallbackInfo == nullptr) {
238 APP_LOGE("asyncCallbackInfo is null");
239 return;
240 }
241 std::unique_ptr<AsyncCallbackInfo> callbackPtr {asyncCallbackInfo};
242 napi_handle_scope scope = nullptr;
243 napi_open_handle_scope(asyncCallbackInfo->env_, &scope);
244 if (scope == nullptr) {
245 APP_LOGE("scope is null");
246 return;
247 }
248 napi_value callback = nullptr;
249 napi_value placeHolder = nullptr;
250 napi_value result[2] = { 0 };
251 napi_get_reference_value(asyncCallbackInfo->env_, asyncCallbackInfo->callback_, &callback);
252 napi_create_string_utf8(
253 asyncCallbackInfo->env_, asyncCallbackInfo->bundleName_.c_str(), NAPI_AUTO_LENGTH, &result[0]);
254 napi_create_uint32(asyncCallbackInfo->env_, asyncCallbackInfo->userId_, &result[1]);
255 napi_call_function(
256 asyncCallbackInfo->env_, nullptr, callback, sizeof(result) / sizeof(result[0]), result, &placeHolder);
257 napi_close_handle_scope(asyncCallbackInfo->env_, scope);
258 if (work != nullptr) {
259 delete work;
260 work = nullptr;
261 }
262 });
263 if (ret != 0) {
264 APP_LOGE("OnBundleRemoved failed due to call uv_queue_work failed");
265 delete asyncCallbackInfo;
266 delete work;
267 }
268 }