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 webDownloadItem->before_download_callback = wrapper; 66 webDownloadDelegate->DownloadBeforeStart(webDownloadItem); 67 } 68 DownloadDidUpdate(NWebDownloadItem *downloadItem, WebDownloadItemCallbackWrapper *wrapper)69 void DownloadDidUpdate(NWebDownloadItem *downloadItem, WebDownloadItemCallbackWrapper *wrapper) 70 { 71 WEBVIEWLOGI("DownloadDidUpdate."); 72 if (wrapper == nullptr) { 73 WEBVIEWLOGE("[DOWNLOAD] WebBeforeDownloadCallbackWrapper is null"); 74 return; 75 } 76 77 int32_t nwebId = WebDownloadItem_NWebId(downloadItem); 78 79 WebDownloadDelegateImpl *webDownloadDelegate = GetWebDownloadDelegate(nwebId); 80 if (!webDownloadDelegate) { 81 WEBVIEWLOGD("[DOWNLOAD] donn't found delegate for nweb."); 82 webDownloadDelegate = g_default_delegate; 83 } 84 85 if (!webDownloadDelegate) { 86 WEBVIEWLOGE("[DOWNLOAD] webDownloadDelegate is null"); 87 return; 88 } 89 WebDownloadItemImpl *webDownloadItem = FFIData::Create<WebDownloadItemImpl>(downloadItem); 90 // destroy download_item since copied content from download_item. 91 WebDownloadItem_Destroy(downloadItem); 92 webDownloadItem->download_item_callback = wrapper; 93 switch (webDownloadItem->state) { 94 case NWebDownloadItemState::PENDING: 95 // When in PENDING state, chromium call downloadDidUpdate 96 // while file path is temporary file, just stop calling ui. 97 webDownloadItem = nullptr; 98 break; 99 case NWebDownloadItemState::IN_PROGRESS: 100 case NWebDownloadItemState::PAUSED: 101 webDownloadDelegate->DownloadDidUpdate(webDownloadItem); 102 break; 103 case NWebDownloadItemState::INTERRUPTED: 104 case NWebDownloadItemState::CANCELED: 105 webDownloadDelegate->DownloadDidFail(webDownloadItem); 106 break; 107 case NWebDownloadItemState::COMPLETE: 108 webDownloadDelegate->DownloadDidFinish(webDownloadItem); 109 break; 110 case NWebDownloadItemState::MAX_DOWNLOAD_STATE: 111 default: 112 webDownloadItem = nullptr; 113 break; 114 } 115 } 116 } // namespace 117 118 // static RegisterDownloadCallback()119 void WebDownloadManagerImpl::RegisterDownloadCallback() 120 { 121 // Only regist once. 122 if (g_download_callback == nullptr) { 123 WEBVIEWLOGI("RegisterDownloadCallback."); 124 WebDownloader_CreateDownloadDelegateCallback(&g_download_callback); 125 WebDownloader_SetDownloadBeforeStart(g_download_callback, &DownloadBeforeStart); 126 WebDownloader_SetDownloadDidUpdate(g_download_callback, &DownloadDidUpdate); 127 WebDownloadManager_PutDownloadCallback(g_download_callback); 128 } else { 129 WEBVIEWLOGE("[DOWNLOAD] had RegisterDownloadCallback."); 130 } 131 } 132 133 // static RemoveDownloadDelegate(WebDownloadDelegateImpl *delegate)134 void WebDownloadManagerImpl::RemoveDownloadDelegate(WebDownloadDelegateImpl *delegate) 135 { 136 auto iterator = g_web_download_delegate_map.begin(); 137 while (iterator != g_web_download_delegate_map.end()) { 138 if (iterator->second == delegate) { 139 g_web_download_delegate_map.erase(iterator++); 140 } else { 141 iterator++; 142 } 143 } 144 } 145 146 // static AddDownloadDelegateForWeb(int32_t nwebId, WebDownloadDelegateImpl *delegate)147 void WebDownloadManagerImpl::AddDownloadDelegateForWeb(int32_t nwebId, WebDownloadDelegateImpl *delegate) 148 { 149 OHOS::NWeb::NWebHelper::Instance().LoadNWebSDK(); 150 g_web_download_delegate_map.insert_or_assign(nwebId, delegate); 151 RegisterDownloadCallback(); 152 } 153 154 // static SetDownloadDelegate(WebDownloadDelegateImpl *delegate)155 void WebDownloadManagerImpl::SetDownloadDelegate(WebDownloadDelegateImpl *delegate) 156 { 157 OHOS::NWeb::NWebHelper::Instance().LoadNWebSDK(); 158 if (!g_default_delegate) { 159 g_default_delegate = delegate; 160 RegisterDownloadCallback(); 161 } 162 } 163 164 // static HasValidDelegate()165 bool WebDownloadManagerImpl::HasValidDelegate() 166 { 167 if (!g_default_delegate) { 168 return false; 169 } 170 171 return true; 172 } 173 174 // static ResumeDownload(const WebDownloadItemImpl *webDownload)175 void WebDownloadManagerImpl::ResumeDownload(const WebDownloadItemImpl *webDownload) 176 { 177 WEBVIEWLOGD("[DOWNLOAD] WebDownloadManager::ResumeDownload"); 178 if (!webDownload) { 179 WEBVIEWLOGE("webDownload is nullptr"); 180 return; 181 } 182 OHOS::NWeb::NWebHelper::Instance().LoadNWebSDK(); 183 NWebDownloadItem *downloadItem = nullptr; 184 WebDownloadItem_CreateWebDownloadItem(&downloadItem); 185 WebDownloadItem_SetGuid(downloadItem, webDownload->guid.c_str()); 186 WebDownloadItem_SetUrl(downloadItem, webDownload->url.c_str()); 187 WebDownloadItem_SetFullPath(downloadItem, webDownload->fullPath.c_str()); 188 WebDownloadItem_SetETag(downloadItem, webDownload->etag.c_str()); 189 WebDownloadItem_SetMimeType(downloadItem, webDownload->mimeType.c_str()); 190 WebDownloadItem_SetReceivedBytes(downloadItem, webDownload->receivedBytes); 191 WebDownloadItem_SetTotalBytes(downloadItem, webDownload->totalBytes); 192 WebDownloadItem_SetReceivedSlices(downloadItem, webDownload->receivedSlices.c_str()); 193 WebDownloadItem_SetLastModified(downloadItem, webDownload->lastModified.c_str()); 194 WebDownloader_ResumeDownloadStatic(downloadItem); 195 return; 196 } 197 } // namespace NWeb 198