1 /*
2  * Copyright (c) 2022-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 "ability_lifecycle_callback.h"
17 
18 #include "hilog_tag_wrapper.h"
19 #include "js_runtime_utils.h"
20 
21 namespace OHOS {
22 namespace AbilityRuntime {
JsAbilityLifecycleCallback(napi_env env)23 JsAbilityLifecycleCallback::JsAbilityLifecycleCallback(napi_env env)
24     : env_(env)
25 {
26 }
27 
28 int32_t JsAbilityLifecycleCallback::serialNumber_ = 0;
29 
CallJsMethodInnerCommon(const std::string & methodName,const std::shared_ptr<NativeReference> & ability,const std::shared_ptr<NativeReference> & windowStage,const std::map<int32_t,std::shared_ptr<NativeReference>> callbacks)30 void JsAbilityLifecycleCallback::CallJsMethodInnerCommon(const std::string &methodName,
31     const std::shared_ptr<NativeReference> &ability, const std::shared_ptr<NativeReference> &windowStage,
32     const std::map<int32_t, std::shared_ptr<NativeReference>> callbacks)
33 {
34     auto nativeAbilityObj = CreateJsNull(env_);
35     if (ability != nullptr) {
36         nativeAbilityObj = ability->GetNapiValue();
37     }
38 
39     bool isWindowStage = false;
40     auto nativeWindowStageObj = CreateJsNull(env_);
41     if (windowStage != nullptr) {
42         nativeWindowStageObj = windowStage->GetNapiValue();
43         isWindowStage = true;
44     }
45 
46     for (auto &callback : callbacks) {
47         if (!callback.second) {
48             TAG_LOGE(AAFwkTag::APPKIT, "Invalid jsCallback");
49             return;
50         }
51 
52         auto obj = callback.second->GetNapiValue();
53         if (!CheckTypeForNapiValue(env_, obj, napi_object)) {
54             TAG_LOGE(AAFwkTag::APPKIT, "Failed to get object");
55             return;
56         }
57 
58         napi_value method = nullptr;
59         napi_get_named_property(env_, obj, methodName.data(), &method);
60         if (method == nullptr) {
61             TAG_LOGE(AAFwkTag::APPKIT, "Failed to get %{public}s from object",
62                 methodName.data());
63             return;
64         }
65 
66         if (!isWindowStage) {
67             napi_value argv[] = { nativeAbilityObj };
68             napi_call_function(env_, obj, method, ArraySize(argv), argv, nullptr);
69         } else {
70             napi_value argv[] = { nativeAbilityObj, nativeWindowStageObj };
71             napi_call_function(env_, obj, method, ArraySize(argv), argv, nullptr);
72         }
73     }
74 }
75 
CallJsMethod(const std::string & methodName,const std::shared_ptr<NativeReference> & ability)76 void JsAbilityLifecycleCallback::CallJsMethod(
77     const std::string &methodName, const std::shared_ptr<NativeReference> &ability)
78 {
79     TAG_LOGD(AAFwkTag::APPKIT, "methodName = %{public}s", methodName.c_str());
80     if (!ability) {
81         TAG_LOGE(AAFwkTag::APPKIT, "ability is nullptr");
82         return;
83     }
84     HandleScope handleScope(env_);
85     CallJsMethodInnerCommon(methodName, ability, nullptr, callbacks_);
86     CallJsMethodInnerCommon(methodName, ability, nullptr, callbacksSync_);
87 }
88 
CallWindowStageJsMethod(const std::string & methodName,const std::shared_ptr<NativeReference> & ability,const std::shared_ptr<NativeReference> & windowStage)89 void JsAbilityLifecycleCallback::CallWindowStageJsMethod(const std::string &methodName,
90     const std::shared_ptr<NativeReference> &ability, const std::shared_ptr<NativeReference> &windowStage)
91 {
92     TAG_LOGD(AAFwkTag::APPKIT, "methodName = %{public}s", methodName.c_str());
93     if (!ability || !windowStage) {
94         TAG_LOGE(AAFwkTag::APPKIT, "ability or windowStage is nullptr");
95         return;
96     }
97     HandleScope handleScope(env_);
98     CallJsMethodInnerCommon(methodName, ability, windowStage, callbacks_);
99     CallJsMethodInnerCommon(methodName, ability, windowStage, callbacksSync_);
100 }
101 
OnAbilityCreate(const std::shared_ptr<NativeReference> & ability)102 void JsAbilityLifecycleCallback::OnAbilityCreate(const std::shared_ptr<NativeReference> &ability)
103 {
104     CallJsMethod("onAbilityCreate", ability);
105 }
106 
OnWindowStageCreate(const std::shared_ptr<NativeReference> & ability,const std::shared_ptr<NativeReference> & windowStage)107 void JsAbilityLifecycleCallback::OnWindowStageCreate(const std::shared_ptr<NativeReference> &ability,
108     const std::shared_ptr<NativeReference> &windowStage)
109 {
110     CallWindowStageJsMethod("onWindowStageCreate", ability, windowStage);
111 }
112 
OnWindowStageDestroy(const std::shared_ptr<NativeReference> & ability,const std::shared_ptr<NativeReference> & windowStage)113 void JsAbilityLifecycleCallback::OnWindowStageDestroy(const std::shared_ptr<NativeReference> &ability,
114     const std::shared_ptr<NativeReference> &windowStage)
115 {
116     CallWindowStageJsMethod("onWindowStageDestroy", ability, windowStage);
117 }
118 
OnWindowStageActive(const std::shared_ptr<NativeReference> & ability,const std::shared_ptr<NativeReference> & windowStage)119 void JsAbilityLifecycleCallback::OnWindowStageActive(const std::shared_ptr<NativeReference> &ability,
120     const std::shared_ptr<NativeReference> &windowStage)
121 {
122     CallWindowStageJsMethod("onWindowStageActive", ability, windowStage);
123 }
124 
OnWindowStageInactive(const std::shared_ptr<NativeReference> & ability,const std::shared_ptr<NativeReference> & windowStage)125 void JsAbilityLifecycleCallback::OnWindowStageInactive(const std::shared_ptr<NativeReference> &ability,
126     const std::shared_ptr<NativeReference> &windowStage)
127 {
128     CallWindowStageJsMethod("onWindowStageInactive", ability, windowStage);
129 }
130 
OnAbilityDestroy(const std::shared_ptr<NativeReference> & ability)131 void JsAbilityLifecycleCallback::OnAbilityDestroy(const std::shared_ptr<NativeReference> &ability)
132 {
133     CallJsMethod("onAbilityDestroy", ability);
134 }
135 
OnAbilityForeground(const std::shared_ptr<NativeReference> & ability)136 void JsAbilityLifecycleCallback::OnAbilityForeground(const std::shared_ptr<NativeReference> &ability)
137 {
138     CallJsMethod("onAbilityForeground", ability);
139 }
140 
OnAbilityBackground(const std::shared_ptr<NativeReference> & ability)141 void JsAbilityLifecycleCallback::OnAbilityBackground(const std::shared_ptr<NativeReference> &ability)
142 {
143     CallJsMethod("onAbilityBackground", ability);
144 }
145 
OnAbilityContinue(const std::shared_ptr<NativeReference> & ability)146 void JsAbilityLifecycleCallback::OnAbilityContinue(const std::shared_ptr<NativeReference> &ability)
147 {
148     CallJsMethod("onAbilityContinue", ability);
149 }
150 
OnAbilityWillContinue(const std::shared_ptr<NativeReference> & ability)151 void JsAbilityLifecycleCallback::OnAbilityWillContinue(const std::shared_ptr<NativeReference> &ability)
152 {
153     CallJsMethod("onAbilityWillContinue", ability);
154 }
155 
OnWindowStageWillRestore(const std::shared_ptr<NativeReference> & ability,const std::shared_ptr<NativeReference> & windowStage)156 void JsAbilityLifecycleCallback::OnWindowStageWillRestore(const std::shared_ptr<NativeReference> &ability,
157     const std::shared_ptr<NativeReference> &windowStage)
158 {
159     CallWindowStageJsMethod("onWindowStageWillRestore", ability, windowStage);
160 }
161 
OnWindowStageRestore(const std::shared_ptr<NativeReference> & ability,const std::shared_ptr<NativeReference> & windowStage)162 void JsAbilityLifecycleCallback::OnWindowStageRestore(const std::shared_ptr<NativeReference> &ability,
163     const std::shared_ptr<NativeReference> &windowStage)
164 {
165     CallWindowStageJsMethod("onWindowStageRestore", ability, windowStage);
166 }
167 
OnAbilityWillSaveState(const std::shared_ptr<NativeReference> & ability)168 void JsAbilityLifecycleCallback::OnAbilityWillSaveState(const std::shared_ptr<NativeReference> &ability)
169 {
170     CallJsMethod("onAbilityWillSaveState", ability);
171 }
172 
OnAbilitySaveState(const std::shared_ptr<NativeReference> & ability)173 void JsAbilityLifecycleCallback::OnAbilitySaveState(const std::shared_ptr<NativeReference> &ability)
174 {
175     CallJsMethod("onAbilitySaveState", ability);
176 }
177 
Register(napi_value jsCallback,bool isSync)178 int32_t JsAbilityLifecycleCallback::Register(napi_value jsCallback, bool isSync)
179 {
180     TAG_LOGD(AAFwkTag::APPKIT, "enter");
181     if (env_ == nullptr) {
182         return -1;
183     }
184     int32_t callbackId = serialNumber_;
185     if (serialNumber_ < INT32_MAX) {
186         serialNumber_++;
187     } else {
188         serialNumber_ = 0;
189     }
190     napi_ref ref = nullptr;
191     napi_create_reference(env_, jsCallback, 1, &ref);
192     if (isSync) {
193         callbacksSync_.emplace(callbackId, std::shared_ptr<NativeReference>(reinterpret_cast<NativeReference*>(ref)));
194     } else {
195         callbacks_.emplace(callbackId, std::shared_ptr<NativeReference>(reinterpret_cast<NativeReference*>(ref)));
196     }
197     return callbackId;
198 }
199 
UnRegister(int32_t callbackId,bool isSync)200 bool JsAbilityLifecycleCallback::UnRegister(int32_t callbackId, bool isSync)
201 {
202     TAG_LOGI(AAFwkTag::APPKIT, "callbackId : %{public}d", callbackId);
203     if (isSync) {
204         auto it = callbacksSync_.find(callbackId);
205         if (it == callbacksSync_.end()) {
206             TAG_LOGE(AAFwkTag::APPKIT, "callbackId: %{public}d is not in callbacksSync_", callbackId);
207             return false;
208         }
209         return callbacksSync_.erase(callbackId) == 1;
210     }
211     auto it = callbacks_.find(callbackId);
212     if (it == callbacks_.end()) {
213         TAG_LOGE(AAFwkTag::APPKIT, "callbackId: %{public}d is not in callbacks_", callbackId);
214         return false;
215     }
216     return callbacks_.erase(callbackId) == 1;
217 }
218 
OnNewWant(const std::shared_ptr<NativeReference> & ability)219 void JsAbilityLifecycleCallback::OnNewWant(const std::shared_ptr<NativeReference> &ability)
220 {
221     CallJsMethod("onNewWant", ability);
222 }
223 
OnWillNewWant(const std::shared_ptr<NativeReference> & ability)224 void JsAbilityLifecycleCallback::OnWillNewWant(const std::shared_ptr<NativeReference> &ability)
225 {
226     CallJsMethod("onWillNewWant", ability);
227 }
228 
OnAbilityWillCreate(const std::shared_ptr<NativeReference> & ability)229 void JsAbilityLifecycleCallback::OnAbilityWillCreate(const std::shared_ptr<NativeReference> &ability)
230 {
231     CallJsMethod("onAbilityWillCreate", ability);
232 }
233 
OnWindowStageWillCreate(const std::shared_ptr<NativeReference> & ability,const std::shared_ptr<NativeReference> & windowStage)234 void JsAbilityLifecycleCallback::OnWindowStageWillCreate(const std::shared_ptr<NativeReference> &ability,
235     const std::shared_ptr<NativeReference> &windowStage)
236 {
237     CallWindowStageJsMethod("onWindowStageWillCreate", ability, windowStage);
238 }
239 
OnWindowStageWillDestroy(const std::shared_ptr<NativeReference> & ability,const std::shared_ptr<NativeReference> & windowStage)240 void JsAbilityLifecycleCallback::OnWindowStageWillDestroy(const std::shared_ptr<NativeReference> &ability,
241     const std::shared_ptr<NativeReference> &windowStage)
242 {
243     CallWindowStageJsMethod("onWindowStageWillDestroy", ability, windowStage);
244 }
245 
OnAbilityWillDestroy(const std::shared_ptr<NativeReference> & ability)246 void JsAbilityLifecycleCallback::OnAbilityWillDestroy(const std::shared_ptr<NativeReference> &ability)
247 {
248     CallJsMethod("onAbilityWillDestroy", ability);
249 }
250 
OnAbilityWillForeground(const std::shared_ptr<NativeReference> & ability)251 void JsAbilityLifecycleCallback::OnAbilityWillForeground(const std::shared_ptr<NativeReference> &ability)
252 {
253     CallJsMethod("onAbilityWillForeground", ability);
254 }
255 
OnAbilityWillBackground(const std::shared_ptr<NativeReference> & ability)256 void JsAbilityLifecycleCallback::OnAbilityWillBackground(const std::shared_ptr<NativeReference> &ability)
257 {
258     CallJsMethod("onAbilityWillBackground", ability);
259 }
260 
IsEmpty() const261 bool JsAbilityLifecycleCallback::IsEmpty() const
262 {
263     return callbacks_.empty() && callbacksSync_.empty();
264 }
265 }  // namespace AbilityRuntime
266 }  // namespace OHOS
267