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_ability_foreground_state_observer.h"
17 
18 #include "hilog_tag_wrapper.h"
19 #include "js_runtime_utils.h"
20 
21 namespace OHOS {
22 namespace AbilityRuntime {
23 namespace {
24 constexpr size_t ARGC_ONE = 1;
25 }
JSAbilityForegroundStateObserver(napi_env env)26 JSAbilityForegroundStateObserver::JSAbilityForegroundStateObserver(napi_env env) : env_(env) {}
27 
OnAbilityStateChanged(const AbilityStateData & abilityStateData)28 void JSAbilityForegroundStateObserver::OnAbilityStateChanged(const AbilityStateData &abilityStateData)
29 {
30     TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
31     if (!valid_) {
32         TAG_LOGE(AAFwkTag::ABILITYMGR, "invalid appms");
33         return;
34     }
35     wptr<JSAbilityForegroundStateObserver> jsObserver = this;
36     std::unique_ptr<NapiAsyncTask::CompleteCallback> complete = std::make_unique<NapiAsyncTask::CompleteCallback>(
37         [jsObserver, abilityStateData](napi_env env, NapiAsyncTask &task, int32_t status) {
38             sptr<JSAbilityForegroundStateObserver> jsObserverSptr = jsObserver.promote();
39             if (jsObserverSptr == nullptr) {
40                 TAG_LOGE(AAFwkTag::ABILITYMGR, "null observer");
41                 return;
42             }
43             jsObserverSptr->HandleOnAbilityStateChanged(abilityStateData);
44         });
45     napi_ref callback = nullptr;
46     NapiAsyncTask::Schedule("JSAbilityForegroundStateObserver::OnAbilityStateChanged", env_,
47         std::make_unique<NapiAsyncTask>(callback, nullptr, std::move(complete)));
48 }
49 
HandleOnAbilityStateChanged(const AbilityStateData & abilityStateData)50 void JSAbilityForegroundStateObserver::HandleOnAbilityStateChanged(const AbilityStateData &abilityStateData)
51 {
52     TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
53     for (auto &item : jsObserverObjectSet_) {
54         if (item == nullptr) {
55             continue;
56         }
57         napi_value obj = item->GetNapiValue();
58         napi_value argv[] = { CreateJsAbilityStateData(env_, abilityStateData) };
59         CallJsFunction(obj, "onAbilityStateChanged", argv, ARGC_ONE);
60     }
61 }
62 
CallJsFunction(const napi_value & value,const char * methodName,const napi_value * argv,const size_t argc)63 void JSAbilityForegroundStateObserver::CallJsFunction(
64     const napi_value &value, const char *methodName, const napi_value *argv, const size_t argc)
65 {
66     TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
67     if (value == nullptr) {
68         TAG_LOGE(AAFwkTag::ABILITYMGR, "null value");
69         return;
70     }
71 
72     napi_value method = nullptr;
73     napi_get_named_property(env_, value, methodName, &method);
74     if (method == nullptr) {
75         TAG_LOGE(AAFwkTag::ABILITYMGR, "null method");
76         return;
77     }
78     napi_value callResult = nullptr;
79     napi_status status = napi_call_function(env_, value, method, argc, argv, &callResult);
80     if (status != napi_ok) {
81         TAG_LOGE(AAFwkTag::ABILITYMGR, "call js func failed: %{public}d", status);
82     }
83     TAG_LOGD(AAFwkTag::ABILITYMGR, "end");
84 }
85 
IsObserverObjectExsit(const napi_value & jsObserverObject)86 bool JSAbilityForegroundStateObserver::IsObserverObjectExsit(const napi_value &jsObserverObject)
87 {
88     if (jsObserverObject == nullptr) {
89         TAG_LOGE(AAFwkTag::ABILITYMGR, "null observer");
90         return false;
91     }
92 
93     if (GetObserverObject(jsObserverObject) == nullptr) {
94         TAG_LOGD(AAFwkTag::ABILITYMGR, "observer not exist");
95         return false;
96     }
97     return true;
98 }
99 
AddJsObserverObject(const napi_value & jsObserverObject)100 void JSAbilityForegroundStateObserver::AddJsObserverObject(const napi_value &jsObserverObject)
101 {
102     if (jsObserverObject == nullptr) {
103         TAG_LOGE(AAFwkTag::ABILITYMGR, "null observer");
104         return;
105     }
106 
107     if (IsObserverObjectExsit(jsObserverObject)) {
108         TAG_LOGD(AAFwkTag::ABILITYMGR, "observer not exist");
109         return;
110     }
111     napi_ref ref = nullptr;
112     napi_create_reference(env_, jsObserverObject, 1, &ref);
113     jsObserverObjectSet_.emplace(std::shared_ptr<NativeReference>(reinterpret_cast<NativeReference *>(ref)));
114 }
115 
RemoveJsObserverObject(const napi_value & jsObserverObject)116 void JSAbilityForegroundStateObserver::RemoveJsObserverObject(const napi_value &jsObserverObject)
117 {
118     if (jsObserverObject == nullptr) {
119         TAG_LOGE(AAFwkTag::ABILITYMGR, "null observer");
120         return;
121     }
122 
123     auto observer = GetObserverObject(jsObserverObject);
124     if (observer != nullptr) {
125         jsObserverObjectSet_.erase(observer);
126     }
127 }
128 
RemoveAllJsObserverObject()129 void JSAbilityForegroundStateObserver::RemoveAllJsObserverObject()
130 {
131     if (!jsObserverObjectSet_.empty()) {
132         jsObserverObjectSet_.clear();
133     }
134 }
135 
GetObserverObject(const napi_value & jsObserverObject)136 std::shared_ptr<NativeReference> JSAbilityForegroundStateObserver::GetObserverObject(const napi_value &jsObserverObject)
137 {
138     if (jsObserverObject == nullptr) {
139         TAG_LOGE(AAFwkTag::ABILITYMGR, "null observer");
140         return nullptr;
141     }
142     for (auto &observer : jsObserverObjectSet_) {
143         if (observer == nullptr) {
144             TAG_LOGE(AAFwkTag::ABILITYMGR, "null observer");
145             continue;
146         }
147 
148         napi_value value = observer->GetNapiValue();
149         if (value == nullptr) {
150             TAG_LOGE(AAFwkTag::ABILITYMGR, "get object failed");
151             continue;
152         }
153 
154         bool isEqual = false;
155         napi_strict_equals(env_, value, jsObserverObject, &isEqual);
156         if (isEqual) {
157             return observer;
158         }
159     }
160     return nullptr;
161 }
162 
SetValid(const bool valid)163 void JSAbilityForegroundStateObserver::SetValid(const bool valid)
164 {
165     valid_ = valid;
166 }
167 
IsEmpty()168 bool JSAbilityForegroundStateObserver::IsEmpty()
169 {
170     return jsObserverObjectSet_.empty();
171 }
172 } // namespace AbilityRuntime
173 } // namespace OHOS
174