• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2024 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 
16 #include "js_free_install_observer.h"
17 
18 #include "ability_manager_errors.h"
19 #include "hilog_tag_wrapper.h"
20 #include "hitrace_meter.h"
21 #include "js_error_utils.h"
22 #include "js_runtime.h"
23 #include "js_runtime_utils.h"
24 #include "napi/native_api.h"
25 
26 namespace OHOS {
27 namespace AbilityRuntime {
JsFreeInstallObserver(napi_env env)28 JsFreeInstallObserver::JsFreeInstallObserver(napi_env env) : env_(env) {}
29 
30 JsFreeInstallObserver::~JsFreeInstallObserver() = default;
31 
OnInstallFinished(const std::string & bundleName,const std::string & abilityName,const std::string & startTime,int32_t resultCode)32 void JsFreeInstallObserver::OnInstallFinished(const std::string &bundleName, const std::string &abilityName,
33     const std::string &startTime, int32_t resultCode)
34 {
35     TAG_LOGD(AAFwkTag::FREE_INSTALL, "call");
36     wptr<JsFreeInstallObserver> jsObserver = this;
37     std::unique_ptr<NapiAsyncTask::CompleteCallback> complete = std::make_unique<NapiAsyncTask::CompleteCallback>
38         ([jsObserver, bundleName, abilityName, startTime, resultCode](napi_env env, NapiAsyncTask &task,
39             int32_t status) {
40             sptr<JsFreeInstallObserver> jsObserverSptr = jsObserver.promote();
41             if (jsObserverSptr) {
42                 jsObserverSptr->HandleOnInstallFinished(bundleName, abilityName, startTime, resultCode);
43             }
44         });
45     napi_ref callback = nullptr;
46     std::unique_ptr<NapiAsyncTask::ExecuteCallback> execute = nullptr;
47     NapiAsyncTask::Schedule("JsFreeInstallObserver::OnInstallFinished", env_, std::make_unique<NapiAsyncTask>(callback,
48         std::move(execute), std::move(complete)));
49 }
50 
OnInstallFinishedByUrl(const std::string & startTime,const std::string & url,int32_t resultCode)51 void JsFreeInstallObserver::OnInstallFinishedByUrl(const std::string &startTime, const std::string& url,
52     int32_t resultCode)
53 {
54     TAG_LOGD(AAFwkTag::FREE_INSTALL, "call");
55     wptr<JsFreeInstallObserver> jsObserver = this;
56     std::unique_ptr<NapiAsyncTask::CompleteCallback> complete = std::make_unique<NapiAsyncTask::CompleteCallback>
57         ([jsObserver, startTime, url, resultCode](napi_env env, NapiAsyncTask &task,
58             int32_t status) {
59             sptr<JsFreeInstallObserver> jsObserverSptr = jsObserver.promote();
60             if (jsObserverSptr) {
61                 jsObserverSptr->HandleOnInstallFinishedByUrl(startTime, url, resultCode);
62             }
63         });
64     napi_ref callback = nullptr;
65     std::unique_ptr<NapiAsyncTask::ExecuteCallback> execute = nullptr;
66     NapiAsyncTask::Schedule("JsFreeInstallObserver::OnInstallFinished", env_, std::make_unique<NapiAsyncTask>(callback,
67         std::move(execute), std::move(complete)));
68 }
69 
OnInstallFinished(const std::string & bundleName,const std::string & abilityName,const std::string & startTime,napi_value abilityResult)70 void JsFreeInstallObserver::OnInstallFinished(const std::string &bundleName, const std::string &abilityName,
71     const std::string &startTime, napi_value abilityResult)
72 {
73     TAG_LOGD(AAFwkTag::FREE_INSTALL, "call");
74     std::vector<napi_deferred> promises;
75     std::vector<napi_ref> callbacks;
76     {
77         std::unique_lock<std::mutex> lock(jsObserverObjectListLock_);
78         for (auto it = jsObserverObjectList_.begin(); it != jsObserverObjectList_.end();) {
79             if ((it->bundleName != bundleName) || (it->abilityName != abilityName) || (it->startTime != startTime)) {
80                 it++;
81                 continue;
82             }
83             if (it->callback == nullptr && it->deferred == nullptr) {
84                 it++;
85                 continue;
86             }
87             if (!it->isAbilityResult) {
88                 it++;
89                 continue;
90             }
91             if (it->deferred != nullptr) {
92                 promises.emplace_back(it->deferred);
93             } else {
94                 callbacks.emplace_back(it->callback);
95             }
96             it = jsObserverObjectList_.erase(it);
97             TAG_LOGD(AAFwkTag::FREE_INSTALL,
98                 "jsObserverObjectList_ size:%{public}zu", jsObserverObjectList_.size());
99         }
100     }
101 
102     for (const napi_deferred& promise : promises) {
103         CallPromise(promise, abilityResult);
104         FinishAsyncTrace(HITRACE_TAG_ABILITY_MANAGER, "StartFreeInstall", atoi(startTime.c_str()));
105     }
106     for (const napi_ref& callback : callbacks) {
107         CallCallback(callback, abilityResult);
108         FinishAsyncTrace(HITRACE_TAG_ABILITY_MANAGER, "StartFreeInstall", atoi(startTime.c_str()));
109     }
110 }
111 
HandleOnInstallFinished(const std::string & bundleName,const std::string & abilityName,const std::string & startTime,int32_t resultCode)112 void JsFreeInstallObserver::HandleOnInstallFinished(const std::string &bundleName, const std::string &abilityName,
113     const std::string &startTime, int32_t resultCode)
114 {
115     TAG_LOGD(AAFwkTag::FREE_INSTALL, "call");
116     std::vector<napi_deferred> promises;
117     std::vector<napi_ref> callbacks;
118     {
119         std::unique_lock<std::mutex> lock(jsObserverObjectListLock_);
120         for (auto it = jsObserverObjectList_.begin(); it != jsObserverObjectList_.end();) {
121             if ((it->bundleName != bundleName) || (it->abilityName != abilityName) || (it->startTime != startTime)) {
122                 it++;
123                 continue;
124             }
125             if (it->callback == nullptr && it->deferred == nullptr) {
126                 it++;
127                 continue;
128             }
129             if (it->isAbilityResult && resultCode == ERR_OK) {
130                 it++;
131                 continue;
132             }
133             if (it->deferred != nullptr) {
134                 promises.emplace_back(it->deferred);
135             } else {
136                 callbacks.emplace_back(it->callback);
137             }
138             it = jsObserverObjectList_.erase(it);
139         }
140     }
141 
142     for (const napi_deferred& promise : promises) {
143         CallPromise(promise, resultCode);
144         FinishAsyncTrace(HITRACE_TAG_ABILITY_MANAGER, "StartFreeInstall", atoi(startTime.c_str()));
145     }
146     for (const napi_ref& callback : callbacks) {
147         CallCallback(callback, resultCode);
148         FinishAsyncTrace(HITRACE_TAG_ABILITY_MANAGER, "StartFreeInstall", atoi(startTime.c_str()));
149     }
150 }
151 
HandleOnInstallFinishedByUrl(const std::string & startTime,const std::string & url,int32_t resultCode)152 void JsFreeInstallObserver::HandleOnInstallFinishedByUrl(const std::string &startTime, const std::string& url,
153     int32_t resultCode)
154 {
155     TAG_LOGD(AAFwkTag::FREE_INSTALL, "call");
156     std::vector<napi_deferred> promises;
157     std::vector<napi_ref> callbacks;
158     {
159         std::unique_lock<std::mutex> lock(jsObserverObjectListLock_);
160         for (auto it = jsObserverObjectList_.begin(); it != jsObserverObjectList_.end();) {
161             if ((it->startTime != startTime) || (it->url != url)) {
162                 it++;
163                 continue;
164             }
165             if (it->callback == nullptr && it->deferred == nullptr) {
166                 it++;
167                 continue;
168             }
169             if (it->isAbilityResult && (resultCode == ERR_OK ||
170                 resultCode == AAFwk::ATOMIC_SERVICE_MINIMIZED)) {
171                 it++;
172                 continue;
173             }
174             if (it->deferred != nullptr) {
175                 promises.emplace_back(it->deferred);
176             } else {
177                 callbacks.emplace_back(it->callback);
178             }
179             it = jsObserverObjectList_.erase(it);
180         }
181     }
182 
183     for (const napi_deferred& promise : promises) {
184         CallPromise(promise, resultCode);
185         FinishAsyncTrace(HITRACE_TAG_ABILITY_MANAGER, "StartFreeInstall", atoi(startTime.c_str()));
186     }
187     for (const napi_ref& callback : callbacks) {
188         CallCallback(callback, resultCode);
189         FinishAsyncTrace(HITRACE_TAG_ABILITY_MANAGER, "StartFreeInstall", atoi(startTime.c_str()));
190     }
191 }
192 
CallCallback(napi_ref callback,int32_t resultCode)193 void JsFreeInstallObserver::CallCallback(napi_ref callback, int32_t resultCode)
194 {
195     TAG_LOGD(AAFwkTag::FREE_INSTALL, "call");
196     if (callback == nullptr) {
197         TAG_LOGE(AAFwkTag::FREE_INSTALL, "null callback");
198         return;
199     }
200     napi_value value;
201     if (resultCode == ERR_OK || resultCode == AAFwk::ATOMIC_SERVICE_MINIMIZED) {
202         value = CreateJsUndefined(env_);
203     } else {
204         value = CreateJsError(env_, GetJsErrorCodeByNativeError(resultCode));
205     }
206     napi_value argv[] = { value };
207     napi_value func = nullptr;
208     napi_get_reference_value(env_, callback, &func);
209     napi_call_function(env_, CreateJsUndefined(env_), func, ArraySize(argv), argv, nullptr);
210 }
211 
CallCallback(napi_ref callback,napi_value abilityResult)212 void JsFreeInstallObserver::CallCallback(napi_ref callback, napi_value abilityResult)
213 {
214     TAG_LOGD(AAFwkTag::FREE_INSTALL, "call");
215     if (callback == nullptr) {
216         TAG_LOGE(AAFwkTag::FREE_INSTALL, "null callback");
217         return;
218     }
219     napi_value argv[] = {
220         CreateJsError(env_, 0),
221         abilityResult,
222     };
223     napi_value func = nullptr;
224     napi_get_reference_value(env_, callback, &func);
225     napi_call_function(env_, CreateJsUndefined(env_), func, ArraySize(argv), argv, nullptr);
226 }
227 
CallPromise(napi_deferred deferred,int32_t resultCode)228 void JsFreeInstallObserver::CallPromise(napi_deferred deferred, int32_t resultCode)
229 {
230     if (deferred == nullptr) {
231         TAG_LOGE(AAFwkTag::FREE_INSTALL, "null deferred");
232         return;
233     }
234     if (resultCode == ERR_OK || resultCode == AAFwk::ATOMIC_SERVICE_MINIMIZED) {
235         napi_value value = CreateJsUndefined(env_);
236         napi_resolve_deferred(env_, deferred, value);
237     } else {
238         napi_value error = CreateJsError(env_, GetJsErrorCodeByNativeError(resultCode));
239         napi_reject_deferred(env_, deferred, error);
240     }
241 }
242 
CallPromise(napi_deferred deferred,napi_value abilityResult)243 void JsFreeInstallObserver::CallPromise(napi_deferred deferred, napi_value abilityResult)
244 {
245     if (deferred == nullptr) {
246         TAG_LOGE(AAFwkTag::FREE_INSTALL, "null deferred");
247         return;
248     }
249     napi_resolve_deferred(env_, deferred, abilityResult);
250 }
251 
AddJsObserverObject(const std::string & bundleName,const std::string & abilityName,const std::string & startTime,napi_value jsObserverObject,napi_value * result,bool isAbilityResult)252 void JsFreeInstallObserver::AddJsObserverObject(const std::string &bundleName, const std::string &abilityName,
253     const std::string &startTime, napi_value jsObserverObject, napi_value* result, bool isAbilityResult)
254 {
255     TAG_LOGD(AAFwkTag::FREE_INSTALL, "call");
256     {
257         std::unique_lock<std::mutex> lock(jsObserverObjectListLock_);
258         for (auto it = jsObserverObjectList_.begin(); it != jsObserverObjectList_.end(); ++it) {
259             if (it->bundleName == bundleName && it->abilityName == abilityName &&
260                 it->startTime == startTime) {
261                 TAG_LOGW(AAFwkTag::FREE_INSTALL, "add jsObject");
262                 return;
263             }
264         }
265     }
266 
267     StartAsyncTrace(HITRACE_TAG_ABILITY_MANAGER, "StartFreeInstall", atoi(startTime.c_str()));
268     JsFreeInstallObserverObject object;
269     object.bundleName = bundleName;
270     object.abilityName = abilityName;
271     object.startTime = startTime;
272     AddJsObserverCommon(object, jsObserverObject, result, isAbilityResult);
273 }
274 
AddJsObserverObject(const std::string & startTime,const std::string & url,napi_value jsObserverObject,napi_value * result,bool isAbilityResult)275 void JsFreeInstallObserver::AddJsObserverObject(const std::string &startTime, const std::string &url,
276     napi_value jsObserverObject, napi_value* result, bool isAbilityResult)
277 {
278     TAG_LOGD(AAFwkTag::FREE_INSTALL, "call");
279     {
280         std::unique_lock<std::mutex> lock(jsObserverObjectListLock_);
281         for (auto it = jsObserverObjectList_.begin(); it != jsObserverObjectList_.end(); ++it) {
282             if (it->startTime == startTime && it->url == url) {
283                 TAG_LOGW(AAFwkTag::FREE_INSTALL, "add jsObject");
284                 return;
285             }
286         }
287     }
288 
289     StartAsyncTrace(HITRACE_TAG_ABILITY_MANAGER, "StartFreeInstall", atoi(startTime.c_str()));
290     JsFreeInstallObserverObject object;
291     object.startTime = startTime;
292     object.url = url;
293     AddJsObserverCommon(object, jsObserverObject, result, isAbilityResult);
294 }
295 
AddJsObserverCommon(JsFreeInstallObserverObject & object,napi_value jsObserverObject,napi_value * result,bool isAbilityResult)296 void JsFreeInstallObserver::AddJsObserverCommon(JsFreeInstallObserverObject &object,
297     napi_value jsObserverObject, napi_value* result, bool isAbilityResult)
298 {
299     TAG_LOGD(AAFwkTag::FREE_INSTALL, "call");
300     object.isAbilityResult = isAbilityResult;
301     napi_valuetype type = napi_undefined;
302     napi_typeof(env_, jsObserverObject, &type);
303     if (jsObserverObject == nullptr || type != napi_function) {
304         napi_deferred deferred;
305         napi_create_promise(env_, &deferred, result);
306         object.deferred = deferred;
307         object.callback = nullptr;
308     } else {
309         napi_ref ref = nullptr;
310         napi_get_undefined(env_, result);
311         napi_create_reference(env_, jsObserverObject, 1, &ref);
312         object.deferred = nullptr;
313         object.callback = ref;
314     }
315     std::unique_lock<std::mutex> lock(jsObserverObjectListLock_);
316     jsObserverObjectList_.emplace_back(object);
317 }
318 } // namespace AbilityRuntime
319 } // namespace OHOS