1 /*
2 * Copyright (C) 2025 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 "media_source_loading_request_napi.h"
17 #include "media_log.h"
18 #include "media_dfx.h"
19
20 namespace {
21 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_PLAYER, "MediaSourceLoadingRequestNapi"};
22 constexpr size_t ARRAY_ARG_COUNTS_ONE = 1;
23 constexpr size_t ARRAY_ARG_COUNTS_TWO = 2;
24 constexpr size_t ARRAY_ARG_COUNTS_THREE = 3;
25 constexpr int32_t INDEX_A = 0;
26 constexpr int32_t INDEX_B = 1;
27 constexpr int32_t INDEX_C = 2;
28 }
29
30 namespace OHOS {
31 namespace Media {
32 const std::string CLASS_NAME = "LoadingRequest";
33 thread_local napi_ref MediaSourceLoadingRequestNapi::constructor_ = nullptr;
MediaSourceLoadingRequestNapi()34 MediaSourceLoadingRequestNapi::MediaSourceLoadingRequestNapi()
35 {
36 MEDIA_LOGI("0x%{public}06" PRIXPTR " ctor", FAKE_POINTER(this));
37 }
38
~MediaSourceLoadingRequestNapi()39 MediaSourceLoadingRequestNapi::~MediaSourceLoadingRequestNapi()
40 {
41 MEDIA_LOGI("0x%{public}06" PRIXPTR " dtor", FAKE_POINTER(this));
42 }
43
Init(napi_env env,napi_value exports)44 napi_value MediaSourceLoadingRequestNapi::Init(napi_env env, napi_value exports)
45 {
46 napi_property_descriptor properties[] = {
47 DECLARE_NAPI_FUNCTION("respondData", JsRespondData),
48 DECLARE_NAPI_FUNCTION("respondHeader", JsRespondHeader),
49 DECLARE_NAPI_FUNCTION("finishLoading", JsFinishLoading),
50
51 DECLARE_NAPI_GETTER("url", JsGetUrl),
52 DECLARE_NAPI_GETTER("header", JsGetHeader),
53 };
54
55 napi_value constructor = nullptr;
56 napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
57 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
58 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define Request class");
59
60 status = napi_create_reference(env, constructor, 1, &constructor_);
61 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to create reference of constructor");
62
63 status = napi_set_named_property(env, exports, CLASS_NAME.c_str(), constructor);
64 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to set constructor");
65
66 return exports;
67 }
68
Constructor(napi_env env,napi_callback_info info)69 napi_value MediaSourceLoadingRequestNapi::Constructor(napi_env env, napi_callback_info info)
70 {
71 napi_value result = nullptr;
72 napi_get_undefined(env, &result);
73
74 size_t argc = ARRAY_ARG_COUNTS_ONE;
75 napi_value args[ARRAY_ARG_COUNTS_ONE] = { 0 };
76 napi_value jsThis = nullptr;
77 napi_status status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
78 CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
79 uint64_t requestId = 0;
80 bool lossLess = false;
81 napi_get_value_bigint_uint64(env, args[0], &requestId, &lossLess);
82 if (!lossLess) {
83 MEDIA_LOGE("BigInt values have no lossless converted");
84 return result;
85 }
86 MediaSourceLoadingRequestNapi *jsRequest = new(std::nothrow) MediaSourceLoadingRequestNapi();
87 CHECK_AND_RETURN_RET_LOG(jsRequest != nullptr, result, "failed to new MediaSourceLoadingRequestNapi");
88
89 jsRequest->env_ = env;
90 jsRequest->request_ = RequestContainer::GetInstance().Find(requestId);
91 if (jsRequest->request_ == nullptr) {
92 delete jsRequest;
93 MEDIA_LOGE("failed to getRequest");
94 return result;
95 }
96
97 status = napi_wrap(env, jsThis, reinterpret_cast<void *>(jsRequest),
98 MediaSourceLoadingRequestNapi::Destructor, nullptr, nullptr);
99 if (status != napi_ok) {
100 delete jsRequest;
101 MEDIA_LOGE("Failed to wrap native instance");
102 return result;
103 }
104
105 RequestContainer::GetInstance().Erase(requestId);
106 MEDIA_LOGI("0x%{public}06" PRIXPTR " Constructor success", FAKE_POINTER(jsRequest));
107 return jsThis;
108 }
109
Destructor(napi_env env,void * nativeObject,void * finalize)110 void MediaSourceLoadingRequestNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
111 {
112 (void)env;
113 (void)finalize;
114 if (nativeObject != nullptr) {
115 MediaSourceLoadingRequestNapi *jsRequest = reinterpret_cast<MediaSourceLoadingRequestNapi *>(nativeObject);
116 delete jsRequest;
117 }
118 MEDIA_LOGD("Destructor success");
119 }
120
CreateLoadingRequest(napi_env env,std::shared_ptr<LoadingRequest> request)121 napi_value MediaSourceLoadingRequestNapi::CreateLoadingRequest(napi_env env,
122 std::shared_ptr<LoadingRequest> request)
123 {
124 MediaTrace trace("MediaSourceLoadingRequestNapi::CreateLoadingRequest");
125 MEDIA_LOGD("CreateLoadingRequest >>");
126 CHECK_AND_RETURN_RET_LOG(request != nullptr, nullptr, "request nullptr");
127 napi_status status;
128 napi_value result = nullptr;
129 napi_get_undefined(env, &result);
130 if (constructor_ == nullptr) {
131 napi_value exports = nullptr;
132 napi_create_object(env, &exports);
133 MediaSourceLoadingRequestNapi::Init(env, exports);
134 }
135
136 napi_value constructor = nullptr;
137 status = napi_get_reference_value(env, constructor_, &constructor);
138 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to get");
139
140 size_t argc = ARRAY_ARG_COUNTS_ONE;
141 napi_value args[ARRAY_ARG_COUNTS_ONE] = { 0 };
142 napi_create_bigint_uint64(env, request->GetUniqueId(), &args[0]);
143 RequestContainer::GetInstance().Insert(request->GetUniqueId(), request);
144
145 status = napi_new_instance(env, constructor, argc, args, &result);
146 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to new_instance");
147 return result;
148 }
149
JsRespondData(napi_env env,napi_callback_info info)150 napi_value MediaSourceLoadingRequestNapi::JsRespondData(napi_env env, napi_callback_info info)
151 {
152 MediaTrace trace("MediaSourceLoadingRequestNapi::JsRespondData");
153 napi_value result = nullptr;
154 napi_get_undefined(env, &result);
155 MEDIA_LOGI("JsRespondData In");
156
157 size_t argCount = ARRAY_ARG_COUNTS_THREE; // args[0]:uuid, args[1]:offset, args[2]:arrayBuffer
158 napi_value args[ARRAY_ARG_COUNTS_THREE] = { nullptr };
159 MediaSourceLoadingRequestNapi* jsRequest =
160 MediaSourceLoadingRequestNapi::GetJsInstanceWithParameter(env, info, argCount, args);
161 CHECK_AND_RETURN_RET_LOG(jsRequest != nullptr, result, "failed to GetJsInstance");
162
163 int64_t uuid = 0;
164 int64_t offset = 0;
165 void *arrayBuffer = nullptr;
166 size_t arrayBufferSize = 0;
167
168 CHECK_AND_RETURN_RET_LOG(napi_get_value_int64(env, args[INDEX_A], &uuid) == napi_ok, result, "get uuid fail");
169 CHECK_AND_RETURN_RET_LOG(napi_get_value_int64(env, args[INDEX_B], &offset) == napi_ok, result, "get offset fail");
170 CommonNapi::GetPropertyArrayBuffer(env, args[INDEX_C], &arrayBuffer, &arrayBufferSize);
171 auto buffer = std::make_shared<AVSharedMemoryBase>(static_cast<int32_t>(arrayBufferSize),
172 AVSharedMemory::FLAGS_READ_WRITE, "userBuffer");
173 CHECK_AND_RETURN_RET_LOG(buffer != nullptr, result, "get buffer fail");
174 buffer->Init();
175 buffer->Write(static_cast<uint8_t *>(arrayBuffer), arrayBufferSize);
176 MEDIA_LOGI("JsRespondData getSize: %{public}d", buffer->GetSize());
177 napi_create_int32(env, jsRequest->request_->RespondData(uuid, offset, buffer), &result);
178 return result;
179 }
180
JsRespondHeader(napi_env env,napi_callback_info info)181 napi_value MediaSourceLoadingRequestNapi::JsRespondHeader(napi_env env, napi_callback_info info)
182 {
183 MediaTrace trace("MediaSourceLoadingRequestNapi::JsRespondHeader");
184 napi_value result = nullptr;
185 napi_get_undefined(env, &result);
186 MEDIA_LOGI("JsRespondHeader In");
187
188 size_t argCount = ARRAY_ARG_COUNTS_THREE; // args[0]:uuid, args[1]:header, args[2]:redirectUrl
189 napi_value args[ARRAY_ARG_COUNTS_THREE] = { nullptr };
190 MediaSourceLoadingRequestNapi* jsRequest =
191 MediaSourceLoadingRequestNapi::GetJsInstanceWithParameter(env, info, argCount, args);
192 CHECK_AND_RETURN_RET_LOG(jsRequest != nullptr, result, "failed to GetJsInstance");
193 MEDIA_LOGI("JsRespondHeader argCount %{public}d", static_cast<int32_t>(argCount));
194 int64_t uuid = 0;
195 std::map<std::string, std::string> header {};
196 CHECK_AND_RETURN_RET_LOG(napi_get_value_int64(env, args[INDEX_A], &uuid) == napi_ok, result, "get uuid fail");
197 MEDIA_LOGI("JsRespondHeader uuid %{public}" PRId64, uuid);
198 CommonNapi::GetPropertyMap(env, args[INDEX_B], header);
199 for (auto [x, y]: header) {
200 MEDIA_LOGI("JsRespondHeader x %{private}s, y %{private}s", x.c_str(), y.c_str());
201 }
202 std::string redirectUrl = CommonNapi::GetStringArgument(env, args[INDEX_C]);
203 jsRequest->request_->RespondHeader(uuid, header, redirectUrl);
204 MEDIA_LOGI("JsRespondHeader redirectUrl %{private}s", redirectUrl.c_str());
205 return result;
206 }
207
JsFinishLoading(napi_env env,napi_callback_info info)208 napi_value MediaSourceLoadingRequestNapi::JsFinishLoading(napi_env env, napi_callback_info info)
209 {
210 MediaTrace trace("MediaSourceLoadingRequestNapi::JsFinishLoading");
211 napi_value result = nullptr;
212 napi_get_undefined(env, &result);
213 MEDIA_LOGI("JsFinishLoading In");
214
215 size_t argCount = ARRAY_ARG_COUNTS_TWO; // args[0]:uuid, args[1]:state
216 napi_value args[ARRAY_ARG_COUNTS_TWO] = { nullptr };
217 MediaSourceLoadingRequestNapi* jsRequest =
218 MediaSourceLoadingRequestNapi::GetJsInstanceWithParameter(env, info, argCount, args);
219 CHECK_AND_RETURN_RET_LOG(jsRequest != nullptr, result, "failed to GetJsInstance");
220
221 int64_t uuid = 0;
222 int32_t requestError = 0;
223 CHECK_AND_RETURN_RET_LOG(napi_get_value_int64(env, args[INDEX_A], &uuid) == napi_ok, result, "get uuid fail");
224 CHECK_AND_RETURN_RET_LOG(napi_get_value_int32(env, args[INDEX_B], &requestError) == napi_ok,
225 result, "get requestError fail");
226 jsRequest->request_->FinishLoading(uuid, requestError);
227 return result;
228 }
229
JsGetUrl(napi_env env,napi_callback_info info)230 napi_value MediaSourceLoadingRequestNapi::JsGetUrl(napi_env env, napi_callback_info info)
231 {
232 MediaTrace trace("MediaSourceLoadingRequestNapi::JsGetUrl");
233 napi_value result = nullptr;
234 napi_get_undefined(env, &result);
235 MEDIA_LOGI("JsGetUrl In");
236
237 MediaSourceLoadingRequestNapi* jsRequest = MediaSourceLoadingRequestNapi::GetJsInstance(env, info);
238 CHECK_AND_RETURN_RET_LOG(jsRequest != nullptr, result, "failed to GetJsInstance");
239
240 (void)napi_create_string_utf8(env, jsRequest->request_->GetUrl().c_str(), NAPI_AUTO_LENGTH, &result);
241 return result;
242 }
243
JsGetHeader(napi_env env,napi_callback_info info)244 napi_value MediaSourceLoadingRequestNapi::JsGetHeader(napi_env env, napi_callback_info info)
245 {
246 MediaTrace trace("MediaSourceLoadingRequestNapi::JsGetHeader");
247 napi_value result = nullptr;
248 napi_get_undefined(env, &result);
249 MEDIA_LOGI("JsGetHeader In");
250
251 MediaSourceLoadingRequestNapi* jsRequest = MediaSourceLoadingRequestNapi::GetJsInstance(env, info);
252 CHECK_AND_RETURN_RET_LOG(jsRequest != nullptr, result, "failed to GetJsInstance");
253
254 std::map<std::string, std::string> header = jsRequest->request_->GetHeader();
255 (void)napi_create_object(env, &result);
256 for (auto &[key, value] : header) {
257 CommonNapi::SetPropertyString(env, result, key, value);
258 }
259 return result;
260 }
261
GetJsInstance(napi_env env,napi_callback_info info)262 MediaSourceLoadingRequestNapi* MediaSourceLoadingRequestNapi::GetJsInstance(napi_env env, napi_callback_info info)
263 {
264 size_t argc = 0;
265 napi_value jsThis = nullptr;
266 napi_status status = napi_get_cb_info(env, info, &argc, nullptr, &jsThis, nullptr);
267 CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, nullptr, "failed to napi_get_cb_info");
268
269 MediaSourceLoadingRequestNapi *jsRequest = nullptr;
270 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&jsRequest));
271 CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsRequest != nullptr, nullptr, "failed to napi_unwrap");
272
273 return jsRequest;
274 }
275
GetJsInstanceWithParameter(napi_env env,napi_callback_info info,size_t & argc,napi_value * argv)276 MediaSourceLoadingRequestNapi* MediaSourceLoadingRequestNapi::GetJsInstanceWithParameter(napi_env env,
277 napi_callback_info info, size_t &argc, napi_value *argv)
278 {
279 napi_value jsThis = nullptr;
280 napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
281 CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, nullptr, "failed to napi_get_cb_info");
282
283 MediaSourceLoadingRequestNapi *jsRequest = nullptr;
284 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&jsRequest));
285 CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsRequest != nullptr, nullptr, "failed to napi_unwrap");
286
287 return jsRequest;
288 }
289 } // namespace Media
290 } // namespace OHOS