• 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 "common/block_object.h"
19 #include "napi_common_want.h"
20 #include "pasteboard_common.h"
21 #include "pasteboard_error.h"
22 #include "pasteboard_hilog.h"
23 #include "pasteboard_js_err.h"
24 #include "systempasteboard_napi.h"
25 using namespace OHOS::MiscServices;
26 using namespace OHOS::Media;
27 
28 namespace OHOS {
29 namespace MiscServicesNapi {
30 static thread_local napi_ref g_systemPasteboard = nullptr;
31 static thread_local napi_ref g_systemPasteboard_instance = nullptr;
32 thread_local std::map<napi_ref, std::shared_ptr<PasteboardObserverInstance>> SystemPasteboardNapi::observers_;
33 constexpr size_t MAX_ARGS = 6;
34 const std::string STRING_UPDATE = "update";
PasteboardObserverInstance(const napi_env & env,const napi_ref & ref)35 PasteboardObserverInstance::PasteboardObserverInstance(const napi_env &env, const napi_ref &ref) : env_(env), ref_(ref)
36 {
37     stub_ = new (std::nothrow) PasteboardObserverInstance::PasteboardObserverImpl();
38 }
39 
~PasteboardObserverInstance()40 PasteboardObserverInstance::~PasteboardObserverInstance()
41 {
42     napi_delete_reference(env_, ref_);
43 }
44 
GetStub()45 sptr<PasteboardObserverInstance::PasteboardObserverImpl> PasteboardObserverInstance::GetStub()
46 {
47     return stub_;
48 }
49 
UvQueueWorkOnPasteboardChanged(uv_work_t * work,int status)50 void UvQueueWorkOnPasteboardChanged(uv_work_t *work, int status)
51 {
52     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "UvQueueWorkOnPasteboardChanged start");
53     if (work == nullptr) {
54         return;
55     }
56     PasteboardDataWorker *pasteboardDataWorker = (PasteboardDataWorker *)work->data;
57     if (pasteboardDataWorker == nullptr || pasteboardDataWorker->observer == nullptr) {
58         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "pasteboardDataWorker or ref is null");
59         delete work;
60         work = nullptr;
61         return;
62     }
63 
64     auto env = pasteboardDataWorker->observer->GetEnv();
65     auto ref = pasteboardDataWorker->observer->GetRef();
66 
67     napi_handle_scope scope = nullptr;
68     napi_open_handle_scope(env, &scope);
69     if (scope == nullptr) {
70         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "scope null");
71         return;
72     }
73     napi_value undefined = nullptr;
74     napi_get_undefined(env, &undefined);
75 
76     napi_value callback = nullptr;
77     napi_value resultOut = nullptr;
78     napi_get_reference_value(env, ref, &callback);
79     napi_value result = NapiGetNull(env);
80     napi_call_function(env, undefined, callback, 0, &result, &resultOut);
81 
82     napi_close_handle_scope(env, scope);
83     delete pasteboardDataWorker;
84     pasteboardDataWorker = nullptr;
85     delete work;
86 }
87 
OnPasteboardChanged()88 void PasteboardObserverInstance::OnPasteboardChanged()
89 {
90     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "OnPasteboardChanged is called!");
91     uv_loop_s *loop = nullptr;
92     napi_get_uv_event_loop(env_, &loop);
93     if (loop == nullptr) {
94         PASTEBOARD_HILOGW(PASTEBOARD_MODULE_JS_NAPI, "loop instance is nullptr");
95         return;
96     }
97 
98     uv_work_t *work = new (std::nothrow) uv_work_t;
99     if (work == nullptr) {
100         PASTEBOARD_HILOGW(PASTEBOARD_MODULE_JS_NAPI, "work is null");
101         return;
102     }
103     PasteboardDataWorker *pasteboardDataWorker = new (std::nothrow) PasteboardDataWorker();
104     if (pasteboardDataWorker == nullptr) {
105         PASTEBOARD_HILOGW(PASTEBOARD_MODULE_JS_NAPI, "pasteboardDataWorker is null");
106         delete work;
107         work = nullptr;
108         return;
109     }
110     pasteboardDataWorker->observer = shared_from_this();
111 
112     work->data = (void *)pasteboardDataWorker;
113 
114     int ret = uv_queue_work(
115         loop, work, [](uv_work_t *work) {}, UvQueueWorkOnPasteboardChanged);
116     if (ret != 0) {
117         delete pasteboardDataWorker;
118         pasteboardDataWorker = nullptr;
119         delete work;
120         work = nullptr;
121     }
122     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "OnPasteboardChanged end");
123 }
124 
CheckAgrsOfOnAndOff(napi_env env,bool checkArgsCount,napi_value * argv,size_t argc)125 bool SystemPasteboardNapi::CheckAgrsOfOnAndOff(napi_env env, bool checkArgsCount, napi_value *argv, size_t argc)
126 {
127     if (!CheckExpression(
128         env, checkArgsCount, JSErrorCode::INVALID_PARAMETERS, "Parameter error. Wrong number of arguments.") ||
129         !CheckArgsType(env, argv[0], napi_string, "Parameter error. The type of mimeType must be string.")) {
130         return false;
131     }
132     std::string mimeType;
133     bool ret = GetValue(env, argv[0], mimeType);
134     if (!ret) {
135         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "GetValue failed");
136         return false;
137     }
138     if (!CheckExpression(env, mimeType == STRING_UPDATE, JSErrorCode::INVALID_PARAMETERS,
139         "Parameter error. The value of type must be update")) {
140         return false;
141     }
142     return true;
143 }
144 
On(napi_env env,napi_callback_info info)145 napi_value SystemPasteboardNapi::On(napi_env env, napi_callback_info info)
146 {
147     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi on() is called!");
148     size_t argc = MAX_ARGS;
149     napi_value argv[MAX_ARGS] = { 0 };
150     napi_value thisVar = 0;
151     void *data = nullptr;
152     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
153     // on(type: 'update', callback: () => void) has 2 args
154     if (!CheckAgrsOfOnAndOff(env, argc >= 2, argv, argc) ||
155         !CheckArgsType(env, argv[1], napi_function, "Parameter error. The type of callback must be function.")) {
156         return nullptr;
157     }
158 
159     napi_value result = nullptr;
160     napi_get_undefined(env, &result);
161     auto observer = GetObserver(env, argv[1]);
162     if (observer != nullptr) {
163         PASTEBOARD_HILOGW(PASTEBOARD_MODULE_JS_NAPI, "observer exist.");
164         return result;
165     }
166     napi_ref ref = nullptr;
167     napi_create_reference(env, argv[1], 1, &ref);
168     observer = std::make_shared<PasteboardObserverInstance>(env, ref);
169     observer->GetStub()->SetObserverWrapper(observer);
170     PasteboardClient::GetInstance()->AddPasteboardChangedObserver(observer->GetStub());
171     observers_[ref] = observer;
172     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi on() is end!");
173     return result;
174 }
175 
Off(napi_env env,napi_callback_info info)176 napi_value SystemPasteboardNapi::Off(napi_env env, napi_callback_info info)
177 {
178     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi off () is called!");
179     size_t argc = MAX_ARGS;
180     napi_value argv[MAX_ARGS] = { 0 };
181     napi_value thisVar = 0;
182     void *data = nullptr;
183     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
184     // off(type: 'update', callback?: () => void) has at least 1 arg
185     if (!CheckAgrsOfOnAndOff(env, argc >= 1, argv, argc)) {
186         return nullptr;
187     }
188 
189     std::shared_ptr<PasteboardObserverInstance> observer = nullptr;
190     // 1: is the observer parameter
191     if (argc > 1) {
192         if (!CheckArgsType(env, argv[1], napi_function, "Parameter error. The type of callback must be function.")) {
193             return nullptr;
194         }
195         observer = GetObserver(env, argv[1]);
196     }
197 
198     DeleteObserver(observer);
199     napi_value result = nullptr;
200     napi_get_undefined(env, &result);
201     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi off () is called!");
202     return result;
203 }
204 
Clear(napi_env env,napi_callback_info info)205 napi_value SystemPasteboardNapi::Clear(napi_env env, napi_callback_info info)
206 {
207     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "Clear is called!");
208     auto context = std::make_shared<AsyncCall::Context>();
209     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
210         // clear has 0 or 1 args
211         if (argc > 0 &&
212             !CheckArgsType(env, argv[0], napi_function, "Parameter error. The type of callback must be function.")) {
213             return napi_invalid_arg;
214         }
215         return napi_ok;
216     };
217     auto exec = [context](AsyncCall::Context *ctx) {
218         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "exec Clear");
219         PasteboardClient::GetInstance()->Clear();
220     };
221     context->SetAction(std::move(input));
222     // 0: the AsyncCall at the first position;
223     AsyncCall asyncCall(env, info, context, 0);
224     return asyncCall.Call(env, exec);
225 }
226 
ClearData(napi_env env,napi_callback_info info)227 napi_value SystemPasteboardNapi::ClearData(napi_env env, napi_callback_info info)
228 {
229     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "ClearData is called!");
230     return Clear(env, info);
231 }
232 
HasPasteData(napi_env env,napi_callback_info info)233 napi_value SystemPasteboardNapi::HasPasteData(napi_env env, napi_callback_info info)
234 {
235     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "HasPasteData is called!");
236     auto context = std::make_shared<HasContextInfo>();
237     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
238         // hasPasteData has 0 or 1 args
239         if (argc > 0 &&
240             !CheckArgsType(env, argv[0], napi_function, "Parameter error. The type of callback must be function.")) {
241             return napi_invalid_arg;
242         }
243         return napi_ok;
244     };
245     auto output = [context](napi_env env, napi_value *result) -> napi_status {
246         napi_status status = napi_get_boolean(env, context->hasPasteData, result);
247         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "napi_get_boolean status = %{public}d", status);
248         return status;
249     };
250     auto exec = [context](AsyncCall::Context *ctx) {
251         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "exec HasPasteData");
252         context->hasPasteData = PasteboardClient::GetInstance()->HasPasteData();
253         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "HasPasteData result = %{public}d", context->hasPasteData);
254         context->status = napi_ok;
255     };
256     context->SetAction(std::move(input), std::move(output));
257     // 0: the AsyncCall at the first position;
258     AsyncCall asyncCall(env, info, context, 0);
259     return asyncCall.Call(env, exec);
260 }
261 
HasData(napi_env env,napi_callback_info info)262 napi_value SystemPasteboardNapi::HasData(napi_env env, napi_callback_info info)
263 {
264     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "HasData is called!");
265     return HasPasteData(env, info);
266 }
267 
GetDataCommon(std::shared_ptr<GetContextInfo> & context)268 void SystemPasteboardNapi::GetDataCommon(std::shared_ptr<GetContextInfo> &context)
269 {
270     auto input = [](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
271         // 1: GetPasteData has 0 or 1 args
272         if (argc > 0 &&
273             !CheckArgsType(env, argv[0], napi_function, "Parameter error. The type of callback must be function.")) {
274             return napi_invalid_arg;
275         }
276         return napi_ok;
277     };
278 
279     auto output = [context](napi_env env, napi_value *result) -> napi_status {
280         napi_value instance = nullptr;
281         PasteDataNapi::NewInstance(env, instance);
282         PasteDataNapi *obj = nullptr;
283         napi_status ret = napi_unwrap(env, instance, reinterpret_cast<void **>(&obj));
284         if ((ret == napi_ok) || (obj != nullptr)) {
285             obj->value_ = context->pasteData;
286         } else {
287             return napi_generic_failure;
288         }
289         *result = instance;
290         return napi_ok;
291     };
292     context->SetAction(std::move(input), std::move(output));
293 }
294 
GetPasteData(napi_env env,napi_callback_info info)295 napi_value SystemPasteboardNapi::GetPasteData(napi_env env, napi_callback_info info)
296 {
297     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetPasteData is called!");
298 
299     auto context = std::make_shared<GetContextInfo>();
300     context->pasteData = std::make_shared<PasteData>();
301     GetDataCommon(context);
302 
303     auto exec = [context](AsyncCall::Context *ctx) {
304         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetPasteData Begin");
305         PasteboardClient::GetInstance()->GetPasteData(*context->pasteData);
306         context->status = napi_ok;
307         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetPasteData End");
308     };
309 
310     // 0: the AsyncCall at the first position;
311     AsyncCall asyncCall(env, info, context, 0);
312     return asyncCall.Call(env, exec);
313 }
314 
GetData(napi_env env,napi_callback_info info)315 napi_value SystemPasteboardNapi::GetData(napi_env env, napi_callback_info info)
316 {
317     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetData is called!");
318 
319     auto context = std::make_shared<GetContextInfo>();
320     context->pasteData = std::make_shared<PasteData>();
321     GetDataCommon(context);
322 
323     auto exec = [context](AsyncCall::Context *ctx) {
324         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetData Begin");
325         int32_t ret = PasteboardClient::GetInstance()->GetPasteData(*context->pasteData);
326         if (ret == static_cast<int32_t>(PasteboardError::E_IS_BEGING_PROCESSED)) {
327             context->SetErrInfo(ret, "Another getData is being processed");
328         } else {
329             context->status = napi_ok;
330         }
331         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetData End");
332     };
333     // 0: the AsyncCall at the first position;
334     AsyncCall asyncCall(env, info, context, 0);
335     return asyncCall.Call(env, exec);
336 }
337 
SetDataCommon(std::shared_ptr<SetContextInfo> & context)338 void SystemPasteboardNapi::SetDataCommon(std::shared_ptr<SetContextInfo> &context)
339 {
340     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
341         // setData has 1 or 2 args
342         if (!CheckExpression(
343             env, argc > 0, JSErrorCode::INVALID_PARAMETERS, "Parameter error. Wrong number of arguments.") ||
344             !CheckExpression(env, PasteDataNapi::IsPasteData(env, argv[0]), JSErrorCode::INVALID_PARAMETERS,
345             "Parameter error. The Type of data must be pasteData.")) {
346             return napi_invalid_arg;
347         }
348         if (argc > 1 &&
349             !CheckArgsType(env, argv[1], napi_function, "Parameter error. The type of callback must be function.")) {
350             return napi_invalid_arg;
351         }
352         PasteDataNapi *pasteData = nullptr;
353         napi_unwrap(env, argv[0], reinterpret_cast<void **>(&pasteData));
354         if (pasteData != nullptr) {
355             context->obj = pasteData->value_;
356         }
357         return napi_ok;
358     };
359     context->SetAction(std::move(input));
360 }
361 
SetPasteData(napi_env env,napi_callback_info info)362 napi_value SystemPasteboardNapi::SetPasteData(napi_env env, napi_callback_info info)
363 {
364     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SetPasteData is called!");
365     auto context = std::make_shared<SetContextInfo>();
366     SetDataCommon(context);
367 
368     auto exec = [context](AsyncCall::Context *ctx) {
369         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "exec SetPasteData");
370         if (context->obj != nullptr) {
371             PasteboardClient::GetInstance()->SetPasteData(*(context->obj));
372             context->obj = nullptr;
373         }
374         context->status = napi_ok;
375     };
376     // 1: the AsyncCall at the second position
377     AsyncCall asyncCall(env, info, context, 1);
378     return asyncCall.Call(env, exec);
379 }
380 
SetData(napi_env env,napi_callback_info info)381 napi_value SystemPasteboardNapi::SetData(napi_env env, napi_callback_info info)
382 {
383     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SetData is called!");
384     auto context = std::make_shared<SetContextInfo>();
385     SetDataCommon(context);
386 
387     auto exec = [context](AsyncCall::Context *ctx) {
388         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "exec SetPasteData");
389         int32_t ret = static_cast<int32_t>(PasteboardError::E_ERROR);
390         if (context->obj != nullptr) {
391             ret = PasteboardClient::GetInstance()->SetPasteData(*(context->obj));
392             context->obj = nullptr;
393         }
394         if (ret == static_cast<int>(PasteboardError::E_OK)) {
395             context->status = napi_ok;
396         } else if (ret == static_cast<int>(PasteboardError::E_COPY_FORBIDDEN)) {
397             context->SetErrInfo(ret, "The system prohibits copying");
398         } else if (ret == static_cast<int>(PasteboardError::E_IS_BEGING_PROCESSED)) {
399             context->SetErrInfo(ret, "Another setData is being processed");
400         }
401         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "exec context->status[%{public}d]", context->status);
402     };
403     // 1: the AsyncCall at the second position
404     AsyncCall asyncCall(env, info, context, 1);
405     return asyncCall.Call(env, exec);
406 }
407 
SystemPasteboardInit(napi_env env,napi_value exports)408 napi_value SystemPasteboardNapi::SystemPasteboardInit(napi_env env, napi_value exports)
409 {
410     napi_status status = napi_ok;
411     napi_property_descriptor descriptors[] = {
412         DECLARE_NAPI_FUNCTION("on", On),
413         DECLARE_NAPI_FUNCTION("off", Off),
414         DECLARE_NAPI_FUNCTION("clear", Clear),
415         DECLARE_NAPI_FUNCTION("getPasteData", GetPasteData),
416         DECLARE_NAPI_FUNCTION("hasPasteData", HasPasteData),
417         DECLARE_NAPI_FUNCTION("setPasteData", SetPasteData),
418         DECLARE_NAPI_FUNCTION("clearData", ClearData),
419         DECLARE_NAPI_FUNCTION("getData", GetData),
420         DECLARE_NAPI_FUNCTION("hasData", HasData),
421         DECLARE_NAPI_FUNCTION("setData", SetData),
422     };
423     napi_value constructor;
424     napi_define_class(env, "SystemPasteboard", NAPI_AUTO_LENGTH, New, nullptr,
425         sizeof(descriptors) / sizeof(napi_property_descriptor), descriptors, &constructor);
426     if (status != napi_ok) {
427         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to define class at SystemPasteboardInit");
428         return nullptr;
429     }
430     napi_create_reference(env, constructor, 1, &g_systemPasteboard);
431     status = napi_set_named_property(env, exports, "SystemPasteboard", constructor);
432     if (status != napi_ok) {
433         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Set property failed when SystemPasteboardInit");
434         return nullptr;
435     }
436     return exports;
437 }
438 
SystemPasteboardNapi()439 SystemPasteboardNapi::SystemPasteboardNapi() : env_(nullptr)
440 {
441     value_ = std::make_shared<PasteDataNapi>();
442 }
443 
~SystemPasteboardNapi()444 SystemPasteboardNapi::~SystemPasteboardNapi()
445 {
446 }
447 
Destructor(napi_env env,void * nativeObject,void * finalize_hint)448 void SystemPasteboardNapi::Destructor(napi_env env, void *nativeObject, void *finalize_hint)
449 {
450     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "Destructor");
451     SystemPasteboardNapi *obj = static_cast<SystemPasteboardNapi *>(nativeObject);
452     delete obj;
453 }
454 
New(napi_env env,napi_callback_info info)455 napi_value SystemPasteboardNapi::New(napi_env env, napi_callback_info info)
456 {
457     size_t argc = MAX_ARGS;
458     napi_value argv[MAX_ARGS] = { 0 };
459     napi_value thisVar = nullptr;
460     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
461     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "proc.");
462     // get native object
463     SystemPasteboardNapi *obj = new (std::nothrow) SystemPasteboardNapi();
464     if (!obj) {
465         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "New obj is null");
466         return nullptr;
467     }
468     obj->env_ = env;
469     NAPI_CALL(env, napi_wrap(env, thisVar, obj, SystemPasteboardNapi::Destructor,
470                        nullptr, // finalize_hint
471                        nullptr));
472     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "end.");
473     return thisVar;
474 }
475 
NewInstance(napi_env env,napi_value & instance)476 napi_status SystemPasteboardNapi::NewInstance(napi_env env, napi_value &instance)
477 {
478     napi_status status;
479     if (g_systemPasteboard_instance != nullptr) {
480         status = napi_get_reference_value(env, g_systemPasteboard_instance, &instance);
481         if (status != napi_ok) {
482             PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "get instance failed");
483             return status;
484         }
485         return napi_ok;
486     }
487 
488     napi_value constructor;
489     status = napi_get_reference_value(env, g_systemPasteboard, &constructor);
490     if (status != napi_ok) {
491         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "get reference failed");
492         return status;
493     }
494 
495     status = napi_new_instance(env, constructor, 0, nullptr, &instance);
496     if (status != napi_ok) {
497         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "new instance failed");
498         return status;
499     }
500     napi_create_reference(env, instance, 1, &g_systemPasteboard_instance);
501     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "new instance ok");
502 
503     return napi_ok;
504 }
505 
GetObserver(napi_env env,napi_value observer)506 std::shared_ptr<PasteboardObserverInstance> SystemPasteboardNapi::GetObserver(napi_env env, napi_value observer)
507 {
508     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetObserver start");
509     for (auto &[refKey, observerValue] : observers_) {
510         napi_value callback = nullptr;
511         napi_get_reference_value(env, refKey, &callback);
512         bool isEqual = false;
513         napi_strict_equals(env, observer, callback, &isEqual);
514         if (isEqual) {
515             return observerValue;
516         }
517     }
518     return nullptr;
519 }
520 
DeleteObserver(const std::shared_ptr<PasteboardObserverInstance> & observer)521 void SystemPasteboardNapi::DeleteObserver(const std::shared_ptr<PasteboardObserverInstance> &observer)
522 {
523     PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "observer == null: %{public}d, size: %{public}zu",
524         observer == nullptr, observers_.size());
525     std::vector<std::shared_ptr<PasteboardObserverInstance>> observers;
526     {
527         for (auto it = observers_.begin(); it != observers_.end();) {
528             if (it->second == observer) {
529                 observers.push_back(observer);
530                 observers_.erase(it++);
531                 break;
532             }
533             if (observer == nullptr) {
534                 observers.push_back(it->second);
535                 observers_.erase(it++);
536             } else {
537                 it++;
538             }
539         }
540     }
541     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "delete observer size: %{public}zu", observers.size());
542     for (auto &delObserver : observers) {
543         PasteboardClient::GetInstance()->RemovePasteboardChangedObserver(delObserver->GetStub());
544     }
545 }
546 
OnPasteboardChanged()547 void PasteboardObserverInstance::PasteboardObserverImpl::OnPasteboardChanged()
548 {
549     std::shared_ptr<PasteboardObserverInstance> observerInstance(wrapper_.lock());
550     if (observerInstance == nullptr) {
551         PASTEBOARD_HILOGW(PASTEBOARD_MODULE_JS_NAPI, "expired callback");
552         return;
553     }
554     observerInstance->OnPasteboardChanged();
555 }
556 
SetObserverWrapper(const std::shared_ptr<PasteboardObserverInstance> & observerInstance)557 void PasteboardObserverInstance::PasteboardObserverImpl::SetObserverWrapper(
558     const std::shared_ptr<PasteboardObserverInstance> &observerInstance)
559 {
560     wrapper_ = observerInstance;
561 }
562 } // namespace MiscServicesNapi
563 } // namespace OHOS