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 "application_state_change_callback.h"
17
18 #include "hilog_tag_wrapper.h"
19 #include "js_data_struct_converter.h"
20 #include "js_runtime_utils.h"
21
22 namespace OHOS {
23 namespace AbilityRuntime {
JsApplicationStateChangeCallback(napi_env env)24 JsApplicationStateChangeCallback::JsApplicationStateChangeCallback(napi_env env)
25 : env_(env)
26 {
27 }
28
CallJsMethodInnerCommon(const std::string & methodName,const std::set<std::shared_ptr<NativeReference>> callbacks)29 void JsApplicationStateChangeCallback::CallJsMethodInnerCommon(
30 const std::string &methodName, const std::set<std::shared_ptr<NativeReference>> callbacks)
31 {
32 for (auto &callback : callbacks) {
33 if (!callback) {
34 TAG_LOGE(AAFwkTag::APPKIT, "Invalid jsCallback");
35 continue;
36 }
37
38 auto obj = callback->GetNapiValue();
39 if (!CheckTypeForNapiValue(env_, obj, napi_object)) {
40 TAG_LOGE(AAFwkTag::APPKIT, "Failed to get object");
41 continue;
42 }
43
44 napi_value method = nullptr;
45 napi_get_named_property(env_, obj, methodName.data(), &method);
46 if (method == nullptr) {
47 TAG_LOGE(AAFwkTag::APPKIT, "Failed to get %{public}s from object", methodName.data());
48 continue;
49 }
50 napi_call_function(env_, obj, method, 0, nullptr, nullptr);
51 }
52 }
53
CallJsMethod(const std::string & methodName)54 void JsApplicationStateChangeCallback::CallJsMethod(const std::string &methodName)
55 {
56 TAG_LOGD(AAFwkTag::APPKIT, "MethodName = %{public}s", methodName.c_str());
57 std::weak_ptr<JsApplicationStateChangeCallback> thisWeakPtr(shared_from_this());
58 std::unique_ptr<NapiAsyncTask::CompleteCallback> complete = std::make_unique<NapiAsyncTask::CompleteCallback>(
59 [thisWeakPtr, methodName, callbacks = callbacks_]
60 (napi_env env, NapiAsyncTask &task, int32_t status) {
61 std::shared_ptr<JsApplicationStateChangeCallback> jsCallback = thisWeakPtr.lock();
62 if (jsCallback) {
63 jsCallback->CallJsMethodInnerCommon(methodName, callbacks);
64 }
65 }
66 );
67 napi_ref callback = nullptr;
68 std::unique_ptr<NapiAsyncTask::ExecuteCallback> execute = nullptr;
69 NapiAsyncTask::Schedule("JsApplicationStateChangeCallback::CallJsMethod:" + methodName,
70 env_, std::make_unique<NapiAsyncTask>(callback, std::move(execute), std::move(complete)));
71 }
72
NotifyApplicationForeground()73 void JsApplicationStateChangeCallback::NotifyApplicationForeground()
74 {
75 CallJsMethod("onApplicationForeground");
76 }
77
NotifyApplicationBackground()78 void JsApplicationStateChangeCallback::NotifyApplicationBackground()
79 {
80 CallJsMethod("onApplicationBackground");
81 }
82
Register(napi_value jsCallback)83 void JsApplicationStateChangeCallback::Register(napi_value jsCallback)
84 {
85 if (env_ == nullptr || jsCallback == nullptr) {
86 TAG_LOGE(AAFwkTag::APPKIT, "env or jsCallback is nullptr");
87 return;
88 }
89 napi_ref ref = nullptr;
90 napi_create_reference(env_, jsCallback, 1, &ref);
91 callbacks_.emplace(std::shared_ptr<NativeReference>(reinterpret_cast<NativeReference*>(ref)));
92 }
93
UnRegister(napi_value jsCallback)94 bool JsApplicationStateChangeCallback::UnRegister(napi_value jsCallback)
95 {
96 if (jsCallback == nullptr) {
97 TAG_LOGI(AAFwkTag::APPKIT, "jsCallback is nullptr, delete all callback");
98 callbacks_.clear();
99 return true;
100 }
101
102 for (auto &callback : callbacks_) {
103 if (!callback) {
104 TAG_LOGE(AAFwkTag::APPKIT, "Invalid jsCallback");
105 continue;
106 }
107
108 napi_value value = callback->GetNapiValue();
109 if (value == nullptr) {
110 TAG_LOGE(AAFwkTag::APPKIT, "Failed to get object");
111 continue;
112 }
113
114 bool isEqual = false;
115 napi_strict_equals(env_, value, jsCallback, &isEqual);
116 if (isEqual) {
117 return callbacks_.erase(callback) == 1;
118 }
119 }
120 return false;
121 }
122
IsEmpty() const123 bool JsApplicationStateChangeCallback::IsEmpty() const
124 {
125 return callbacks_.empty();
126 }
127 } // namespace AbilityRuntime
128 } // namespace OHOS