• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <fstream>
17 #include <iostream>
18 #include <securec.h>
19 
20 #include "business_error.h"
21 #include "napi_parse_utils.h"
22 #include "nweb_napi_scope.h"
23 #include "nweb_log.h"
24 #include "web_errors.h"
25 #include "webview_createpdf_execute_callback.h"
26 namespace OHOS::NWeb {
27 using namespace NWebError;
28 const std::string JS_EXT_ARR_CLASS_NAME = "PdfData";
29 thread_local napi_ref g_jsArrExtClassRef;
30 // static
InitJSExcute(napi_env env,napi_value exports)31 void WebviewCreatePDFExecuteCallback::InitJSExcute(napi_env env, napi_value exports)
32 {
33     napi_value jsArrExtClass = nullptr;
34     napi_property_descriptor jsArrExtClsProperties[] = { DECLARE_NAPI_FUNCTION(
35         "pdfArrayBuffer", NapiArrayBufferExt::GetArrayBuffer) };
36     napi_define_class(env, JS_EXT_ARR_CLASS_NAME.c_str(), JS_EXT_ARR_CLASS_NAME.length(),
37         NapiArrayBufferExt::JsConstructor, nullptr, sizeof(jsArrExtClsProperties) / sizeof(jsArrExtClsProperties[0]),
38         jsArrExtClsProperties, &jsArrExtClass);
39     napi_create_reference(env, jsArrExtClass, 1, &g_jsArrExtClassRef);
40     napi_set_named_property(env, exports, JS_EXT_ARR_CLASS_NAME.c_str(), jsArrExtClass);
41 }
42 
ReleaseArrayBufferExecuteParamAndUvWork(ArrayBufferExecuteParam * param,uv_work_t * work)43 void WebviewCreatePDFExecuteCallback::ReleaseArrayBufferExecuteParamAndUvWork(
44     ArrayBufferExecuteParam* param, uv_work_t* work)
45 {
46     if (param != nullptr) {
47         if (param->result_ != nullptr) {
48             delete[] param->result_;
49             param->result_ = nullptr;
50         }
51         delete param;
52         param = nullptr;
53     }
54     if (work != nullptr) {
55         delete work;
56         work = nullptr;
57     }
58 }
59 
OnReceiveValue(const char * value,const long size)60 void WebviewCreatePDFExecuteCallback::OnReceiveValue(const char* value, const long size)
61 {
62     if (value == nullptr || size <= 0) {
63         WVLOG_E("[CreatePDF] value is null or size is invalid");
64         return;
65     }
66 
67     ArrayBufferExecuteParam* param = new (std::nothrow) ArrayBufferExecuteParam();
68     if (param == nullptr) {
69         WVLOG_E("[CreatePDF] allocate ArrayBufferExecuteParam failed");
70         return;
71     }
72     param->env_ = env_;
73     param->callbackRef_ = callbackRef_;
74     param->deferred_ = deferred_;
75     param->result_ = new (std::nothrow) char[size + 1];
76     if (param->result_ == nullptr) {
77         WVLOG_E("new char failed");
78         delete param;
79         return;
80     }
81     if (memcpy_s(param->result_, size, value, size) != 0) {
82         WVLOG_E("[CreatePDF] memcpy failed");
83         delete[] param->result_;
84         delete param;
85         return;
86     }
87     param->size_ = size;
88     auto task = [param]() {
89         std::shared_ptr<ArrayBufferExecuteParam> context(
90             static_cast<ArrayBufferExecuteParam*>(param), [](ArrayBufferExecuteParam* ptr) {
91                 delete[] ptr->result_;
92                 delete ptr;
93             });
94         napi_env env = param->env_;
95         NApiScope scope(env);
96         if (!scope.IsVaild()) {
97             WVLOG_E("[CreatePDF] open handle scope failed");
98             return;
99         }
100 
101         if (param->callbackRef_) {
102             UvAfterWorkCbAsync(env, param->callbackRef_, param->result_, param->size_);
103         } else if (param->deferred_) {
104             UvAfterWorkCbPromise(env, param->deferred_, param->result_, param->size_);
105         }
106     };
107     if (napi_status::napi_ok != napi_send_event(env_, task, napi_eprio_immediate)) {
108         WVLOG_E("OnReceiveValue: Failed to SendEvent");
109         delete[] param->result_;
110         delete param;
111     }
112 }
113 
UvAfterWorkCbAsync(napi_env env,napi_ref callbackRef,const char * result,const long size)114 void WebviewCreatePDFExecuteCallback::UvAfterWorkCbAsync(
115     napi_env env, napi_ref callbackRef, const char* result, const long size)
116 {
117     napi_value setResult[INTEGER_TWO] = { 0 };
118 
119     if (result == nullptr) {
120         setResult[INTEGER_ZERO] = BusinessError::CreateError(env, NWebError::INVALID_RESOURCE);
121         napi_get_null(env, &setResult[INTEGER_ONE]);
122     } else {
123         napi_get_undefined(env, &setResult[INTEGER_ZERO]);
124         napi_value jsArrExt = nullptr;
125         NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, g_jsArrExtClassRef, &jsArrExt));
126         NAPI_CALL_RETURN_VOID(env, napi_new_instance(env, jsArrExt, 0, NULL, &setResult[INTEGER_ONE]));
127 
128         WebJsArrayBufferExt* webArrayBufferExt = new (std::nothrow) WebJsArrayBufferExt(result, size);
129         if (webArrayBufferExt == nullptr) {
130             WVLOG_E("new WebJsArrayBufferExt failed.");
131             return;
132         }
133 
134         napi_status status = napi_wrap(
135             env, setResult[INTEGER_ONE], webArrayBufferExt,
136             [](napi_env env, void* data, void* hint) {
137                 WebJsArrayBufferExt* webArrayBufferExt = static_cast<WebJsArrayBufferExt*>(data);
138                 delete webArrayBufferExt;
139                 webArrayBufferExt = nullptr;
140             },
141             nullptr, nullptr);
142         if (status != napi_status::napi_ok) {
143             if (webArrayBufferExt) {
144                 delete webArrayBufferExt;
145                 webArrayBufferExt = nullptr;
146             }
147             WVLOG_E("napi_wrap failed");
148             return;
149         }
150     }
151     napi_value args[INTEGER_TWO] = { setResult[INTEGER_ZERO], setResult[INTEGER_ONE] };
152     napi_value callback = nullptr;
153     napi_value callbackResult = nullptr;
154 
155     napi_get_reference_value(env, callbackRef, &callback);
156     napi_call_function(env, nullptr, callback, INTEGER_TWO, args, &callbackResult);
157     napi_delete_reference(env, callbackRef);
158 }
159 
UvAfterWorkCbPromise(napi_env env,napi_deferred deferred,const char * result,const long size)160 void WebviewCreatePDFExecuteCallback::UvAfterWorkCbPromise(
161     napi_env env, napi_deferred deferred, const char* result, const long size)
162 {
163     napi_value setResult[INTEGER_TWO] = { 0 };
164     setResult[INTEGER_ZERO] = NWebError::BusinessError::CreateError(env, NWebError::INVALID_RESOURCE);
165 
166     napi_value jsArrExt = nullptr;
167     napi_status status = napi_get_reference_value(env, g_jsArrExtClassRef, &jsArrExt);
168     if (status != napi_status::napi_ok) {
169         WVLOG_E("napi_get_reference_value failed.");
170         return;
171     }
172     status = napi_new_instance(env, jsArrExt, 0, NULL, &setResult[INTEGER_ONE]);
173     if (status != napi_status::napi_ok) {
174         WVLOG_E("napi_new_instance failed.");
175         return;
176     }
177     WebJsArrayBufferExt* webArrayBufferExt = new (std::nothrow) WebJsArrayBufferExt(result, size);
178     if (webArrayBufferExt == nullptr) {
179         WVLOG_E("new WebJsArrayBufferExt failed.");
180         return;
181     }
182 
183     status = napi_wrap(
184         env, setResult[INTEGER_ONE], webArrayBufferExt,
185         [](napi_env env, void* data, void* hint) {
186             WebJsArrayBufferExt* webArrayBufferExt = static_cast<WebJsArrayBufferExt*>(data);
187             delete webArrayBufferExt;
188             webArrayBufferExt = nullptr;
189         },
190         nullptr, nullptr);
191     if (status != napi_status::napi_ok) {
192         if (webArrayBufferExt) {
193             delete webArrayBufferExt;
194             webArrayBufferExt = nullptr;
195         }
196         WVLOG_E("napi_wrap failed.");
197         return;
198     }
199 
200     napi_value args[INTEGER_TWO] = { setResult[INTEGER_ZERO], setResult[INTEGER_ONE] };
201     if (result == nullptr) {
202         napi_reject_deferred(env, deferred, args[INTEGER_ZERO]);
203     } else {
204         napi_resolve_deferred(env, deferred, args[INTEGER_ONE]);
205     }
206 }
207 
JsConstructor(napi_env env,napi_callback_info info)208 napi_value NapiArrayBufferExt::JsConstructor(napi_env env, napi_callback_info info)
209 {
210     napi_value thisVar = nullptr;
211     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
212     return thisVar;
213 }
214 
GetArrayBuffer(napi_env env,napi_callback_info info)215 napi_value NapiArrayBufferExt::GetArrayBuffer(napi_env env, napi_callback_info info)
216 {
217     napi_value thisVar = nullptr;
218     napi_value result = nullptr;
219     size_t argc = INTEGER_ONE;
220     napi_value argv[INTEGER_ONE] = { 0 };
221 
222     WebJsArrayBufferExt* webArrayBufferExt = nullptr;
223     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
224     NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&webArrayBufferExt));
225     if (webArrayBufferExt == nullptr) {
226         WVLOG_E("unwrap webArrayBufferExt failed.");
227         return result;
228     }
229 
230     const char* pdfResult = webArrayBufferExt->GetPDFResult();
231     const long size = webArrayBufferExt->GetPDFSize();
232     if (pdfResult == nullptr || size <= 0) {
233         WVLOG_E("[CreatePDF] invalid PDF result or size");
234         return nullptr;
235     }
236     napi_value arraybuffer = nullptr;
237     void* bufferData = nullptr;
238 
239     napi_status status = napi_create_arraybuffer(env, size, &bufferData, &arraybuffer);
240     if (status != napi_ok) {
241         WVLOG_E("[CreatePDF] create array buffer failed, status: %{public}d", status);
242         return nullptr;
243     }
244     if (bufferData == nullptr) {
245         WVLOG_E("[CreatePDF] bufferData is null after array buffer creation");
246         return nullptr;
247     }
248     if (memcpy_s(bufferData, size, pdfResult, size) != 0) {
249         WVLOG_E("[CreatePDF] memcpy failed");
250         return nullptr;
251     }
252     status = napi_create_typedarray(env, napi_typedarray_type::napi_uint8_array, size, arraybuffer, 0, &result);
253     if (status != napi_ok) {
254         WVLOG_E("[CreatePDF] create typed array failed, status: %{public}d", status);
255         return nullptr;
256     }
257     return result;
258 }
259 
260 } // namespace OHOS::NWeb
261