• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "napi_web_async_controller.h"
17 #include "nweb_napi_scope.h"
18 #include "nweb.h"
19 #include "nweb_helper.h"
20 #include "nweb_store_web_archive_callback.h"
21 #include <memory>
22 
23 #undef LOG_TAG
24 #define LOG_TAG "NapiWebAsyncController"
25 
26 namespace {
27 // Max length of string.
28 constexpr size_t MAX_WEB_STRING_LENGTH = 40960;
29 } // namespace
30 
31 namespace OHOS {
32 namespace NWeb {
Init(napi_env env,napi_value exports)33 napi_value NapiWebAsyncController::Init(napi_env env, napi_value exports)
34 {
35     const std::string WEB_ASYNC_CLIENT_CLASS_NAME = "WebAsyncController";
36     napi_property_descriptor properties[] = {
37         {"storeWebArchive", nullptr, JS_StoreWebArchive, nullptr, nullptr, nullptr,
38          napi_default, nullptr},
39     };
40     napi_value constructor = nullptr;
41     napi_define_class(env, WEB_ASYNC_CLIENT_CLASS_NAME.c_str(), WEB_ASYNC_CLIENT_CLASS_NAME.length(),
42         JS_NapiWebAsyncController, nullptr, sizeof(properties) / sizeof(properties[0]), properties, &constructor);
43     NAPI_ASSERT(env, constructor != nullptr, "define js class WebAsyncController failed");
44     napi_status status = napi_set_named_property(env, exports, "WebAsyncController", constructor);
45     NAPI_ASSERT(env, status == napi_ok, "set property WebAsyncController failed");
46     return exports;
47 }
48 
StoreWebArchiveInternal(napi_env env,napi_callback_info cbinfo,const std::string & baseName,bool autoName)49 napi_value NapiWebAsyncController::StoreWebArchiveInternal(napi_env env, napi_callback_info cbinfo,
50     const std::string &baseName, bool autoName)
51 {
52     napi_value thisVar = nullptr;
53     size_t argc = 1;
54     size_t argcPromise = 2;
55     size_t argcCallback = 3;
56     napi_value argv[3] = {0};
57 
58     napi_value result = nullptr;
59     napi_get_undefined(env, &result);
60 
61     napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr);
62 
63     // Get the native object of NapiWebAsyncController.
64     NapiWebAsyncController *webAsyncController = nullptr;
65     napi_unwrap(env, thisVar, (void **)&webAsyncController);
66 
67     if (!webAsyncController) {
68         return result;
69     }
70 
71     // If there are three parameters, it is considered to be called by callback,
72     // if it is one, it is considered to be called by returning a promise.
73     if (argc == argcCallback) {
74         napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr);
75         napi_ref jsCallback = nullptr;
76         napi_create_reference(env, argv[argcCallback - 1], 1, &jsCallback);
77 
78         if (jsCallback) {
79             webAsyncController->StoreWebArchiveCallback(baseName, autoName, env, std::move(jsCallback));
80         }
81         return result;
82     } else if (argc == argcPromise) {
83         napi_deferred deferred = nullptr;
84         napi_value promise = nullptr;
85         napi_create_promise(env, &deferred, &promise);
86         if (promise && deferred) {
87             webAsyncController->StoreWebArchivePromise(baseName, autoName, env, deferred);
88         }
89         return promise;
90     }
91 
92     return result;
93 }
94 
JS_StoreWebArchive(napi_env env,napi_callback_info cbinfo)95 napi_value NapiWebAsyncController::JS_StoreWebArchive(napi_env env, napi_callback_info cbinfo)
96 {
97     napi_value thisVar = nullptr;
98 
99     size_t argc = 1;
100     size_t argcPromise = 2;
101     size_t argcCallback = 3;
102     napi_value argv[3] = {0};
103 
104     napi_value result = nullptr;
105     napi_get_undefined(env, &result);
106 
107     napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr);
108     NAPI_ASSERT(env, argc == argcPromise || argc == argcCallback, "requires 2 or 3 parameter");
109 
110     // Check first param is string.
111     napi_valuetype valueType = napi_null;
112     napi_typeof(env, argv[0], &valueType);
113     NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter 1");
114 
115     // Get the first param as string.
116     size_t bufferSize = 0;
117     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &bufferSize);
118     NAPI_ASSERT_BASE(env, bufferSize > 0, "buffer len = 0", result);
119 
120     bufferSize = std::min(bufferSize, MAX_WEB_STRING_LENGTH);
121     char stringValue[bufferSize + 1];
122     size_t jsStringLength = 0;
123     napi_get_value_string_utf8(env, argv[0], stringValue, bufferSize + 1, &jsStringLength);
124     NAPI_ASSERT_BASE(env, jsStringLength == bufferSize, "string length wrong", result);
125     std::string baseName(stringValue);
126 
127     // Check second param is boolean.
128     napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr);
129     napi_typeof(env, argv[1], &valueType);
130     NAPI_ASSERT(env, valueType == napi_boolean, "type mismatch for parameter 2");
131 
132     // Get the second param as bool.
133     bool autoName = false;
134     NAPI_CALL(env, napi_get_value_bool(env, argv[1], &autoName));
135 
136     // Check third param is a function.
137     if (argc == argcCallback) {
138         napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr);
139         napi_typeof(env, argv[argcCallback - 1], &valueType);
140         NAPI_ASSERT(env, valueType == napi_function, "type mismatch for parameter 3");
141     }
142 
143     return StoreWebArchiveInternal(env, cbinfo, baseName, autoName);
144 }
145 
JS_NapiWebAsyncController(napi_env env,napi_callback_info info)146 napi_value NapiWebAsyncController::JS_NapiWebAsyncController(napi_env env, napi_callback_info info)
147 {
148     size_t argc = 1;
149     napi_value argv[1] = {0};
150     napi_value thisVar = nullptr;
151     void *data = nullptr;
152     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
153 
154     napi_valuetype valueType;
155     NAPI_CALL(env, napi_typeof(env, argv[0], &valueType));
156 
157     NAPI_ASSERT(env, valueType == napi_object, "Wrong type of arguments. Expects an object as first argument.");
158 
159     napi_value obj = argv[0];
160     napi_value getNWebIdFunc;
161 
162     napi_status status = napi_get_named_property(env, obj, "getWebId", &getNWebIdFunc);
163     if (status != napi_status::napi_ok) {
164         return nullptr;
165     }
166 
167     napi_value result;
168     status = napi_call_function(env, obj, getNWebIdFunc, 0, nullptr, &result);
169     if (status != napi_status::napi_ok) {
170         return nullptr;
171     }
172 
173     int32_t nwebId = -1;
174     napi_get_value_int32(env, result, &nwebId);
175 
176     NapiWebAsyncController *webAsyncController = new (std::nothrow) NapiWebAsyncController(env, thisVar, nwebId);
177     if (webAsyncController == nullptr) {
178         HILOG_ERROR(LOG_APP, "new webAsyncController failed");
179         return nullptr;
180     }
181 
182     napi_wrap(
183         env, thisVar, webAsyncController,
184         [](napi_env env, void *data, void *hint) {
185             NapiWebAsyncController *webAsyncController = static_cast<NapiWebAsyncController *>(data);
186             delete webAsyncController;
187         },
188         nullptr, nullptr);
189 
190     return thisVar;
191 }
192 
NapiWebAsyncController(napi_env env,napi_value thisVar,int32_t nwebId)193 NapiWebAsyncController::NapiWebAsyncController(napi_env env, napi_value thisVar, int32_t nwebId) : nwebId_(nwebId) {}
194 
StoreWebArchiveCallback(const std::string & baseName,bool autoName,napi_env env,napi_ref jsCallback)195 void NapiWebAsyncController::StoreWebArchiveCallback(const std::string &baseName, bool autoName, napi_env env,
196     napi_ref jsCallback)
197 {
198     std::shared_ptr<NWeb> nweb = NWebHelper::Instance().GetNWeb(nwebId_);
199     if (!nweb) {
200         HILOG_ERROR(LOG_APP, "not found a valid nweb");
201         napi_value callback = nullptr;
202         napi_value jsResult = nullptr;
203         napi_value callbackResult = nullptr;
204 
205         napi_get_reference_value(env, jsCallback, &callback);
206         napi_get_null(env, &jsResult);
207         napi_call_function(env, nullptr, callback, 1, &jsResult, &callbackResult);
208         napi_delete_reference(env, jsCallback);
209         return;
210     }
211 
212     if (jsCallback == nullptr) {
213         return;
214     }
215 
216     auto callbackImpl = std::make_shared<OHOS::NWeb::NWebStoreWebArchiveCallback>();
217     callbackImpl->SetCallBack([env, jCallback = std::move(jsCallback)](std::string result) {
218         if (!env) {
219             return;
220         }
221         NApiScope scope(env);
222         if (!scope.IsVaild()) {
223             return;
224         }
225 
226         napi_value callback = nullptr;
227         napi_get_reference_value(env, jCallback, &callback);
228 
229         napi_value jsResult = nullptr;
230         napi_value callbackResult = nullptr;
231         if (result.empty()) {
232             napi_get_null(env, &jsResult);
233         } else {
234             napi_create_string_utf8(env, result.c_str(), NAPI_AUTO_LENGTH, &jsResult);
235         }
236         napi_call_function(env, nullptr, callback, 1, &jsResult, &callbackResult);
237 
238         napi_delete_reference(env, jCallback);
239     });
240     nweb->StoreWebArchive(baseName, autoName, callbackImpl);
241 
242     return;
243 }
244 
StoreWebArchivePromise(const std::string & baseName,bool autoName,napi_env env,napi_deferred deferred)245 void NapiWebAsyncController::StoreWebArchivePromise(const std::string &baseName, bool autoName, napi_env env,
246     napi_deferred deferred)
247 {
248     std::shared_ptr<NWeb> nweb = NWebHelper::Instance().GetNWeb(nwebId_);
249     if (!nweb) {
250         HILOG_ERROR(LOG_APP, "not found a valid nweb");
251         napi_value jsResult = nullptr;
252         napi_get_null(env, &jsResult);
253         napi_reject_deferred(env, deferred, jsResult);
254         return;
255     }
256 
257     if (deferred == nullptr) {
258         return;
259     }
260 
261     auto callbackImpl = std::make_shared<OHOS::NWeb::NWebStoreWebArchiveCallback>();
262     callbackImpl->SetCallBack([env, deferred](std::string result) {
263         if (!env) {
264             return;
265         }
266         NApiScope scope(env);
267         if (!scope.IsVaild()) {
268             return;
269         }
270 
271         napi_value jsResult = nullptr;
272         if (!result.empty()) {
273             napi_create_string_utf8(env, result.c_str(), NAPI_AUTO_LENGTH, &jsResult);
274             napi_resolve_deferred(env, deferred, jsResult);
275         } else {
276             napi_get_null(env, &jsResult);
277             napi_reject_deferred(env, deferred, jsResult);
278         }
279     });
280     nweb->StoreWebArchive(baseName, autoName, callbackImpl);
281     return;
282 }
283 } // namespace NWeb
284 } // namespace OHOS
285