1 /*
2  * Copyright (c) 2022-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 
16 #include "dm_native_event.h"
17 
18 #include "dm_log.h"
19 
20 using namespace OHOS::DistributedHardware;
21 
DmNativeEvent(napi_env env, napi_value thisVar)22 DmNativeEvent::DmNativeEvent(napi_env env, napi_value thisVar)
23 {
24     env_ = env;
25     thisVarRef_ = nullptr;
26     napi_create_reference(env, thisVar, 1, &thisVarRef_);
27 }
28 
~DmNativeEvent()29 DmNativeEvent::~DmNativeEvent()
30 {
31     for (auto iter = eventMap_.begin(); iter != eventMap_.end(); iter++) {
32         auto listener = iter->second;
33         if (listener != nullptr) {
34             napi_delete_reference(env_, listener->handlerRef);
35         }
36     }
37     eventMap_.clear();
38     napi_delete_reference(env_, thisVarRef_);
39 }
40 
On(std::string &eventType, napi_value handler)41 void DmNativeEvent::On(std::string &eventType, napi_value handler)
42 {
43     LOGI("DmNativeEvent On in for event: %{public}s", eventType.c_str());
44     std::lock_guard<std::mutex> autoLock(lock_);
45     auto listener = std::make_shared<DmEventListener>();
46     listener->eventType = eventType;
47     napi_create_reference(env_, handler, 1, &listener->handlerRef);
48     eventMap_[eventType] = listener;
49 }
50 
Off(std::string &eventType)51 void DmNativeEvent::Off(std::string &eventType)
52 {
53     LOGI("DmNativeEvent Off in for event: %{public}s", eventType.c_str());
54     napi_handle_scope scope = nullptr;
55     napi_open_handle_scope(env_, &scope);
56     if (scope == nullptr) {
57         LOGE("scope is nullptr");
58         return;
59     }
60 
61     std::lock_guard<std::mutex> autoLock(lock_);
62     auto iter = eventMap_.find(eventType);
63     if (iter == eventMap_.end()) {
64         LOGE("eventType %{public}s not find", eventType.c_str());
65         napi_close_handle_scope(env_, scope);
66         return;
67     }
68     auto listener = iter->second;
69     napi_delete_reference(env_, listener->handlerRef);
70     eventMap_.erase(eventType);
71     napi_close_handle_scope(env_, scope);
72 }
73 
OnEvent(const std::string &eventType, size_t argc, const napi_value *argv)74 void DmNativeEvent::OnEvent(const std::string &eventType, size_t argc, const napi_value *argv)
75 {
76     LOGI("OnEvent for %{public}s", eventType.c_str());
77     napi_handle_scope scope = nullptr;
78     napi_open_handle_scope(env_, &scope);
79     if (scope == nullptr) {
80         LOGE("scope is nullptr");
81         return;
82     }
83 
84     std::lock_guard<std::mutex> autoLock(lock_);
85     auto iter = eventMap_.find(eventType);
86     if (iter == eventMap_.end()) {
87         LOGE("eventType %{public}s not find", eventType.c_str());
88         napi_close_handle_scope(env_, scope);
89         return;
90     }
91     auto listener = iter->second;
92     napi_value thisVar = nullptr;
93     napi_status status = napi_get_reference_value(env_, thisVarRef_, &thisVar);
94     if (status != napi_ok) {
95         LOGE("napi_get_reference_value thisVar for %{public}s failed, status = %{public}d", eventType.c_str(), status);
96         napi_close_handle_scope(env_, scope);
97         return;
98     }
99 
100     napi_value handler = nullptr;
101     status = napi_get_reference_value(env_, listener->handlerRef, &handler);
102     if (status != napi_ok) {
103         LOGE("napi_get_reference_value handler for %{public}s failed, status = %{public}d", eventType.c_str(), status);
104         napi_close_handle_scope(env_, scope);
105         return;
106     }
107 
108     napi_value callResult = nullptr;
109     status = napi_call_function(env_, thisVar, handler, argc, argv, &callResult);
110     if (status != napi_ok) {
111         LOGE("napi_call_function for %{public}s failed, status = %{public}d", eventType.c_str(), status);
112         napi_close_handle_scope(env_, scope);
113         return;
114     }
115     napi_close_handle_scope(env_, scope);
116 }
117