• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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