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_auto_startup_callback.h"
17
18 #include "hilog_tag_wrapper.h"
19 #include "js_ability_auto_startup_manager_utils.h"
20 #include "js_runtime.h"
21 #include "js_runtime_utils.h"
22
23 namespace OHOS {
24 namespace AbilityRuntime {
25 namespace {
26 const std::string METHOD_ON = "onAutoStartupOn";
27 const std::string METHOD_OFF = "onAutoStartupOff";
28 } // namespace
JsAbilityAutoStartupCallBack(napi_env env)29 JsAbilityAutoStartupCallBack::JsAbilityAutoStartupCallBack(napi_env env) : env_(env) {}
30
~JsAbilityAutoStartupCallBack()31 JsAbilityAutoStartupCallBack::~JsAbilityAutoStartupCallBack() {}
32
OnAutoStartupOn(const AutoStartupInfo & info)33 void JsAbilityAutoStartupCallBack::OnAutoStartupOn(const AutoStartupInfo &info)
34 {
35 TAG_LOGD(AAFwkTag::AUTO_STARTUP, "called");
36 JSCallFunction(info, METHOD_ON);
37 }
38
OnAutoStartupOff(const AutoStartupInfo & info)39 void JsAbilityAutoStartupCallBack::OnAutoStartupOff(const AutoStartupInfo &info)
40 {
41 TAG_LOGD(AAFwkTag::AUTO_STARTUP, "called");
42 JSCallFunction(info, METHOD_OFF);
43 }
44
Register(napi_value value)45 void JsAbilityAutoStartupCallBack::Register(napi_value value)
46 {
47 TAG_LOGD(AAFwkTag::AUTO_STARTUP, "called");
48 std::lock_guard<std::mutex> lock(mutexlock_);
49 for (const auto &callback : callbacks_) {
50 if (IsJsCallbackEquals(callback, value)) {
51 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "callback exist");
52 return;
53 }
54 }
55
56 napi_ref ref = nullptr;
57 napi_create_reference(env_, value, 1, &ref);
58 callbacks_.emplace_back(std::unique_ptr<NativeReference>(reinterpret_cast<NativeReference *>(ref)));
59 }
60
UnRegister(napi_value value)61 void JsAbilityAutoStartupCallBack::UnRegister(napi_value value)
62 {
63 TAG_LOGD(AAFwkTag::AUTO_STARTUP, "called");
64 napi_valuetype type = napi_undefined;
65 napi_typeof(env_, value, &type);
66 std::lock_guard<std::mutex> lock(mutexlock_);
67 if (type == napi_undefined || type == napi_null) {
68 TAG_LOGD(AAFwkTag::AUTO_STARTUP, "invalid callback, clear all callback");
69 callbacks_.clear();
70 return;
71 }
72
73 for (auto item = callbacks_.begin(); item != callbacks_.end();) {
74 if (IsJsCallbackEquals(*item, value)) {
75 item = callbacks_.erase(item);
76 } else {
77 item++;
78 }
79 }
80 }
81
IsCallbacksEmpty()82 bool JsAbilityAutoStartupCallBack::IsCallbacksEmpty()
83 {
84 return callbacks_.empty();
85 }
86
JSCallFunction(const AutoStartupInfo & info,const std::string & methodName)87 void JsAbilityAutoStartupCallBack::JSCallFunction(const AutoStartupInfo &info, const std::string &methodName)
88 {
89 wptr<JsAbilityAutoStartupCallBack> stub = iface_cast<JsAbilityAutoStartupCallBack>(AsObject());
90 NapiAsyncTask::CompleteCallback complete = [stub, info, methodName](
91 napi_env env, NapiAsyncTask &task, int32_t status) {
92 sptr<JsAbilityAutoStartupCallBack> obj = stub.promote();
93 if (obj == nullptr) {
94 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "null obj");
95 return;
96 }
97
98 obj->JSCallFunctionWorker(info, methodName);
99 };
100
101 NapiAsyncTask::Schedule("JsAbilityAutoStartupCallBack::JSCallFunction:" + methodName, env_,
102 CreateAsyncTaskWithLastParam(env_, nullptr, nullptr, std::move(complete), nullptr));
103 }
104
JSCallFunctionWorker(const AutoStartupInfo & info,const std::string & methodName)105 void JsAbilityAutoStartupCallBack::JSCallFunctionWorker(const AutoStartupInfo &info, const std::string &methodName)
106 {
107 std::lock_guard<std::mutex> lock(mutexlock_);
108 for (auto callback : callbacks_) {
109 if (callback == nullptr) {
110 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "null callback");
111 continue;
112 }
113
114 auto obj = callback->GetNapiValue();
115 if (obj == nullptr) {
116 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "null obj");
117 continue;
118 }
119
120 napi_value funcObject;
121 if (napi_get_named_property(env_, obj, methodName.c_str(), &funcObject) != napi_ok) {
122 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "get func failed");
123 continue;
124 }
125
126 napi_value argv[] = { CreateJsAutoStartupInfo(env_, info) };
127 napi_call_function(env_, obj, funcObject, ArraySize(argv), argv, nullptr);
128 }
129 }
130
IsJsCallbackEquals(const std::shared_ptr<NativeReference> & callback,napi_value value)131 bool JsAbilityAutoStartupCallBack::IsJsCallbackEquals(const std::shared_ptr<NativeReference> &callback,
132 napi_value value)
133 {
134 if (callback == nullptr) {
135 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "null callback");
136 return false;
137 }
138
139 auto object = callback->GetNapiValue();
140 if (object == nullptr) {
141 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "null object");
142 return false;
143 }
144
145 bool result = false;
146 if (napi_strict_equals(env_, object, value, &result) != napi_ok) {
147 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "objects not match");
148 return false;
149 }
150
151 return result;
152 }
153 } // namespace AbilityRuntime
154 } // namespace OHOS