• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 <ani.h>
17 #include <array>
18 #include <iostream>
19 #include <map>
20 #include <unordered_map>
21 #include <memory>
22 #include <thread>
23 #include "pasteboard_error.h"
24 #include "pasteboard_hilog.h"
25 #include "pasteboard_client.h"
26 #include "pasteboard_js_err.h"
27 #include "common/block_object.h"
28 #include "ani_common_want.h"
29 #include "image_ani_utils.h"
30 #include "pasteboard_ani_utils.h"
31 #include "unified_meta.h"
32 
33 using namespace OHOS::MiscServices;
34 
35 constexpr size_t SYNC_TIMEOUT = 3500;
36 constexpr size_t MIMETYPE_MAX_LEN = 1024;
37 
ThrowBusinessError(ani_env * env,int errCode,std::string && errMsg)38 static void ThrowBusinessError(ani_env *env, int errCode, std::string&& errMsg)
39 {
40     PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "into ThrowBusinessError.");
41     if (env == nullptr) {
42         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "into ThrowBusinessError. env is null, return.");
43         return;
44     }
45     static const char *errorClsName = "L@ohos/base/BusinessError;";
46     ani_class cls {};
47     if (env->FindClass(errorClsName, &cls) != ANI_OK) {
48         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "findClass BusinessError failed.");
49         return;
50     }
51     ani_method ctor;
52     if (env->Class_FindMethod(cls, "<ctor>", ":V", &ctor) != ANI_OK) {
53         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "find method BusinessError.constructor failed.");
54         return;
55     }
56     ani_object errorObject;
57     if (env->Object_New(cls, ctor, &errorObject) != ANI_OK) {
58         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "create BusinessError object failed.");
59         return;
60     }
61     ani_double aniErrCode = static_cast<ani_double>(errCode);
62     ani_string errMsgStr;
63     if (env->String_NewUTF8(errMsg.c_str(), errMsg.size(), &errMsgStr) != ANI_OK) {
64         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "convert errMsg to ani_string failed.");
65         return;
66     }
67     if (env->Object_SetFieldByName_Double(errorObject, "code", aniErrCode) != ANI_OK) {
68         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "set error code failed.");
69         return;
70     }
71     if (env->Object_SetPropertyByName_Ref(errorObject, "message", errMsgStr) != ANI_OK) {
72         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "set error message failed.");
73         return;
74     }
75     ani_status flag = env->ThrowError(static_cast<ani_error>(errorObject));
76     if (flag != ANI_OK) {
77         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "ThrowError failed, flag: %{public}d.", flag);
78     } else {
79         PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_ANI, "flag: %{public}d.", flag);
80     }
81     return;
82 }
83 
GetNullObject(ani_env * env)84 ani_object GetNullObject(ani_env *env)
85 {
86     if (env == nullptr) {
87         return nullptr;
88     }
89     ani_ref ref;
90     if (env->GetNull(&ref) != ANI_OK) {
91         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "env->GetNull failed.");
92         return NULL;
93     }
94     return static_cast<ani_object>(ref);
95 }
96 
Create(ani_env * env,std::shared_ptr<PasteData> & ptrPasteData)97 ani_object Create([[maybe_unused]] ani_env *env, std::shared_ptr<PasteData> &ptrPasteData)
98 {
99     if (env == nullptr) {
100         return nullptr;
101     }
102     static const char *className = "L@ohos/pasteboard/PasteDataImpl;";
103     ani_class cls;
104     if (ANI_OK != env->FindClass(className, &cls)) {
105         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "create failed.");
106         return nullptr;
107     }
108 
109     auto shareptrPasteData = new SharedPtrHolder<PasteData>(ptrPasteData);
110     ani_object obj = NativeObjectWrapper<SharedPtrHolder<PasteData>>::Wrap(env, cls, shareptrPasteData);
111     if (obj == nullptr) {
112         delete shareptrPasteData;
113         return nullptr;
114     }
115     return obj;
116 }
117 
UnwrapAndGetPasteDataPtr(ani_env * env,ani_object object)118 PasteData* UnwrapAndGetPasteDataPtr([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object)
119 {
120     if (env == nullptr) {
121         return nullptr;
122     }
123     auto shareptrPasteData = NativeObjectWrapper<SharedPtrHolder<PasteData>>::Unwrap(env, object);
124     if (shareptrPasteData == nullptr) {
125         return nullptr;
126     }
127     return shareptrPasteData->Get().get();
128 }
129 
CreateObjectFromClass(ani_env * env,const char * className)130 ani_object CreateObjectFromClass([[maybe_unused]] ani_env *env, const char* className)
131 {
132     if (env == nullptr || className == nullptr) {
133         return nullptr;
134     }
135     ani_object obj = nullptr;
136     ani_class cls;
137     if (ANI_OK != env->FindClass(className, &cls)) {
138         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[CreateObjectFromClass] Not found class.");
139         return obj;
140     }
141     ani_method ctor;
142     if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) {
143         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[CreateObjectFromClass] get ctor failed.");
144         return obj;
145     }
146     if (ANI_OK != env->Object_New(cls, ctor, &obj)) {
147         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[CreateObjectFromClass] Create Object failed.");
148         return obj;
149     }
150 
151     return obj;
152 }
153 
GetStdStringFromUnion(ani_env * env,ani_object union_obj)154 std::string GetStdStringFromUnion([[maybe_unused]] ani_env *env, ani_object union_obj)
155 {
156     if (env == nullptr) {
157         return "";
158     }
159     UnionAccessor unionAccessor(env, union_obj);
160     ani_string str;
161     if (!unionAccessor.IsInstanceOf("Lstd/core/String;")) {
162         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[GetStdStringFromUnion] union_obj is not string!");
163         ThrowBusinessError(env, static_cast<int32_t>(JSErrorCode::INVALID_PARAMETERS),
164             "The type of mimeType must be string.");
165         return "";
166     }
167     if (!unionAccessor.TryConvert<ani_string>(str)) {
168         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI,
169             "[GetStdStringFromUnion] try to convert union object to ani_string failed!");
170         return "";
171     }
172 
173     return ANIUtils_ANIStringToStdString(env, str);
174 }
175 
GetArrayBuffer(ani_env * env,ani_object unionObj,std::vector<uint8_t> & vec)176 bool GetArrayBuffer([[maybe_unused]] ani_env *env, ani_object unionObj, std::vector<uint8_t> &vec)
177 {
178     if (env == nullptr) {
179         return false;
180     }
181     std::string classname("Lescompat/ArrayBuffer;");
182     bool isArrayBuffer = ANIUtils_UnionIsInstanceOf(env, unionObj, classname);
183     if (!isArrayBuffer) {
184         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI,
185             "[getArrayBuffer] Failed: is not arraybuffer.");
186         return false;
187     }
188 
189     void* data;
190     size_t length;
191     if (ANI_OK != env->ArrayBuffer_GetInfo(static_cast<ani_arraybuffer>(unionObj), &data, &length)) {
192         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI,
193             "[getArrayBuffer] Failed: env->ArrayBuffer_GetInfo().");
194         return false;
195     }
196 
197     auto pVal = static_cast<uint8_t*>(data);
198     vec.assign(pVal, pVal + length);
199 
200     return true;
201 }
202 
CheckMimeType(ani_env * env,std::string & mimeType)203 bool CheckMimeType(ani_env *env, std::string &mimeType)
204 {
205     if (env == nullptr) {
206         return false;
207     }
208     if (mimeType.size() == 0) {
209         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "The length of mimeType is 0.");
210         ThrowBusinessError(env, static_cast<int32_t>(JSErrorCode::INVALID_PARAMETERS),
211             "The length of mimeType is 0.");
212         return false;
213     }
214 
215     if (mimeType.size() > MIMETYPE_MAX_LEN) {
216         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI,
217             "The length of mimeType cannot be greater than 1024 bytes.");
218         ThrowBusinessError(env, static_cast<int32_t>(JSErrorCode::INVALID_PARAMETERS),
219             "The length of mimeType cannot be greater than 1024 bytes.");
220         return false;
221     }
222 
223     return true;
224 }
225 
GetEnumItem(ani_env * env,ani_int shareOption)226 static ani_enum_item GetEnumItem(ani_env *env, ani_int shareOption)
227 {
228     if (env == nullptr) {
229         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[GetEnumItem] env is null.");
230         return nullptr;
231     }
232     ani_namespace ns;
233     const char *nameSpaceName = "L@ohos/pasteboard/pasteboard;";
234     if (ANI_OK != env->FindNamespace(nameSpaceName, &ns)) {
235         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[GetEnumItem] Not found namespace: %{public}s", nameSpaceName);
236         return nullptr;
237     }
238 
239     ani_enum enumType;
240     const char *enumName = "LShareOption;";
241     if (ANI_OK != env->Namespace_FindEnum(ns, enumName, &enumType)) {
242         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[GetEnumItem] Find Enum failed: %{public}s", enumName);
243         return nullptr;
244     }
245 
246     ani_enum_item enumItem;
247     if (ANI_OK != env->Enum_GetEnumItemByIndex(enumType, shareOption, &enumItem)) {
248         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[GetEnumItem] Enum_GetEnumItemByIndex failed.");
249         return nullptr;
250     }
251 
252     return enumItem;
253 }
254 
GetRecordCount(ani_env * env,ani_object object)255 static ani_double GetRecordCount([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object)
256 {
257     if (env == nullptr) {
258         return 0;
259     }
260     PasteData* pPasteData = UnwrapAndGetPasteDataPtr(env, object);
261     if (pPasteData == nullptr) {
262         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[GetRecordCount] pPasteData is null.");
263         return 0;
264     }
265 
266     return pPasteData->GetRecordCount();
267 }
268 
AddRecordByPasteDataRecord(ani_env * env,ani_object object,ani_object record)269 static void AddRecordByPasteDataRecord([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object,
270     ani_object record)
271 {
272     if (env == nullptr) {
273         return;
274     }
275     ani_ref uri;
276     if (ANI_OK != env->Object_GetPropertyByName_Ref(static_cast<ani_object>(record), "uri", &uri)) {
277         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[AddRecord] Object_GetPropertyByName_Ref failed.");
278         return;
279     }
280 
281     auto uri_str = ANIUtils_ANIStringToStdString(env, static_cast<ani_string>(uri));
282 
283     PasteData* pPasteData = UnwrapAndGetPasteDataPtr(env, object);
284     if (pPasteData == nullptr) {
285         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[AddRecord] pPasteData is null.");
286         return;
287     }
288 
289     PasteDataRecord::Builder builder("");
290     builder.SetUri(std::make_shared<OHOS::Uri>(OHOS::Uri(uri_str)));
291     std::shared_ptr<PasteDataRecord> result = builder.Build();
292     if (result == nullptr) {
293         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[AddRecord] result is null.");
294         return;
295     }
296     pPasteData->AddRecord(*(result.get()));
297 }
298 
ProcessStrValueOfRecord(ani_env * env,ani_object union_obj,std::string mimeType,PasteData * pPasteData)299 static void ProcessStrValueOfRecord([[maybe_unused]] ani_env *env, ani_object union_obj, std::string mimeType,
300     PasteData *pPasteData)
301 {
302     if (env == nullptr) {
303         return;
304     }
305     if (pPasteData == nullptr) {
306         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI,
307             "[ProcessStrValueOfRecord] pPasteData is null.");
308         return;
309     }
310 
311     auto value_str = GetStdStringFromUnion(env, union_obj);
312     if (mimeType == MIMETYPE_TEXT_HTML) {
313         pPasteData->AddHtmlRecord(value_str);
314     } else if (mimeType == MIMETYPE_TEXT_PLAIN) {
315         pPasteData->AddTextRecord(value_str);
316     } else {
317         pPasteData->AddUriRecord(OHOS::Uri(value_str));
318     }
319 }
320 
AddRecordByTypeValue(ani_env * env,ani_object object,ani_string type,ani_object union_obj)321 static void AddRecordByTypeValue([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object,
322     ani_string type, ani_object union_obj)
323 {
324     if (env == nullptr) {
325         return;
326     }
327     auto mimeType = ANIUtils_ANIStringToStdString(env, static_cast<ani_string>(type));
328     if (!CheckMimeType(env, mimeType)) {
329         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI,
330             "[AddRecordByTypeValue] minetype length is error. %{public}s", mimeType.c_str());
331         return;
332     }
333 
334     PasteData* pPasteData = UnwrapAndGetPasteDataPtr(env, object);
335     if (pPasteData == nullptr) {
336         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[AddRecordByTypeValue] pPasteData is null.");
337         return;
338     }
339 
340     if (mimeType == MIMETYPE_PIXELMAP) {
341         OHOS::Media::PixelMap* rawPixelMap = OHOS::Media::ImageAniUtils::GetPixelMapFromEnv(env, union_obj);
342         if (rawPixelMap == nullptr) {
343             PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[AddRecordByTypeValue] GetPixelMapFromEnv failed.");
344             return;
345         }
346         auto pixelMap = std::shared_ptr<OHOS::Media::PixelMap>(rawPixelMap);
347         pPasteData->AddPixelMapRecord(pixelMap);
348         return;
349     } else if (mimeType == MIMETYPE_TEXT_WANT) {
350         OHOS::AAFwk::Want want;
351         if (!OHOS::AppExecFwk::UnwrapWant(env, union_obj, want)) {
352             PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[AddRecordByTypeValue] UnwrapWant failed.");
353             return;
354         }
355         pPasteData->AddWantRecord(std::make_shared<OHOS::AAFwk::Want>(want));
356         return;
357     }
358 
359     if (mimeType == MIMETYPE_TEXT_HTML || mimeType == MIMETYPE_TEXT_PLAIN || mimeType == MIMETYPE_TEXT_URI) {
360         ProcessStrValueOfRecord(env, union_obj, mimeType, pPasteData);
361         return;
362     }
363 
364     std::vector<uint8_t> vec;
365     vec.clear();
366     if (!GetArrayBuffer(env, union_obj, vec)) {
367         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[AddRecordByTypeValue] getArrayBuffer failed.");
368         return;
369     }
370     pPasteData->AddKvRecord(mimeType, vec);
371 
372     return;
373 }
374 
SetNamedPropertyByStr(ani_env * env,ani_class cls,const char * propertyName,std::string propertyValue,ani_object & obj)375 static void SetNamedPropertyByStr(ani_env *env, ani_class cls, const char *propertyName, std::string propertyValue,
376     ani_object &obj)
377 {
378     if (env == nullptr || propertyName == nullptr) {
379         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[SetNamedPropertyByStr] env or propertyName is null.");
380         return;
381     }
382     ani_string propertyAniStr = {};
383     env->String_NewUTF8(propertyValue.c_str(), propertyValue.length(), &propertyAniStr);
384 
385     ani_method propertySetter;
386     if (ANI_OK != env->Class_FindMethod(cls, propertyName, nullptr, &propertySetter)) {
387         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI,
388             "[SetNamedPropertyByStr] Class_FindMethod failed: %{public}s.", propertyName);
389         return;
390     }
391     if (ANI_OK != env->Object_CallMethod_Void(obj, propertySetter, propertyAniStr)) {
392         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI,
393             "[SetNamedPropertyByStr] Object_CallMethod_Void failed: %{public}s.", propertyName);
394         return;
395     }
396 }
397 
FillPasteDataRecordObject(ani_env * env,std::shared_ptr<PasteDataRecord> recordFromBottom,ani_object & obj)398 static void FillPasteDataRecordObject(ani_env *env, std::shared_ptr<PasteDataRecord> recordFromBottom, ani_object &obj)
399 {
400     if (env == nullptr || recordFromBottom == nullptr) {
401         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[FillPasteDataRecordObject] env or recordFromBottom is null.");
402         return;
403     }
404 
405     ani_class cls;
406     if (ANI_OK != env->FindClass("L@ohos/pasteboard/PasteDataRecordImpl;", &cls)) {
407         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[FillPasteDataRecordObject] Not found class.");
408         return;
409     }
410 
411     auto mimeType = recordFromBottom->GetMimeType();
412     SetNamedPropertyByStr(env, cls, "<set>mimeType", mimeType, obj);
413 
414     auto plainTextPtr = recordFromBottom->GetPlainTextV0();
415     if (plainTextPtr != nullptr) {
416         SetNamedPropertyByStr(env, cls, "<set>plainText", *plainTextPtr.get(), obj);
417     }
418 
419     auto uriPtr = recordFromBottom->GetUriV0();
420     if (uriPtr != nullptr) {
421         SetNamedPropertyByStr(env, cls, "<set>uri", uriPtr->ToString(), obj);
422     }
423 }
424 
GetRecord(ani_env * env,ani_object object,ani_double index)425 static ani_object GetRecord([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object,
426     [[maybe_unused]] ani_double index)
427 {
428     if (env == nullptr) {
429         return nullptr;
430     }
431     PasteData* pPasteData = UnwrapAndGetPasteDataPtr(env, object);
432     if (pPasteData == nullptr) {
433         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[GetRecord] pPasteData is null.");
434         return GetNullObject(env);
435     }
436 
437     if (index >= pPasteData->GetRecordCount() || index < 0) {
438         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[GetRecord] index is out of range.");
439         ThrowBusinessError(env, static_cast<int32_t>(JSErrorCode::OUT_OF_RANGE),
440             "index out of range.");
441         return GetNullObject(env);
442     }
443 
444     std::shared_ptr<PasteDataRecord> recordFromBottom = pPasteData->GetRecordAt(static_cast<std::size_t>(index));
445     if (recordFromBottom == nullptr) {
446         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[GetRecord] recordFromBottom is null.");
447         return GetNullObject(env);
448     }
449 
450     ani_object record = CreateObjectFromClass(env, "L@ohos/pasteboard/PasteDataRecordImpl;");
451     if (record == nullptr) {
452         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[GetRecord] CreateObjectFromClass failed.");
453         return GetNullObject(env);
454     }
455     FillPasteDataRecordObject(env, recordFromBottom, record);
456 
457     return record;
458 }
459 
SetProperty(ani_env * env,ani_object object,ani_object property)460 static void SetProperty([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, ani_object property)
461 {
462     if (env == nullptr) {
463         return;
464     }
465     PasteData* pPasteData = UnwrapAndGetPasteDataPtr(env, object);
466     if (pPasteData == nullptr) {
467         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[SetProperty] pPasteData is null.");
468         return;
469     }
470 
471     ani_ref shareOption;
472     if (ANI_OK != env->Object_GetPropertyByName_Ref(static_cast<ani_object>(property), "shareOption", &shareOption)) {
473         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[SetProperty] Object_GetPropertyByName_Ref failed.");
474         return;
475     }
476     ani_int shareOptionValue;
477     if (ANI_OK != env->EnumItem_GetValue_Int(static_cast<ani_enum_item>(shareOption), &shareOptionValue)) {
478         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[SetProperty] EnumItem_GetValue_Int failed.");
479         return;
480     }
481     ani_int localOnlyValue = shareOptionValue == ShareOption::CrossDevice ? false : true;
482     pPasteData->SetLocalOnly(localOnlyValue);
483     pPasteData->SetShareOption(static_cast<ShareOption>(shareOptionValue));
484 
485     ani_ref tag;
486     if (ANI_OK != env->Object_GetPropertyByName_Ref(static_cast<ani_object>(property), "tag", &tag)) {
487         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[SetProperty] Object_GetPropertyByName_Ref failed.");
488         return;
489     }
490     auto tag_str = ANIUtils_ANIStringToStdString(env, static_cast<ani_string>(tag));
491     pPasteData->SetTag(tag_str);
492 
493     return;
494 }
495 
SetNamedPropertyByEnumInt(ani_env * env,ani_class cls,const char * propertyName,ani_int shareOpionValue,ani_object & obj)496 static void SetNamedPropertyByEnumInt(ani_env *env, ani_class cls, const char *propertyName, ani_int shareOpionValue,
497     ani_object &obj)
498 {
499     if (env == nullptr || propertyName == nullptr) {
500         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[SetNamedPropertyByEnumInt] env or propertyName is null.");
501         return;
502     }
503     ani_enum_item enumItem = GetEnumItem(env, shareOpionValue);
504     if (enumItem == nullptr) {
505         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[SetNamedPropertyByEnumInt] Class_FindMethod failed.");
506         return;
507     }
508     ani_method shareOptionSetter;
509     if (ANI_OK != env->Class_FindMethod(cls, propertyName, nullptr, &shareOptionSetter)) {
510         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[SetNamedPropertyByEnumInt] Class_FindMethod failed.");
511         return;
512     }
513     if (ANI_OK != env->Object_CallMethod_Void(obj, shareOptionSetter, enumItem)) {
514         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[SetNamedPropertyByEnumInt] Object_CallMethod_Void failed.");
515         return;
516     }
517 }
518 
FillPasteDataPropertyObject(ani_env * env,PasteDataProperty & property,ani_object & obj)519 static void FillPasteDataPropertyObject(ani_env *env, PasteDataProperty &property, ani_object &obj)
520 {
521     if (env == nullptr) {
522         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[FillPasteDataPropertyObject] env is null.");
523         return;
524     }
525 
526     ani_class cls;
527     if (ANI_OK != env->FindClass("L@ohos/pasteboard/PasteDataPropertyImpl;", &cls)) {
528         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[FillPasteDataPropertyObject] Not found class.");
529         return;
530     }
531 
532     ani_int shareOpionValue = property.shareOption;
533     SetNamedPropertyByEnumInt(env, cls, "<set>shareOption", shareOpionValue, obj);
534     SetNamedPropertyByStr(env, cls, "<set>tag", property.tag, obj);
535 
536     ani_double timestampValue = property.timestamp;
537     ani_method timestampSetter;
538     if (ANI_OK != env->Class_FindMethod(cls, "<set>timestamp", nullptr, &timestampSetter)) {
539         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[FillPasteDataPropertyObject] Class_FindMethod failed.");
540         return;
541     }
542     if (ANI_OK != env->Object_CallMethod_Void(obj, timestampSetter, timestampValue)) {
543         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[FillPasteDataPropertyObject] Object_CallMethod_Void failed.");
544         return;
545     }
546 }
547 
GetProperty(ani_env * env,ani_object object)548 static ani_object GetProperty([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object)
549 {
550     if (env == nullptr) {
551         return nullptr;
552     }
553     PasteData* pPasteData = UnwrapAndGetPasteDataPtr(env, object);
554     if (pPasteData == nullptr) {
555         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[GetProperty] pPasteData is null.");
556         return GetNullObject(env);
557     }
558 
559     PasteDataProperty property = pPasteData->GetProperty();
560 
561     ani_object propertyToAbove = CreateObjectFromClass(env, "L@ohos/pasteboard/PasteDataPropertyImpl;");
562     if (propertyToAbove == nullptr) {
563         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[GetProperty] CreateObjectFromClass failed.");
564         return GetNullObject(env);
565     }
566     FillPasteDataPropertyObject(env, property, propertyToAbove);
567 
568     return propertyToAbove;
569 }
570 
CreateHtmlData(ani_env * env,ani_object union_obj)571 static ani_object CreateHtmlData([[maybe_unused]] ani_env *env, ani_object union_obj)
572 {
573     if (env == nullptr) {
574         return nullptr;
575     }
576     auto value_str = GetStdStringFromUnion(env, union_obj);
577     auto ptr = PasteboardClient::GetInstance()->CreateHtmlData(value_str);
578     if (ptr == nullptr) {
579         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[CreateHtmlData] CreateHtmlData failed.");
580         return GetNullObject(env);
581     }
582     ani_object PasteDataImpl = Create(env, ptr);
583 
584     return PasteDataImpl;
585 }
586 
CreatePlainTextData(ani_env * env,ani_object union_obj)587 static ani_object CreatePlainTextData([[maybe_unused]] ani_env *env, ani_object union_obj)
588 {
589     if (env == nullptr) {
590         return nullptr;
591     }
592     auto value_str = GetStdStringFromUnion(env, union_obj);
593     auto ptr = PasteboardClient::GetInstance()->CreatePlainTextData(value_str);
594     if (ptr == nullptr) {
595         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[CreatePlainTextData] CreatePlainTextData failed.");
596         return GetNullObject(env);
597     }
598     ani_object PasteDataImpl = Create(env, ptr);
599 
600     return PasteDataImpl;
601 }
602 
CreateUriData(ani_env * env,ani_object union_obj)603 static ani_object CreateUriData([[maybe_unused]] ani_env *env, ani_object union_obj)
604 {
605     if (env == nullptr) {
606         return nullptr;
607     }
608     auto value_str = GetStdStringFromUnion(env, union_obj);
609     auto ptr = PasteboardClient::GetInstance()->CreateUriData(OHOS::Uri(value_str));
610     if (ptr == nullptr) {
611         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[CreateUriData] CreateUriData failed.");
612         return GetNullObject(env);
613     }
614     ani_object PasteDataImpl = Create(env, ptr);
615 
616     return PasteDataImpl;
617 }
618 
CreatePixelMapData(ani_env * env,ani_object union_obj)619 static ani_object CreatePixelMapData([[maybe_unused]] ani_env *env, ani_object union_obj)
620 {
621     if (env == nullptr) {
622         return nullptr;
623     }
624     OHOS::Media::PixelMap* rawPixelMap = OHOS::Media::ImageAniUtils::GetPixelMapFromEnv(env, union_obj);
625     if (rawPixelMap == nullptr) {
626         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[CreatePixelMapData] GetPixelMapFromEnv failed.");
627         return GetNullObject(env);
628     }
629 
630     auto pixelMap = std::shared_ptr<OHOS::Media::PixelMap>(rawPixelMap);
631     auto ptr = PasteboardClient::GetInstance()->CreatePixelMapData(pixelMap);
632     if (ptr == nullptr) {
633         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[CreatePixelMapData] CreatePixelMapData failed.");
634         return GetNullObject(env);
635     }
636     ani_object PasteDataImpl = Create(env, ptr);
637 
638     return PasteDataImpl;
639 }
640 
CreateWantData(ani_env * env,ani_object union_obj)641 static ani_object CreateWantData([[maybe_unused]] ani_env *env, ani_object union_obj)
642 {
643     if (env == nullptr) {
644         return nullptr;
645     }
646     OHOS::AAFwk::Want want;
647     bool ret = OHOS::AppExecFwk::UnwrapWant(env, union_obj, want);
648     if (!ret) {
649         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[CreateWantData] UnwrapWant failed.");
650         return GetNullObject(env);
651     }
652 
653     auto ptr = PasteboardClient::GetInstance()->CreateWantData(std::make_shared<OHOS::AAFwk::Want>(want));
654     if (ptr == nullptr) {
655         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[CreateWantData] CreateWantData failed.");
656         return GetNullObject(env);
657     }
658     ani_object PasteDataImpl = Create(env, ptr);
659 
660     return PasteDataImpl;
661 }
662 
ProcessSpecialMimeType(ani_env * env,ani_object union_obj,std::string type)663 ani_object ProcessSpecialMimeType([[maybe_unused]] ani_env *env, ani_object union_obj, std::string type)
664 {
665     if (env == nullptr) {
666         return nullptr;
667     }
668     if (type == "text/html") {
669         return CreateHtmlData(env, union_obj);
670     } else if (type == "text/plain") {
671         return CreatePlainTextData(env, union_obj);
672     } else if (type == "text/uri") {
673         return CreateUriData(env, union_obj);
674     } else if (type == "pixelMap") {
675         return CreatePixelMapData(env, union_obj);
676     } else if (type == "text/want") {
677         return CreateWantData(env, union_obj);
678     }
679 
680     return nullptr;
681 }
682 
CreateDataTypeValue(ani_env * env,ani_string type,ani_object union_obj)683 static ani_object CreateDataTypeValue([[maybe_unused]] ani_env *env, ani_string type, ani_object union_obj)
684 {
685     if (env == nullptr) {
686         return nullptr;
687     }
688     auto type_str = ANIUtils_ANIStringToStdString(env, static_cast<ani_string>(type));
689     if (!CheckMimeType(env, type_str)) {
690         return GetNullObject(env);
691     }
692     if (type_str == "text/html" || type_str == "text/plain" ||
693         type_str == "text/uri" || type_str == "pixelMap" || type_str == "text/want") {
694         return ProcessSpecialMimeType(env, union_obj, type_str);
695     }
696 
697     std::string classname("Lescompat/ArrayBuffer;");
698     bool isArrayBuffer = ANIUtils_UnionIsInstanceOf(env, union_obj, classname);
699     if (!isArrayBuffer) {
700         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[CreateDataTypeValue] not ArrayBuffer.");
701         return GetNullObject(env);
702     }
703 
704     void* data;
705     size_t length;
706     if (ANI_OK != env->ArrayBuffer_GetInfo(static_cast<ani_arraybuffer>(union_obj), &data, &length)) {
707         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI,
708             "[CreateDataTypeValue] Failed: env->ArrayBuffer_GetInfo().");
709         return GetNullObject(env);
710     }
711 
712     auto pVal = static_cast<uint8_t*>(data);
713     std::vector<uint8_t> vec(pVal, pVal + length);
714 
715     auto ptr = PasteboardClient::GetInstance()->CreateKvData(type_str, vec);
716     if (ptr == nullptr) {
717         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[CreateDataTypeValue] CreateKvData failed.");
718         return GetNullObject(env);
719     }
720     ani_object PasteDataImpl = Create(env, ptr);
721 
722     return PasteDataImpl;
723 }
724 
ParsekeyValAndProcess(ani_env * env,ani_ref key_value,ani_object value_obj,std::shared_ptr<std::vector<std::pair<std::string,std::shared_ptr<EntryValue>>>> result)725 bool ParsekeyValAndProcess([[maybe_unused]] ani_env *env, ani_ref key_value, ani_object value_obj,
726     std::shared_ptr<std::vector<std::pair<std::string, std::shared_ptr<EntryValue>>>> result)
727 {
728     if (env == nullptr) {
729         return false;
730     }
731     std::string keyStr = ANIUtils_ANIStringToStdString(env, static_cast<ani_string>(key_value));
732     if (!CheckMimeType(env, keyStr)) {
733         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI,
734             "[ParsekeyValAndProcess] keyStr is empty or length is more than 1024 bytes.");
735         return false;
736     }
737 
738     std::shared_ptr<EntryValue> entryValue = std::make_shared<EntryValue>();
739     std::vector<uint8_t> vec;
740     vec.clear();
741     if (GetArrayBuffer(env, value_obj, vec)) {
742         *entryValue = std::vector<uint8_t>(vec.begin(), vec.end());
743         result->emplace_back(std::make_pair(keyStr, entryValue));
744         return true;
745     }
746 
747     if (keyStr == "pixelMap") {
748         OHOS::Media::PixelMap* rawPixelMap = OHOS::Media::ImageAniUtils::GetPixelMapFromEnv(env, value_obj);
749         if (rawPixelMap == nullptr) {
750             PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[ParsekeyValAndProcess] GetPixelMapFromEnv failed.");
751             return false;
752         }
753         *entryValue = std::shared_ptr<OHOS::Media::PixelMap>(rawPixelMap);
754     } else if (keyStr == "text/want") {
755         OHOS::AAFwk::Want want;
756         if (!OHOS::AppExecFwk::UnwrapWant(env, value_obj, want)) {
757             PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[ParsekeyValAndProcess] UnwrapWant failed.");
758             return false;
759         }
760         *entryValue = std::make_shared<OHOS::AAFwk::Want>(want);
761     } else {
762         auto value_str = GetStdStringFromUnion(env, value_obj);
763         if (value_str.length() == 0) {
764             PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[ParsekeyValAndProcess] value_str is null.");
765             return false;
766         }
767         *entryValue = value_str;
768     }
769 
770     result->emplace_back(std::make_pair(keyStr, entryValue));
771 
772     return true;
773 }
774 
ForEachMapEntry(ani_env * env,ani_object map_object,std::shared_ptr<std::vector<std::pair<std::string,std::shared_ptr<EntryValue>>>> typeValueVector)775 bool ForEachMapEntry(ani_env *env, ani_object map_object,
776     std::shared_ptr<std::vector<std::pair<std::string, std::shared_ptr<EntryValue>>>> typeValueVector)
777 {
778     if (env == nullptr) {
779         return false;
780     }
781     ani_ref keys;
782     if (ANI_OK != env->Object_CallMethodByName_Ref(map_object, "keys", ":Lescompat/IterableIterator;", &keys)) {
783         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[forEachMapEntry] Failed to get keys iterator.");
784         return false;
785     }
786 
787     bool success = true;
788     while (success) {
789         ani_ref next;
790         ani_boolean done = false;
791         if (ANI_OK != env->Object_CallMethodByName_Ref(
792             static_cast<ani_object>(keys), "next", nullptr, &next)) {
793             PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[forEachMapEntry] Failed to get next key.");
794             success = false;
795             break;
796         }
797 
798         if (ANI_OK != env->Object_GetFieldByName_Boolean(
799             static_cast<ani_object>(next), "done", &done)) {
800             PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[forEachMapEntry] Failed to check iterator done.");
801             success = false;
802             break;
803         }
804         if (done) {
805             PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_ANI, "[forEachMapEntry] done break.");
806             break;
807         }
808 
809         ani_ref key_value;
810         if (ANI_OK != env->Object_GetFieldByName_Ref(static_cast<ani_object>(next),
811             "value", &key_value)) {
812             PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[forEachMapEntry] Failed to get key value.");
813             success = false;
814             break;
815         }
816 
817         ani_ref value_obj;
818         if (ANI_OK != env->Object_CallMethodByName_Ref(map_object, "$_get", nullptr,
819             &value_obj, key_value)) {
820             PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "[forEachMapEntry] Failed to get value for key.");
821             success = false;
822             break;
823         }
824         ParsekeyValAndProcess(env, key_value, static_cast<ani_object>(value_obj), typeValueVector);
825     }
826     return success;
827 }
828 
CreateDataRecord(ani_env * env,ani_object map_object)829 static ani_object CreateDataRecord([[maybe_unused]] ani_env *env, ani_object map_object)
830 {
831     if (env == nullptr) {
832         return nullptr;
833     }
834     std::shared_ptr<std::vector<std::pair<std::string, std::shared_ptr<EntryValue>>>> typeValueVector =
835         std::make_shared<std::vector<std::pair<std::string, std::shared_ptr<EntryValue>>>>();
836     ForEachMapEntry(env, map_object, typeValueVector);
837     if (typeValueVector == nullptr || typeValueVector->empty()) {
838         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[CreateDataRecord] typeValueVector is null or empty.");
839         return GetNullObject(env);
840     }
841 
842     std::shared_ptr<std::map<std::string, std::shared_ptr<EntryValue>>> typeValueMap =
843             std::make_shared<std::map<std::string, std::shared_ptr<EntryValue>>>();
844     for (const auto &item : *typeValueVector) {
845         typeValueMap->emplace(item.first, item.second);
846     }
847     auto ptr = PasteboardClient::GetInstance()->CreateMultiTypeData(std::move(typeValueMap),
848         typeValueVector->begin()->first);
849     if (ptr == nullptr) {
850         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[CreateDataRecord] CreateMultiTypeData failed.");
851         return GetNullObject(env);
852     }
853 
854     ani_object PasteDataImpl = Create(env, ptr);
855     return PasteDataImpl;
856 }
857 
GetSystemPasteboard(ani_env * env)858 static ani_object GetSystemPasteboard([[maybe_unused]] ani_env *env)
859 {
860     if (env == nullptr) {
861         return nullptr;
862     }
863     ani_object systemPasteboard = nullptr;
864     static const char *className = "L@ohos/pasteboard/SystemPasteboardImpl;";
865     ani_class cls;
866     if (ANI_OK != env->FindClass(className, &cls)) {
867         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[GetSystemPasteboard] Not found classname.");
868         return systemPasteboard;
869     }
870 
871     ani_method ctor;
872     if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) {
873         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[GetSystemPasteboard] get ctor failed.");
874         return systemPasteboard;
875     }
876 
877     if (ANI_OK != env->Object_New(cls, ctor, &systemPasteboard)) {
878         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[GetSystemPasteboard] Create Object failed.");
879         return systemPasteboard;
880     }
881 
882     return systemPasteboard;
883 }
884 
HasDataType(ani_env * env,ani_object object,ani_string mimeType)885 static ani_boolean HasDataType([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, ani_string mimeType)
886 {
887     if (env == nullptr) {
888         return false;
889     }
890     auto mimeType_str = ANIUtils_ANIStringToStdString(env, static_cast<ani_string>(mimeType));
891 
892     auto block = std::make_shared<OHOS::BlockObject<std::shared_ptr<int>>>(SYNC_TIMEOUT);
893     std::thread thread([block, mimeType_str]() {
894         auto ret = PasteboardClient::GetInstance()->HasDataType(mimeType_str);
895         std::shared_ptr<int> value = std::make_shared<int>(static_cast<int>(ret));
896         block->SetValue(value);
897     });
898     thread.detach();
899     auto value = block->GetValue();
900     if (value == nullptr) {
901         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[HasDataType] time out. ");
902         ThrowBusinessError(env, static_cast<int32_t>(JSErrorCode::REQUEST_TIME_OUT), "request timed out.");
903         return false;
904     }
905 
906     return *value;
907 }
908 
SetData(ani_env * env,ani_object object,ani_object pasteData)909 static ani_int SetData([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, ani_object pasteData)
910 {
911     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_ANI, "SetData is called!");
912     int32_t ret = static_cast<int32_t>(PasteboardError::INVALID_DATA_ERROR);
913     auto data = UnwrapAndGetPasteDataPtr(env, pasteData);
914     if (data == nullptr) {
915         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "PasteData is null.");
916         return ret;
917     }
918 
919     std::map<uint32_t, std::shared_ptr<OHOS::UDMF::EntryGetter>> entryGetters;
920     for (auto record : data->AllRecords()) {
921         if (record != nullptr && record->GetEntryGetter() != nullptr) {
922             entryGetters.emplace(record->GetRecordId(), record->GetEntryGetter());
923         }
924     }
925     ret = PasteboardClient::GetInstance()->SetPasteData(*data, nullptr, entryGetters);
926     if (ret == static_cast<int>(PasteboardError::E_OK)) {
927         PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_ANI, "SetPasteData successfully.");
928     } else if (ret == static_cast<int>(PasteboardError::PROHIBIT_COPY)) {
929         ThrowBusinessError(env, static_cast<int32_t>(PasteboardError::PROHIBIT_COPY),
930             "The system prohibits copying.");
931         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "The system prohibits copying.");
932     } else if (ret == static_cast<int>(PasteboardError::TASK_PROCESSING)) {
933         ThrowBusinessError(env, static_cast<int32_t>(PasteboardError::TASK_PROCESSING),
934             "Another setData is being processed.");
935         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "Another setData is being processed.");
936     }
937 
938     return ret;
939 }
940 
ClearData(ani_env * env)941 static void ClearData([[maybe_unused]] ani_env *env)
942 {
943     PasteboardClient::GetInstance()->Clear();
944 }
945 
GetDataSync(ani_env * env,ani_object object)946 static ani_object GetDataSync([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object)
947 {
948     if (env == nullptr) {
949         return nullptr;
950     }
951     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_ANI, "GetDataSync called.");
952     auto pasteData = std::make_shared<PasteData>();
953     auto block = std::make_shared<OHOS::BlockObject<std::shared_ptr<int32_t>>>(SYNC_TIMEOUT);
954     std::thread thread([block, pasteData]() mutable {
955         auto ret = PasteboardClient::GetInstance()->GetPasteData(*pasteData);
956         std::shared_ptr<int32_t> value = std::make_shared<int32_t>(ret);
957         block->SetValue(value);
958     });
959     thread.detach();
960     auto value = block->GetValue();
961     if (value == nullptr) {
962         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "time out, GetDataSync failed.");
963         ThrowBusinessError(env, static_cast<int32_t>(JSErrorCode::REQUEST_TIME_OUT), "request timed out.");
964         return GetNullObject(env);
965     }
966     ani_object pasteDataObj = Create(env, pasteData);
967 
968     return pasteDataObj;
969 }
970 
GetDataSource(ani_env * env,ani_object object)971 static ani_string GetDataSource([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object)
972 {
973     if (env == nullptr) {
974         return nullptr;
975     }
976     std::string bundleName;
977     auto block = std::make_shared<OHOS::BlockObject<std::shared_ptr<int>>>(SYNC_TIMEOUT);
978     std::thread thread([block, &bundleName]() mutable {
979         auto ret = PasteboardClient::GetInstance()->GetDataSource(bundleName);
980         std::shared_ptr<int> value = std::make_shared<int>(ret);
981         block->SetValue(value);
982     });
983     thread.detach();
984 
985     auto value = block->GetValue();
986     if (value == nullptr) {
987         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "time out, GetDataSource failed.");
988         ThrowBusinessError(env, static_cast<int32_t>(JSErrorCode::REQUEST_TIME_OUT), "request timed out.");
989         return nullptr;
990     }
991 
992     if (*value != static_cast<int>(PasteboardError::E_OK)) {
993         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "GetDataSource, failed, ret = %{public}d.", *value);
994         return nullptr;
995     }
996 
997     ani_string aniStr = nullptr;
998     if (ANI_OK != env->String_NewUTF8(bundleName.data(), bundleName.size(), &aniStr)) {
999         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "Unsupported ANI_VERSION_1");
1000         return nullptr;
1001     }
1002 
1003     return aniStr;
1004 }
1005 
ANI_Constructor_Namespace(ani_env * env)1006 ANI_EXPORT ani_status ANI_Constructor_Namespace(ani_env *env)
1007 {
1008     if (env == nullptr) {
1009         return ANI_ERROR;
1010     }
1011     ani_namespace ns;
1012     static const char *nameSpaceName = "L@ohos/pasteboard/pasteboard;";
1013     if (ANI_OK != env->FindNamespace(nameSpaceName, &ns)) {
1014         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI,
1015             "[ANI_Constructor_Namespace] Not found namespace: %s", nameSpaceName);
1016         return ANI_NOT_FOUND;
1017     }
1018 
1019     std::array methods = {
1020         ani_native_function {"createDataTypeValue", nullptr, reinterpret_cast<void *>(CreateDataTypeValue)},
1021         ani_native_function {"createDataRecord", nullptr, reinterpret_cast<void *>(CreateDataRecord)},
1022         ani_native_function {"getSystemPasteboard", nullptr, reinterpret_cast<void *>(GetSystemPasteboard)},
1023     };
1024 
1025     if (ANI_OK != env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size())) {
1026         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI,
1027             "[ANI_Constructor_Namespace] Cannot bind native methods to %s.", nameSpaceName);
1028         return ANI_ERROR;
1029     };
1030 
1031     return ANI_OK;
1032 }
1033 
ANI_Constructor_PasteData(ani_env * env)1034 ANI_EXPORT ani_status ANI_Constructor_PasteData(ani_env *env)
1035 {
1036     if (env == nullptr) {
1037         return ANI_ERROR;
1038     }
1039     static const char *className = "L@ohos/pasteboard/PasteDataImpl;";
1040     ani_class cls;
1041     if (ANI_OK != env->FindClass(className, &cls)) {
1042         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[ANI_Constructor_PasteData] Not found %s.", className);
1043         return ANI_NOT_FOUND;
1044     }
1045 
1046     std::array methods = {
1047         ani_native_function {"addRecordByPasteDataRecord",
1048             nullptr, reinterpret_cast<void *>(AddRecordByPasteDataRecord)},
1049         ani_native_function {"addRecordByTypeValue", nullptr, reinterpret_cast<void *>(AddRecordByTypeValue)},
1050         ani_native_function {"getRecordCount", nullptr, reinterpret_cast<void *>(GetRecordCount)},
1051         ani_native_function {"getRecord", nullptr, reinterpret_cast<void *>(GetRecord)},
1052         ani_native_function {"setProperty", nullptr, reinterpret_cast<void *>(SetProperty)},
1053         ani_native_function {"getProperty", nullptr, reinterpret_cast<void *>(GetProperty)},
1054     };
1055 
1056     if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) {
1057         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI,
1058             "[ANI_Constructor_PasteData] Cannot bind native methods to %s.", className);
1059         return ANI_ERROR;
1060     };
1061 
1062     return ANI_OK;
1063 }
1064 
ANI_Constructor_SystemPasteboard(ani_env * env)1065 ANI_EXPORT ani_status ANI_Constructor_SystemPasteboard(ani_env *env)
1066 {
1067     if (env == nullptr) {
1068         return ANI_ERROR;
1069     }
1070     static const char *className = "L@ohos/pasteboard/SystemPasteboardImpl;";
1071     ani_class cls;
1072     if (ANI_OK != env->FindClass(className, &cls)) {
1073         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[ANI_Constructor_SystemPasteboard] Not found %s.", className);
1074         return ANI_NOT_FOUND;
1075     }
1076 
1077     std::array methods = {
1078         ani_native_function {"hasDataType", nullptr, reinterpret_cast<void *>(HasDataType)},
1079         ani_native_function {"nativeSetData", nullptr, reinterpret_cast<void *>(SetData)},
1080         ani_native_function {"nativeClearData", nullptr, reinterpret_cast<void *>(ClearData)},
1081         ani_native_function {"getDataSync", nullptr, reinterpret_cast<void *>(GetDataSync)},
1082         ani_native_function {"getDataSource", nullptr, reinterpret_cast<void *>(GetDataSource)},
1083     };
1084 
1085     if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) {
1086         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI,
1087             "[ANI_Constructor_SystemPasteboard] Cannot bind native methods to %s.", className);
1088         return ANI_ERROR;
1089     };
1090 
1091     return ANI_OK;
1092 }
1093 
BindCleanerclassMethods(ani_env * env)1094 static ani_status BindCleanerclassMethods(ani_env *env)
1095 {
1096     if (env == nullptr) {
1097         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[BindCleanerclassMethods] env is null.");
1098         return ANI_ERROR;
1099     }
1100 
1101     static const char *className = "L@ohos/pasteboard/Cleaner;";
1102     ani_class cleanerCls;
1103     ani_status status = env->FindClass(className, &cleanerCls);
1104     if (ANI_OK != status) {
1105         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI,
1106             "[BindCleanerclassMethods] Not found ohos/pasteboard/Cleaner. status:%{public}d.", status);
1107         return ANI_NOT_FOUND;
1108     }
1109     return NativePtrCleaner(env).Bind(cleanerCls);
1110 }
1111 
ANI_Constructor(ani_vm * vm,uint32_t * result)1112 ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result)
1113 {
1114     if (vm == nullptr || result == nullptr) {
1115         return ANI_ERROR;
1116     }
1117     ani_env *env;
1118     if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) {
1119         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI, "[ANI_Constructor] Unsupported ANI_VERSION_1.");
1120         return ANI_ERROR;
1121     }
1122 
1123     ani_status namespaceStatus = ANI_Constructor_Namespace(env);
1124     if (namespaceStatus != ANI_OK) {
1125         return namespaceStatus;
1126     }
1127 
1128     ani_status pasteDataStatus = ANI_Constructor_PasteData(env);
1129     if (pasteDataStatus != ANI_OK) {
1130         return pasteDataStatus;
1131     }
1132 
1133     ani_status systemboardStatus = ANI_Constructor_SystemPasteboard(env);
1134     if (systemboardStatus != ANI_OK) {
1135         return systemboardStatus;
1136     }
1137 
1138     if (ANI_OK != BindCleanerclassMethods(env)) {
1139         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_ANI,
1140             "[ANI_Constructor_PasteData]BindCleanerclassMethods failed.");
1141         return ANI_ERROR;
1142     }
1143 
1144     *result = ANI_VERSION_1;
1145     return ANI_OK;
1146 }
1147