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 return result;
164 }
165 napi_ref ref = nullptr;
166 napi_create_reference(env, argv[1], 1, &ref);
167 observer = std::make_shared<PasteboardObserverInstance>(env, ref);
168 observer->GetStub()->SetObserverWrapper(observer);
169 PasteboardClient::GetInstance()->AddPasteboardChangedObserver(observer->GetStub());
170 observers_[ref] = observer;
171 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi on() is end!");
172 return result;
173 }
174
Off(napi_env env,napi_callback_info info)175 napi_value SystemPasteboardNapi::Off(napi_env env, napi_callback_info info)
176 {
177 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi off () is called!");
178 size_t argc = MAX_ARGS;
179 napi_value argv[MAX_ARGS] = { 0 };
180 napi_value thisVar = 0;
181 void *data = nullptr;
182 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
183 // off(type: 'update', callback?: () => void) has at least 1 arg
184 if (!CheckAgrsOfOnAndOff(env, argc >= 1, argv, argc)) {
185 return nullptr;
186 }
187
188 std::shared_ptr<PasteboardObserverInstance> observer = nullptr;
189 // 1: is the observer parameter
190 if (argc > 1) {
191 if (!CheckArgsType(env, argv[1], napi_function, "Parameter error. The type of callback must be function.")) {
192 return nullptr;
193 }
194 observer = GetObserver(env, argv[1]);
195 }
196
197 DeleteObserver(observer);
198 napi_value result = nullptr;
199 napi_get_undefined(env, &result);
200 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi off () is called!");
201 return result;
202 }
203
Clear(napi_env env,napi_callback_info info)204 napi_value SystemPasteboardNapi::Clear(napi_env env, napi_callback_info info)
205 {
206 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "Clear is called!");
207 auto context = std::make_shared<AsyncCall::Context>();
208 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
209 // clear has 0 or 1 args
210 if (argc > 0
211 && !CheckArgsType(env, argv[0], napi_function, "Parameter error. The type of callback must be function.")) {
212 return napi_invalid_arg;
213 }
214 return napi_ok;
215 };
216 auto exec = [context](AsyncCall::Context *ctx) {
217 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "exec Clear");
218 PasteboardClient::GetInstance()->Clear();
219 };
220 context->SetAction(std::move(input));
221 // 0: the AsyncCall at the first position;
222 AsyncCall asyncCall(env, info, context, 0);
223 return asyncCall.Call(env, exec);
224 }
225
ClearData(napi_env env,napi_callback_info info)226 napi_value SystemPasteboardNapi::ClearData(napi_env env, napi_callback_info info)
227 {
228 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "ClearData is called!");
229 return Clear(env, info);
230 }
231
HasPasteData(napi_env env,napi_callback_info info)232 napi_value SystemPasteboardNapi::HasPasteData(napi_env env, napi_callback_info info)
233 {
234 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "HasPasteData is called!");
235 auto context = std::make_shared<HasContextInfo>();
236 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
237 // hasPasteData has 0 or 1 args
238 if (argc > 0
239 && !CheckArgsType(env, argv[0], napi_function, "Parameter error. The type of callback must be function.")) {
240 return napi_invalid_arg;
241 }
242 return napi_ok;
243 };
244 auto output = [context](napi_env env, napi_value *result) -> napi_status {
245 napi_status status = napi_get_boolean(env, context->hasPasteData, result);
246 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "napi_get_boolean status = %{public}d", status);
247 return status;
248 };
249 auto exec = [context](AsyncCall::Context *ctx) {
250 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "exec HasPasteData");
251 context->hasPasteData = PasteboardClient::GetInstance()->HasPasteData();
252 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "HasPasteData result = %{public}d", context->hasPasteData);
253 context->status = napi_ok;
254 };
255 context->SetAction(std::move(input), std::move(output));
256 // 0: the AsyncCall at the first position;
257 AsyncCall asyncCall(env, info, context, 0);
258 return asyncCall.Call(env, exec);
259 }
260
HasData(napi_env env,napi_callback_info info)261 napi_value SystemPasteboardNapi::HasData(napi_env env, napi_callback_info info)
262 {
263 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "HasData is called!");
264 return HasPasteData(env, info);
265 }
266
GetDataCommon(std::shared_ptr<GetContextInfo> & context)267 void SystemPasteboardNapi::GetDataCommon(std::shared_ptr<GetContextInfo> &context)
268 {
269 auto input = [](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
270 // 1: GetPasteData has 0 or 1 args
271 if (argc > 0
272 && !CheckArgsType(env, argv[0], napi_function, "Parameter error. The type of callback must be function.")) {
273 return napi_invalid_arg;
274 }
275 return napi_ok;
276 };
277
278 auto output = [context](napi_env env, napi_value *result) -> napi_status {
279 napi_value instance = nullptr;
280 PasteDataNapi::NewInstance(env, instance);
281 PasteDataNapi *obj = nullptr;
282 napi_status ret = napi_unwrap(env, instance, reinterpret_cast<void **>(&obj));
283 if ((ret == napi_ok) || (obj != nullptr)) {
284 obj->value_ = context->pasteData;
285 } else {
286 return napi_generic_failure;
287 }
288 *result = instance;
289 return napi_ok;
290 };
291 context->SetAction(std::move(input), std::move(output));
292 }
293
GetPasteData(napi_env env,napi_callback_info info)294 napi_value SystemPasteboardNapi::GetPasteData(napi_env env, napi_callback_info info)
295 {
296 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "GetPasteData is called!");
297
298 auto context = std::make_shared<GetContextInfo>();
299 context->pasteData = std::make_shared<PasteData>();
300 GetDataCommon(context);
301
302 auto exec = [context](AsyncCall::Context *ctx) {
303 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetPasteData Begin");
304 PasteboardClient::GetInstance()->GetPasteData(*context->pasteData);
305 context->status = napi_ok;
306 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetPasteData End");
307 };
308
309 // 0: the AsyncCall at the first position;
310 AsyncCall asyncCall(env, info, context, 0);
311 return asyncCall.Call(env, exec);
312 }
313
GetData(napi_env env,napi_callback_info info)314 napi_value SystemPasteboardNapi::GetData(napi_env env, napi_callback_info info)
315 {
316 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "GetData is called!");
317
318 auto context = std::make_shared<GetContextInfo>();
319 context->pasteData = std::make_shared<PasteData>();
320 GetDataCommon(context);
321
322 auto exec = [context](AsyncCall::Context *ctx) {
323 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetData Begin");
324 int32_t ret = PasteboardClient::GetInstance()->GetPasteData(*context->pasteData);
325 if (ret == static_cast<int32_t>(PasteboardError::E_IS_BEGING_PROCESSED)) {
326 context->SetErrInfo(ret, "Another getData is being processed");
327 } else {
328 context->status = napi_ok;
329 }
330 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetData End");
331 };
332 // 0: the AsyncCall at the first position;
333 AsyncCall asyncCall(env, info, context, 0);
334 return asyncCall.Call(env, exec);
335 }
336
SetDataCommon(std::shared_ptr<SetContextInfo> & context)337 void SystemPasteboardNapi::SetDataCommon(std::shared_ptr<SetContextInfo> &context)
338 {
339 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
340 // setData has 1 or 2 args
341 if (!CheckExpression(
342 env, argc > 0, JSErrorCode::INVALID_PARAMETERS, "Parameter error. Wrong number of arguments.")
343 || !CheckExpression(env, PasteDataNapi::IsPasteData(env, argv[0]), JSErrorCode::INVALID_PARAMETERS,
344 "Parameter error. The Type of data must be pasteData.")) {
345 return napi_invalid_arg;
346 }
347 if (argc > 1
348 && !CheckArgsType(env, argv[1], napi_function, "Parameter error. The type of callback must be function.")) {
349 return napi_invalid_arg;
350 }
351 PasteDataNapi *pasteData = nullptr;
352 napi_unwrap(env, argv[0], reinterpret_cast<void **>(&pasteData));
353 if (pasteData != nullptr) {
354 context->obj = pasteData->value_;
355 }
356 return napi_ok;
357 };
358 context->SetAction(std::move(input));
359 }
360
SetPasteData(napi_env env,napi_callback_info info)361 napi_value SystemPasteboardNapi::SetPasteData(napi_env env, napi_callback_info info)
362 {
363 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "SetPasteData is called!");
364 auto context = std::make_shared<SetContextInfo>();
365 SetDataCommon(context);
366
367 auto exec = [context](AsyncCall::Context *ctx) {
368 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "exec SetPasteData");
369 if (context->obj != nullptr) {
370 PasteboardClient::GetInstance()->SetPasteData(*(context->obj));
371 context->obj = nullptr;
372 }
373 context->status = napi_ok;
374 };
375 // 1: the AsyncCall at the second position
376 AsyncCall asyncCall(env, info, context, 1);
377 return asyncCall.Call(env, exec);
378 }
379
SetData(napi_env env,napi_callback_info info)380 napi_value SystemPasteboardNapi::SetData(napi_env env, napi_callback_info info)
381 {
382 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "SetData is called!");
383 auto context = std::make_shared<SetContextInfo>();
384 SetDataCommon(context);
385
386 auto exec = [context](AsyncCall::Context *ctx) {
387 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "exec SetPasteData");
388 int32_t ret = static_cast<int32_t>(PasteboardError::E_ERROR);
389 if (context->obj != nullptr) {
390 ret = PasteboardClient::GetInstance()->SetPasteData(*(context->obj));
391 context->obj = nullptr;
392 }
393 if (ret == static_cast<int>(PasteboardError::E_OK)) {
394 context->status = napi_ok;
395 } else if (ret == static_cast<int>(PasteboardError::E_COPY_FORBIDDEN)) {
396 context->SetErrInfo(ret, "The system prohibits copying");
397 } else if (ret == static_cast<int>(PasteboardError::E_IS_BEGING_PROCESSED)) {
398 context->SetErrInfo(ret, "Another setData is being processed");
399 }
400 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "exec context->status[%{public}d]", context->status);
401 };
402 // 1: the AsyncCall at the second position
403 AsyncCall asyncCall(env, info, context, 1);
404 return asyncCall.Call(env, exec);
405 }
406
SystemPasteboardInit(napi_env env,napi_value exports)407 napi_value SystemPasteboardNapi::SystemPasteboardInit(napi_env env, napi_value exports)
408 {
409 napi_status status = napi_ok;
410 napi_property_descriptor descriptors[] = {
411 DECLARE_NAPI_FUNCTION("on", On),
412 DECLARE_NAPI_FUNCTION("off", Off),
413 DECLARE_NAPI_FUNCTION("clear", Clear),
414 DECLARE_NAPI_FUNCTION("getPasteData", GetPasteData),
415 DECLARE_NAPI_FUNCTION("hasPasteData", HasPasteData),
416 DECLARE_NAPI_FUNCTION("setPasteData", SetPasteData),
417 DECLARE_NAPI_FUNCTION("clearData", ClearData),
418 DECLARE_NAPI_FUNCTION("getData", GetData),
419 DECLARE_NAPI_FUNCTION("hasData", HasData),
420 DECLARE_NAPI_FUNCTION("setData", SetData),
421 };
422 napi_value constructor;
423 napi_define_class(env, "SystemPasteboard", NAPI_AUTO_LENGTH, New, nullptr,
424 sizeof(descriptors) / sizeof(napi_property_descriptor), descriptors, &constructor);
425 if (status != napi_ok) {
426 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to define class at SystemPasteboardInit");
427 return nullptr;
428 }
429 napi_create_reference(env, constructor, 1, &g_systemPasteboard);
430 status = napi_set_named_property(env, exports, "SystemPasteboard", constructor);
431 if (status != napi_ok) {
432 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Set property failed when SystemPasteboardInit");
433 return nullptr;
434 }
435 return exports;
436 }
437
SystemPasteboardNapi()438 SystemPasteboardNapi::SystemPasteboardNapi() : env_(nullptr), wrapper_(nullptr)
439 {
440 value_ = std::make_shared<PasteDataNapi>();
441 }
442
~SystemPasteboardNapi()443 SystemPasteboardNapi::~SystemPasteboardNapi()
444 {
445 napi_delete_reference(env_, wrapper_);
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 SystemPasteboardNapi *obj = static_cast<SystemPasteboardNapi *>(nativeObject);
451 delete obj;
452 }
453
New(napi_env env,napi_callback_info info)454 napi_value SystemPasteboardNapi::New(napi_env env, napi_callback_info info)
455 {
456 size_t argc = MAX_ARGS;
457 napi_value argv[MAX_ARGS] = { 0 };
458 napi_value thisVar = nullptr;
459 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
460 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "proc.");
461 // get native object
462 SystemPasteboardNapi *obj = new (std::nothrow) SystemPasteboardNapi();
463 if (!obj) {
464 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "New obj is null");
465 return nullptr;
466 }
467 obj->env_ = env;
468 NAPI_CALL(env, napi_wrap(env, thisVar, obj, SystemPasteboardNapi::Destructor,
469 nullptr, // finalize_hint
470 &obj->wrapper_));
471 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "end.");
472 return thisVar;
473 }
474
NewInstance(napi_env env,napi_value & instance)475 napi_status SystemPasteboardNapi::NewInstance(napi_env env, napi_value &instance)
476 {
477 napi_status status;
478
479 napi_value constructor;
480 status = napi_get_reference_value(env, g_systemPasteboard, &constructor);
481 if (status != napi_ok) {
482 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "get reference failed");
483 return status;
484 }
485
486 status = napi_new_instance(env, constructor, 0, nullptr, &instance);
487 if (status != napi_ok) {
488 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "new instance failed");
489 return status;
490 }
491 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "new instance ok");
492
493 return napi_ok;
494 }
495
GetObserver(napi_env env,napi_value observer)496 std::shared_ptr<PasteboardObserverInstance> SystemPasteboardNapi::GetObserver(napi_env env, napi_value observer)
497 {
498 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "GetObserver start");
499 for (auto &[refKey, observerValue] : observers_) {
500 napi_value callback = nullptr;
501 napi_get_reference_value(env, refKey, &callback);
502 bool isEqual = false;
503 napi_strict_equals(env, observer, callback, &isEqual);
504 if (isEqual) {
505 return observerValue;
506 }
507 }
508 return nullptr;
509 }
510
DeleteObserver(const std::shared_ptr<PasteboardObserverInstance> & observer)511 void SystemPasteboardNapi::DeleteObserver(const std::shared_ptr<PasteboardObserverInstance> &observer)
512 {
513 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "observer == null: %{public}d, size: %{public}zu",
514 observer == nullptr, observers_.size());
515 std::vector<std::shared_ptr<PasteboardObserverInstance>> observers;
516 {
517 for (auto it = observers_.begin(); it != observers_.end();) {
518 observers.push_back(it->second);
519 observers_.erase(it++);
520 if (it->second == observer) {
521 break;
522 }
523 }
524 }
525 for (auto &delObserver : observers) {
526 PasteboardClient::GetInstance()->RemovePasteboardChangedObserver(delObserver->GetStub());
527 }
528 }
529
OnPasteboardChanged()530 void PasteboardObserverInstance::PasteboardObserverImpl::OnPasteboardChanged()
531 {
532 std::shared_ptr<PasteboardObserverInstance> observerInstance(wrapper_.lock());
533 if (observerInstance == nullptr) {
534 PASTEBOARD_HILOGW(PASTEBOARD_MODULE_JS_NAPI, "expired callback");
535 return;
536 }
537 observerInstance->OnPasteboardChanged();
538 }
539
SetObserverWrapper(const std::shared_ptr<PasteboardObserverInstance> & observerInstance)540 void PasteboardObserverInstance::PasteboardObserverImpl::SetObserverWrapper(
541 const std::shared_ptr<PasteboardObserverInstance>& observerInstance)
542 {
543 wrapper_ = observerInstance;
544 }
545 } // namespace MiscServicesNapi
546 } // namespace OHOS