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 #include <thread>
16
17 #include "ffrt/ffrt_utils.h"
18 #include "napi_pasteboard_common.h"
19 #include "pasteboard_app_event_dfx.h"
20 #include "pasteboard_hilog.h"
21 using namespace OHOS::MiscServices;
22 using namespace OHOS::Media;
23
24 namespace OHOS {
25 namespace MiscServicesNapi {
26 static thread_local napi_ref g_systemPasteboard = nullptr;
27 static thread_local napi_ref g_systemPasteboard_instance = nullptr;
28 thread_local std::map<napi_ref, sptr<PasteboardObserverInstance>> SystemPasteboardNapi::observers_;
29 std::shared_ptr<PasteboardDelayGetterInstance> SystemPasteboardNapi::delayGetter_;
30 std::mutex SystemPasteboardNapi::delayMutex_;
31 constexpr int ARGC_TYPE_SET1 = 1;
32 constexpr size_t MAX_ARGS = 6;
33 constexpr size_t SYNC_TIMEOUT = 3500;
34 constexpr size_t DELAY_TIMEOUT = 2;
35 const std::string STRING_UPDATE = "update";
36 std::recursive_mutex SystemPasteboardNapi::listenerMutex_;
37 std::map<std::string, std::shared_ptr<ProgressListenerFn>> SystemPasteboardNapi::listenerMap_;
38
PasteboardDelayGetterInstance(const napi_env & env,const napi_ref & ref)39 PasteboardDelayGetterInstance::PasteboardDelayGetterInstance(const napi_env &env, const napi_ref &ref)
40 : env_(env), ref_(ref)
41 {
42 stub_ = std::make_shared<PasteboardDelayGetterInstance::PasteboardDelayGetterImpl>();
43 }
44
~PasteboardDelayGetterInstance()45 PasteboardDelayGetterInstance::~PasteboardDelayGetterInstance()
46 {
47 ref_ = nullptr;
48 }
49
UvQueueWorkGetDelayPasteData(uv_work_t * work,int status)50 void UvQueueWorkGetDelayPasteData(uv_work_t *work, int status)
51 {
52 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "UvQueueWorkGetDelayPasteData start");
53 if (UV_ECANCELED == status || work == nullptr || work->data == nullptr) {
54 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "invalid parameter");
55 return;
56 }
57 PasteboardDelayWorker *pasteboardDelayWorker = (PasteboardDelayWorker *)work->data;
58 if (pasteboardDelayWorker == nullptr || pasteboardDelayWorker->delayGetter == nullptr) {
59 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "pasteboardDataWorker or delayGetter is null");
60 delete work;
61 work = nullptr;
62 return;
63 }
64 auto env = pasteboardDelayWorker->delayGetter->GetEnv();
65 auto ref = pasteboardDelayWorker->delayGetter->GetRef();
66 napi_handle_scope scope = nullptr;
67 napi_open_handle_scope(env, &scope);
68 if (scope == nullptr) {
69 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "scope is null");
70 return;
71 }
72 napi_value undefined = nullptr;
73 napi_get_undefined(env, &undefined);
74 napi_value argv[1] = { CreateNapiString(env, pasteboardDelayWorker->dataType) };
75 napi_value callback = nullptr;
76 napi_value resultOut = nullptr;
77 napi_get_reference_value(env, ref, &callback);
78 {
79 std::unique_lock<std::mutex> lock(pasteboardDelayWorker->mutex);
80 auto ret = napi_call_function(env, undefined, callback, 1, argv, &resultOut);
81 if (ret == napi_ok) {
82 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "get delay data success");
83 UDMF::UnifiedDataNapi *unifiedDataNapi = nullptr;
84 napi_unwrap(env, resultOut, reinterpret_cast<void **>(&unifiedDataNapi));
85 if (unifiedDataNapi != nullptr) {
86 pasteboardDelayWorker->unifiedData = unifiedDataNapi->value_;
87 }
88 }
89 napi_close_handle_scope(env, scope);
90 pasteboardDelayWorker->complete = true;
91 if (!pasteboardDelayWorker->clean) {
92 pasteboardDelayWorker->cv.notify_all();
93 return;
94 }
95 }
96 delete pasteboardDelayWorker;
97 pasteboardDelayWorker = nullptr;
98 delete work;
99 work = nullptr;
100 }
101
ReleasePasteboardResource(PasteboardDelayWorker ** pasteboardDelayWorker,uv_work_t ** work)102 static void ReleasePasteboardResource(PasteboardDelayWorker **pasteboardDelayWorker, uv_work_t **work)
103 {
104 if (pasteboardDelayWorker == nullptr || work == nullptr ||
105 *pasteboardDelayWorker == nullptr || *work == nullptr) {
106 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "invalid parameter");
107 return;
108 }
109 delete *pasteboardDelayWorker;
110 *pasteboardDelayWorker = nullptr;
111 delete *work;
112 *work = nullptr;
113 }
114
GetUnifiedData(const std::string & type,UDMF::UnifiedData & data)115 void PasteboardDelayGetterInstance::GetUnifiedData(const std::string &type, UDMF::UnifiedData &data)
116 {
117 uv_loop_s *loop = nullptr;
118 napi_get_uv_event_loop(env_, &loop);
119 if (loop == nullptr) {
120 PASTEBOARD_HILOGW(PASTEBOARD_MODULE_JS_NAPI, "loop instance is nullptr");
121 return;
122 }
123 uv_work_t *work = new (std::nothrow) uv_work_t;
124 if (work == nullptr) {
125 PASTEBOARD_HILOGW(PASTEBOARD_MODULE_JS_NAPI, "work is null");
126 return;
127 }
128 PasteboardDelayWorker *pasteboardDelayWorker = new (std::nothrow) PasteboardDelayWorker();
129 if (pasteboardDelayWorker == nullptr) {
130 PASTEBOARD_HILOGW(PASTEBOARD_MODULE_JS_NAPI, "pasteboardDataWorker is null");
131 delete work;
132 work = nullptr;
133 return;
134 }
135 pasteboardDelayWorker->delayGetter = shared_from_this();
136 pasteboardDelayWorker->dataType = type;
137 work->data = (void *)pasteboardDelayWorker;
138 bool noNeedClean = false;
139 {
140 std::unique_lock<std::mutex> lock(pasteboardDelayWorker->mutex);
141 int ret = uv_queue_work(loop, work, [](uv_work_t *work) {
142 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetUnifiedData callback");
143 }, UvQueueWorkGetDelayPasteData);
144 if (ret != 0) {
145 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "uv_queue_work ret is not 0");
146 ReleasePasteboardResource(&pasteboardDelayWorker, &work);
147 return;
148 }
149 if (pasteboardDelayWorker->cv.wait_for(lock, std::chrono::seconds(DELAY_TIMEOUT),
150 [pasteboardDelayWorker] { return pasteboardDelayWorker->complete; }) &&
151 pasteboardDelayWorker->unifiedData != nullptr) {
152 data = *(pasteboardDelayWorker->unifiedData);
153 }
154 if (!pasteboardDelayWorker->complete && uv_cancel((uv_req_t*)work) != 0) {
155 pasteboardDelayWorker->clean = true;
156 noNeedClean = true;
157 }
158 }
159 if (!noNeedClean) {
160 ReleasePasteboardResource(&pasteboardDelayWorker, &work);
161 }
162 }
163
CheckArgsOfOnAndOff(napi_env env,bool checkArgsCount,napi_value * argv,size_t argc)164 bool SystemPasteboardNapi::CheckArgsOfOnAndOff(napi_env env, bool checkArgsCount, napi_value *argv, size_t argc)
165 {
166 if (!CheckExpression(
167 env, checkArgsCount, JSErrorCode::INVALID_PARAMETERS, "Parameter error. The number of arguments is wrong.") ||
168 !CheckArgsType(env, argv[0], napi_string, "Parameter error. The type of mimeType must be string.")) {
169 return false;
170 }
171 std::string mimeType;
172 bool ret = GetValue(env, argv[0], mimeType);
173 if (!ret) {
174 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "GetValue failed");
175 return false;
176 }
177 if (!CheckExpression(env, mimeType == STRING_UPDATE, JSErrorCode::INVALID_PARAMETERS,
178 "Parameter error. The value of type must be update")) {
179 return false;
180 }
181 return true;
182 }
183
On(napi_env env,napi_callback_info info)184 napi_value SystemPasteboardNapi::On(napi_env env, napi_callback_info info)
185 {
186 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi on() is called!");
187 napi_value result = nullptr;
188 napi_get_undefined(env, &result);
189
190 size_t argc = MAX_ARGS;
191 napi_value argv[MAX_ARGS] = { 0 };
192 napi_value thisVar = 0;
193 void *data = nullptr;
194 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
195 // on(type: 'update', callback: () => void) has 2 args
196 if (!CheckArgsOfOnAndOff(env, argc >= 2, argv, argc) ||
197 !CheckArgsType(env, argv[1], napi_function, "Parameter error. The type of callback must be function.")) {
198 return result;
199 }
200
201 napi_value jsCallback = argv[1];
202 auto observer = GetObserver(env, jsCallback);
203 PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(observer == nullptr, result, PASTEBOARD_MODULE_JS_NAPI, "observer exist");
204
205 AddObserver(env, jsCallback);
206 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi on() is end!");
207 return result;
208 }
209
Off(napi_env env,napi_callback_info info)210 napi_value SystemPasteboardNapi::Off(napi_env env, napi_callback_info info)
211 {
212 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi off () is called!");
213 napi_value result = nullptr;
214 napi_get_undefined(env, &result);
215
216 size_t argc = MAX_ARGS;
217 napi_value argv[MAX_ARGS] = { 0 };
218 napi_value thisVar = 0;
219 void *data = nullptr;
220 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
221 // off(type: 'update', callback?: () => void) has at least 1 arg
222 if (!CheckArgsOfOnAndOff(env, argc >= 1, argv, argc)) {
223 return result;
224 }
225
226 sptr<PasteboardObserverInstance> observer = nullptr;
227 // 1: is the observer parameter
228 if (argc > 1) {
229 if (!CheckArgsType(env, argv[1], napi_function, "Parameter error. The type of callback must be function.")) {
230 return result;
231 }
232 observer = GetObserver(env, argv[1]);
233 PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(observer != nullptr, result,
234 PASTEBOARD_MODULE_JS_NAPI, "observer not find");
235 }
236
237 DeleteObserver(env, observer);
238 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi off () is called!");
239 return result;
240 }
241
Clear(napi_env env,napi_callback_info info)242 napi_value SystemPasteboardNapi::Clear(napi_env env, napi_callback_info info)
243 {
244 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "Clear is called!");
245 auto context = std::make_shared<AsyncCall::Context>();
246 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
247 // clear has 0 or 1 args
248 if (argc > 0 &&
249 !CheckArgsType(env, argv[0], napi_function, "Parameter error. The type of callback must be function.")) {
250 return napi_invalid_arg;
251 }
252 return napi_ok;
253 };
254 auto exec = [context](AsyncCall::Context *ctx) {
255 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "exec Clear");
256 PasteboardClient::GetInstance()->Clear();
257 };
258 context->SetAction(std::move(input));
259 // 0: the AsyncCall at the first position;
260 AsyncCall asyncCall(env, info, context, 0);
261 return asyncCall.Call(env, exec);
262 }
263
ClearData(napi_env env,napi_callback_info info)264 napi_value SystemPasteboardNapi::ClearData(napi_env env, napi_callback_info info)
265 {
266 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "ClearData is called!");
267 return Clear(env, info);
268 }
269
HasPasteData(napi_env env,napi_callback_info info)270 napi_value SystemPasteboardNapi::HasPasteData(napi_env env, napi_callback_info info)
271 {
272 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "HasPasteData is called!");
273 auto context = std::make_shared<HasContextInfo>();
274 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
275 // hasPasteData has 0 or 1 args
276 if (argc > 0 &&
277 !CheckArgsType(env, argv[0], napi_function, "Parameter error. The type of callback must be function.")) {
278 return napi_invalid_arg;
279 }
280 return napi_ok;
281 };
282 auto output = [context](napi_env env, napi_value *result) -> napi_status {
283 napi_status status = napi_get_boolean(env, context->hasPasteData, result);
284 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "napi_get_boolean status = %{public}d", status);
285 return status;
286 };
287 auto exec = [context](AsyncCall::Context *ctx) {
288 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "exec HasPasteData");
289 context->hasPasteData = PasteboardClient::GetInstance()->HasPasteData();
290 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "HasPasteData result = %{public}d", context->hasPasteData);
291 context->status = napi_ok;
292 };
293 context->SetAction(std::move(input), std::move(output));
294 // 0: the AsyncCall at the first position;
295 AsyncCall asyncCall(env, info, context, 0);
296 return asyncCall.Call(env, exec);
297 }
298
HasData(napi_env env,napi_callback_info info)299 napi_value SystemPasteboardNapi::HasData(napi_env env, napi_callback_info info)
300 {
301 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "HasData is called!");
302 return HasPasteData(env, info);
303 }
304
GetDataCommon(std::shared_ptr<GetContextInfo> & context)305 void SystemPasteboardNapi::GetDataCommon(std::shared_ptr<GetContextInfo> &context)
306 {
307 auto input = [](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
308 // 1: GetPasteData has 0 or 1 args
309 if (argc > 0 &&
310 !CheckArgsType(env, argv[0], napi_function, "Parameter error. The type of callback must be function.")) {
311 return napi_invalid_arg;
312 }
313 return napi_ok;
314 };
315
316 auto output = [context](napi_env env, napi_value *result) -> napi_status {
317 napi_value instance = nullptr;
318 napi_status status = PasteDataNapi::NewInstance(env, instance);
319 if (status != napi_ok) {
320 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "NewInstance failed");
321 return status;
322 }
323 PasteDataNapi *obj = nullptr;
324 napi_status ret = napi_unwrap(env, instance, reinterpret_cast<void **>(&obj));
325 if ((ret == napi_ok) && (obj != nullptr)) {
326 obj->value_ = context->pasteData;
327 } else {
328 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "obj is null or ret not ok");
329 return napi_generic_failure;
330 }
331 *result = instance;
332 return napi_ok;
333 };
334 context->SetAction(std::move(input), std::move(output));
335 }
336
GetPasteData(napi_env env,napi_callback_info info)337 napi_value SystemPasteboardNapi::GetPasteData(napi_env env, napi_callback_info info)
338 {
339 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetPasteData is called!");
340
341 auto context = std::make_shared<GetContextInfo>();
342 context->pasteData = std::make_shared<PasteData>();
343 GetDataCommon(context);
344
345 auto exec = [context](AsyncCall::Context *ctx) {
346 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetPasteData Begin");
347 PasteboardClient::GetInstance()->GetPasteData(*context->pasteData);
348 context->status = napi_ok;
349 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetPasteData End");
350 };
351
352 // 0: the AsyncCall at the first position;
353 AsyncCall asyncCall(env, info, context, 0);
354 return asyncCall.Call(env, exec);
355 }
356
GetData(napi_env env,napi_callback_info info)357 napi_value SystemPasteboardNapi::GetData(napi_env env, napi_callback_info info)
358 {
359 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetData is called!");
360 std::shared_ptr<DfxAppEvent> processorEvent = std::make_shared<DfxAppEvent>();
361
362 auto context = std::make_shared<GetContextInfo>();
363 context->pasteData = std::make_shared<PasteData>();
364 GetDataCommon(context);
365
366 auto exec = [context, processorEvent](AsyncCall::Context *ctx) {
367 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetData Begin");
368 int32_t ret = PasteboardClient::GetInstance()->GetPasteData(*context->pasteData);
369 if (ret == static_cast<int32_t>(PasteboardError::TASK_PROCESSING)) {
370 context->SetErrInfo(ret, "Another getData is being processed");
371 } else {
372 context->status = napi_ok;
373 }
374 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetData End");
375 PASTEBOARD_CHECK_AND_RETURN_LOGE(processorEvent != nullptr, PASTEBOARD_MODULE_JS_NAPI,
376 "processorEvent is null");
377 processorEvent->SetEvent("getData", ret, ret == static_cast<int32_t>(PasteboardError::E_OK) ?
378 EventReportResult::EVENT_REPORT_SUCCESS : EventReportResult::EVENT_REPORT_FAIL);
379 };
380 // 0: the AsyncCall at the first position;
381 AsyncCall asyncCall(env, info, context, 0);
382 return asyncCall.Call(env, exec);
383 }
384
SetDataCommon(std::shared_ptr<SetContextInfo> & context)385 void SystemPasteboardNapi::SetDataCommon(std::shared_ptr<SetContextInfo> &context)
386 {
387 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
388 // setData has 1 or 2 args
389 if (!CheckExpression(
390 env, argc > 0, JSErrorCode::INVALID_PARAMETERS,
391 "Parameter error. The number of arguments must be greater than zero.") ||
392 !CheckExpression(env, PasteDataNapi::IsPasteData(env, argv[0]), JSErrorCode::INVALID_PARAMETERS,
393 "Parameter error. The Type of data must be pasteData.")) {
394 return napi_invalid_arg;
395 }
396 if (argc > 1 &&
397 !CheckArgsType(env, argv[1], napi_function, "Parameter error. The type of callback must be function.")) {
398 return napi_invalid_arg;
399 }
400 PasteDataNapi *pasteData = nullptr;
401 napi_unwrap(env, argv[0], reinterpret_cast<void **>(&pasteData));
402 if (pasteData != nullptr) {
403 context->obj = pasteData->value_;
404 }
405 return napi_ok;
406 };
407 context->SetAction(std::move(input));
408 }
409
SetPasteData(napi_env env,napi_callback_info info)410 napi_value SystemPasteboardNapi::SetPasteData(napi_env env, napi_callback_info info)
411 {
412 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SetPasteData is called!");
413 auto context = std::make_shared<SetContextInfo>();
414 SetDataCommon(context);
415
416 auto exec = [context](AsyncCall::Context *ctx) {
417 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "exec SetPasteData");
418 if (context->obj != nullptr) {
419 PasteboardClient::GetInstance()->SetPasteData(*(context->obj));
420 context->obj = nullptr;
421 }
422 context->status = napi_ok;
423 };
424 // 1: the AsyncCall at the second position
425 AsyncCall asyncCall(env, info, context, 1);
426 return asyncCall.Call(env, exec);
427 }
428
SetData(napi_env env,napi_callback_info info)429 napi_value SystemPasteboardNapi::SetData(napi_env env, napi_callback_info info)
430 {
431 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SetData is called!");
432 std::shared_ptr<DfxAppEvent> processorEvent = std::make_shared<DfxAppEvent>();
433 auto context = std::make_shared<SetContextInfo>();
434 SetDataCommon(context);
435
436 auto exec = [context, processorEvent](AsyncCall::Context *ctx) {
437 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "exec SetPasteData");
438 int32_t ret = static_cast<int32_t>(PasteboardError::INVALID_DATA_ERROR);
439 if (context->obj != nullptr) {
440 std::map<uint32_t, std::shared_ptr<UDMF::EntryGetter>> entryGetters;
441 for (auto record : context->obj->AllRecords()) {
442 if (record != nullptr && record->GetEntryGetter() != nullptr) {
443 entryGetters.emplace(record->GetRecordId(), record->GetEntryGetter());
444 }
445 }
446 ret = PasteboardClient::GetInstance()->SetPasteData(*(context->obj), nullptr, entryGetters);
447 context->obj = nullptr;
448 }
449 if (ret == static_cast<int32_t>(PasteboardError::E_OK)) {
450 context->status = napi_ok;
451 } else if (ret == static_cast<int32_t>(PasteboardError::PROHIBIT_COPY)) {
452 context->SetErrInfo(ret, "The system prohibits copying");
453 } else if (ret == static_cast<int32_t>(PasteboardError::TASK_PROCESSING)) {
454 context->SetErrInfo(ret, "Another setData is being processed");
455 }
456 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "exec context->status[%{public}d]", context->status);
457 PASTEBOARD_CHECK_AND_RETURN_LOGE(processorEvent != nullptr, PASTEBOARD_MODULE_JS_NAPI,
458 "processorEvent is null");
459 processorEvent->SetEvent("setData", ret, ret == static_cast<int32_t>(PasteboardError::E_OK) ?
460 EventReportResult::EVENT_REPORT_SUCCESS : EventReportResult::EVENT_REPORT_FAIL);
461 };
462 // 1: the AsyncCall at the second position
463 AsyncCall asyncCall(env, info, context, 1);
464 return asyncCall.Call(env, exec);
465 }
466
SetUnifiedData(napi_env env,napi_callback_info info)467 napi_value SystemPasteboardNapi::SetUnifiedData(napi_env env, napi_callback_info info)
468 {
469 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SetUnifiedData is called!");
470 std::shared_ptr<DfxAppEvent> processorEvent = std::make_shared<DfxAppEvent>();
471 auto context = std::make_shared<SetUnifiedContextInfo>();
472 SetDataCommon(context);
473
474 auto exec = [context, processorEvent](AsyncCall::Context* ctx) {
475 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "exec SetPasteData");
476 int32_t ret = static_cast<int32_t>(PasteboardError::INVALID_DATA_ERROR);
477 if (context->obj != nullptr) {
478 if (context->isDelay && context->delayGetter != nullptr && context->delayGetter->GetStub() != nullptr) {
479 ret = PasteboardClient::GetInstance()->SetUnifiedData(*(context->obj), context->delayGetter->GetStub());
480 } else {
481 ret = PasteboardClient::GetInstance()->SetUnifiedData(*(context->obj));
482 }
483 context->obj = nullptr;
484 }
485 if (ret == static_cast<int32_t>(PasteboardError::E_OK)) {
486 context->status = napi_ok;
487 } else if (ret == static_cast<int32_t>(PasteboardError::PROHIBIT_COPY)) {
488 context->SetErrInfo(ret, "The system prohibits copying");
489 } else if (ret == static_cast<int32_t>(PasteboardError::TASK_PROCESSING)) {
490 context->SetErrInfo(ret, "Another setData is being processed");
491 }
492 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "exec context->status[%{public}d]", context->status);
493 PASTEBOARD_CHECK_AND_RETURN_LOGE(processorEvent != nullptr, PASTEBOARD_MODULE_JS_NAPI,
494 "processorEvent is null");
495 processorEvent->SetEvent("setUnifiedData", ret, ret == static_cast<int32_t>(PasteboardError::E_OK) ?
496 EventReportResult::EVENT_REPORT_SUCCESS : EventReportResult::EVENT_REPORT_FAIL);
497 };
498 // 1: the AsyncCall at the second position
499 AsyncCall asyncCall(env, info, context, 1);
500 return asyncCall.Call(env, exec);
501 }
502
GetUnifiedData(napi_env env,napi_callback_info info)503 napi_value SystemPasteboardNapi::GetUnifiedData(napi_env env, napi_callback_info info)
504 {
505 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetUnifiedData is called!");
506 std::shared_ptr<DfxAppEvent> processorEvent = std::make_shared<DfxAppEvent>();
507
508 auto context = std::make_shared<GetUnifiedContextInfo>();
509 context->unifiedData = std::make_shared<UDMF::UnifiedData>();
510 GetDataCommon(context);
511
512 auto exec = [context, processorEvent](AsyncCall::Context* ctx) {
513 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetUnifiedData Begin");
514 int32_t ret = PasteboardClient::GetInstance()->GetUnifiedData(*context->unifiedData);
515 if (ret == static_cast<int32_t>(PasteboardError::TASK_PROCESSING)) {
516 context->SetErrInfo(ret, "Another getData is being processed");
517 } else {
518 context->status = napi_ok;
519 }
520 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetUnifiedData End");
521 PASTEBOARD_CHECK_AND_RETURN_LOGE(processorEvent != nullptr, PASTEBOARD_MODULE_JS_NAPI,
522 "processorEvent is null");
523 processorEvent->SetEvent("getUnifiedData", ret, ret == static_cast<int32_t>(PasteboardError::E_OK) ?
524 EventReportResult::EVENT_REPORT_SUCCESS : EventReportResult::EVENT_REPORT_FAIL);
525 };
526 // 0: the AsyncCall at the first position;
527 AsyncCall asyncCall(env, info, context, 0);
528 return asyncCall.Call(env, exec);
529 }
530
GetUnifiedDataSync(napi_env env,napi_callback_info info)531 napi_value SystemPasteboardNapi::GetUnifiedDataSync(napi_env env, napi_callback_info info)
532 {
533 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi GetUnifiedDataSync is called!");
534 std::shared_ptr<DfxAppEvent> processorEvent = std::make_shared<DfxAppEvent>();
535 napi_value instance = nullptr;
536 std::shared_ptr<UDMF::UnifiedData> unifiedData = std::make_shared<UDMF::UnifiedData>();
537
538 NAPI_CALL(env, UDMF::UnifiedDataNapi::NewInstance(env, unifiedData, instance));
539 UDMF::UnifiedDataNapi* obj = nullptr;
540 napi_status status = napi_unwrap(env, instance, reinterpret_cast<void**>(&obj));
541 if ((status != napi_ok) || (obj == nullptr) || obj->value_ == nullptr) {
542 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "GetUnifiedDataSync get obj failed.");
543 processorEvent->SetEvent("getUnifiedDataSync", static_cast<int32_t>(JSErrorCode::INVALID_PARAMETERS),
544 EventReportResult::EVENT_REPORT_FAIL);
545 return nullptr;
546 }
547 auto block = std::make_shared<BlockObject<std::shared_ptr<int32_t>>>(SYNC_TIMEOUT);
548 std::thread thread([block, unifiedData = obj->value_]() mutable {
549 auto ret = PasteboardClient::GetInstance()->GetUnifiedData(*unifiedData);
550 std::shared_ptr<int32_t> value = std::make_shared<int32_t>(ret);
551 block->SetValue(value);
552 });
553 thread.detach();
554 auto value = block->GetValue();
555 if (!CheckExpression(env, value != nullptr, JSErrorCode::REQUEST_TIME_OUT,
556 "Excessive processing time for internal data.")) {
557 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "time out, GetUnifiedDataSync failed.");
558 }
559 int32_t ret = (value != nullptr) ? *value : static_cast<int32_t>(PasteboardError::TIMEOUT_ERROR);
560 processorEvent->SetEvent("getUnifiedDataSync", ret, ret == static_cast<int32_t>(PasteboardError::E_OK) ?
561 EventReportResult::EVENT_REPORT_SUCCESS : EventReportResult::EVENT_REPORT_FAIL);
562 return instance;
563 }
564
SetUnifiedDataSync(napi_env env,napi_callback_info info)565 napi_value SystemPasteboardNapi::SetUnifiedDataSync(napi_env env, napi_callback_info info)
566 {
567 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi SetUnifiedDataSync is called!");
568 std::shared_ptr<DfxAppEvent> processorEvent = std::make_shared<DfxAppEvent>();
569 size_t argc = ARGC_TYPE_SET1;
570 napi_value argv[ARGC_TYPE_SET1] = {0};
571 napi_value thisVar = nullptr;
572
573 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
574 if (!CheckExpression(
575 env, argc > 0, JSErrorCode::INVALID_PARAMETERS, "Parameter error. Wrong number of arguments.")) {
576 processorEvent->SetEvent("setUnifiedDataSync", static_cast<int32_t>(JSErrorCode::INVALID_PARAMETERS),
577 EventReportResult::EVENT_REPORT_FAIL);
578 return nullptr;
579 }
580 UDMF::UnifiedDataNapi* unifiedDataNapi = nullptr;
581 napi_unwrap(env, argv[0], reinterpret_cast<void**>(&unifiedDataNapi));
582 if (!CheckExpression(env, (unifiedDataNapi != nullptr && unifiedDataNapi->value_ != nullptr),
583 JSErrorCode::INVALID_PARAMETERS, "Parameter error. The Type of data must be unifiedData.")) {
584 processorEvent->SetEvent("setUnifiedDataSync", static_cast<int32_t>(JSErrorCode::INVALID_PARAMETERS),
585 EventReportResult::EVENT_REPORT_FAIL);
586 return nullptr;
587 }
588 auto properties = unifiedDataNapi->GetPropertiesNapi(env);
589 bool isDelay = false;
590 std::shared_ptr<PasteboardDelayGetterInstance> delayGetter = nullptr;
591 if (properties != nullptr && properties->delayDataRef_ != nullptr) {
592 delayGetter = std::make_shared<PasteboardDelayGetterInstance>(env, properties->delayDataRef_);
593 delayGetter->GetStub()->SetDelayGetterWrapper(delayGetter);
594 isDelay = true;
595 }
596 auto block = std::make_shared<BlockObject<std::shared_ptr<int32_t>>>(SYNC_TIMEOUT);
597 std::shared_ptr<UDMF::UnifiedData> unifiedData = unifiedDataNapi->value_;
598 std::thread thread([block, unifiedData, isDelay, delayGetter]() mutable {
599 int32_t ret = isDelay ?
600 PasteboardClient::GetInstance()->SetUnifiedData(*unifiedData, delayGetter->GetStub()) :
601 PasteboardClient::GetInstance()->SetUnifiedData(*unifiedData);
602 std::shared_ptr<int32_t> value = std::make_shared<int32_t>(ret);
603 block->SetValue(value);
604 });
605 thread.detach();
606 auto value = block->GetValue();
607 if (!CheckExpression(env, value != nullptr, JSErrorCode::REQUEST_TIME_OUT,
608 "Excessive processing time for internal data.")) {
609 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "time out, SetUnifiedDataSync failed.");
610 processorEvent->SetEvent("setUnifiedDataSync", static_cast<int32_t>(JSErrorCode::REQUEST_TIME_OUT),
611 EventReportResult::EVENT_REPORT_FAIL);
612 return nullptr;
613 }
614 if (*value != static_cast<int32_t>(PasteboardError::E_OK)) {
615 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "operate invalid, SetUnifiedDataSync failed");
616 processorEvent->SetEvent("setUnifiedDataSync", *value, *value == static_cast<int32_t>(PasteboardError::E_OK) ?
617 EventReportResult::EVENT_REPORT_SUCCESS : EventReportResult::EVENT_REPORT_FAIL);
618 return nullptr;
619 }
620 {
621 std::lock_guard<std::mutex> lck(delayMutex_);
622 delayGetter_ = delayGetter;
623 }
624 processorEvent->SetEvent("setUnifiedDataSync", *value, *value == static_cast<int32_t>(PasteboardError::E_OK) ?
625 EventReportResult::EVENT_REPORT_SUCCESS : EventReportResult::EVENT_REPORT_FAIL);
626 return nullptr;
627 }
628
SetAppShareOptions(napi_env env,napi_callback_info info)629 napi_value SystemPasteboardNapi::SetAppShareOptions(napi_env env, napi_callback_info info)
630 {
631 size_t argc = ARGC_TYPE_SET1;
632 napi_value argv[ARGC_TYPE_SET1] = {0};
633 napi_value thisArg = nullptr;
634 void *data = nullptr;
635 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisArg, &data));
636 if (!CheckExpression(env, argc > 0, JSErrorCode::INVALID_PARAMETERS,
637 "Parameter error. Mandatory parameters are left unspecified.")) {
638 return nullptr;
639 }
640 int32_t shareOptions;
641 auto status = napi_get_value_int32(env, argv[0], &shareOptions);
642 if (!CheckExpression(env, status == napi_ok, JSErrorCode::INVALID_PARAMETERS,
643 "Parameter error. Incorrect parameter types.")) {
644 return nullptr;
645 }
646 auto result = PasteboardClient::GetInstance()->SetAppShareOptions(static_cast<ShareOption>(shareOptions));
647 if (!CheckExpression(env, result != static_cast<int32_t>(PasteboardError::INVALID_PARAM_ERROR),
648 JSErrorCode::INVALID_PARAMETERS, "Parameter error. Parameter verification failed.")) {
649 return nullptr;
650 }
651 if (!CheckExpression(env, result != static_cast<int32_t>(PasteboardError::PERMISSION_VERIFICATION_ERROR),
652 JSErrorCode::NO_PERMISSION,
653 "Permission verification failed. A non-permission application calls a API.")) {
654 return nullptr;
655 }
656 if (!CheckExpression(env, result != static_cast<int32_t>(PasteboardError::INVALID_OPERATION_ERROR),
657 JSErrorCode::SETTINGS_ALREADY_EXIST, "Settings already exist.")) {
658 return nullptr;
659 }
660 return nullptr;
661 }
662
RemoveAppShareOptions(napi_env env,napi_callback_info info)663 napi_value SystemPasteboardNapi::RemoveAppShareOptions(napi_env env, napi_callback_info info)
664 {
665 auto result = PasteboardClient::GetInstance()->RemoveAppShareOptions();
666 CheckExpression(env, result != static_cast<int32_t>(PasteboardError::PERMISSION_VERIFICATION_ERROR),
667 JSErrorCode::NO_PERMISSION,
668 "Permission verification failed. A non-permission application calls a API.");
669 return nullptr;
670 }
671
SetDataCommon(std::shared_ptr<SetUnifiedContextInfo> & context)672 void SystemPasteboardNapi::SetDataCommon(std::shared_ptr<SetUnifiedContextInfo>& context)
673 {
674 auto input = [context](napi_env env, size_t argc, napi_value* argv, napi_value self) -> napi_status {
675 // setData has 1 arg
676 if (!CheckExpression(
677 env, argc > 0, JSErrorCode::INVALID_PARAMETERS, "Parameter error. Wrong number of arguments.")) {
678 return napi_invalid_arg;
679 }
680 UDMF::UnifiedDataNapi* unifiedDataNapi = nullptr;
681 context->status = napi_unwrap(env, argv[0], reinterpret_cast<void**>(&unifiedDataNapi));
682 if (!CheckExpression(env, unifiedDataNapi != nullptr,
683 JSErrorCode::INVALID_PARAMETERS, "Parameter error. The Type of data must be unifiedData.")) {
684 return napi_invalid_arg;
685 }
686 context->obj = unifiedDataNapi->value_;
687 auto properties = unifiedDataNapi->GetPropertiesNapi(env);
688 if (properties != nullptr && properties->delayDataRef_ != nullptr) {
689 context->delayGetter = std::make_shared<PasteboardDelayGetterInstance>(env, properties->delayDataRef_);
690 if (context->delayGetter == nullptr || context->delayGetter->GetStub() == nullptr) {
691 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "SetDataCommon delayGetter is null");
692 return napi_invalid_arg;
693 }
694 context->delayGetter->GetStub()->SetDelayGetterWrapper(context->delayGetter);
695 context->isDelay = true;
696 }
697 return napi_ok;
698 };
699 auto output = [context](napi_env env, napi_value *result) -> napi_status {
700 if (context->status == napi_ok) {
701 std::lock_guard<std::mutex> lck(delayMutex_);
702 delayGetter_ = std::move(context->delayGetter);
703 }
704 return napi_ok;
705 };
706 context->SetAction(std::move(input), std::move(output));
707 }
708
GetDataCommon(std::shared_ptr<GetUnifiedContextInfo> & context)709 void SystemPasteboardNapi::GetDataCommon(std::shared_ptr<GetUnifiedContextInfo>& context)
710 {
711 auto input = [](napi_env env, size_t argc, napi_value* argv, napi_value self) -> napi_status {
712 // 1: GetPasteData has 0 or 1 args
713 if (argc > 0 &&
714 !CheckArgsType(env, argv[0], napi_function, "Parameter error. The type of callback must be function.")) {
715 return napi_invalid_arg;
716 }
717 return napi_ok;
718 };
719
720 auto output = [context](napi_env env, napi_value* result) -> napi_status {
721 napi_value instance = nullptr;
722 std::shared_ptr<UDMF::UnifiedData> unifiedData = std::make_shared<UDMF::UnifiedData>();
723 napi_status status = UDMF::UnifiedDataNapi::NewInstance(env, unifiedData, instance);
724 if (status != napi_ok) {
725 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "NewInstance failed");
726 return status;
727 }
728
729 UDMF::UnifiedDataNapi* obj = nullptr;
730 napi_status ret = napi_unwrap(env, instance, reinterpret_cast<void**>(&obj));
731 if ((ret == napi_ok) && (obj != nullptr)) {
732 obj->value_ = context->unifiedData;
733 } else {
734 return napi_generic_failure;
735 }
736 *result = instance;
737 return napi_ok;
738 };
739 context->SetAction(std::move(input), std::move(output));
740 }
741
IsRemoteData(napi_env env,napi_callback_info info)742 napi_value SystemPasteboardNapi::IsRemoteData(napi_env env, napi_callback_info info)
743 {
744 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi IsRemoteData() is called!");
745 auto block = std::make_shared<BlockObject<std::shared_ptr<int32_t>>>(SYNC_TIMEOUT);
746 std::thread thread([block]() {
747 auto ret = PasteboardClient::GetInstance()->IsRemoteData();
748 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "value=%{public}d", ret);
749 std::shared_ptr<int32_t> value = std::make_shared<int32_t>(static_cast<int32_t>(ret));
750 block->SetValue(value);
751 });
752 thread.detach();
753 auto value = block->GetValue();
754 if (!CheckExpression(env, value != nullptr, JSErrorCode::REQUEST_TIME_OUT,
755 "Excessive processing time for internal data.")) {
756 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "time out, IsRemoteData failed.");
757 return nullptr;
758 }
759 napi_value result = nullptr;
760 napi_get_boolean(env, *value, &result);
761 return result;
762 }
763
GetDataSource(napi_env env,napi_callback_info info)764 napi_value SystemPasteboardNapi::GetDataSource(napi_env env, napi_callback_info info)
765 {
766 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi GetDataSource() is called!");
767 std::string bundleName;
768 auto block = std::make_shared<BlockObject<std::shared_ptr<int32_t>>>(SYNC_TIMEOUT);
769 std::thread thread([block, &bundleName]() mutable {
770 auto ret = PasteboardClient::GetInstance()->GetDataSource(bundleName);
771 std::shared_ptr<int32_t> value = std::make_shared<int32_t>(ret);
772 block->SetValue(value);
773 });
774 thread.detach();
775 auto value = block->GetValue();
776 if (!CheckExpression(env, value != nullptr, JSErrorCode::REQUEST_TIME_OUT,
777 "Excessive processing time for internal data.")) {
778 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "time out, GetDataSource failed.");
779 return nullptr;
780 }
781
782 if (*value != static_cast<int32_t>(PasteboardError::E_OK)) {
783 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "GetDataSource, failed, ret = %{public}d", *value);
784 return nullptr;
785 }
786 napi_value result = nullptr;
787 napi_create_string_utf8(env, bundleName.c_str(), NAPI_AUTO_LENGTH, &result);
788 return result;
789 }
790
GetMimeTypes(napi_env env,napi_callback_info info)791 napi_value SystemPasteboardNapi::GetMimeTypes(napi_env env, napi_callback_info info)
792 {
793 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi GetMimeTypes() is called!");
794 auto context = std::make_shared<GetMimeTypesContextInfo>();
795 auto input = [](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
796 if (argc > 0 &&
797 !CheckArgsType(env, argv[0], napi_function, "Parameter error. The type of callback must be function.")) {
798 return napi_invalid_arg;
799 }
800 return napi_ok;
801 };
802 auto output = [context](napi_env env, napi_value *result) -> napi_status {
803 napi_status status = NapiDataUtils::SetValue(env, context->mimeTypes, *result);
804 return status;
805 };
806 auto exec = [context](AsyncCall::Context *ctx) {
807 context->mimeTypes = PasteboardClient::GetInstance()->GetMimeTypes();
808 context->status = napi_ok;
809 };
810 context->SetAction(std::move(input), std::move(output));
811 AsyncCall asyncCall(env, info, context, 1);
812 return asyncCall.Call(env, exec);
813 }
814
GetChangeCount(napi_env env,napi_callback_info info)815 napi_value SystemPasteboardNapi::GetChangeCount(napi_env env, napi_callback_info info)
816 {
817 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi GetChangeCount() is called!");
818 uint32_t changeCount = 0;
819 PasteboardClient::GetInstance()->GetChangeCount(changeCount);
820 napi_value result = nullptr;
821 napi_create_uint32(env, changeCount, &result);
822 return result;
823 }
824
HasDataType(napi_env env,napi_callback_info info)825 napi_value SystemPasteboardNapi::HasDataType(napi_env env, napi_callback_info info)
826 {
827 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi HasDataType() is called!");
828 size_t argc = ARGC_TYPE_SET1;
829 napi_value argv[ARGC_TYPE_SET1] = {0};
830 napi_value thisVar = nullptr;
831
832 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
833 if ((!CheckExpression(env, argc >= ARGC_TYPE_SET1, JSErrorCode::INVALID_PARAMETERS,
834 "Parameter error. The number of arguments must be grater than zero.")) ||
835 (!CheckArgsType(env, argv[0], napi_string, "Parameter error. The type of mimeType must be string."))) {
836 return nullptr;
837 }
838
839 std::string mimeType;
840 if (!GetValue(env, argv[0], mimeType)) {
841 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to GetValue!");
842 return nullptr;
843 }
844 auto block = std::make_shared<BlockObject<std::shared_ptr<int32_t>>>(SYNC_TIMEOUT);
845 ffrt::submit([block, mimeType]() {
846 auto ret = PasteboardClient::GetInstance()->HasDataType(mimeType);
847 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "ret = %{public}d", ret);
848 std::shared_ptr<int32_t> value = std::make_shared<int32_t>(static_cast<int32_t>(ret));
849 block->SetValue(value);
850 }, {}, {}, ffrt::task_attr().qos(static_cast<int32_t>(ffrt::qos_user_interactive)));
851 auto value = block->GetValue();
852 if (!CheckExpression(env, value != nullptr, JSErrorCode::REQUEST_TIME_OUT,
853 "Excessive processing time for internal data.")) {
854 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "time out, HasDataType failed.");
855 return nullptr;
856 }
857 napi_value result = nullptr;
858 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "value = %{public}d", *value);
859 napi_get_boolean(env, *value, &result);
860 return result;
861 }
862
DetectPatterns(napi_env env,napi_callback_info info)863 napi_value SystemPasteboardNapi::DetectPatterns(napi_env env, napi_callback_info info)
864 {
865 auto context = std::make_shared<DetectPatternsContextInfo>();
866 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
867 if (!CheckExpression(env, argc == ARGC_TYPE_SET1, JSErrorCode::INVALID_PARAMETERS,
868 "Parameter error. The number of arguments must be one.")) {
869 return napi_invalid_arg;
870 }
871 bool getValueRes = GetValue(env, argv[0], context->patternsToCheck);
872 if (!CheckExpression(env, getValueRes, JSErrorCode::INVALID_PARAMETERS,
873 "Parameter error. Array<Pattern> expected.")) {
874 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to GetValue.");
875 return napi_invalid_arg;
876 }
877 return napi_ok;
878 };
879 auto output = [context](napi_env env, napi_value *result) -> napi_status {
880 napi_status status = SetValue(env, context->patternsDetect, *result);
881 return status;
882 };
883 auto exec = [context](AsyncCall::Context *ctx) {
884 context->patternsDetect = PasteboardClient::GetInstance()->DetectPatterns(context->patternsToCheck);
885 context->status = napi_ok;
886 };
887 context->SetAction(std::move(input), std::move(output));
888 AsyncCall asyncCall(env, info, context, 1);
889 return asyncCall.Call(env, exec);
890 }
891
ClearDataSync(napi_env env,napi_callback_info info)892 napi_value SystemPasteboardNapi::ClearDataSync(napi_env env, napi_callback_info info)
893 {
894 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi ClearDataSync() is called!");
895 auto block = std::make_shared<BlockObject<std::shared_ptr<int32_t>>>(SYNC_TIMEOUT);
896 std::thread thread([block]() {
897 PasteboardClient::GetInstance()->Clear();
898 std::shared_ptr<int32_t> value = std::make_shared<int32_t>(0);
899 block->SetValue(value);
900 });
901 thread.detach();
902 auto value = block->GetValue();
903 if (!CheckExpression(env, value != nullptr, JSErrorCode::REQUEST_TIME_OUT,
904 "Excessive processing time for internal data.")) {
905 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "time out, ClearDataSync failed.");
906 }
907 return nullptr;
908 }
909
GetDataSync(napi_env env,napi_callback_info info)910 napi_value SystemPasteboardNapi::GetDataSync(napi_env env, napi_callback_info info)
911 {
912 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi GetDataSync() is called!");
913 std::shared_ptr<DfxAppEvent> processorEvent = std::make_shared<DfxAppEvent>();
914 napi_value instance = nullptr;
915 NAPI_CALL(env, PasteDataNapi::NewInstance(env, instance));
916 PasteDataNapi *obj = nullptr;
917 napi_status status = napi_unwrap(env, instance, reinterpret_cast<void **>(&obj));
918 if ((status != napi_ok) || (obj == nullptr) || obj->value_ == nullptr) {
919 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "GetDataSync napi_unwrap failed");
920 processorEvent->SetEvent("getDataSync", static_cast<int32_t>(JSErrorCode::INVALID_PARAMETERS),
921 EventReportResult::EVENT_REPORT_FAIL);
922 return nullptr;
923 }
924 auto block = std::make_shared<BlockObject<std::shared_ptr<int32_t>>>(SYNC_TIMEOUT);
925 std::thread thread([block, pasteData = obj->value_]() mutable {
926 auto ret = PasteboardClient::GetInstance()->GetPasteData(*pasteData);
927 std::shared_ptr<int32_t> value = std::make_shared<int32_t>(ret);
928 block->SetValue(value);
929 });
930 thread.detach();
931 auto value = block->GetValue();
932 if (!CheckExpression(env, value != nullptr, JSErrorCode::REQUEST_TIME_OUT,
933 "Excessive processing time for internal data.")) {
934 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "time out, GetDataSync failed.");
935 }
936 int32_t ret = (value != nullptr) ? *value : static_cast<int32_t>(PasteboardError::TIMEOUT_ERROR);
937 processorEvent->SetEvent("getDataSync", ret, ret == static_cast<int32_t>(PasteboardError::E_OK) ?
938 EventReportResult::EVENT_REPORT_SUCCESS : EventReportResult::EVENT_REPORT_FAIL);
939 return instance;
940 }
941
SetDataSync(napi_env env,napi_callback_info info)942 napi_value SystemPasteboardNapi::SetDataSync(napi_env env, napi_callback_info info)
943 {
944 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi SetDataSync() is called!");
945 std::shared_ptr<DfxAppEvent> processorEvent = std::make_shared<DfxAppEvent>();
946 size_t argc = ARGC_TYPE_SET1;
947 napi_value argv[ARGC_TYPE_SET1] = {0};
948 napi_value thisVar = nullptr;
949
950 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
951 if (!CheckExpression(env, argc > 0, JSErrorCode::INVALID_PARAMETERS,
952 "Parameter error. The number of arguments must be one.") ||
953 !CheckExpression(env, PasteDataNapi::IsPasteData(env, argv[0]), JSErrorCode::INVALID_PARAMETERS,
954 "Parameter error. The Type of data must be pasteData.")) {
955 processorEvent->SetEvent("setDataSync", static_cast<int32_t>(JSErrorCode::INVALID_PARAMETERS),
956 EventReportResult::EVENT_REPORT_FAIL);
957 return nullptr;
958 }
959
960 PasteDataNapi *pasteData = nullptr;
961 napi_unwrap(env, argv[0], reinterpret_cast<void **>(&pasteData));
962 if (pasteData == nullptr || pasteData->value_ == nullptr) {
963 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to GetValue!");
964 processorEvent->SetEvent("setDataSync", static_cast<int32_t>(JSErrorCode::INVALID_PARAMETERS),
965 EventReportResult::EVENT_REPORT_FAIL);
966 return nullptr;
967 }
968 auto block = std::make_shared<BlockObject<std::shared_ptr<int32_t>>>(SYNC_TIMEOUT);
969 std::shared_ptr<PasteData> data = pasteData->value_;
970 std::thread thread([block, data]() {
971 auto ret = PasteboardClient::GetInstance()->SetPasteData(*data);
972 std::shared_ptr<int32_t> value = std::make_shared<int32_t>(ret);
973 block->SetValue(value);
974 });
975 thread.detach();
976 auto value = block->GetValue();
977 if (!CheckExpression(env, value != nullptr, JSErrorCode::REQUEST_TIME_OUT,
978 "Excessive processing time for internal data.")) {
979 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "time out, SetDataSync failed.");
980 processorEvent->SetEvent("setDataSync", static_cast<int32_t>(JSErrorCode::REQUEST_TIME_OUT),
981 EventReportResult::EVENT_REPORT_FAIL);
982 return nullptr;
983 }
984
985 if (*value != static_cast<int32_t>(PasteboardError::E_OK)) {
986 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "operate invalid, SetDataSync failed");
987 processorEvent->SetEvent("setDataSync", *value, EventReportResult::EVENT_REPORT_FAIL);
988 return nullptr;
989 }
990 processorEvent->SetEvent("setDataSync", *value, EventReportResult::EVENT_REPORT_SUCCESS);
991 return nullptr;
992 }
993
HasDataSync(napi_env env,napi_callback_info info)994 napi_value SystemPasteboardNapi::HasDataSync(napi_env env, napi_callback_info info)
995 {
996 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi HasDataSync() is called!");
997 auto block = std::make_shared<BlockObject<std::shared_ptr<int32_t>>>(SYNC_TIMEOUT);
998 std::thread thread([block]() {
999 auto ret = PasteboardClient::GetInstance()->HasPasteData();
1000 std::shared_ptr<int32_t> value = std::make_shared<int32_t>(static_cast<int32_t>(ret));
1001 block->SetValue(value);
1002 });
1003 thread.detach();
1004 auto value = block->GetValue();
1005 if (!CheckExpression(env, value != nullptr, JSErrorCode::REQUEST_TIME_OUT,
1006 "Excessive processing time for internal data.")) {
1007 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "time out, HasDataSync failed.");
1008 return nullptr;
1009 }
1010 napi_value result = nullptr;
1011 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "value=%{public}d", *value);
1012 napi_get_boolean(env, *value, &result);
1013 return result;
1014 }
1015
ProgressNotify(std::shared_ptr<GetDataParams> params)1016 void SystemPasteboardNapi::ProgressNotify(std::shared_ptr<GetDataParams> params)
1017 {
1018 if (params == nullptr) {
1019 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "params is null!");
1020 return;
1021 }
1022
1023 if (params->info == nullptr) {
1024 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "params->info is null!");
1025 return;
1026 }
1027 std::shared_ptr<ProgressListenerFn> listenerFn = nullptr;
1028 std::lock_guard<std::recursive_mutex> lock(listenerMutex_);
1029 auto it = listenerMap_.find("progressNotify");
1030 if (it != listenerMap_.end()) {
1031 listenerFn = it->second;
1032 }
1033
1034 if (listenerFn == nullptr || listenerFn->tsFunction == nullptr) {
1035 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "thread safe function is nullptr!");
1036 return;
1037 }
1038
1039 napi_status status = napi_acquire_threadsafe_function(listenerFn->tsFunction);
1040 if (status != napi_ok) {
1041 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "acquire progressNotify failed!");
1042 return;
1043 }
1044
1045 MiscServices::ProgressInfo *progress = new ProgressInfo();
1046 progress->percentage = params->info->percentage;
1047 status = napi_call_threadsafe_function(listenerFn->tsFunction, static_cast<void *>(progress), napi_tsfn_blocking);
1048 if (status != napi_ok) {
1049 delete progress;
1050 progress = nullptr;
1051 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "call progressNotify failed!");
1052 return;
1053 }
1054
1055 status = napi_release_threadsafe_function(listenerFn->tsFunction, napi_tsfn_release);
1056 if (status != napi_ok) {
1057 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "release progressNotify failed!");
1058 return;
1059 }
1060 }
1061
CallJsProgressNotify(napi_env env,napi_value jsFunction,void * context,void * data)1062 void SystemPasteboardNapi::CallJsProgressNotify(napi_env env, napi_value jsFunction, void *context, void *data)
1063 {
1064 #define AGR_COUNT 1
1065 #define DEVICE_NAME_LEN 512
1066 (void)context;
1067 ProgressInfo *info = (ProgressInfo *)data;
1068 if (info == nullptr) {
1069 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "progressInfo is nullptr!");
1070 return;
1071 }
1072
1073 int progress = info->percentage;
1074 delete info;
1075 info = nullptr;
1076
1077 napi_value percentage;
1078 NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, progress, &percentage));
1079
1080 napi_value progressInfo = nullptr;
1081 NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &progressInfo));
1082 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, progressInfo, "progress", percentage));
1083
1084 napi_value argv[AGR_COUNT] = { progressInfo };
1085 NAPI_CALL_RETURN_VOID(env, napi_call_function(env, NULL, jsFunction, AGR_COUNT, argv, NULL));
1086 }
1087
CreateThreadSafeFunc(napi_env env,const std::shared_ptr<ProgressListenerFn> listenerFn)1088 bool SystemPasteboardNapi::CreateThreadSafeFunc(napi_env env, const std::shared_ptr<ProgressListenerFn> listenerFn)
1089 {
1090 #define MAX_LISTENER_LEN 20
1091 napi_value name = nullptr;
1092 if (listenerFn->jsCallback == nullptr) {
1093 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "jsCallback is null!");
1094 return false;
1095 }
1096
1097 NAPI_CALL_BASE(env, napi_create_string_utf8(env, "progressNotify", MAX_LISTENER_LEN, &name), false);
1098 napi_status status = napi_create_threadsafe_function(env, listenerFn->jsCallback, NULL, name, 0, 1, NULL,
1099 NULL, NULL, CallJsProgressNotify, &listenerFn->tsFunction);
1100 if (status != napi_ok) {
1101 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "create threadsafe failed!");
1102 return false;
1103 }
1104 return true;
1105 }
1106
AddProgressListener(napi_env env,std::shared_ptr<MiscServices::GetDataParams> getDataParam,const std::shared_ptr<ProgressListenerFn> listenerFn)1107 bool SystemPasteboardNapi::AddProgressListener(napi_env env, std::shared_ptr<MiscServices::GetDataParams> getDataParam,
1108 const std::shared_ptr<ProgressListenerFn> listenerFn)
1109 {
1110 std::lock_guard<std::recursive_mutex> lock(listenerMutex_);
1111 auto it = listenerMap_.find("progressNotify");
1112 if (it == listenerMap_.end()) {
1113 listenerMap_.insert({ "progressNotify", listenerFn });
1114 }
1115
1116 if (!CreateThreadSafeFunc(env, listenerFn)) {
1117 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "CreateThreadSafeFunc failed!");
1118 listenerMap_.erase("progressNotify");
1119 return false;
1120 }
1121
1122 getDataParam->listener.ProgressNotify = ProgressNotify;
1123 return true;
1124 }
1125
CheckParamsType(napi_env env,napi_value in,napi_valuetype expectedType)1126 bool SystemPasteboardNapi::CheckParamsType(napi_env env, napi_value in, napi_valuetype expectedType)
1127 {
1128 napi_valuetype type = napi_undefined;
1129 NAPI_CALL_BASE(env, napi_typeof(env, in, &type), false);
1130 if (type != expectedType) {
1131 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "invalid parameters!");
1132 return false;
1133 }
1134 return true;
1135 }
1136
ParseJsGetDataWithProgress(napi_env env,napi_value in,std::shared_ptr<MiscServices::GetDataParams> & getDataParam)1137 bool SystemPasteboardNapi::ParseJsGetDataWithProgress(napi_env env, napi_value in,
1138 std::shared_ptr<MiscServices::GetDataParams> &getDataParam)
1139 {
1140 #define MAX_DESTURI_LEN 250
1141 napi_value destUri = nullptr;
1142 NAPI_CALL_BASE(env, napi_get_named_property(env, in, "destUri", &destUri), false);
1143 if (CheckParamsType(env, destUri, napi_string)) {
1144 size_t destUriLen = 0;
1145 NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, destUri, nullptr, 0, &destUriLen), false);
1146 if (destUriLen <= 0 || destUriLen > MAX_DESTURI_LEN) {
1147 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "destUriLen check failed!");
1148 return false;
1149 }
1150 char *uri = (char *)malloc(destUriLen + 1);
1151 if (uri == nullptr) {
1152 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "malloc failed, uri is nullptr.");
1153 return false;
1154 }
1155 NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, destUri, uri, destUriLen + 1, &destUriLen), false);
1156 getDataParam->destUri = uri;
1157 free(uri);
1158 }
1159 napi_value fileConflictOption;
1160 NAPI_CALL_BASE(env, napi_get_named_property(env, in, "fileConflictOptions", &fileConflictOption), false);
1161 getDataParam->fileConflictOption = FILE_OVERWRITE;
1162 if (CheckParamsType(env, fileConflictOption, napi_number)) {
1163 NAPI_CALL_BASE(env, napi_get_value_int32(env, fileConflictOption,
1164 reinterpret_cast<int *>(&getDataParam->fileConflictOption)), false);
1165 }
1166 napi_value progressIndicator;
1167 NAPI_CALL_BASE(env, napi_get_named_property(env, in, "progressIndicator", &progressIndicator), false);
1168 NAPI_CALL_BASE(env, napi_get_value_int32(env, progressIndicator,
1169 reinterpret_cast<int *>(&getDataParam->progressIndicator)), false);
1170
1171 std::shared_ptr<ProgressListenerFn> listenerFn = std::make_shared<ProgressListenerFn>();
1172 NAPI_CALL_BASE(env, napi_get_named_property(env, in, "progressListener", &listenerFn->jsCallback), false);
1173 if (CheckParamsType(env, listenerFn->jsCallback, napi_function)) {
1174 if (!AddProgressListener(env, getDataParam, listenerFn)) {
1175 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "add listener failed!");
1176 return false;
1177 }
1178 }
1179 return true;
1180 }
1181
GetDataWithProgressParam(std::shared_ptr<GetDataParamsContextInfo> & context)1182 void SystemPasteboardNapi::GetDataWithProgressParam(std::shared_ptr<GetDataParamsContextInfo> &context)
1183 {
1184 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
1185 // 1: GetPasteData has 0 or 1 args
1186 if (argc > 0 &&
1187 !CheckArgsType(env, argv[0], napi_object, "Parameter error. The type of object must be function.")) {
1188 return napi_invalid_arg;
1189 }
1190 if (!CheckExpression(env, ParseJsGetDataWithProgress(env, argv[0], context->getDataParams),
1191 JSErrorCode::INVALID_PARAMETERS, "Parameter error. parse param failed!")) {
1192 return napi_invalid_arg;
1193 }
1194 return napi_ok;
1195 };
1196
1197 auto output = [context](napi_env env, napi_value *result) -> napi_status {
1198 napi_value instance = nullptr;
1199 napi_status status = PasteDataNapi::NewInstance(env, instance);
1200 if (status != napi_ok) {
1201 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "NewInstance failed!");
1202 return napi_invalid_arg;
1203 }
1204 PasteDataNapi *obj = nullptr;
1205 napi_status ret = napi_unwrap(env, instance, reinterpret_cast<void **>(&obj));
1206 if ((ret == napi_ok) && (obj != nullptr)) {
1207 obj->value_ = context->pasteData;
1208 } else {
1209 return napi_generic_failure;
1210 }
1211 *result = instance;
1212 return napi_ok;
1213 };
1214 context->SetAction(std::move(input), std::move(output));
1215 }
1216
GetDataWithProgress(napi_env env,napi_callback_info info)1217 napi_value SystemPasteboardNapi::GetDataWithProgress(napi_env env, napi_callback_info info)
1218 {
1219 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetDataWithProgress is called!");
1220 std::shared_ptr<DfxAppEvent> processorEvent = std::make_shared<DfxAppEvent>();
1221
1222 auto context = std::make_shared<GetDataParamsContextInfo>();
1223 context->pasteData = std::make_shared<PasteData>();
1224 context->getDataParams = std::make_shared<GetDataParams>();
1225 GetDataWithProgressParam(context);
1226
1227 auto exec = [context, processorEvent](AsyncCall::Context *ctx) {
1228 context->getDataParams->info = new (std::nothrow)ProgressInfo();
1229 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetDataWithProgress Begin");
1230 int32_t ret = PasteboardClient::GetInstance()->GetDataWithProgress(*context->pasteData,
1231 context->getDataParams);
1232 auto it = ErrorCodeMap.find(PasteboardError(ret));
1233 if (it != ErrorCodeMap.end()) {
1234 context->SetErrInfo(static_cast<int32_t>(it->second.first), it->second.second);
1235 } else {
1236 if (ret != static_cast<int32_t>(PasteboardError::E_OK)) {
1237 context->SetErrInfo(static_cast<int32_t>(JSErrorCode::ERR_GET_DATA_FAILED),
1238 "System error occurred during paste execution.");
1239 } else {
1240 context->status = napi_ok;
1241 }
1242 }
1243 listenerMap_.erase("progressNotify");
1244 if (context->getDataParams->info != nullptr) {
1245 delete context->getDataParams->info;
1246 context->getDataParams->info = nullptr;
1247 }
1248 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetDataWithProgress End");
1249 PASTEBOARD_CHECK_AND_RETURN_LOGE(processorEvent != nullptr, PASTEBOARD_MODULE_JS_NAPI,
1250 "processorEvent is null");
1251 processorEvent->SetEvent("getDataWithProgress", ret, ret == static_cast<int32_t>(PasteboardError::E_OK) ?
1252 EventReportResult::EVENT_REPORT_SUCCESS : EventReportResult::EVENT_REPORT_FAIL);
1253 };
1254 // 0: the AsyncCall at the first position;
1255 AsyncCall asyncCall(env, info, context, 0);
1256 return asyncCall.Call(env, exec);
1257 }
1258
SystemPasteboardInit(napi_env env,napi_value exports)1259 napi_value SystemPasteboardNapi::SystemPasteboardInit(napi_env env, napi_value exports)
1260 {
1261 napi_status status = napi_ok;
1262 napi_property_descriptor descriptors[] = {
1263 DECLARE_NAPI_FUNCTION("on", On),
1264 DECLARE_NAPI_FUNCTION("off", Off),
1265 DECLARE_NAPI_FUNCTION("clear", Clear),
1266 DECLARE_NAPI_FUNCTION("getPasteData", GetPasteData),
1267 DECLARE_NAPI_FUNCTION("hasPasteData", HasPasteData),
1268 DECLARE_NAPI_FUNCTION("setPasteData", SetPasteData),
1269 DECLARE_NAPI_FUNCTION("clearData", ClearData),
1270 DECLARE_NAPI_FUNCTION("getData", GetData),
1271 DECLARE_NAPI_FUNCTION("hasData", HasData),
1272 DECLARE_NAPI_FUNCTION("setData", SetData),
1273 DECLARE_NAPI_FUNCTION("isRemoteData", IsRemoteData),
1274 DECLARE_NAPI_FUNCTION("getDataSource", GetDataSource),
1275 DECLARE_NAPI_FUNCTION("getMimeTypes", GetMimeTypes),
1276 DECLARE_NAPI_FUNCTION("hasDataType", HasDataType),
1277 DECLARE_NAPI_FUNCTION("detectPatterns", DetectPatterns),
1278 DECLARE_NAPI_FUNCTION("clearDataSync", ClearDataSync),
1279 DECLARE_NAPI_FUNCTION("getDataSync", GetDataSync),
1280 DECLARE_NAPI_FUNCTION("hasDataSync", HasDataSync),
1281 DECLARE_NAPI_FUNCTION("setDataSync", SetDataSync),
1282 DECLARE_NAPI_FUNCTION("setUnifiedData", SetUnifiedData),
1283 DECLARE_NAPI_FUNCTION("getUnifiedData", GetUnifiedData),
1284 DECLARE_NAPI_FUNCTION("setUnifiedDataSync", SetUnifiedDataSync),
1285 DECLARE_NAPI_FUNCTION("getUnifiedDataSync", GetUnifiedDataSync),
1286 DECLARE_NAPI_FUNCTION("setAppShareOptions", SetAppShareOptions),
1287 DECLARE_NAPI_FUNCTION("removeAppShareOptions", RemoveAppShareOptions),
1288 DECLARE_NAPI_FUNCTION("getDataWithProgress", GetDataWithProgress),
1289 DECLARE_NAPI_FUNCTION("getChangeCount", GetChangeCount),
1290 };
1291 napi_value constructor;
1292 napi_define_class(env, "SystemPasteboard", NAPI_AUTO_LENGTH, New, nullptr,
1293 sizeof(descriptors) / sizeof(napi_property_descriptor), descriptors, &constructor);
1294 if (status != napi_ok) {
1295 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to define class at SystemPasteboardInit");
1296 return nullptr;
1297 }
1298 napi_create_reference(env, constructor, 1, &g_systemPasteboard);
1299 status = napi_set_named_property(env, exports, "SystemPasteboard", constructor);
1300 if (status != napi_ok) {
1301 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Set property failed when SystemPasteboardInit");
1302 return nullptr;
1303 }
1304 return exports;
1305 }
1306
SystemPasteboardNapi()1307 SystemPasteboardNapi::SystemPasteboardNapi() : env_(nullptr)
1308 {
1309 value_ = std::make_shared<PasteDataNapi>();
1310 }
1311
~SystemPasteboardNapi()1312 SystemPasteboardNapi::~SystemPasteboardNapi()
1313 {
1314 value_ = nullptr;
1315 }
1316
Destructor(napi_env env,void * nativeObject,void * finalize_hint)1317 void SystemPasteboardNapi::Destructor(napi_env env, void *nativeObject, void *finalize_hint)
1318 {
1319 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "Destructor");
1320 (void)nativeObject;
1321 SystemPasteboardNapi *obj = static_cast<SystemPasteboardNapi *>(nativeObject);
1322 delete obj;
1323 }
1324
New(napi_env env,napi_callback_info info)1325 napi_value SystemPasteboardNapi::New(napi_env env, napi_callback_info info)
1326 {
1327 size_t argc = MAX_ARGS;
1328 napi_value argv[MAX_ARGS] = { 0 };
1329 napi_value thisVar = nullptr;
1330 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1331 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "proc.");
1332 // get native object
1333 SystemPasteboardNapi *obj = new (std::nothrow) SystemPasteboardNapi();
1334 if (!obj) {
1335 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "New obj is null");
1336 return nullptr;
1337 }
1338 obj->env_ = env;
1339 ASSERT_CALL(env, napi_wrap(env, thisVar, obj, SystemPasteboardNapi::Destructor,
1340 nullptr, // finalize_hint
1341 nullptr), obj);
1342 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "end.");
1343 return thisVar;
1344 }
1345
NewInstance(napi_env env,napi_value & instance)1346 napi_status SystemPasteboardNapi::NewInstance(napi_env env, napi_value &instance)
1347 {
1348 napi_status status;
1349 if (g_systemPasteboard_instance != nullptr) {
1350 status = napi_get_reference_value(env, g_systemPasteboard_instance, &instance);
1351 if (status != napi_ok) {
1352 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "get instance failed");
1353 return status;
1354 }
1355 return napi_ok;
1356 }
1357
1358 napi_value constructor;
1359 status = napi_get_reference_value(env, g_systemPasteboard, &constructor);
1360 if (status != napi_ok) {
1361 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "get reference failed");
1362 return status;
1363 }
1364
1365 status = napi_new_instance(env, constructor, 0, nullptr, &instance);
1366 if (status != napi_ok) {
1367 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "new instance failed");
1368 return status;
1369 }
1370 napi_create_reference(env, instance, 1, &g_systemPasteboard_instance);
1371 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "new instance ok");
1372
1373 return napi_ok;
1374 }
1375
GetObserver(napi_env env,napi_value jsCallback)1376 sptr<PasteboardObserverInstance> SystemPasteboardNapi::GetObserver(napi_env env, napi_value jsCallback)
1377 {
1378 for (const auto &[refKey, observerValue] : observers_) {
1379 napi_value callback = nullptr;
1380 napi_get_reference_value(env, refKey, &callback);
1381 bool isEqual = false;
1382 napi_strict_equals(env, jsCallback, callback, &isEqual);
1383 if (isEqual) {
1384 return observerValue;
1385 }
1386 }
1387 return nullptr;
1388 }
1389
AddObserver(napi_env env,napi_value jsCallback)1390 void SystemPasteboardNapi::AddObserver(napi_env env, napi_value jsCallback)
1391 {
1392 PasteboardNapiScope scope(env);
1393
1394 napi_value name = nullptr;
1395 napi_status status = napi_create_string_utf8(env, "pasteboardChanged", NAPI_AUTO_LENGTH, &name);
1396 PASTEBOARD_CHECK_AND_RETURN_LOGE(status == napi_ok, PASTEBOARD_MODULE_JS_NAPI,
1397 "create string failed, status=%{public}d", status);
1398
1399 napi_ref ref = nullptr;
1400 status = napi_create_reference(env, jsCallback, 1, &ref);
1401 PASTEBOARD_CHECK_AND_RETURN_LOGE(status == napi_ok, PASTEBOARD_MODULE_JS_NAPI,
1402 "create reference failed, status=%{public}d", status);
1403
1404 napi_threadsafe_function napiCallback = nullptr;
1405 status = napi_create_threadsafe_function(env, jsCallback, nullptr, name, 0, 1, nullptr, nullptr, nullptr,
1406 nullptr, &napiCallback);
1407 if (status != napi_ok) {
1408 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "create callback failed, status=%{public}d", status);
1409 napi_delete_reference(env, ref);
1410 return;
1411 }
1412
1413 auto observer = sptr<PasteboardObserverInstance>::MakeSptr(napiCallback, env);
1414 if (observer == nullptr) {
1415 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "malloc observer failed");
1416 napi_release_threadsafe_function(napiCallback, napi_tsfn_release);
1417 napi_delete_reference(env, ref);
1418 return;
1419 }
1420
1421 bool ret = PasteboardClient::GetInstance()->Subscribe(PasteboardObserverType::OBSERVER_LOCAL, observer);
1422 if (!ret) {
1423 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "subscribe observer failed");
1424 napi_delete_reference(env, ref);
1425 return;
1426 }
1427
1428 observers_[ref] = observer;
1429 }
1430
DeleteObserver(napi_env env,const sptr<PasteboardObserverInstance> & observer)1431 void SystemPasteboardNapi::DeleteObserver(napi_env env, const sptr<PasteboardObserverInstance> &observer)
1432 {
1433 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "observer == null: %{public}d, size: %{public}zu",
1434 observer == nullptr, observers_.size());
1435 std::vector<sptr<PasteboardObserverInstance>> observers;
1436 std::vector<napi_ref> refs;
1437 for (auto it = observers_.begin(); it != observers_.end();) {
1438 if (it->second == observer) {
1439 refs.push_back(it->first);
1440 observers.push_back(observer);
1441 it = observers_.erase(it);
1442 break;
1443 }
1444 if (observer == nullptr) {
1445 refs.push_back(it->first);
1446 observers.push_back(it->second);
1447 it = observers_.erase(it);
1448 } else {
1449 it++;
1450 }
1451 }
1452 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "delete observer size: %{public}zu", observers.size());
1453 for (auto &delObserver : observers) {
1454 PasteboardClient::GetInstance()->Unsubscribe(PasteboardObserverType::OBSERVER_LOCAL, delObserver);
1455 }
1456 for (auto &ref : refs) {
1457 napi_delete_reference(env, ref);
1458 }
1459 }
1460
GetUnifiedData(const std::string & type,UDMF::UnifiedData & data)1461 void PasteboardDelayGetterInstance::PasteboardDelayGetterImpl::GetUnifiedData(
1462 const std::string &type, UDMF::UnifiedData &data)
1463 {
1464 std::shared_ptr<PasteboardDelayGetterInstance> delayGetterInstance(wrapper_.lock());
1465 if (delayGetterInstance == nullptr) {
1466 PASTEBOARD_HILOGW(PASTEBOARD_MODULE_JS_NAPI, "no delay getter");
1467 return;
1468 }
1469 delayGetterInstance->GetUnifiedData(type, data);
1470 }
1471
GetPasteData(const std::string & type,MiscServices::PasteData & data)1472 void PasteboardDelayGetterInstance::PasteboardDelayGetterImpl::GetPasteData(
1473 const std::string &type, MiscServices::PasteData &data)
1474 {
1475 }
1476
SetDelayGetterWrapper(const std::shared_ptr<PasteboardDelayGetterInstance> delayGetterInstance)1477 void PasteboardDelayGetterInstance::PasteboardDelayGetterImpl::SetDelayGetterWrapper(
1478 const std::shared_ptr<PasteboardDelayGetterInstance> delayGetterInstance)
1479 {
1480 wrapper_ = delayGetterInstance;
1481 }
1482 } // namespace MiscServicesNapi
1483 } // namespace OHOS