1 /*
2 * Copyright (C) 2021-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 "entry_getter.h"
17 #include "pasteboard_hilog.h"
18 #include "pastedata_record_napi.h"
19
20 using namespace OHOS::MiscServices;
21 using namespace OHOS::Media;
22
23 namespace OHOS {
24 namespace MiscServicesNapi {
25 static thread_local napi_ref g_pasteDataRecord = nullptr;
26 const int ARGC_TYPE_SET0 = 0;
27 const int ARGC_TYPE_SET1 = 1;
28 const int ARGC_TYPE_SET2 = 2;
29 constexpr int32_t MIMETYPE_MAX_SIZE = 1024;
30 constexpr size_t ENTRY_GETTER_TIMEOUT = 2;
31
PasteDataRecordNapi()32 PasteDataRecordNapi::PasteDataRecordNapi() : env_(nullptr) {}
33
~PasteDataRecordNapi()34 PasteDataRecordNapi::~PasteDataRecordNapi() {}
35
NewInstanceByRecord(napi_env env,napi_value & instance,const std::shared_ptr<MiscServices::PasteDataRecord> & record)36 bool PasteDataRecordNapi::NewInstanceByRecord(
37 napi_env env, napi_value &instance, const std::shared_ptr<MiscServices::PasteDataRecord> &record)
38 {
39 PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(record != nullptr, false, PASTEBOARD_MODULE_CLIENT,
40 "invalid parameter record");
41 NAPI_CALL_BASE(env, PasteDataRecordNapi::NewInstance(env, instance), false);
42 PasteDataRecordNapi *obj = nullptr;
43 napi_status status = napi_unwrap(env, instance, reinterpret_cast<void **>(&obj));
44 if ((status != napi_ok) || (obj == nullptr)) {
45 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "unwrap failed");
46 return false;
47 }
48 obj->value_ = record;
49 obj->JSFillInstance(env, instance);
50 return true;
51 }
52
NewHtmlTextRecordInstance(napi_env env,const std::string & text,napi_value & instance)53 bool PasteDataRecordNapi::NewHtmlTextRecordInstance(napi_env env, const std::string &text, napi_value &instance)
54 {
55 NAPI_CALL_BASE(env, PasteDataRecordNapi::NewInstance(env, instance), false);
56 PasteDataRecordNapi *obj = nullptr;
57 napi_status status = napi_unwrap(env, instance, reinterpret_cast<void **>(&obj));
58 if ((status != napi_ok) || (obj == nullptr)) {
59 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "unwrap failed");
60 return false;
61 }
62 obj->value_ = PasteboardClient::GetInstance()->CreateHtmlTextRecord(text);
63 obj->JSFillInstance(env, instance);
64 return true;
65 }
66
NewPlainTextRecordInstance(napi_env env,const std::string & text,napi_value & instance)67 bool PasteDataRecordNapi::NewPlainTextRecordInstance(napi_env env, const std::string &text, napi_value &instance)
68 {
69 NAPI_CALL_BASE(env, PasteDataRecordNapi::NewInstance(env, instance), false);
70 PasteDataRecordNapi *obj = nullptr;
71 napi_status status = napi_unwrap(env, instance, reinterpret_cast<void **>(&obj));
72 if ((status != napi_ok) || (obj == nullptr)) {
73 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "unwrap failed");
74 return false;
75 }
76 obj->value_ = PasteboardClient::GetInstance()->CreatePlainTextRecord(text);
77 obj->JSFillInstance(env, instance);
78 return true;
79 }
80
NewPixelMapRecordInstance(napi_env env,const std::shared_ptr<PixelMap> pixelMap,napi_value & instance)81 bool PasteDataRecordNapi::NewPixelMapRecordInstance(
82 napi_env env, const std::shared_ptr<PixelMap> pixelMap, napi_value &instance)
83 {
84 if (pixelMap == nullptr) {
85 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "pixelMap is nullptr.");
86 return false;
87 }
88
89 NAPI_CALL_BASE(env, PasteDataRecordNapi::NewInstance(env, instance), false);
90 PasteDataRecordNapi *obj = nullptr;
91 napi_status status = napi_unwrap(env, instance, reinterpret_cast<void **>(&obj));
92 if ((status != napi_ok) || (obj == nullptr)) {
93 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "unwrap failed.");
94 return false;
95 }
96 obj->value_ = PasteboardClient::GetInstance()->CreatePixelMapRecord(pixelMap);
97 obj->JSFillInstance(env, instance);
98 return true;
99 }
100
NewUriRecordInstance(napi_env env,const std::string & text,napi_value & instance)101 bool PasteDataRecordNapi::NewUriRecordInstance(napi_env env, const std::string &text, napi_value &instance)
102 {
103 NAPI_CALL_BASE(env, PasteDataRecordNapi::NewInstance(env, instance), false);
104 PasteDataRecordNapi *obj = nullptr;
105 napi_status status = napi_unwrap(env, instance, reinterpret_cast<void **>(&obj));
106 if ((status != napi_ok) || (obj == nullptr)) {
107 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "unwrap failed");
108 return false;
109 }
110 obj->value_ = PasteboardClient::GetInstance()->CreateUriRecord(OHOS::Uri(text));
111 obj->JSFillInstance(env, instance);
112 return true;
113 }
114
NewWantRecordInstance(napi_env env,const std::shared_ptr<OHOS::AAFwk::Want> want,napi_value & instance)115 bool PasteDataRecordNapi::NewWantRecordInstance(
116 napi_env env, const std::shared_ptr<OHOS::AAFwk::Want> want, napi_value &instance)
117 {
118 PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(want != nullptr, false,
119 PASTEBOARD_MODULE_CLIENT, "invalid parameter want");
120 NAPI_CALL_BASE(env, PasteDataRecordNapi::NewInstance(env, instance), false);
121 PasteDataRecordNapi *obj = nullptr;
122 napi_status status = napi_unwrap(env, instance, reinterpret_cast<void **>(&obj));
123 if ((status != napi_ok) || (obj == nullptr)) {
124 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "unwrap failed");
125 return false;
126 }
127 obj->value_ = PasteboardClient::GetInstance()->CreateWantRecord(want);
128 obj->JSFillInstance(env, instance);
129 return true;
130 }
131
NewKvRecordInstance(napi_env env,const std::string & mimeType,const std::vector<uint8_t> & arrayBuffer,napi_value & instance)132 bool PasteDataRecordNapi::NewKvRecordInstance(
133 napi_env env, const std::string &mimeType, const std::vector<uint8_t> &arrayBuffer, napi_value &instance)
134 {
135 NAPI_CALL_BASE(env, PasteDataRecordNapi::NewInstance(env, instance), false);
136 PasteDataRecordNapi *obj = nullptr;
137 napi_status status = napi_unwrap(env, instance, reinterpret_cast<void **>(&obj));
138 if ((status != napi_ok) || (obj == nullptr)) {
139 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "unwrap failed");
140 return false;
141 }
142 obj->value_ = PasteboardClient::GetInstance()->CreateKvRecord(mimeType, arrayBuffer);
143 obj->JSFillInstance(env, instance);
144 return true;
145 }
146
NewEntryGetterRecordInstance(const std::vector<std::string> & mimeTypes,std::shared_ptr<PastedataRecordEntryGetterInstance> entryGetter,napi_value & instance)147 bool PasteDataRecordNapi::NewEntryGetterRecordInstance(const std::vector<std::string> &mimeTypes,
148 std::shared_ptr<PastedataRecordEntryGetterInstance> entryGetter, napi_value &instance)
149 {
150 if (entryGetter == nullptr) {
151 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "no entry getter");
152 return false;
153 }
154 NAPI_CALL_BASE(entryGetter->GetEnv(), PasteDataRecordNapi::NewInstance(entryGetter->GetEnv(), instance), false);
155 PasteDataRecordNapi *obj = nullptr;
156 napi_status status = napi_unwrap(entryGetter->GetEnv(), instance, reinterpret_cast<void **>(&obj));
157 if ((status != napi_ok) || (obj == nullptr)) {
158 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "unwrap failed");
159 return false;
160 }
161 obj->value_ = PasteboardClient::GetInstance()->CreateMultiDelayRecord(mimeTypes, entryGetter->GetStub());
162 obj->JSFillInstance(entryGetter->GetEnv(), instance);
163 return true;
164 }
165
SetNamedPropertyByStr(napi_env env,napi_value & instance,const char * propName,const char * propValue)166 void PasteDataRecordNapi::SetNamedPropertyByStr(
167 napi_env env, napi_value &instance, const char *propName, const char *propValue)
168 {
169 if (propName == nullptr || propValue == nullptr) {
170 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "invalid parameter");
171 return;
172 }
173 napi_value prop = nullptr;
174 if (napi_create_string_utf8(env, propValue, NAPI_AUTO_LENGTH, &prop) == napi_ok) {
175 napi_set_named_property(env, instance, propName, prop);
176 }
177 }
178
SetNapiKvData(napi_env env,std::shared_ptr<MineCustomData> customData)179 napi_value PasteDataRecordNapi::SetNapiKvData(napi_env env, std::shared_ptr<MineCustomData> customData)
180 {
181 PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(customData != nullptr, nullptr,
182 PASTEBOARD_MODULE_CLIENT, "invalid parameter");
183 napi_value jsCustomData = nullptr;
184 napi_create_object(env, &jsCustomData);
185 auto itemData = customData->GetItemData();
186 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "size = %{public}zu.", itemData.size());
187 for (const auto &item : itemData) {
188 void *data = nullptr;
189 napi_value arrayBuffer = nullptr;
190 size_t len = item.second.size();
191 NAPI_CALL(env, napi_create_arraybuffer(env, len, &data, &arrayBuffer));
192 errno_t ret = (len == 0) ? EOK : memcpy_s(data, len, reinterpret_cast<const void *>(item.second.data()), len);
193 if (ret != EOK) {
194 PASTEBOARD_HILOGW(PASTEBOARD_MODULE_CLIENT, "copy %{public}s failed, ret=%{public}d",
195 item.first.c_str(), ret);
196 }
197 NAPI_CALL(env, napi_set_named_property(env, jsCustomData, item.first.c_str(), arrayBuffer));
198 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "mimeType = %{public}s.", item.first.c_str());
199 }
200 return jsCustomData;
201 }
202
GetNativeKvData(napi_env env,napi_value napiValue)203 std::shared_ptr<MineCustomData> PasteDataRecordNapi::GetNativeKvData(napi_env env, napi_value napiValue)
204 {
205 napi_valuetype valueType = napi_undefined;
206 NAPI_CALL(env, napi_typeof(env, napiValue, &valueType));
207 NAPI_ASSERT(env, valueType == napi_object, "Wrong argument type. Object expected.");
208
209 napi_value mimeTypes = nullptr;
210 NAPI_CALL(env, napi_get_property_names(env, napiValue, &mimeTypes));
211 uint32_t mimeTypesNum = 0;
212 NAPI_CALL(env, napi_get_array_length(env, mimeTypes, &mimeTypesNum));
213
214 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "mimeTypesNum = %{public}u", mimeTypesNum);
215 std::shared_ptr<MineCustomData> customData = std::make_shared<MineCustomData>();
216 for (uint32_t i = 0; i < mimeTypesNum; i++) {
217 napi_value mimeTypeNapi = nullptr;
218 NAPI_CALL(env, napi_get_element(env, mimeTypes, i, &mimeTypeNapi));
219
220 std::string mimeType;
221 bool ret = GetValue(env, mimeTypeNapi, mimeType);
222 if (!ret || (mimeType.size() > MIMETYPE_MAX_SIZE) || mimeType == "") {
223 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "mimeType size or mimeType invalid");
224 return nullptr;
225 }
226 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "mimeType = %{public}s,", mimeType.c_str());
227
228 napi_value napiArrayBuffer = nullptr;
229 NAPI_CALL(env, napi_get_property(env, napiValue, mimeTypeNapi, &napiArrayBuffer));
230 void *data = nullptr;
231 size_t dataLen;
232 NAPI_CALL(env, napi_get_arraybuffer_info(env, napiArrayBuffer, &data, &dataLen));
233 customData->AddItemData(mimeType,
234 std::vector<uint8_t>(reinterpret_cast<uint8_t *>(data), reinterpret_cast<uint8_t *>(data) + dataLen));
235 }
236 return customData;
237 }
238
JSFillInstance(napi_env env,napi_value & instance)239 void PasteDataRecordNapi::JSFillInstance(napi_env env, napi_value &instance)
240 {
241 if (value_ == nullptr) {
242 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "invalid parameter");
243 return;
244 }
245 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "mimeType = %{public}s.", value_->GetMimeType().c_str());
246
247 auto mimeType = value_->GetMimeType();
248 SetNamedPropertyByStr(env, instance, "mimeType", mimeType.c_str());
249
250 auto plainText = value_->GetPlainTextV0();
251 if (plainText != nullptr) {
252 SetNamedPropertyByStr(env, instance, "plainText", plainText->c_str());
253 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "fill plainText.");
254 }
255
256 auto htmlText = value_->GetHtmlTextV0();
257 if (htmlText != nullptr) {
258 SetNamedPropertyByStr(env, instance, "htmlText", htmlText->c_str());
259 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "fill htmlText.");
260 }
261
262 auto uri = value_->GetUriV0();
263 if (uri != nullptr) {
264 SetNamedPropertyByStr(env, instance, "uri", uri->ToString().c_str());
265 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "fill uri.");
266 }
267
268 auto want = value_->GetWant();
269 if (want != nullptr) {
270 napi_value jsWant = OHOS::AppExecFwk::WrapWant(env, *want);
271 napi_set_named_property(env, instance, "want", jsWant);
272 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "fill want.");
273 }
274
275 auto pixelMap = value_->GetPixelMapV0();
276 if (pixelMap != nullptr) {
277 napi_value jsPixelMap = OHOS::Media::PixelMapNapi::CreatePixelMap(env, pixelMap);
278 napi_set_named_property(env, instance, "pixelMap", jsPixelMap);
279 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "fill pixelMap.");
280 }
281
282 auto customData = value_->GetCustomData();
283 if (customData != nullptr) {
284 napi_value jsCustomData = PasteDataRecordNapi::SetNapiKvData(env, customData);
285 napi_set_named_property(env, instance, "data", jsCustomData);
286 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "fill data.");
287 }
288 }
289
ConvertToText(napi_env env,napi_callback_info info)290 napi_value PasteDataRecordNapi::ConvertToText(napi_env env, napi_callback_info info)
291 {
292 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "ConvertToText is called!");
293
294 struct ExeContext {
295 std::string text;
296 PasteDataRecordNapi *obj = nullptr;
297 };
298 auto exeContext = std::make_shared<ExeContext>();
299 auto input = [exeContext](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
300 // convertToText(callback: AsyncCallback<string>) has 1 args
301 if (argc > 0 &&
302 !CheckArgsType(env, argv[0], napi_function, "Parameter error. The type of callback must be function.")) {
303 return napi_invalid_arg;
304 }
305 PasteDataRecordNapi *obj = nullptr;
306 napi_status status = napi_unwrap(env, self, reinterpret_cast<void **>(&obj));
307 if (status == napi_ok && obj != nullptr) {
308 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "unwrap failed");
309 exeContext->obj = obj;
310 }
311 return napi_ok;
312 };
313
314 auto exec = [exeContext](AsyncCall::Context *ctx) {
315 if ((exeContext->obj != nullptr) && (exeContext->obj->value_ != nullptr)) {
316 exeContext->text = exeContext->obj->value_->ConvertToText();
317 }
318 };
319 auto output = [exeContext](napi_env env, napi_value *result) -> napi_status {
320 napi_status status =
321 napi_create_string_utf8(env, (exeContext->text).c_str(), (exeContext->text).length(), result);
322 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "napi_create_string_utf8 status = %{public}d", status);
323 return status;
324 };
325
326 // 0: the AsyncCall at the first position;
327 AsyncCall asyncCall(env, info, std::make_shared<AsyncCall::Context>(std::move(input), std::move(output)), 0);
328 return asyncCall.Call(env, exec);
329 }
330
ConvertToTextV9(napi_env env,napi_callback_info info)331 napi_value PasteDataRecordNapi::ConvertToTextV9(napi_env env, napi_callback_info info)
332 {
333 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "ConvertToTextV9 is called!");
334 return ConvertToText(env, info);
335 }
336
ToPlainText(napi_env env,napi_callback_info info)337 napi_value PasteDataRecordNapi::ToPlainText(napi_env env, napi_callback_info info)
338 {
339 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "ToPlainText is called!");
340 size_t argc = ARGC_TYPE_SET1;
341 napi_value argv[ARGC_TYPE_SET1] = {0};
342 napi_value thisVar = nullptr;
343
344 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
345 NAPI_ASSERT(env, argc >= ARGC_TYPE_SET0, "Wrong number of arguments");
346
347 PasteDataRecordNapi *obj = nullptr;
348 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
349 if ((status != napi_ok) || (obj == nullptr) || (obj->value_ == nullptr)) {
350 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get ToPlainText object failed");
351 return nullptr;
352 }
353
354 std::string str = obj->value_->ConvertToText();
355 napi_value result = nullptr;
356 napi_create_string_utf8(env, str.c_str(), NAPI_AUTO_LENGTH, &result);
357 return result;
358 }
359
AddEntry(napi_env env,napi_callback_info info)360 napi_value PasteDataRecordNapi::AddEntry(napi_env env, napi_callback_info info)
361 {
362 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "AddEntry is called!");
363 size_t argc = ARGC_TYPE_SET2;
364 napi_value argv[ARGC_TYPE_SET2] = { 0 };
365 napi_value thisVar = nullptr;
366 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
367 std::string mimeType;
368 if (!CheckArgs(env, argv, argc, mimeType)) {
369 return nullptr;
370 }
371
372 PasteDataRecordNapi *obj = nullptr;
373 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
374 if ((status != napi_ok) || (obj == nullptr) || (obj->value_ == nullptr)) {
375 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get AddEntry object failed");
376 return nullptr;
377 }
378
379 EntryValue entryValue;
380 if (!GetNativeValue(env, mimeType, argv[1], entryValue)) {
381 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "GetNativeValue failed");
382 return nullptr;
383 }
384
385 auto utdType = CommonUtils::Convert2UtdId(UDMF::UD_BUTT, mimeType);
386 std::shared_ptr<PasteDataEntry> pasteDataEntry = std::make_shared<PasteDataEntry>(utdType, entryValue);
387 obj->value_->AddEntry(utdType, pasteDataEntry);
388 return nullptr;
389 }
390
GetValidTypes(napi_env env,napi_callback_info info)391 napi_value PasteDataRecordNapi::GetValidTypes(napi_env env, napi_callback_info info)
392 {
393 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetValidType is called!");
394 size_t argc = ARGC_TYPE_SET1;
395 napi_value argv[ARGC_TYPE_SET1] = { 0 };
396 napi_value thisVar = nullptr;
397 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
398 std::vector<std::string> mimeTypes;
399
400 if (!CheckExpression(env, argc >= ARGC_TYPE_SET1, JSErrorCode::INVALID_PARAMETERS,
401 "Parameter error. The number of arguments cannot be less than one.") ||
402 !CheckArgsArray(env, argv[0], mimeTypes)) {
403 return nullptr;
404 }
405
406 PasteDataRecordNapi *obj = nullptr;
407 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
408 if ((status != napi_ok) || (obj == nullptr) || (obj->value_ == nullptr)) {
409 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get GetValidType object failed");
410 return nullptr;
411 }
412 std::vector<std::string> validTypes = obj->value_->GetValidMimeTypes(mimeTypes);
413 napi_value result = nullptr;
414 NAPI_CALL(env, napi_create_array(env, &result));
415 for (uint32_t i = 0; i < validTypes.size(); i++) {
416 napi_value element;
417 NAPI_CALL(env, napi_create_string_utf8(env, validTypes[i].c_str(), NAPI_AUTO_LENGTH, &element));
418 NAPI_CALL(env, napi_set_element(env, result, i, element));
419 }
420 return result;
421 }
422
GetRecordData(napi_env env,napi_callback_info info)423 napi_value PasteDataRecordNapi::GetRecordData(napi_env env, napi_callback_info info)
424 {
425 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetValidType is called!");
426
427 struct ExeContext {
428 std::string mimeType;
429 std::shared_ptr<PasteDataEntry> entryValue;
430 PasteDataRecordNapi *obj = nullptr;
431 };
432 auto exeContext = std::make_shared<ExeContext>();
433 auto input = [exeContext](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
434 if (!CheckExpression(env, argc >= ARGC_TYPE_SET1, JSErrorCode::INVALID_PARAMETERS,
435 "Parameter error. The number of arguments cannot be less than one.") ||
436 !CheckArgsMimeType(env, argv[0], exeContext->mimeType)) {
437 return napi_invalid_arg;
438 }
439 if (argc > ARGC_TYPE_SET1 &&
440 !CheckArgsType(env, argv[ARGC_TYPE_SET1], napi_function,
441 "Parameter error. The type of callback must be function.")) {
442 return napi_invalid_arg;
443 }
444 napi_status status = napi_unwrap(env, self, reinterpret_cast<void **>(&(exeContext->obj)));
445 if ((status != napi_ok) || (exeContext->obj == nullptr)) {
446 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "unwrap failed");
447 return napi_object_expected;
448 }
449 return napi_ok;
450 };
451
452 auto exec = [exeContext](AsyncCall::Context *ctx) {
453 if ((exeContext->obj != nullptr) && (exeContext->obj->value_ != nullptr)) {
454 exeContext->entryValue = exeContext->obj->value_->GetEntryByMimeType(exeContext->mimeType);
455 }
456 };
457 auto output = [exeContext](napi_env env, napi_value *result) -> napi_status {
458 napi_status status = ConvertEntryValue(env, result, exeContext->mimeType, exeContext->entryValue);
459 return status;
460 };
461
462 // 1: the AsyncCall at the first position;
463 AsyncCall asyncCall(env, info, std::make_shared<AsyncCall::Context>(std::move(input),
464 std::move(output)), ARGC_TYPE_SET1);
465 return asyncCall.Call(env, exec);
466 }
467
PasteDataRecordInit(napi_env env,napi_value exports)468 napi_value PasteDataRecordNapi::PasteDataRecordInit(napi_env env, napi_value exports)
469 {
470 napi_property_descriptor properties[] = {
471 DECLARE_NAPI_FUNCTION("convertToText", ConvertToText),
472 DECLARE_NAPI_FUNCTION("convertToTextV9", ConvertToTextV9),
473 DECLARE_NAPI_FUNCTION("toPlainText", ToPlainText),
474 DECLARE_NAPI_FUNCTION("addEntry", AddEntry),
475 DECLARE_NAPI_FUNCTION("getValidTypes", GetValidTypes),
476 DECLARE_NAPI_FUNCTION("getData", GetRecordData)
477 };
478
479 napi_status status = napi_ok;
480
481 napi_value constructor;
482 status = napi_define_class(env, "PasteDataRecord", NAPI_AUTO_LENGTH, New, nullptr,
483 sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
484 if (status != napi_ok) {
485 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to define class at PasteDataRecordInit");
486 return nullptr;
487 }
488
489 status = napi_create_reference(env, constructor, 1, &g_pasteDataRecord);
490 if (status != napi_ok) {
491 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "PasteDataRecordInit create reference failed");
492 return nullptr;
493 }
494 napi_set_named_property(env, exports, "PasteDataRecord", constructor);
495 return exports;
496 }
497
Destructor(napi_env env,void * nativeObject,void * finalize_hint)498 void PasteDataRecordNapi::Destructor(napi_env env, void *nativeObject, void *finalize_hint)
499 {
500 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "Destructor");
501 PasteDataRecordNapi *obj = static_cast<PasteDataRecordNapi *>(nativeObject);
502 delete obj;
503 }
504
New(napi_env env,napi_callback_info info)505 napi_value PasteDataRecordNapi::New(napi_env env, napi_callback_info info)
506 {
507 size_t argc = ARGC_TYPE_SET1;
508 napi_value argv[ARGC_TYPE_SET1] = {0};
509 napi_value thisVar = nullptr;
510 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
511
512 // get native object
513 PasteDataRecordNapi *obj = new PasteDataRecordNapi();
514 obj->env_ = env;
515 ASSERT_CALL(env, napi_wrap(env, thisVar, obj, PasteDataRecordNapi::Destructor, nullptr, nullptr), obj);
516 return thisVar;
517 }
518
NewInstance(napi_env env,napi_value & instance)519 napi_status PasteDataRecordNapi::NewInstance(napi_env env, napi_value &instance)
520 {
521 napi_status status = napi_invalid_arg;
522
523 napi_value constructor;
524 status = napi_get_reference_value(env, g_pasteDataRecord, &constructor);
525 if (status != napi_ok) {
526 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "get reference failed");
527 return status;
528 }
529
530 status = napi_new_instance(env, constructor, 0, nullptr, &instance);
531 if (status != napi_ok) {
532 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "new instance failed");
533 return status;
534 }
535
536 return napi_ok;
537 }
538
PastedataRecordEntryGetterInstance(const napi_env & env,const napi_ref & ref)539 PastedataRecordEntryGetterInstance::PastedataRecordEntryGetterInstance(const napi_env &env, const napi_ref &ref)
540 : env_(env), ref_(ref)
541 {
542 stub_ = std::make_shared<PastedataRecordEntryGetterInstance::PastedataRecordEntryGetterImpl>();
543 }
544
~PastedataRecordEntryGetterInstance()545 PastedataRecordEntryGetterInstance::~PastedataRecordEntryGetterInstance()
546 {
547 napi_delete_reference(env_, ref_);
548 }
549
UvWorkGetRecordByEntryGetter(uv_work_t * work,int status)550 void UvWorkGetRecordByEntryGetter(uv_work_t *work, int status)
551 {
552 if (UV_ECANCELED == status || work == nullptr || work->data == nullptr) {
553 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "invalid parameter");
554 return;
555 }
556 PasteboardEntryGetterWorker *entryGetterWork = reinterpret_cast<PasteboardEntryGetterWorker *>(work->data);
557 if (entryGetterWork == nullptr || entryGetterWork->entryGetter == nullptr) {
558 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "pasteboardDataWorker or delayGetter is null");
559 delete work;
560 work = nullptr;
561 return;
562 }
563 auto env = entryGetterWork->entryGetter->GetEnv();
564 auto ref = entryGetterWork->entryGetter->GetRef();
565 napi_handle_scope scope = nullptr;
566 napi_open_handle_scope(env, &scope);
567 if (scope == nullptr) {
568 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "scope is null");
569 return;
570 }
571 napi_value undefined = nullptr;
572 napi_get_undefined(env, &undefined);
573 auto mimeType = CommonUtils::Convert2MimeType(entryGetterWork->utdId);
574 napi_value argv[1] = { CreateNapiString(env, mimeType) };
575 napi_value callback = nullptr;
576 napi_value resultOut = nullptr;
577 napi_get_reference_value(env, ref, &callback);
578 {
579 std::unique_lock<std::mutex> lock(entryGetterWork->mutex);
580 auto ret = napi_call_function(env, undefined, callback, 1, argv, &resultOut);
581 if (ret == napi_ok) {
582 EntryValue entryValue;
583 if (GetNativeValue(env, mimeType, resultOut, entryValue)) {
584 entryGetterWork->entryValue = std::make_shared<UDMF::ValueType>(entryValue);
585 }
586 } else {
587 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "call napi_call_function is not ok, ret: %{public}d", ret);
588 }
589 napi_close_handle_scope(env, scope);
590 entryGetterWork->complete = true;
591 if (!entryGetterWork->clean) {
592 entryGetterWork->cv.notify_all();
593 return;
594 }
595 }
596 delete entryGetterWork;
597 entryGetterWork = nullptr;
598 delete work;
599 work = nullptr;
600 }
601
GetValueByType(const std::string & utdId)602 UDMF::ValueType PastedataRecordEntryGetterInstance::GetValueByType(const std::string &utdId)
603 {
604 uv_loop_s *loop = nullptr;
605 napi_get_uv_event_loop(env_, &loop);
606 PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(loop != nullptr, std::monostate{},
607 PASTEBOARD_MODULE_JS_NAPI, "loop instance is nullptr");
608 uv_work_t *work = new (std::nothrow) uv_work_t;
609 PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(work != nullptr, std::monostate{},
610 PASTEBOARD_MODULE_JS_NAPI, "work is null");
611 PasteboardEntryGetterWorker *entryGetterWork = new (std::nothrow) PasteboardEntryGetterWorker();
612 if (entryGetterWork == nullptr) {
613 PASTEBOARD_HILOGW(PASTEBOARD_MODULE_JS_NAPI, "PasteboardEntryGetterWorker is null");
614 delete work;
615 work = nullptr;
616 return std::monostate{};
617 }
618 entryGetterWork->entryGetter = shared_from_this();
619 entryGetterWork->utdId = utdId;
620 work->data = reinterpret_cast<void *>(entryGetterWork);
621 bool noNeedClean = false;
622 {
623 std::unique_lock<std::mutex> lock(entryGetterWork->mutex);
624 int ret = uv_queue_work(loop, work, [](uv_work_t *work) {
625 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetValueByType callback");
626 }, UvWorkGetRecordByEntryGetter);
627 if (ret != 0) {
628 delete entryGetterWork;
629 entryGetterWork = nullptr;
630 delete work;
631 work = nullptr;
632 return std::monostate{};
633 }
634 if (entryGetterWork->cv.wait_for(lock, std::chrono::seconds(ENTRY_GETTER_TIMEOUT),
635 [entryGetterWork] { return entryGetterWork->complete; }) && entryGetterWork->entryValue != nullptr) {
636 return *(entryGetterWork->entryValue);
637 }
638 if (!entryGetterWork->complete && uv_cancel((uv_req_t*)work) != 0) {
639 entryGetterWork->clean = true;
640 noNeedClean = true;
641 }
642 }
643 if (!noNeedClean) {
644 delete entryGetterWork;
645 entryGetterWork = nullptr;
646 delete work;
647 work = nullptr;
648 }
649 return std::monostate{};
650 }
651
GetValueByType(const std::string & utdId)652 UDMF::ValueType PastedataRecordEntryGetterInstance::PastedataRecordEntryGetterImpl::GetValueByType(
653 const std::string &utdId)
654 {
655 if (wrapper_ == nullptr) {
656 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "PastedataRecordEntryGetterImpl::GetValueByType no entry getter");
657 return std::monostate{};
658 }
659 return wrapper_->GetValueByType(utdId);
660 }
661
SetEntryGetterWrapper(const std::shared_ptr<PastedataRecordEntryGetterInstance> entryGetterInstance)662 void PastedataRecordEntryGetterInstance::PastedataRecordEntryGetterImpl::SetEntryGetterWrapper(
663 const std::shared_ptr<PastedataRecordEntryGetterInstance> entryGetterInstance)
664 {
665 wrapper_ = entryGetterInstance;
666 }
667 } // namespace MiscServicesNapi
668 } // namespace OHOS
669