• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #include "scan_async_call.h"
17 #include "napi_scan_utils.h"
18 #include "scan_log.h"
19 
20 namespace OHOS::Scan {
ScanAsyncCall(napi_env env,napi_callback_info info,std::shared_ptr<Context> context)21 ScanAsyncCall::ScanAsyncCall(napi_env env, napi_callback_info info,
22     std::shared_ptr<Context> context) : env_(env)
23 {
24     if (context == nullptr) {
25         SCAN_HILOGE("context is nullptr");
26         return;
27     }
28     context_ = new (std::nothrow) AsyncContext();
29     if (context_ == nullptr) {
30         SCAN_HILOGE("context_ is nullptr");
31         return;
32     }
33     size_t argc = NapiScanUtils::MAX_ARGC;
34     napi_value self = nullptr;
35     napi_value argv[NapiScanUtils::MAX_ARGC] = { nullptr };
36     SCAN_CALL_RETURN_VOID(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
37     context_->paramStatus = (*context)(env, argc, argv, self);
38     context_->ctx = std::move(context);
39     napi_create_reference(env, self, 1, &context_->self);
40 }
41 
~ScanAsyncCall()42 ScanAsyncCall::~ScanAsyncCall()
43 {
44     if (context_ == nullptr) {
45         return;
46     }
47 
48     DeleteContext(env_, context_);
49 }
50 
Call(napi_env env,Context::ExecAction exec)51 napi_value ScanAsyncCall::Call(napi_env env, Context::ExecAction exec)
52 {
53     SCAN_HILOGD("async call exec");
54     if (context_ != nullptr && context_->ctx != nullptr) {
55         context_->ctx->exec_ = std::move(exec);
56     } else {
57         SCAN_HILOGE("context_ is null or context->ctx is null");
58         return nullptr;
59     }
60     napi_value promise = nullptr;
61     napi_create_promise(env, &context_->defer, &promise);
62     napi_async_work work = context_->work;
63     napi_value resource = nullptr;
64     napi_create_string_utf8(env, "ScanAsyncCall", NAPI_AUTO_LENGTH, &resource);
65     napi_create_async_work(env, nullptr, resource, ScanAsyncCall::OnExecute,
66         ScanAsyncCall::OnComplete, context_, &work);
67     context_->work = work;
68     context_ = nullptr;
69     napi_queue_async_work(env, work);
70     return promise;
71 }
72 
OnExecute(napi_env env,void * data)73 void ScanAsyncCall::OnExecute(napi_env env, void *data)
74 {
75     AsyncContext *context = reinterpret_cast<AsyncContext *>(data);
76     if (context == nullptr || context->ctx == nullptr) {
77         SCAN_HILOGE("context->ctx is null");
78         return;
79     }
80 
81     SCAN_HILOGD("run the async runnable");
82     if (context->ctx->GetErrorIndex() == E_SCAN_NONE) {
83         context->ctx->Exec();
84     }
85 }
86 
PrepareSuccessResult(napi_env env,napi_value output,AsyncResult & result)87 void ScanAsyncCall::PrepareSuccessResult(napi_env env, napi_value output, AsyncResult& result)
88 {
89     napi_get_undefined(env, &result.error);
90     if (output != nullptr) {
91         result.data = output;
92         SCAN_HILOGD("async call napi_ok.");
93     } else {
94         napi_get_undefined(env, &result.data);
95     }
96 }
97 
PrepareErrorResult(napi_env env,const AsyncContext * context,AsyncResult & result)98 void ScanAsyncCall::PrepareErrorResult(napi_env env, const AsyncContext* context, AsyncResult& result)
99 {
100     uint32_t errorCode = E_SCAN_GENERIC_FAILURE;
101     if (context->paramStatus != napi_ok) {
102         errorCode = E_SCAN_INVALID_PARAMETER;
103     }
104     if (context->ctx != nullptr) {
105         errorCode = context->ctx->GetErrorIndex();
106     }
107     std::string errorMessage;
108     NapiScanUtils::SetErrorText(errorCode, errorMessage);
109     SCAN_HILOGE("ErrorMessage: [%{public}s], ErrorIndex:[%{public}d]",
110         errorMessage.c_str(), errorCode);
111 
112     napi_value businessError = nullptr;
113     napi_create_object(env, &businessError);
114 
115     napi_value codeValue = nullptr;
116     napi_create_uint32(env, errorCode, &codeValue);
117     napi_set_named_property(env, businessError, "code", codeValue);
118 
119     if (!errorMessage.empty()) {
120         napi_value messageValue = nullptr;
121         napi_create_string_utf8(env, errorMessage.c_str(), errorMessage.length(), &messageValue);
122         napi_set_named_property(env, businessError, "message", messageValue);
123     }
124 
125     result.error = businessError;
126     napi_get_undefined(env, &result.data);
127 }
128 
OnComplete(napi_env env,napi_status status,void * data)129 void ScanAsyncCall::OnComplete(napi_env env, napi_status status, void *data)
130 {
131     AsyncContext *context = reinterpret_cast<AsyncContext *>(data);
132     if (context == nullptr) {
133         SCAN_HILOGE("OnComplete called with null context");
134         return;
135     }
136     if (context->ctx == nullptr || context->ctx->GetErrorIndex() != E_SCAN_NONE) {
137         status = napi_generic_failure;
138     }
139     napi_value output = nullptr;
140     napi_status runStatus = napi_generic_failure;
141     if (context->ctx != nullptr) {
142         runStatus = (*context->ctx)(env, &output);
143     }
144     SCAN_HILOGD("runStatus: [%{public}d], status: [%{public}d]", runStatus, status);
145     AsyncResult result;
146     if (status == napi_ok && runStatus == napi_ok) {
147         PrepareSuccessResult(env, output, result);
148     } else {
149         PrepareErrorResult(env, context, result);
150     }
151     if (status == napi_ok && runStatus == napi_ok) {
152         napi_resolve_deferred(env, context->defer, result.data);
153     } else {
154         napi_reject_deferred(env, context->defer, result.error);
155     }
156     DeleteContext(env, context);
157 }
158 
DeleteContext(napi_env env,AsyncContext * context)159 void ScanAsyncCall::DeleteContext(napi_env env, AsyncContext *context)
160 {
161     if (context == nullptr) {
162         return;
163     }
164     if (context->work != nullptr) {
165         napi_delete_async_work(env, context->work);
166     }
167     if (context->self != nullptr) {
168         napi_delete_reference(env, context->self);
169     }
170     delete context;
171     context = nullptr;
172 }
173 } // namespace OHOS::Scan
174