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