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