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