1 /*
2 * Copyright (c) 2022 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 #include "napi_context_common.h"
16
17 namespace OHOS {
18 namespace Security {
19 namespace AccessToken {
20 namespace {
21 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_PRIVACY, "PrivacyContextCommonNapi"};
22 } // namespace
PrivacyAsyncWorkData(napi_env envValue)23 PrivacyAsyncWorkData::PrivacyAsyncWorkData(napi_env envValue)
24 {
25 env = envValue;
26 }
27
~PrivacyAsyncWorkData()28 PrivacyAsyncWorkData::~PrivacyAsyncWorkData()
29 {
30 if (callbackRef != nullptr) {
31 napi_delete_reference(env, callbackRef);
32 callbackRef = nullptr;
33 }
34
35 if (asyncWork != nullptr) {
36 napi_delete_async_work(env, asyncWork);
37 asyncWork = nullptr;
38 }
39 }
40
~PermActiveChangeContext()41 PermActiveChangeContext::~PermActiveChangeContext()
42 {}
43
PermActiveStatusPtr(const std::vector<std::string> & permList)44 PermActiveStatusPtr::PermActiveStatusPtr(const std::vector<std::string>& permList)
45 : PermActiveStatusCustomizedCbk(permList)
46 {}
47
~PermActiveStatusPtr()48 PermActiveStatusPtr::~PermActiveStatusPtr()
49 {
50 if (ref_ == nullptr) {
51 return;
52 }
53 DeleteNapiRef();
54 }
55
UvQueueWorkDeleteRef(uv_work_t * work,int32_t status)56 void UvQueueWorkDeleteRef(uv_work_t *work, int32_t status)
57 {
58 if (work == nullptr) {
59 ACCESSTOKEN_LOG_ERROR(LABEL, "Work == nullptr : %{public}d", work == nullptr);
60 return;
61 } else if (work->data == nullptr) {
62 ACCESSTOKEN_LOG_ERROR(LABEL, "Work->data == nullptr : %{public}d", work->data == nullptr);
63 return;
64 }
65 PermActiveStatusWorker* permActiveStatusWorker =
66 reinterpret_cast<PermActiveStatusWorker*>(work->data);
67 if (permActiveStatusWorker == nullptr) {
68 delete work;
69 return;
70 }
71 napi_delete_reference(permActiveStatusWorker->env, permActiveStatusWorker->ref);
72 delete permActiveStatusWorker;
73 permActiveStatusWorker = nullptr;
74 delete work;
75 ACCESSTOKEN_LOG_DEBUG(LABEL, "UvQueueWorkDeleteRef end");
76 }
77
DeleteNapiRef()78 void PermActiveStatusPtr::DeleteNapiRef()
79 {
80 uv_loop_s* loop = nullptr;
81 NAPI_CALL_RETURN_VOID(env_, napi_get_uv_event_loop(env_, &loop));
82 if (loop == nullptr) {
83 ACCESSTOKEN_LOG_ERROR(LABEL, "Loop instance is nullptr");
84 return;
85 }
86 uv_work_t* work = new (std::nothrow) uv_work_t;
87 if (work == nullptr) {
88 ACCESSTOKEN_LOG_ERROR(LABEL, "Insufficient memory for work!");
89 return;
90 }
91
92 std::unique_ptr<uv_work_t> uvWorkPtr {work};
93 PermActiveStatusWorker* permActiveStatusWorker =
94 new (std::nothrow) PermActiveStatusWorker();
95 if (permActiveStatusWorker == nullptr) {
96 ACCESSTOKEN_LOG_ERROR(LABEL, "Insufficient memory for RegisterPermStateChangeWorker!");
97 return;
98 }
99 std::unique_ptr<PermActiveStatusWorker> workPtr {permActiveStatusWorker};
100 permActiveStatusWorker->env = env_;
101 permActiveStatusWorker->ref = ref_;
102
103 work->data = reinterpret_cast<void *>(permActiveStatusWorker);
104 NAPI_CALL_RETURN_VOID(env_,
105 uv_queue_work_with_qos(loop, work, [](uv_work_t* work) {}, UvQueueWorkDeleteRef, uv_qos_default));
106 ACCESSTOKEN_LOG_DEBUG(LABEL, "DeleteNapiRef");
107 uvWorkPtr.release();
108 workPtr.release();
109 }
110
SetEnv(const napi_env & env)111 void PermActiveStatusPtr::SetEnv(const napi_env& env)
112 {
113 env_ = env;
114 }
115
SetCallbackRef(const napi_ref & ref)116 void PermActiveStatusPtr::SetCallbackRef(const napi_ref& ref)
117 {
118 ref_ = ref;
119 }
120
ActiveStatusChangeCallback(ActiveChangeResponse & result)121 void PermActiveStatusPtr::ActiveStatusChangeCallback(ActiveChangeResponse& result)
122 {
123 uv_loop_s* loop = nullptr;
124 NAPI_CALL_RETURN_VOID(env_, napi_get_uv_event_loop(env_, &loop));
125 if (loop == nullptr) {
126 ACCESSTOKEN_LOG_ERROR(LABEL, "Loop instance is nullptr");
127 return;
128 }
129 uv_work_t* work = new (std::nothrow) uv_work_t;
130 if (work == nullptr) {
131 ACCESSTOKEN_LOG_ERROR(LABEL, "Insufficient memory for work!");
132 return;
133 }
134 std::unique_ptr<uv_work_t> uvWorkPtr {work};
135 PermActiveStatusWorker* permActiveStatusWorker = new (std::nothrow) PermActiveStatusWorker();
136 if (permActiveStatusWorker == nullptr) {
137 ACCESSTOKEN_LOG_ERROR(LABEL, "Insufficient memory for RegisterPermStateChangeWorker!");
138 return;
139 }
140 std::unique_ptr<PermActiveStatusWorker> workPtr {permActiveStatusWorker};
141 permActiveStatusWorker->env = env_;
142 permActiveStatusWorker->ref = ref_;
143 permActiveStatusWorker->result = result;
144 ACCESSTOKEN_LOG_DEBUG(LABEL,
145 "result: tokenID = %{public}d, permissionName = %{public}s, type = %{public}d",
146 result.tokenID, result.permissionName.c_str(), result.type);
147 permActiveStatusWorker->subscriber = shared_from_this();
148 work->data = reinterpret_cast<void *>(permActiveStatusWorker);
149 NAPI_CALL_RETURN_VOID(env_,
150 uv_queue_work_with_qos(loop, work, [](uv_work_t* work) {}, UvQueueWorkActiveStatusChange, uv_qos_default));
151 uvWorkPtr.release();
152 workPtr.release();
153 }
154
UvQueueWorkActiveStatusChange(uv_work_t * work,int status)155 void UvQueueWorkActiveStatusChange(uv_work_t* work, int status)
156 {
157 (void)status;
158 if (work == nullptr || work->data == nullptr) {
159 ACCESSTOKEN_LOG_ERROR(LABEL, "Work == nullptr || work->data == nullptr");
160 return;
161 }
162 std::unique_ptr<uv_work_t> uvWorkPtr {work};
163 PermActiveStatusWorker* permActiveStatusData = reinterpret_cast<PermActiveStatusWorker*>(work->data);
164 std::unique_ptr<PermActiveStatusWorker> workPtr {permActiveStatusData};
165
166 napi_handle_scope scope = nullptr;
167 napi_open_handle_scope(permActiveStatusData->env, &scope);
168 if (scope == nullptr) {
169 ACCESSTOKEN_LOG_ERROR(LABEL, "Scope is null");
170 return;
171 }
172 NotifyChangeResponse(permActiveStatusData);
173 napi_close_handle_scope(permActiveStatusData->env, scope);
174 }
175
NotifyChangeResponse(const PermActiveStatusWorker * permActiveStatusData)176 void NotifyChangeResponse(const PermActiveStatusWorker* permActiveStatusData)
177 {
178 napi_value result = nullptr;
179 NAPI_CALL_RETURN_VOID(permActiveStatusData->env,
180 napi_create_object(permActiveStatusData->env, &result));
181 if (!ConvertActiveChangeResponse(permActiveStatusData->env, result, permActiveStatusData->result)) {
182 ACCESSTOKEN_LOG_ERROR(LABEL, "ConvertActiveChangeResponse failed");
183 return;
184 }
185 napi_value undefined = nullptr;
186 napi_value callback = nullptr;
187 napi_value resultOut = nullptr;
188 NAPI_CALL_RETURN_VOID(permActiveStatusData->env,
189 napi_get_undefined(permActiveStatusData->env, &undefined));
190 NAPI_CALL_RETURN_VOID(permActiveStatusData->env,
191 napi_get_reference_value(permActiveStatusData->env, permActiveStatusData->ref, &callback));
192 NAPI_CALL_RETURN_VOID(permActiveStatusData->env,
193 napi_call_function(permActiveStatusData->env, undefined, callback, 1, &result, &resultOut));
194 return;
195 }
196
ConvertActiveChangeResponse(napi_env env,napi_value value,const ActiveChangeResponse & result)197 bool ConvertActiveChangeResponse(napi_env env, napi_value value, const ActiveChangeResponse& result)
198 {
199 napi_value element;
200 NAPI_CALL_BASE(env, napi_create_uint32(env, result.tokenID, &element), false);
201 NAPI_CALL_BASE(env, napi_set_named_property(env, value, "tokenId", element), false);
202 element = nullptr;
203 NAPI_CALL_BASE(env, napi_create_string_utf8(env, result.permissionName.c_str(),
204 NAPI_AUTO_LENGTH, &element), false);
205 NAPI_CALL_BASE(env, napi_set_named_property(env, value, "permissionName", element), false);
206 element = nullptr;
207 NAPI_CALL_BASE(env, napi_create_string_utf8(env, result.deviceId.c_str(),
208 NAPI_AUTO_LENGTH, &element), false);
209 NAPI_CALL_BASE(env, napi_set_named_property(env, value, "deviceId", element), false);
210 element = nullptr;
211 NAPI_CALL_BASE(env, napi_create_int32(env, result.type, &element), false);
212 NAPI_CALL_BASE(env, napi_set_named_property(env, value, "activeStatus", element), false);
213 return true;
214 }
215 } // namespace AccessToken
216 } // namespace Security
217 } // namespace OHOS