• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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.h"
20 #include "pasteboard_common.h"
21 #include "pasteboard_js_err.h"
22 #include "pasteboard_hilog.h"
23 #include "systempasteboard_napi.h"
24 #include "pasteboard_error.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 thread_local std::map<napi_ref, std::shared_ptr<PasteboardObserverInstance>> SystemPasteboardNapi::observers_;
32 constexpr size_t MAX_ARGS = 6;
33 const std::string STRING_UPDATE = "update";
PasteboardObserverInstance(const napi_env & env,const napi_ref & ref)34 PasteboardObserverInstance::PasteboardObserverInstance(const napi_env &env, const napi_ref &ref)
35     : 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_HILOGI(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_HILOGI(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_HILOGI(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_HILOGI(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_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "work is null");
101         return;
102     }
103     PasteboardDataWorker *pasteboardDataWorker = new (std::nothrow) PasteboardDataWorker();
104     if (pasteboardDataWorker == nullptr) {
105         PASTEBOARD_HILOGI(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_HILOGI(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_HILOGI(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_HILOGI(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_HILOGI(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_HILOGI(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_HILOGI(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_HILOGI(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_HILOGI(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_HILOGI(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_HILOGI(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_HILOGI(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_HILOGI(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_HILOGI(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_HILOGI(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_HILOGI(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), wrapper_(nullptr)
440 {
441     value_ = std::make_shared<PasteDataNapi>();
442 }
443 
~SystemPasteboardNapi()444 SystemPasteboardNapi::~SystemPasteboardNapi()
445 {
446     napi_delete_reference(env_, wrapper_);
447 }
448 
Destructor(napi_env env,void * nativeObject,void * finalize_hint)449 void SystemPasteboardNapi::Destructor(napi_env env, void *nativeObject, void *finalize_hint)
450 {
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                        &obj->wrapper_));
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 
480     napi_value constructor;
481     status = napi_get_reference_value(env, g_systemPasteboard, &constructor);
482     if (status != napi_ok) {
483         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "get reference failed");
484         return status;
485     }
486 
487     status = napi_new_instance(env, constructor, 0, nullptr, &instance);
488     if (status != napi_ok) {
489         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "new instance failed");
490         return status;
491     }
492     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "new instance ok");
493 
494     return napi_ok;
495 }
496 
GetObserver(napi_env env,napi_value observer)497 std::shared_ptr<PasteboardObserverInstance> SystemPasteboardNapi::GetObserver(napi_env env, napi_value observer)
498 {
499     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetObserver start");
500     for (auto &[refKey, observerValue] : observers_) {
501         napi_value callback = nullptr;
502         napi_get_reference_value(env, refKey, &callback);
503         bool isEqual = false;
504         napi_strict_equals(env, observer, callback, &isEqual);
505         if (isEqual) {
506             return observerValue;
507         }
508     }
509     return nullptr;
510 }
511 
DeleteObserver(const std::shared_ptr<PasteboardObserverInstance> & observer)512 void SystemPasteboardNapi::DeleteObserver(const std::shared_ptr<PasteboardObserverInstance> &observer)
513 {
514     PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "observer == null: %{public}d, size: %{public}zu",
515         observer == nullptr, observers_.size());
516     std::vector<std::shared_ptr<PasteboardObserverInstance>> observers;
517     {
518         for (auto it = observers_.begin(); it != observers_.end();) {
519             observers.push_back(it->second);
520             observers_.erase(it++);
521             if (it->second == observer) {
522                 break;
523             }
524         }
525     }
526     for (auto &delObserver : observers) {
527         PasteboardClient::GetInstance()->RemovePasteboardChangedObserver(delObserver->GetStub());
528     }
529 }
530 
OnPasteboardChanged()531 void PasteboardObserverInstance::PasteboardObserverImpl::OnPasteboardChanged()
532 {
533     std::shared_ptr<PasteboardObserverInstance> observerInstance(wrapper_.lock());
534     if (observerInstance == nullptr) {
535         PASTEBOARD_HILOGW(PASTEBOARD_MODULE_JS_NAPI, "expired callback");
536         return;
537     }
538     observerInstance->OnPasteboardChanged();
539 }
540 
SetObserverWrapper(const std::shared_ptr<PasteboardObserverInstance> & observerInstance)541 void PasteboardObserverInstance::PasteboardObserverImpl::SetObserverWrapper(
542     const std::shared_ptr<PasteboardObserverInstance>& observerInstance)
543 {
544     wrapper_ = observerInstance;
545 }
546 } // namespace MiscServicesNapi
547 } // namespace OHOS