• 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 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 }