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