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