• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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