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
16 #include "event_agent.h"
17
18 #include "securec.h"
19 #include "utils_log.h"
20
21 namespace OHOS {
22 namespace Storage {
23 namespace DistributedFile {
EventAgent(napi_env env,napi_value thisVar)24 EventAgent::EventAgent(napi_env env, napi_value thisVar)
25 : env_(env), thisVarRef_(nullptr), first_(nullptr), last_(nullptr)
26 {
27 napi_create_reference(env, thisVar, 1, &thisVarRef_);
28 }
29
~EventAgent()30 EventAgent::~EventAgent()
31 {
32 EventListener* temp = nullptr;
33 for (EventListener* iter = first_; iter != nullptr; iter = temp) {
34 temp = iter->next;
35 if (iter == first_) {
36 first_ = first_->next;
37 } else if (iter == last_) {
38 last_ = last_->back;
39 } else {
40 iter->next->back = iter->back;
41 iter->back->next = iter->next;
42 }
43 napi_delete_reference(env_, iter->handlerRef);
44 delete iter;
45 }
46 napi_delete_reference(env_, thisVarRef_);
47 }
48
On(const char * type,napi_value handler)49 void EventAgent::On(const char* type, napi_value handler)
50 {
51 auto tmp = new EventListener();
52
53 LOGD("EventAgent::On: JS callback register.\n");
54 if (strncpy_s(tmp->type, LISTENER_TYPTE_MAX_LENGTH, type, strlen(type)) == -1) {
55 delete tmp;
56 tmp = nullptr;
57 return;
58 }
59
60 if (first_ == nullptr) {
61 first_ = last_ = tmp;
62 } else {
63 last_->next = tmp;
64 last_->next->back = last_;
65 last_ = last_->next;
66 }
67 last_->isOnce = false;
68 napi_create_reference(env_, handler, 1, &last_->handlerRef);
69 }
70
Off(const char * type)71 void EventAgent::Off(const char* type)
72 {
73 EventListener* temp = nullptr;
74 LOGD("EventAgent::Off: JS callback unregister.\n");
75 for (EventListener* eventListener = first_; eventListener != nullptr; eventListener = temp) {
76 temp = eventListener->next;
77 if (strcmp(eventListener->type, type) == 0) {
78 if (eventListener == first_) {
79 first_ = first_->next;
80 } else if (eventListener == last_) {
81 last_ = last_->back;
82 } else {
83 eventListener->next->back = eventListener->back;
84 eventListener->back->next = eventListener->next;
85 }
86 napi_delete_reference(env_, eventListener->handlerRef);
87 delete eventListener;
88 eventListener = nullptr;
89 }
90 }
91 }
92
Emit(const char * type,Event * event)93 void EventAgent::Emit(const char* type, Event* event)
94 {
95 napi_handle_scope scope = nullptr;
96 napi_open_handle_scope(env_, &scope);
97
98 napi_value thisVar = nullptr;
99 napi_get_reference_value(env_, thisVarRef_, &thisVar);
100 for (EventListener* eventListener = first_; eventListener != nullptr; eventListener = eventListener->next) {
101 if (strcmp(eventListener->type, type) == 0) {
102 napi_value jsEvent = event ? event->ToJsObject(env_) : nullptr;
103 napi_value handler = nullptr;
104 napi_value callbackResult = nullptr;
105 napi_value result = nullptr;
106 napi_get_undefined(env_, &result);
107 napi_value callbackValues[2] = {0};
108 callbackValues[0] = result;
109 callbackValues[1] = jsEvent;
110 napi_get_reference_value(env_, eventListener->handlerRef, &handler);
111 napi_call_function(env_, thisVar, handler, std::size(callbackValues), callbackValues, &callbackResult);
112 if (eventListener->isOnce) {
113 Off(type);
114 }
115 }
116 }
117
118 LOGD("EventAgent::Emit: [%{public}s]\n", type);
119 napi_close_handle_scope(env_, scope);
120 }
121
InsertDevice(const std::string & deviceId)122 void EventAgent::InsertDevice(const std::string& deviceId)
123 {
124 if (deviceList_.find(deviceId) == deviceList_.end()) {
125 std::unique_lock<std::mutex> lock(deviceListMut_);
126 deviceList_.insert(deviceId);
127 }
128 }
129
RemoveDevice(const std::string & deviceId)130 void EventAgent::RemoveDevice(const std::string& deviceId)
131 {
132 if (deviceList_.find(deviceId) != deviceList_.end()) {
133 std::unique_lock<std::mutex> lock(deviceListMut_);
134 deviceList_.erase(deviceId);
135 }
136 }
137
FindDevice(const std::string & deviceId)138 bool EventAgent::FindDevice(const std::string& deviceId)
139 {
140 return (deviceList_.find(deviceId) != deviceList_.end());
141 }
142
ClearDevice()143 void EventAgent::ClearDevice()
144 {
145 deviceList_.clear();
146 }
147 } // namespace DistributedFile
148 } // namespace Storage
149 } // namespace OHOS