1 /*
2  * Copyright (c) 2023 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 "user_auth_widget_callback_v10.h"
17 
18 #include <uv.h>
19 
20 #include "iam_logger.h"
21 
22 #define LOG_TAG "USER_AUTH_NAPI"
23 
24 namespace OHOS {
25 namespace UserIam {
26 namespace UserAuth {
27 namespace {
28 struct CallbackHolder {
29     std::shared_ptr<UserAuthWidgetCallback> callback {nullptr};
30     std::string cmdData;
31     napi_env env;
32 };
33 
DestoryWork(uv_work_t * work)34 void DestoryWork(uv_work_t *work)
35 {
36     if (work == nullptr) {
37         return;
38     }
39     if (work->data != nullptr) {
40         delete (reinterpret_cast<CallbackHolder *>(work->data));
41     }
42     delete work;
43 }
44 
OnWork(uv_work_t * work,int status)45 void OnWork(uv_work_t *work, int status)
46 {
47     IAM_LOGI("start");
48     if (work == nullptr) {
49         IAM_LOGE("work is null");
50         return;
51     }
52     CallbackHolder *holder = reinterpret_cast<CallbackHolder *>(work->data);
53     if (holder == nullptr || holder->callback == nullptr) {
54         IAM_LOGE("holder is invalid");
55         DestoryWork(work);
56         return;
57     }
58     napi_handle_scope scope = nullptr;
59     napi_open_handle_scope(holder->env, &scope);
60     if (scope == nullptr) {
61         IAM_LOGE("scope is invalid");
62         DestoryWork(work);
63         return;
64     }
65     napi_status ret = holder->callback->DoCommandCallback(holder->cmdData);
66     if (ret != napi_ok) {
67         IAM_LOGE("DoResultCallback fail %{public}d", ret);
68         napi_close_handle_scope(holder->env, scope);
69         DestoryWork(work);
70         return;
71     }
72     napi_close_handle_scope(holder->env, scope);
73     DestoryWork(work);
74 }
75 }
76 
UserAuthWidgetCallback(napi_env env)77 UserAuthWidgetCallback::UserAuthWidgetCallback(napi_env env) : env_(env)
78 {
79     if (env_ == nullptr) {
80         IAM_LOGE("UserAuthWidgetCallback get null env");
81     }
82 }
83 
~UserAuthWidgetCallback()84 UserAuthWidgetCallback::~UserAuthWidgetCallback()
85 {
86 }
87 
SetCommandCallback(const std::shared_ptr<JsRefHolder> & callback)88 void UserAuthWidgetCallback::SetCommandCallback(const std::shared_ptr<JsRefHolder> &callback)
89 {
90     std::lock_guard<std::mutex> guard(mutex_);
91     commandCallback_ = callback;
92 }
93 
ClearCommandCallback()94 void UserAuthWidgetCallback::ClearCommandCallback()
95 {
96     std::lock_guard<std::mutex> guard(mutex_);
97     commandCallback_ = nullptr;
98 }
99 
HasCommandCallback()100 bool UserAuthWidgetCallback::HasCommandCallback()
101 {
102     std::lock_guard<std::mutex> guard(mutex_);
103     return commandCallback_ != nullptr;
104 }
105 
GetCommandCallback()106 std::shared_ptr<JsRefHolder> UserAuthWidgetCallback::GetCommandCallback()
107 {
108     std::lock_guard<std::mutex> guard(mutex_);
109     return commandCallback_;
110 }
111 
DoCommandCallback(const std::string & cmdData)112 napi_status UserAuthWidgetCallback::DoCommandCallback(const std::string &cmdData)
113 {
114     auto commandCallback = GetCommandCallback();
115     if (commandCallback == nullptr) {
116         return napi_ok;
117     }
118     IAM_LOGI("start");
119     napi_value eventInfo = nullptr;
120     napi_status ret = napi_create_string_utf8(env_, cmdData.c_str(), cmdData.size(), &eventInfo);
121     if (ret != napi_ok) {
122         IAM_LOGE("napi_create_object failed %{public}d", ret);
123         return ret;
124     }
125     return UserAuthNapiHelper::CallVoidNapiFunc(env_, commandCallback->Get(), ARGS_ONE, &eventInfo);
126 }
127 
SendCommand(const std::string & cmdData)128 void UserAuthWidgetCallback::SendCommand(const std::string &cmdData)
129 {
130     IAM_LOGI("start");
131     uv_loop_s *loop;
132     napi_status napiStatus = napi_get_uv_event_loop(env_, &loop);
133     if (napiStatus != napi_ok || loop == nullptr) {
134         IAM_LOGE("napi_get_uv_event_loop fail");
135         return;
136     }
137     uv_work_t *work = new (std::nothrow) uv_work_t;
138     if (work == nullptr) {
139         IAM_LOGE("work is null");
140         return;
141     }
142     CallbackHolder *holder = new (std::nothrow) CallbackHolder();
143     if (holder == nullptr) {
144         IAM_LOGE("holder is null");
145         delete work;
146         return;
147     }
148     holder->callback = shared_from_this();
149     holder->cmdData = cmdData;
150     holder->env = env_;
151 
152     work->data = reinterpret_cast<void *>(holder);
153     if (uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, OnWork, uv_qos_user_initiated) != 0) {
154         IAM_LOGE("uv_queue_work_with_qos fail");
155         DestoryWork(work);
156     }
157 }
158 } // namespace UserAuth
159 } // namespace UserIam
160 } // namespace OHOS
161