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