1 /*
2 * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development 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 "nfc_napi_tag_ndef_formatable.h"
17
18 #include "loghelper.h"
19
20 namespace OHOS {
21 namespace NFC {
22 namespace KITS {
23 static const int32_t DEFAULT_REF_COUNT = 1;
24
CheckTagSessionAndThrow(const napi_env & env,const NdefFormatableTag * tagSession)25 static bool CheckTagSessionAndThrow(const napi_env &env, const NdefFormatableTag *tagSession)
26 {
27 if (tagSession == nullptr) {
28 // object null is unexpected, unknown error.
29 napi_throw(env, GenerateBusinessError(env, BUSI_ERR_TAG_STATE_INVALID,
30 BuildErrorMessage(BUSI_ERR_TAG_STATE_INVALID, "", "", "", "")));
31 return false;
32 }
33 return true;
34 }
35
CheckFormatParameters(napi_env env,const napi_value parameters[],size_t parameterCount)36 static bool CheckFormatParameters(napi_env env, const napi_value parameters[], size_t parameterCount)
37 {
38 if (parameterCount == ARGV_NUM_1) {
39 if (!CheckParametersAndThrow(env, parameters, {napi_object}, "message", "NdefMessage")) {
40 return false;
41 }
42 return true;
43 } else if (parameterCount == ARGV_NUM_2) {
44 if (!CheckParametersAndThrow(env, parameters, {napi_object, napi_function},
45 "message & callback", "NdefMessage & function")) {
46 return false;
47 }
48 return true;
49 } else {
50 napi_throw(env, GenerateBusinessError(env, BUSI_ERR_PARAM,
51 BuildErrorMessage(BUSI_ERR_PARAM, "", "", "", "")));
52 return false;
53 }
54 }
55
NativeFormat(napi_env env,void * data)56 static void NativeFormat(napi_env env, void *data)
57 {
58 auto context = static_cast<NdefFormatableContext<int, NapiNdefFormatableTag> *>(data);
59 context->errorCode = BUSI_ERR_TAG_STATE_INVALID;
60
61 NdefFormatableTag *ndefFormatableTagPtr =
62 static_cast<NdefFormatableTag *>(static_cast<void *>(context->objectInfo->tagSession.get()));
63 if (!CheckTagSessionAndThrow(env, ndefFormatableTagPtr)) {
64 return;
65 }
66 context->errorCode = ndefFormatableTagPtr->Format(context->msg);
67 context->resolved = true;
68 }
69
FormatCallback(napi_env env,napi_status status,void * data)70 static void FormatCallback(napi_env env, napi_status status, void *data)
71 {
72 auto context = static_cast<NdefFormatableContext<int, NapiNdefFormatableTag> *>(data);
73 napi_value callbackValue = nullptr;
74 if (status == napi_ok && context->resolved && context->errorCode == ErrorCode::ERR_NONE) {
75 // the return is void.
76 napi_get_undefined(env, &callbackValue);
77 DoAsyncCallbackOrPromise(env, context, callbackValue);
78 } else {
79 int errCode = BuildOutputErrorCode(context->errorCode);
80 std::string errMessage = BuildErrorMessage(errCode, "format", TAG_PERM_DESC, "", "");
81 ThrowAsyncError(env, context, errCode, errMessage);
82 }
83 }
84
Format(napi_env env,napi_callback_info info)85 napi_value NapiNdefFormatableTag::Format(napi_env env, napi_callback_info info)
86 {
87 size_t paramsCount = ARGV_NUM_2;
88 napi_value params[ARGV_NUM_2] = {0};
89 void *data = nullptr;
90 napi_value thisVar = nullptr;
91 NapiNdefFormatableTag *objectInfoCb = nullptr;
92 napi_get_cb_info(env, info, ¶msCount, params, &thisVar, &data);
93
94 // unwrap from thisVar to retrieve the native instance
95 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&objectInfoCb));
96 if (!CheckUnwrapStatusAndThrow(env, status, BUSI_ERR_TAG_STATE_INVALID) ||
97 !CheckFormatParameters(env, params, paramsCount)) {
98 return CreateUndefined(env);
99 }
100 auto context = std::make_unique<NdefFormatableContext<int, NapiNdefFormatableTag>>().release();
101 if (!CheckContextAndThrow(env, context, BUSI_ERR_TAG_STATE_INVALID)) {
102 return CreateUndefined(env);
103 }
104
105 napi_status status2 = napi_unwrap(env, params[ARGV_INDEX_0], reinterpret_cast<void **>(&context->msg));
106 if (!CheckUnwrapStatusAndThrow(env, status2, BUSI_ERR_TAG_STATE_INVALID)) {
107 return CreateUndefined(env);
108 }
109 if (paramsCount == ARGV_NUM_2) {
110 napi_create_reference(env, params[ARGV_INDEX_1], DEFAULT_REF_COUNT, &context->callbackRef);
111 }
112
113 context->objectInfo = objectInfoCb;
114 napi_value result = HandleAsyncWork(env, context, "Format", NativeFormat, FormatCallback);
115 return result;
116 }
117
NativeFormatReadOnly(napi_env env,void * data)118 static void NativeFormatReadOnly(napi_env env, void *data)
119 {
120 auto context = static_cast<NdefFormatableContext<int, NapiNdefFormatableTag> *>(data);
121 context->errorCode = BUSI_ERR_TAG_STATE_INVALID;
122 NdefFormatableTag *ndefFormatableTagPtr =
123 static_cast<NdefFormatableTag *>(static_cast<void *>(context->objectInfo->tagSession.get()));
124 if (!CheckTagSessionAndThrow(env, ndefFormatableTagPtr)) {
125 return;
126 }
127 context->errorCode = ndefFormatableTagPtr->FormatReadOnly(context->msg);
128 context->resolved = true;
129 }
130
FormatReadOnlyCallback(napi_env env,napi_status status,void * data)131 static void FormatReadOnlyCallback(napi_env env, napi_status status, void *data)
132 {
133 auto context = static_cast<NdefFormatableContext<int, NapiNdefFormatableTag> *>(data);
134 napi_value callbackValue = nullptr;
135 if (status == napi_ok && context->resolved && context->errorCode == ErrorCode::ERR_NONE) {
136 // the return is void.
137 napi_get_undefined(env, &callbackValue);
138 DoAsyncCallbackOrPromise(env, context, callbackValue);
139 } else {
140 int errCode = BuildOutputErrorCode(context->errorCode);
141 std::string errMessage = BuildErrorMessage(errCode, "formatReadOnly", TAG_PERM_DESC, "", "");
142 ThrowAsyncError(env, context, errCode, errMessage);
143 }
144 }
145
FormatReadOnly(napi_env env,napi_callback_info info)146 napi_value NapiNdefFormatableTag::FormatReadOnly(napi_env env, napi_callback_info info)
147 {
148 size_t paramsCount = ARGV_NUM_2;
149 napi_value params[ARGV_NUM_2] = {0};
150 void *data = nullptr;
151 napi_value thisVar = nullptr;
152 NapiNdefFormatableTag *objectInfoCb = nullptr;
153 napi_get_cb_info(env, info, ¶msCount, params, &thisVar, &data);
154
155 // unwrap from thisVar to retrieve the native instance
156 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&objectInfoCb));
157 if (!CheckUnwrapStatusAndThrow(env, status, BUSI_ERR_TAG_STATE_INVALID) ||
158 !CheckFormatParameters(env, params, paramsCount)) {
159 return CreateUndefined(env);
160 }
161 auto context = std::make_unique<NdefFormatableContext<int, NapiNdefFormatableTag>>().release();
162 if (!CheckContextAndThrow(env, context, BUSI_ERR_TAG_STATE_INVALID)) {
163 return CreateUndefined(env);
164 }
165
166 napi_status status2 = napi_unwrap(env, params[ARGV_INDEX_0], reinterpret_cast<void **>(&context->msg));
167 if (!CheckUnwrapStatusAndThrow(env, status2, BUSI_ERR_TAG_STATE_INVALID)) {
168 return CreateUndefined(env);
169 }
170 if (paramsCount == ARGV_NUM_2) {
171 napi_create_reference(env, params[ARGV_INDEX_1], DEFAULT_REF_COUNT, &context->callbackRef);
172 }
173
174 context->objectInfo = objectInfoCb;
175 napi_value result = HandleAsyncWork(env, context, "FormatReadOnly", NativeFormatReadOnly, FormatReadOnlyCallback);
176 return result;
177 }
178 } // namespace KITS
179 } // namespace NFC
180 } // namespace OHOS
181