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_manager_impl.h" 17 18 #include <cstring> 19 20 #include "ffi_remote_data.h" 21 #include "nweb_c_api.h" 22 #include "nweb_helper.h" 23 #include "webview_log.h" 24 #include "web_download_delegate_impl.h" 25 26 using namespace OHOS::FFI; 27 28 namespace OHOS::Webview { 29 namespace { 30 static sptr<WebDownloadDelegateImpl> g_default_delegate; 31 static std::unordered_map<int32_t, WebDownloadDelegateImpl *> g_web_download_delegate_map; 32 static WebDownloadDelegateCallback *g_download_callback; 33 GetWebDownloadDelegate(int32_t nwebId)34 WebDownloadDelegateImpl *GetWebDownloadDelegate(int32_t nwebId) 35 { 36 auto it = g_web_download_delegate_map.find(nwebId); 37 if (it != g_web_download_delegate_map.end()) { 38 return it->second; 39 } 40 return nullptr; 41 } 42 DownloadBeforeStart(NWebDownloadItem * downloadItem,WebBeforeDownloadCallbackWrapper * wrapper)43 void DownloadBeforeStart(NWebDownloadItem *downloadItem, WebBeforeDownloadCallbackWrapper *wrapper) 44 { 45 WEBVIEWLOGD("[DOWNLOAD] DownloadBeforeStart."); 46 if (wrapper == nullptr) { 47 WEBVIEWLOGE("[DOWNLOAD] WebBeforeDownloadCallbackWrapper is null"); 48 return; 49 } 50 int32_t nwebId = WebDownloadItem_NWebId(downloadItem); 51 WebDownloadDelegateImpl *webDownloadDelegate = GetWebDownloadDelegate(nwebId); 52 if (!webDownloadDelegate) { 53 WEBVIEWLOGD("[DOWNLOAD] donn't found delegate for nweb."); 54 webDownloadDelegate = g_default_delegate; 55 } 56 57 if (!webDownloadDelegate) { 58 WEBVIEWLOGE("[DOWNLOAD] webDownloadDelegate is null"); 59 return; 60 } 61 62 WebDownloadItemImpl *webDownloadItem = FFIData::Create<WebDownloadItemImpl>(downloadItem); 63 // destroy download_item since copied content from download_item. 64 WebDownloadItem_Destroy(downloadItem); 65 if (!webDownloadItem) { 66 WEBVIEWLOGE("[DOWNLOAD] webDownloadItem is null"); 67 return; 68 } 69 webDownloadItem->before_download_callback = wrapper; 70 webDownloadDelegate->DownloadBeforeStart(webDownloadItem); 71 } 72 DownloadDidUpdate(NWebDownloadItem * downloadItem,WebDownloadItemCallbackWrapper * wrapper)73 void DownloadDidUpdate(NWebDownloadItem *downloadItem, WebDownloadItemCallbackWrapper *wrapper) 74 { 75 WEBVIEWLOGI("DownloadDidUpdate."); 76 if (wrapper == nullptr) { 77 WEBVIEWLOGE("[DOWNLOAD] WebBeforeDownloadCallbackWrapper is null"); 78 return; 79 } 80 81 int32_t nwebId = WebDownloadItem_NWebId(downloadItem); 82 83 WebDownloadDelegateImpl *webDownloadDelegate = GetWebDownloadDelegate(nwebId); 84 if (!webDownloadDelegate) { 85 WEBVIEWLOGD("[DOWNLOAD] donn't found delegate for nweb."); 86 webDownloadDelegate = g_default_delegate; 87 } 88 89 if (!webDownloadDelegate) { 90 WEBVIEWLOGE("[DOWNLOAD] webDownloadDelegate is null"); 91 return; 92 } 93 WebDownloadItemImpl *webDownloadItem = FFIData::Create<WebDownloadItemImpl>(downloadItem); 94 // destroy download_item since copied content from download_item. 95 WebDownloadItem_Destroy(downloadItem); 96 if (!webDownloadItem) { 97 WEBVIEWLOGE("[DOWNLOAD] webDownloadItem is null"); 98 return; 99 } 100 webDownloadItem->download_item_callback = wrapper; 101 switch (webDownloadItem->state) { 102 case NWebDownloadItemState::PENDING: 103 // When in PENDING state, chromium call downloadDidUpdate 104 // while file path is temporary file, just stop calling ui. 105 webDownloadItem = nullptr; 106 break; 107 case NWebDownloadItemState::IN_PROGRESS: 108 case NWebDownloadItemState::PAUSED: 109 webDownloadDelegate->DownloadDidUpdate(webDownloadItem); 110 break; 111 case NWebDownloadItemState::INTERRUPTED: 112 case NWebDownloadItemState::CANCELED: 113 webDownloadDelegate->DownloadDidFail(webDownloadItem); 114 break; 115 case NWebDownloadItemState::COMPLETE: 116 webDownloadDelegate->DownloadDidFinish(webDownloadItem); 117 break; 118 case NWebDownloadItemState::MAX_DOWNLOAD_STATE: 119 default: 120 webDownloadItem = nullptr; 121 break; 122 } 123 } 124 } // namespace 125 126 // static RegisterDownloadCallback()127 void WebDownloadManagerImpl::RegisterDownloadCallback() 128 { 129 // Only regist once. 130 if (g_download_callback == nullptr) { 131 WEBVIEWLOGI("RegisterDownloadCallback."); 132 WebDownloader_CreateDownloadDelegateCallback(&g_download_callback); 133 WebDownloader_SetDownloadBeforeStart(g_download_callback, &DownloadBeforeStart); 134 WebDownloader_SetDownloadDidUpdate(g_download_callback, &DownloadDidUpdate); 135 WebDownloadManager_PutDownloadCallback(g_download_callback); 136 } else { 137 WEBVIEWLOGE("[DOWNLOAD] had RegisterDownloadCallback."); 138 } 139 } 140 141 // static RemoveDownloadDelegate(WebDownloadDelegateImpl * delegate)142 void WebDownloadManagerImpl::RemoveDownloadDelegate(WebDownloadDelegateImpl *delegate) 143 { 144 auto iterator = g_web_download_delegate_map.begin(); 145 while (iterator != g_web_download_delegate_map.end()) { 146 if (iterator->second == delegate) { 147 g_web_download_delegate_map.erase(iterator++); 148 } else { 149 iterator++; 150 } 151 } 152 } 153 154 // static AddDownloadDelegateForWeb(int32_t nwebId,WebDownloadDelegateImpl * delegate)155 void WebDownloadManagerImpl::AddDownloadDelegateForWeb(int32_t nwebId, WebDownloadDelegateImpl *delegate) 156 { 157 OHOS::NWeb::NWebHelper::Instance().LoadNWebSDK(); 158 g_web_download_delegate_map.insert_or_assign(nwebId, delegate); 159 RegisterDownloadCallback(); 160 } 161 162 // static SetDownloadDelegate(WebDownloadDelegateImpl * delegate)163 void WebDownloadManagerImpl::SetDownloadDelegate(WebDownloadDelegateImpl *delegate) 164 { 165 OHOS::NWeb::NWebHelper::Instance().LoadNWebSDK(); 166 if (!g_default_delegate) { 167 g_default_delegate = delegate; 168 RegisterDownloadCallback(); 169 } 170 } 171 172 // static HasValidDelegate()173 bool WebDownloadManagerImpl::HasValidDelegate() 174 { 175 if (!g_default_delegate) { 176 return false; 177 } 178 179 return true; 180 } 181 182 // static ResumeDownload(const WebDownloadItemImpl * webDownload)183 void WebDownloadManagerImpl::ResumeDownload(const WebDownloadItemImpl *webDownload) 184 { 185 WEBVIEWLOGD("[DOWNLOAD] WebDownloadManager::ResumeDownload"); 186 if (!webDownload) { 187 WEBVIEWLOGE("webDownload is nullptr"); 188 return; 189 } 190 OHOS::NWeb::NWebHelper::Instance().LoadNWebSDK(); 191 NWebDownloadItem *downloadItem = nullptr; 192 WebDownloadItem_CreateWebDownloadItem(&downloadItem); 193 WebDownloadItem_SetGuid(downloadItem, webDownload->guid.c_str()); 194 WebDownloadItem_SetUrl(downloadItem, webDownload->url.c_str()); 195 WebDownloadItem_SetFullPath(downloadItem, webDownload->fullPath.c_str()); 196 WebDownloadItem_SetETag(downloadItem, webDownload->etag.c_str()); 197 WebDownloadItem_SetMimeType(downloadItem, webDownload->mimeType.c_str()); 198 WebDownloadItem_SetReceivedBytes(downloadItem, webDownload->receivedBytes); 199 WebDownloadItem_SetTotalBytes(downloadItem, webDownload->totalBytes); 200 WebDownloadItem_SetReceivedSlices(downloadItem, webDownload->receivedSlices.c_str()); 201 WebDownloadItem_SetLastModified(downloadItem, webDownload->lastModified.c_str()); 202 WebDownloader_ResumeDownloadStatic(downloadItem); 203 return; 204 } 205 } // namespace NWeb 206