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 "web_download_ffi.h"
17
18 #include "cj_lambda.h"
19 #include "nweb_helper.h"
20 #include "nweb_init_params.h"
21 #include "web_download.pb.h"
22 #include "web_download_delegate_impl.h"
23 #include "web_download_item_impl.h"
24 #include "web_download_manager_impl.h"
25 #include "web_errors.h"
26 #include "webview_controller_impl.h"
27 #include "webview_log.h"
28 #include "webview_utils.h"
29
30 using namespace OHOS::FFI;
31 using namespace OHOS::NWeb;
32
33 namespace OHOS {
34 namespace Webview {
35 extern "C" {
36 // WebDownloadItemImpl
FfiOHOSWebDownloadItemImplConstructor()37 int64_t FfiOHOSWebDownloadItemImplConstructor()
38 {
39 auto nativeWebDownloadItemImpl = FFIData::Create<WebDownloadItemImpl>();
40 if (nativeWebDownloadItemImpl == nullptr) {
41 WEBVIEWLOGE("new web download item failed");
42 return -1;
43 }
44 return nativeWebDownloadItemImpl->GetID();
45 }
46
FfiOHOSWebDownloadItemImplGetGuid(int64_t id)47 RetDataCString FfiOHOSWebDownloadItemImplGetGuid(int64_t id)
48 {
49 RetDataCString ret = { .code = NWebError::INIT_ERROR, .data = nullptr };
50 auto nativeWebDownloadItemImpl = FFIData::GetData<WebDownloadItemImpl>(id);
51 if (!nativeWebDownloadItemImpl) {
52 return ret;
53 }
54 std::string guid = nativeWebDownloadItemImpl->guid;
55 ret.code = NWebError::NO_ERROR;
56 ret.data = MallocCString(guid);
57 return ret;
58 }
59
FfiOHOSWebDownloadItemImplGetCurrentSpeed(int64_t id,int32_t * errCode)60 int64_t FfiOHOSWebDownloadItemImplGetCurrentSpeed(int64_t id, int32_t* errCode)
61 {
62 auto nativeWebDownloadItemImpl = FFIData::GetData<WebDownloadItemImpl>(id);
63 if (!nativeWebDownloadItemImpl) {
64 *errCode = NWebError::INIT_ERROR;
65 return -1;
66 }
67 *errCode = NWebError::NO_ERROR;
68 return static_cast<int64_t>(nativeWebDownloadItemImpl->currentSpeed);
69 }
70
FfiOHOSWebDownloadItemImplGetPercentComplete(int64_t id,int32_t * errCode)71 int64_t FfiOHOSWebDownloadItemImplGetPercentComplete(int64_t id, int32_t* errCode)
72 {
73 auto nativeWebDownloadItemImpl = FFIData::GetData<WebDownloadItemImpl>(id);
74 if (!nativeWebDownloadItemImpl) {
75 *errCode = NWebError::INIT_ERROR;
76 return -1;
77 }
78 *errCode = NWebError::NO_ERROR;
79 return static_cast<int64_t>(nativeWebDownloadItemImpl->percentComplete);
80 }
81
FfiOHOSWebDownloadItemImplGetTotalBytes(int64_t id,int32_t * errCode)82 int64_t FfiOHOSWebDownloadItemImplGetTotalBytes(int64_t id, int32_t* errCode)
83 {
84 auto nativeWebDownloadItemImpl = FFIData::GetData<WebDownloadItemImpl>(id);
85 if (!nativeWebDownloadItemImpl) {
86 *errCode = NWebError::INIT_ERROR;
87 return -1;
88 }
89 *errCode = NWebError::NO_ERROR;
90 return static_cast<int64_t>(nativeWebDownloadItemImpl->totalBytes);
91 }
92
FfiOHOSWebDownloadItemImplGetReceivedBytes(int64_t id,int32_t * errCode)93 int64_t FfiOHOSWebDownloadItemImplGetReceivedBytes(int64_t id, int32_t* errCode)
94 {
95 auto nativeWebDownloadItemImpl = FFIData::GetData<WebDownloadItemImpl>(id);
96 if (!nativeWebDownloadItemImpl) {
97 *errCode = NWebError::INIT_ERROR;
98 return -1;
99 }
100 *errCode = NWebError::NO_ERROR;
101 return static_cast<int64_t>(nativeWebDownloadItemImpl->receivedBytes);
102 }
103
FfiOHOSWebDownloadItemImplGetState(int64_t id,int32_t * errCode)104 int32_t FfiOHOSWebDownloadItemImplGetState(int64_t id, int32_t* errCode)
105 {
106 auto nativeWebDownloadItemImpl = FFIData::GetData<WebDownloadItemImpl>(id);
107 if (!nativeWebDownloadItemImpl) {
108 *errCode = NWebError::INIT_ERROR;
109 return -1;
110 }
111 *errCode = NWebError::NO_ERROR;
112 return static_cast<int32_t>(nativeWebDownloadItemImpl->state);
113 }
114
FfiOHOSWebDownloadItemImplGetLastErrorCode(int64_t id,int32_t * errCode)115 int32_t FfiOHOSWebDownloadItemImplGetLastErrorCode(int64_t id, int32_t* errCode)
116 {
117 auto nativeWebDownloadItemImpl = FFIData::GetData<WebDownloadItemImpl>(id);
118 if (!nativeWebDownloadItemImpl) {
119 *errCode = NWebError::INIT_ERROR;
120 return -1;
121 }
122 *errCode = NWebError::NO_ERROR;
123 return static_cast<int32_t>(nativeWebDownloadItemImpl->lastErrorCode);
124 }
125
FfiOHOSWebDownloadItemImplGetMethod(int64_t id)126 RetDataCString FfiOHOSWebDownloadItemImplGetMethod(int64_t id)
127 {
128 RetDataCString ret = { .code = NWebError::INIT_ERROR, .data = nullptr };
129 auto nativeWebDownloadItemImpl = FFIData::GetData<WebDownloadItemImpl>(id);
130 if (!nativeWebDownloadItemImpl) {
131 return ret;
132 }
133 std::string methodValue = nativeWebDownloadItemImpl->method;
134 ret.code = NWebError::NO_ERROR;
135 ret.data = MallocCString(methodValue);
136 return ret;
137 }
138
FfiOHOSWebDownloadItemImplGetMimeType(int64_t id)139 RetDataCString FfiOHOSWebDownloadItemImplGetMimeType(int64_t id)
140 {
141 RetDataCString ret = { .code = NWebError::INIT_ERROR, .data = nullptr };
142 auto nativeWebDownloadItemImpl = FFIData::GetData<WebDownloadItemImpl>(id);
143 if (!nativeWebDownloadItemImpl) {
144 return ret;
145 }
146 std::string mimeTypeValue = nativeWebDownloadItemImpl->mimeType;
147 ret.code = NWebError::NO_ERROR;
148 ret.data = MallocCString(mimeTypeValue);
149 return ret;
150 }
151
FfiOHOSWebDownloadItemImplGetUrl(int64_t id)152 RetDataCString FfiOHOSWebDownloadItemImplGetUrl(int64_t id)
153 {
154 RetDataCString ret = { .code = NWebError::INIT_ERROR, .data = nullptr };
155 auto nativeWebDownloadItemImpl = FFIData::GetData<WebDownloadItemImpl>(id);
156 if (!nativeWebDownloadItemImpl) {
157 return ret;
158 }
159 std::string urlValue = nativeWebDownloadItemImpl->url;
160 ret.code = NWebError::NO_ERROR;
161 ret.data = MallocCString(urlValue);
162 return ret;
163 }
164
FfiOHOSWebDownloadItemImplGetSuggestedFileName(int64_t id)165 RetDataCString FfiOHOSWebDownloadItemImplGetSuggestedFileName(int64_t id)
166 {
167 RetDataCString ret = { .code = NWebError::INIT_ERROR, .data = nullptr };
168 auto nativeWebDownloadItemImpl = FFIData::GetData<WebDownloadItemImpl>(id);
169 if (!nativeWebDownloadItemImpl) {
170 return ret;
171 }
172 std::string fileNameValue = nativeWebDownloadItemImpl->suggestedFileName;
173 ret.code = NWebError::NO_ERROR;
174 ret.data = MallocCString(fileNameValue);
175 return ret;
176 }
177
FfiOHOSWebDownloadItemImplGetFullPath(int64_t id)178 RetDataCString FfiOHOSWebDownloadItemImplGetFullPath(int64_t id)
179 {
180 RetDataCString ret = { .code = NWebError::INIT_ERROR, .data = nullptr };
181 auto nativeWebDownloadItemImpl = FFIData::GetData<WebDownloadItemImpl>(id);
182 if (!nativeWebDownloadItemImpl) {
183 return ret;
184 }
185 std::string fullPath = nativeWebDownloadItemImpl->fullPath;
186 ret.code = NWebError::NO_ERROR;
187 ret.data = MallocCString(fullPath);
188 return ret;
189 }
190
FfiOHOSWebDownloadItemImplStart(int64_t id,char * downloadPath)191 int32_t FfiOHOSWebDownloadItemImplStart(int64_t id, char* downloadPath)
192 {
193 std::string sDownloadPath = downloadPath;
194 auto nativeWebDownloadItemImpl = FFIData::GetData<WebDownloadItemImpl>(id);
195 if (!nativeWebDownloadItemImpl) {
196 return NWebError::INIT_ERROR;
197 }
198 nativeWebDownloadItemImpl->downloadPath = sDownloadPath;
199 WebDownload_Continue(
200 nativeWebDownloadItemImpl->before_download_callback, nativeWebDownloadItemImpl->downloadPath.c_str());
201 return NWebError::NO_ERROR;
202 }
203
FfiOHOSWebDownloadItemImplCancel(int64_t id)204 int32_t FfiOHOSWebDownloadItemImplCancel(int64_t id)
205 {
206 auto nativeWebDownloadItemImpl = FFIData::GetData<WebDownloadItemImpl>(id);
207 if (!nativeWebDownloadItemImpl) {
208 return NWebError::INIT_ERROR;
209 }
210 if (nativeWebDownloadItemImpl->download_item_callback) {
211 WebDownload_Cancel(nativeWebDownloadItemImpl->download_item_callback);
212 } else if (nativeWebDownloadItemImpl->before_download_callback) {
213 WebDownload_CancelBeforeDownload(nativeWebDownloadItemImpl->before_download_callback);
214 } else {
215 WEBVIEWLOGE("[DOWNLOAD] WebDownloadItem::Cancel failed for callback nullptr");
216 }
217 return NWebError::NO_ERROR;
218 }
219
FfiOHOSWebDownloadItemImplPause(int64_t id)220 int32_t FfiOHOSWebDownloadItemImplPause(int64_t id)
221 {
222 auto nativeWebDownloadItemImpl = FFIData::GetData<WebDownloadItemImpl>(id);
223 if (!nativeWebDownloadItemImpl) {
224 return NWebError::INIT_ERROR;
225 }
226 NWebDownloadItemState state =
227 WebDownload_GetItemState(nativeWebDownloadItemImpl->nwebId, nativeWebDownloadItemImpl->webDownloadId);
228 if (state != NWebDownloadItemState::IN_PROGRESS && state != NWebDownloadItemState::PENDING) {
229 return NWebError::DOWNLOAD_NOT_START;
230 }
231 if (nativeWebDownloadItemImpl->download_item_callback) {
232 WebDownload_Pause(nativeWebDownloadItemImpl->download_item_callback);
233 } else if (nativeWebDownloadItemImpl->before_download_callback) {
234 WebDownload_PauseBeforeDownload(nativeWebDownloadItemImpl->before_download_callback);
235 } else {
236 WEBVIEWLOGE("[DOWNLOAD] WebDownloadItem::Pause failed for callback nullptr");
237 }
238 return NWebError::NO_ERROR;
239 }
240
FfiOHOSWebDownloadItemImplResume(int64_t id)241 int32_t FfiOHOSWebDownloadItemImplResume(int64_t id)
242 {
243 auto nativeWebDownloadItemImpl = FFIData::GetData<WebDownloadItemImpl>(id);
244 if (!nativeWebDownloadItemImpl) {
245 return NWebError::INIT_ERROR;
246 }
247 NWebDownloadItemState state =
248 WebDownload_GetItemState(nativeWebDownloadItemImpl->nwebId, nativeWebDownloadItemImpl->webDownloadId);
249 if (state != NWebDownloadItemState::PAUSED) {
250 return NWebError::DOWNLOAD_NOT_PAUSED;
251 }
252
253 if (nativeWebDownloadItemImpl->download_item_callback) {
254 WebDownload_Resume(nativeWebDownloadItemImpl->download_item_callback);
255 } else if (nativeWebDownloadItemImpl->before_download_callback) {
256 WebDownload_ResumeBeforeDownload(nativeWebDownloadItemImpl->before_download_callback);
257 } else {
258 WEBVIEWLOGE("[DOWNLOAD] WebDownloadItem::Resume failed for callback nullptr");
259 }
260 return NWebError::NO_ERROR;
261 }
262
FfiOHOSWebDownloadItemImplSerialize(int64_t id,int32_t * errCode)263 CArrUI8 FfiOHOSWebDownloadItemImplSerialize(int64_t id, int32_t* errCode)
264 {
265 auto nativeWebDownloadItemImpl = FFIData::GetData<WebDownloadItemImpl>(id);
266 if (!nativeWebDownloadItemImpl) {
267 *errCode = NWebError::INIT_ERROR;
268 return CArrUI8 { nullptr, 0 };
269 }
270
271 browser_service::WebDownload webDownloadPb;
272 webDownloadPb.set_web_download_id(nativeWebDownloadItemImpl->webDownloadId);
273 webDownloadPb.set_current_speed(nativeWebDownloadItemImpl->currentSpeed);
274 webDownloadPb.set_percent_complete(nativeWebDownloadItemImpl->percentComplete);
275 webDownloadPb.set_total_bytes(nativeWebDownloadItemImpl->totalBytes);
276 webDownloadPb.set_received_bytes(nativeWebDownloadItemImpl->receivedBytes);
277 webDownloadPb.set_guid(nativeWebDownloadItemImpl->guid);
278 webDownloadPb.set_full_path(nativeWebDownloadItemImpl->fullPath);
279 webDownloadPb.set_url(nativeWebDownloadItemImpl->url);
280 webDownloadPb.set_etag(nativeWebDownloadItemImpl->etag);
281 webDownloadPb.set_original_url(nativeWebDownloadItemImpl->originalUrl);
282 webDownloadPb.set_suggested_file_name(nativeWebDownloadItemImpl->suggestedFileName);
283 webDownloadPb.set_content_disposition(nativeWebDownloadItemImpl->contentDisposition);
284 webDownloadPb.set_mime_type(nativeWebDownloadItemImpl->mimeType);
285 webDownloadPb.set_last_modified(nativeWebDownloadItemImpl->lastModified);
286 webDownloadPb.set_state(
287 static_cast<browser_service::WebDownload::WebDownloadState>(nativeWebDownloadItemImpl->state));
288 webDownloadPb.set_method(nativeWebDownloadItemImpl->method);
289 webDownloadPb.set_last_error_code(nativeWebDownloadItemImpl->lastErrorCode);
290 webDownloadPb.set_received_slices(nativeWebDownloadItemImpl->receivedSlices);
291 webDownloadPb.set_download_path(nativeWebDownloadItemImpl->downloadPath);
292
293 std::string webDownloadValue;
294 webDownloadPb.SerializeToString(&webDownloadValue);
295 uint8_t* result = MallocUInt8(webDownloadValue);
296 if (result == nullptr) {
297 WEBVIEWLOGE("[DOWNLOAD] malloc failed");
298 *errCode = NWebError::NEW_OOM;
299 return CArrUI8 { nullptr, 0 };
300 }
301 *errCode = NWebError::NO_ERROR;
302 return CArrUI8 { result, webDownloadValue.length() };
303 }
304
FfiOHOSWebDownloadItemImplDeserialize(CArrUI8 serializedData,int32_t * errCode)305 int64_t FfiOHOSWebDownloadItemImplDeserialize(CArrUI8 serializedData, int32_t* errCode)
306 {
307 char* buffer = reinterpret_cast<char*>(serializedData.head);
308 browser_service::WebDownload webDownloadPb;
309 bool result = webDownloadPb.ParseFromArray(buffer, serializedData.size);
310 if (!result) {
311 *errCode = NWebError::INIT_ERROR;
312 return -1;
313 }
314 WebDownloadItemImpl* webDownloadItem = FFIData::Create<WebDownloadItemImpl>();
315 if (webDownloadItem == nullptr) {
316 WEBVIEWLOGE("new web download item failed");
317 *errCode = NWebError::INIT_ERROR;
318 return -1;
319 }
320 webDownloadItem->webDownloadId = webDownloadPb.web_download_id();
321 webDownloadItem->currentSpeed = webDownloadPb.current_speed();
322 webDownloadItem->percentComplete = webDownloadPb.percent_complete();
323 webDownloadItem->totalBytes = webDownloadPb.total_bytes();
324 webDownloadItem->receivedBytes = webDownloadPb.received_bytes();
325 webDownloadItem->guid = webDownloadPb.guid();
326 webDownloadItem->fullPath = webDownloadPb.full_path();
327 webDownloadItem->url = webDownloadPb.url();
328 webDownloadItem->etag = webDownloadPb.etag();
329 webDownloadItem->originalUrl = webDownloadPb.original_url();
330 webDownloadItem->suggestedFileName = webDownloadPb.suggested_file_name();
331 webDownloadItem->contentDisposition = webDownloadPb.content_disposition();
332 webDownloadItem->mimeType = webDownloadPb.mime_type();
333 webDownloadItem->lastModified = webDownloadPb.last_modified();
334 webDownloadItem->state = static_cast<NWebDownloadItemState>(webDownloadPb.state());
335 webDownloadItem->method = webDownloadPb.method();
336 webDownloadItem->lastErrorCode = webDownloadPb.last_error_code();
337 webDownloadItem->receivedSlices = webDownloadPb.received_slices();
338 webDownloadItem->downloadPath = webDownloadPb.download_path();
339 *errCode = NWebError::NO_ERROR;
340 return webDownloadItem->GetID();
341 }
342
343 // WebDownloadDelegateImpl
FfiOHOSWebDownloadDelegateImplConstructor()344 int64_t FfiOHOSWebDownloadDelegateImplConstructor()
345 {
346 auto nativeWebDownloadDelegateImpl = FFIData::Create<WebDownloadDelegateImpl>();
347 if (nativeWebDownloadDelegateImpl == nullptr) {
348 WEBVIEWLOGE("new web download delegate failed");
349 return -1;
350 }
351 return nativeWebDownloadDelegateImpl->GetID();
352 }
353
FfiOHOSWebDownloadDelegateImplOnBeforeDownload(int64_t id,void (* callback)(int64_t))354 void FfiOHOSWebDownloadDelegateImplOnBeforeDownload(int64_t id, void (*callback)(int64_t))
355 {
356 auto nativeWebDownloadDelegateImpl = FFIData::GetData<WebDownloadDelegateImpl>(id);
357 if (!nativeWebDownloadDelegateImpl) {
358 WEBVIEWLOGE("[DOWNLOAD] webDownloadDelegate is null");
359 return;
360 }
361 nativeWebDownloadDelegateImpl->PutDownloadBeforeStart(CJLambda::Create(callback));
362 }
363
FfiOHOSWebDownloadDelegateImplOnDownloadUpdated(int64_t id,void (* callback)(int64_t))364 void FfiOHOSWebDownloadDelegateImplOnDownloadUpdated(int64_t id, void (*callback)(int64_t))
365 {
366 auto nativeWebDownloadDelegateImpl = FFIData::GetData<WebDownloadDelegateImpl>(id);
367 if (!nativeWebDownloadDelegateImpl) {
368 WEBVIEWLOGE("[DOWNLOAD] webDownloadDelegate is null");
369 return;
370 }
371 nativeWebDownloadDelegateImpl->PutDownloadDidUpdate(CJLambda::Create(callback));
372 }
373
FfiOHOSWebDownloadDelegateImplOnDownloadFinish(int64_t id,void (* callback)(int64_t))374 void FfiOHOSWebDownloadDelegateImplOnDownloadFinish(int64_t id, void (*callback)(int64_t))
375 {
376 auto nativeWebDownloadDelegateImpl = FFIData::GetData<WebDownloadDelegateImpl>(id);
377 if (!nativeWebDownloadDelegateImpl) {
378 WEBVIEWLOGE("[DOWNLOAD] webDownloadDelegate is null");
379 return;
380 }
381 nativeWebDownloadDelegateImpl->PutDownloadDidFinish(CJLambda::Create(callback));
382 }
383
FfiOHOSWebDownloadDelegateImplOnDownloadFailed(int64_t id,void (* callback)(int64_t))384 void FfiOHOSWebDownloadDelegateImplOnDownloadFailed(int64_t id, void (*callback)(int64_t))
385 {
386 auto nativeWebDownloadDelegateImpl = FFIData::GetData<WebDownloadDelegateImpl>(id);
387 if (!nativeWebDownloadDelegateImpl) {
388 WEBVIEWLOGE("[DOWNLOAD] webDownloadDelegate is null");
389 return;
390 }
391 nativeWebDownloadDelegateImpl->PutDownloadDidFail(CJLambda::Create(callback));
392 }
393
394 // WebDownloadManagerImpl
FfiOHOSWebDownloadManagerImplSetDownloadDelegate(int64_t delegateId)395 void FfiOHOSWebDownloadManagerImplSetDownloadDelegate(int64_t delegateId)
396 {
397 auto nativeWebDownloadDelegateImpl = FFIData::GetData<WebDownloadDelegateImpl>(delegateId);
398 if (!nativeWebDownloadDelegateImpl) {
399 WEBVIEWLOGE("[DOWNLOAD] webDownloadDelegate is null");
400 return;
401 }
402 WebDownloadManagerImpl::SetDownloadDelegate(nativeWebDownloadDelegateImpl);
403 }
404
FfiOHOSWebDownloadManagerImplResumeDownload(int64_t itemId)405 int32_t FfiOHOSWebDownloadManagerImplResumeDownload(int64_t itemId)
406 {
407 if (!WebDownloadManagerImpl::HasValidDelegate()) {
408 return NWebError::NO_DOWNLOAD_DELEGATE_SET;
409 }
410 auto nativeWebDownloadItemImpl = FFIData::GetData<WebDownloadItemImpl>(itemId);
411 if (!nativeWebDownloadItemImpl) {
412 WEBVIEWLOGE("[DOWNLOAD] webDownloadDelegate is null");
413 return NWebError::INIT_ERROR;
414 }
415 WebDownloadManagerImpl::ResumeDownload(nativeWebDownloadItemImpl);
416 return NWebError::NO_ERROR;
417 }
418 }
419 } // namespace Webview
420 } // namespace OHOS