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