1 /*
2 * Copyright (c) 2024 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 "js_ability_connection_session_listener.h"
17
18 #include "dtbcollabmgr_log.h"
19 #include "js_runtime_utils.h"
20 #include "napi_common_util.h"
21 #include "pixel_map_napi.h"
22
23 namespace OHOS {
24 namespace DistributedCollab {
25 using namespace OHOS::AbilityRuntime;
26 namespace {
27 const std::string TAG = "JsAbilityConnectionSessionListener";
28 }
29
SetCallback(const napi_value & jsListenerObj)30 void JsAbilityConnectionSessionListener::SetCallback(const napi_value& jsListenerObj)
31 {
32 HILOGI("called.");
33 napi_ref tempRef = nullptr;
34 std::unique_ptr<NativeReference> callbackRef;
35 if (env_ == nullptr) {
36 HILOGE("env_ is nullptr");
37 return;
38 }
39 napi_create_reference(env_, jsListenerObj, 1, &tempRef);
40 callbackRef.reset(reinterpret_cast<NativeReference *>(tempRef));
41 callbackRef_ = std::move(callbackRef);
42 }
43
CallJsMethod(const EventCallbackInfo & eventCallbackInfo)44 void JsAbilityConnectionSessionListener::CallJsMethod(const EventCallbackInfo& eventCallbackInfo)
45 {
46 CallJsMethodTemplate(eventCallbackInfo);
47 }
48
CallJsMethod(const CollaborateEventInfo & collaborateEventInfo)49 void JsAbilityConnectionSessionListener::CallJsMethod(const CollaborateEventInfo& collaborateEventInfo)
50 {
51 CallJsMethodTemplate(collaborateEventInfo);
52 }
53
54 template <typename T>
CallJsMethodTemplate(const T & callbackInfo)55 void JsAbilityConnectionSessionListener::CallJsMethodTemplate(const T& callbackInfo)
56 {
57 HILOGI("called.");
58 if (env_ == nullptr) {
59 HILOGE("env_ is nullptr");
60 return;
61 }
62
63 auto task = [this, callbackInfo]() {
64 HILOGI("called js method template.");
65 napi_handle_scope scope = nullptr;
66 auto env = this->env_;
67 napi_status result = napi_open_handle_scope(env, &scope);
68 if (result != napi_ok || scope == nullptr) {
69 HILOGE("open handle scope failed!");
70 return;
71 }
72
73 CallJsMethodInner(callbackInfo);
74 result = napi_close_handle_scope(env, scope);
75 if (result != napi_ok) {
76 HILOGE("close handle scope failed!");
77 }
78 HILOGI("end.");
79 };
80 if (napi_status::napi_ok != napi_send_event(env_, task, napi_eprio_vip)) {
81 HILOGE("send event failed!");
82 }
83 }
84
CallJsMethodInner(const EventCallbackInfo & eventCallbackInfo)85 void JsAbilityConnectionSessionListener::CallJsMethodInner(const EventCallbackInfo& eventCallbackInfo)
86 {
87 CallJsMethodInnerTemplate(eventCallbackInfo);
88 }
89
CallJsMethodInner(const CollaborateEventInfo & collaborateEventInfo)90 void JsAbilityConnectionSessionListener::CallJsMethodInner(const CollaborateEventInfo& collaborateEventInfo)
91 {
92 CallJsMethodInnerTemplate(collaborateEventInfo);
93 }
94
95 template <typename T>
CallJsMethodInnerTemplate(const T & callbackInfo)96 void JsAbilityConnectionSessionListener::CallJsMethodInnerTemplate(const T& callbackInfo)
97 {
98 HILOGI("called.");
99 if (callbackRef_ == nullptr) {
100 HILOGE("callbackRef_ is nullptr");
101 return;
102 }
103
104 napi_value method = callbackRef_->GetNapiValue();
105 if (method == nullptr) {
106 HILOGE("Failed to get method from object");
107 return;
108 }
109 napi_value argv[] = { WrapEventCallbackInfo(env_, callbackInfo) };
110 napi_call_function(env_, CreateJsUndefined(env_), method, ArraySize(argv), argv, nullptr);
111 HILOGI("end.");
112 }
113
WrapEventCallbackInfo(napi_env & env,const EventCallbackInfo & eventCallbackInfo)114 napi_value JsAbilityConnectionSessionListener::WrapEventCallbackInfo(napi_env& env,
115 const EventCallbackInfo& eventCallbackInfo)
116 {
117 napi_value jsObject;
118 napi_create_object(env, &jsObject);
119
120 napi_value jsSessionId;
121 napi_create_int32(env, eventCallbackInfo.sessionId, &jsSessionId);
122 napi_set_named_property(env, jsObject, "sessionId", jsSessionId);
123
124 napi_value jsEventType;
125 napi_create_string_utf8(env, eventCallbackInfo.eventType.c_str(), NAPI_AUTO_LENGTH, &jsEventType);
126 napi_set_named_property(env, jsObject, "eventType", jsEventType);
127
128 if (eventCallbackInfo.reason != DisconnectReason::UNKNOW) {
129 napi_value jsReason;
130 napi_create_int32(env, static_cast<int32_t>(eventCallbackInfo.reason), &jsReason);
131 napi_set_named_property(env, jsObject, "reason", jsReason);
132 }
133
134 if (!eventCallbackInfo.msg.empty()) {
135 napi_value jsMsg;
136 napi_create_string_utf8(env, eventCallbackInfo.msg.c_str(), NAPI_AUTO_LENGTH, &jsMsg);
137 napi_set_named_property(env, jsObject, "msg", jsMsg);
138 }
139
140 if (eventCallbackInfo.data != nullptr) {
141 napi_value jsDataBuffer = WrapAVTransDataBuffer(env, eventCallbackInfo.data);
142 napi_set_named_property(env, jsObject, "data", jsDataBuffer);
143 }
144
145 if (eventCallbackInfo.image != nullptr) {
146 napi_value jsPixelMap = Media::PixelMapNapi::CreatePixelMap(env, eventCallbackInfo.image);
147 napi_set_named_property(env, jsObject, "image", jsPixelMap);
148 }
149 return jsObject;
150 }
151
WrapEventCallbackInfo(napi_env & env,const CollaborateEventInfo & collaborateEventInfo)152 napi_value JsAbilityConnectionSessionListener::WrapEventCallbackInfo(napi_env& env,
153 const CollaborateEventInfo& collaborateEventInfo)
154 {
155 napi_value jsCallbackInfo;
156 napi_create_object(env, &jsCallbackInfo);
157
158 napi_value jsSessionId;
159 napi_create_int32(env, collaborateEventInfo.sessionId, &jsSessionId);
160 napi_set_named_property(env, jsCallbackInfo, "sessionId", jsSessionId);
161
162 napi_value jsEventType;
163 napi_create_int32(env, static_cast<int32_t>(collaborateEventInfo.eventType), &jsEventType);
164 napi_set_named_property(env, jsCallbackInfo, "eventType", jsEventType);
165
166 napi_value jsEventMsg;
167 napi_create_string_utf8(env, collaborateEventInfo.eventMsg.c_str(), NAPI_AUTO_LENGTH, &jsEventMsg);
168 napi_set_named_property(env, jsCallbackInfo, "eventMsg", jsEventMsg);
169
170 return jsCallbackInfo;
171 }
172
WrapAVTransDataBuffer(napi_env & env,const std::shared_ptr<AVTransDataBuffer> & dataBuffer)173 napi_value JsAbilityConnectionSessionListener::WrapAVTransDataBuffer(
174 napi_env& env, const std::shared_ptr<AVTransDataBuffer>& dataBuffer)
175 {
176 size_t dataSize = dataBuffer->Size();
177 uint8_t* data = dataBuffer->Data();
178
179 napi_value arrayBuffer;
180 void* arrayBufferData;
181 NAPI_CALL(env, napi_create_arraybuffer(env, dataSize, &arrayBufferData, &arrayBuffer));
182
183 int32_t ret = memcpy_s(arrayBufferData, dataSize, data, dataSize);
184 if (ret != EOK) {
185 HILOGE("memory copy failed, ret %{public}d", ret);
186 return nullptr;
187 }
188 return arrayBuffer;
189 }
190 } // namespace DistributedCollab
191 } // namespace OHOS