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