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) {},
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) {},
98 [](uv_work_t* work, int status) {
99 // JS Thread
100 AsyncCallbackInfo* asyncCallbackInfo = reinterpret_cast<AsyncCallbackInfo*>(work->data);
101 if (asyncCallbackInfo == nullptr) {
102 return;
103 }
104 std::unique_ptr<AsyncCallbackInfo> callbackPtr {asyncCallbackInfo};
105 napi_handle_scope scope = nullptr;
106 napi_open_handle_scope(asyncCallbackInfo->env_, &scope);
107 if (scope == nullptr) {
108 return;
109 }
110 napi_value callback = nullptr;
111 napi_value placeHolder = nullptr;
112 napi_value result[2] = { 0 };
113 napi_get_reference_value(asyncCallbackInfo->env_, asyncCallbackInfo->callback_, &callback);
114 napi_create_string_utf8(
115 asyncCallbackInfo->env_, asyncCallbackInfo->bundleName_.c_str(), NAPI_AUTO_LENGTH, &result[0]);
116 napi_create_uint32(asyncCallbackInfo->env_, asyncCallbackInfo->userId_, &result[1]);
117 napi_call_function(
118 asyncCallbackInfo->env_, nullptr, callback, sizeof(result) / sizeof(result[0]), result, &placeHolder);
119 napi_close_handle_scope(asyncCallbackInfo->env_, scope);
120 if (work != nullptr) {
121 delete work;
122 work = nullptr;
123 }
124 });
125 if (ret != 0) {
126 delete asyncCallbackInfo;
127 delete work;
128 }
129 }
130
OnBundleUpdated(const std::string & bundleName,const int userId)131 void BundleStatusCallback::OnBundleUpdated(const std::string& bundleName, const int userId)
132 {
133 uv_loop_s* loop = nullptr;
134 napi_get_uv_event_loop(env_, &loop);
135 uv_work_t* work = new (std::nothrow) uv_work_t;
136 if (work == nullptr) {
137 APP_LOGW("BundleStatusCallback OnBundleUpdated work is nullptr bundleName : %{public}s", bundleName.c_str());
138 return;
139 }
140 AsyncCallbackInfo* asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo {
141 .env_ = env_,
142 .callback_ = updatedCallback_,
143 .bundleName_ = bundleName,
144 .userId_ = userId,
145 };
146 if (asyncCallbackInfo == nullptr) {
147 APP_LOGW("BundleStatusCallback OnBundleUpdated asyncCallbackInfo is nullptr bundleName : %{public}s",
148 bundleName.c_str());
149 delete work;
150 return;
151 }
152 work->data = reinterpret_cast<void*>(asyncCallbackInfo);
153 if (loop == nullptr) {
154 APP_LOGW("BundleStatusCallback OnBundleUpdated loop is nullptr bundleName : %{public}s", bundleName.c_str());
155 delete work;
156 return;
157 }
158 int ret = uv_queue_work(
159 loop, work, [](uv_work_t* work) {},
160 [](uv_work_t* work, int status) {
161 AsyncCallbackInfo* asyncCallbackInfo = reinterpret_cast<AsyncCallbackInfo*>(work->data);
162 if (asyncCallbackInfo == nullptr) {
163 return;
164 }
165 std::unique_ptr<AsyncCallbackInfo> callbackPtr {asyncCallbackInfo};
166 napi_handle_scope scope = nullptr;
167 napi_open_handle_scope(asyncCallbackInfo->env_, &scope);
168 if (scope == nullptr) {
169 return;
170 }
171 napi_value callback = nullptr;
172 napi_value placeHolder = nullptr;
173 napi_value result[2] = { 0 };
174 napi_get_reference_value(asyncCallbackInfo->env_, asyncCallbackInfo->callback_, &callback);
175 napi_create_string_utf8(
176 asyncCallbackInfo->env_, asyncCallbackInfo->bundleName_.c_str(), NAPI_AUTO_LENGTH, &result[0]);
177 napi_create_uint32(asyncCallbackInfo->env_, asyncCallbackInfo->userId_, &result[1]);
178 napi_call_function(
179 asyncCallbackInfo->env_, nullptr, callback, sizeof(result) / sizeof(result[0]), result, &placeHolder);
180 napi_close_handle_scope(asyncCallbackInfo->env_, scope);
181 if (work != nullptr) {
182 delete work;
183 work = nullptr;
184 }
185 });
186 if (ret != 0) {
187 if (asyncCallbackInfo != nullptr) {
188 delete asyncCallbackInfo;
189 }
190 if (work != nullptr) {
191 delete work;
192 }
193 }
194 }
195
OnBundleRemoved(const std::string & bundleName,const int userId)196 void BundleStatusCallback::OnBundleRemoved(const std::string& bundleName, const int userId)
197 {
198 uv_loop_s* loop = nullptr;
199 napi_get_uv_event_loop(env_, &loop);
200 uv_work_t* work = new (std::nothrow) uv_work_t;
201 if (work == nullptr) {
202 APP_LOGW("BundleStatusCallback OnBundleRemoved work is nullptr bundleName : %{public}s", bundleName.c_str());
203 return;
204 }
205 AsyncCallbackInfo* asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo {
206 .env_ = env_,
207 .callback_ = removeCallback_,
208 .bundleName_ = bundleName,
209 .userId_ = userId,
210 };
211 if (asyncCallbackInfo == nullptr) {
212 APP_LOGW("BundleStatusCallback OnBundleUpdated asyncCallbackInfo is nullptr bundleName : %{public}s",
213 bundleName.c_str());
214 delete work;
215 return;
216 }
217 work->data = reinterpret_cast<void*>(asyncCallbackInfo);
218 if (loop == nullptr) {
219 APP_LOGW("BundleStatusCallback OnBundleRemoved loop is nullptr bundleName : %{public}s", bundleName.c_str());
220 delete work;
221 return;
222 }
223 int ret = uv_queue_work(
224 loop, work, [](uv_work_t* work) {},
225 [](uv_work_t* work, int status) {
226 // JS Thread
227 AsyncCallbackInfo* asyncCallbackInfo = reinterpret_cast<AsyncCallbackInfo*>(work->data);
228 if (asyncCallbackInfo == nullptr) {
229 return;
230 }
231 std::unique_ptr<AsyncCallbackInfo> callbackPtr {asyncCallbackInfo};
232 napi_handle_scope scope = nullptr;
233 napi_open_handle_scope(asyncCallbackInfo->env_, &scope);
234 if (scope == nullptr) {
235 return;
236 }
237 napi_value callback = nullptr;
238 napi_value placeHolder = nullptr;
239 napi_value result[2] = { 0 };
240 napi_get_reference_value(asyncCallbackInfo->env_, asyncCallbackInfo->callback_, &callback);
241 napi_create_string_utf8(
242 asyncCallbackInfo->env_, asyncCallbackInfo->bundleName_.c_str(), NAPI_AUTO_LENGTH, &result[0]);
243 napi_create_uint32(asyncCallbackInfo->env_, asyncCallbackInfo->userId_, &result[1]);
244 napi_call_function(
245 asyncCallbackInfo->env_, nullptr, callback, sizeof(result) / sizeof(result[0]), result, &placeHolder);
246 napi_close_handle_scope(asyncCallbackInfo->env_, scope);
247 if (work != nullptr) {
248 delete work;
249 work = nullptr;
250 }
251 });
252 if (ret != 0) {
253 delete asyncCallbackInfo;
254 delete work;
255 }
256 }