* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "web_download_manager.h"
#include <cstring>
#include "nweb_c_api.h"
#include "nweb_helper.h"
#include "nweb_log.h"
#include "web_download_delegate.h"
namespace OHOS {
namespace NWeb {
namespace {
static std::unique_ptr<OHOS::NWeb::WebDownloadDelegate> g_default_delegate;
static std::unordered_map<int32_t, WebDownloadDelegate *> g_web_download_delegate_map;
static WebDownloadDelegateCallback *g_download_callback;
WebDownloadDelegate *GetWebDownloadDelegate(int32_t nwebId)
{
auto it = g_web_download_delegate_map.find(nwebId);
if (it != g_web_download_delegate_map.end()) {
return it->second;
}
return nullptr;
}
void DownloadBeforeStart(NWebDownloadItem *downloadItem, WebBeforeDownloadCallbackWrapper *wrapper)
{
WVLOG_D("[DOWNLOAD] DownloadBeforeStart.");
if (wrapper == nullptr) {
WVLOG_E("[DOWNLOAD] WebBeforeDownloadCallbackWrapper is null");
return;
}
int32_t nwebId = WebDownloadItem_NWebId(downloadItem);
WebDownloadDelegate *webDownloadDelegate = GetWebDownloadDelegate(nwebId);
if (!webDownloadDelegate) {
WVLOG_D("[DOWNLOAD] donn't found delegate for nweb.");
webDownloadDelegate = g_default_delegate.get();
}
if (!webDownloadDelegate) {
WVLOG_E("[DOWNLOAD] webDownloadDelegate is null");
return;
}
WebDownloadItem *webDownloadItem = new WebDownloadItem(webDownloadDelegate->GetEnv(), downloadItem);
WebDownloadItem_Destroy(downloadItem);
webDownloadItem->before_download_callback = wrapper;
webDownloadDelegate->DownloadBeforeStart(webDownloadItem);
}
void DownloadDidUpdate(NWebDownloadItem *downloadItem, WebDownloadItemCallbackWrapper *wrapper)
{
WVLOG_D("DownloadDidUpdate.");
if (wrapper == nullptr) {
WVLOG_E("[DOWNLOAD] WebBeforeDownloadCallbackWrapper is null");
return;
}
int32_t nwebId = WebDownloadItem_NWebId(downloadItem);
WebDownloadDelegate *webDownloadDelegate = GetWebDownloadDelegate(nwebId);
if (!webDownloadDelegate) {
WVLOG_D("[DOWNLOAD] donn't found delegate for nweb.");
webDownloadDelegate = g_default_delegate.get();
}
if (!webDownloadDelegate) {
WVLOG_E("[DOWNLOAD] webDownloadDelegate is null");
return;
}
WebDownloadItem *webDownloadItem = new WebDownloadItem(webDownloadDelegate->GetEnv(), downloadItem);
WebDownloadItem_Destroy(downloadItem);
webDownloadItem->download_item_callback = wrapper;
switch (webDownloadItem->state) {
case NWebDownloadItemState::PENDING:
delete webDownloadItem;
webDownloadItem = nullptr;
break;
case NWebDownloadItemState::IN_PROGRESS:
case NWebDownloadItemState::PAUSED:
webDownloadDelegate->DownloadDidUpdate(webDownloadItem);
break;
case NWebDownloadItemState::INTERRUPTED:
case NWebDownloadItemState::CANCELED:
webDownloadDelegate->DownloadDidFail(webDownloadItem);
break;
case NWebDownloadItemState::COMPLETE:
webDownloadDelegate->DownloadDidFinish(webDownloadItem);
break;
case NWebDownloadItemState::MAX_DOWNLOAD_STATE:
default:
delete webDownloadItem;
webDownloadItem = nullptr;
break;
}
}
}
void WebDownloadManager::RegisterDownloadCallback()
{
if (g_download_callback == nullptr) {
WVLOG_I("RegisterDownloadCallback.");
WebDownloader_CreateDownloadDelegateCallback(&g_download_callback);
WebDownloader_SetDownloadBeforeStart(g_download_callback, &DownloadBeforeStart);
WebDownloader_SetDownloadDidUpdate(g_download_callback, &DownloadDidUpdate);
WebDownloadManager_PutDownloadCallback(g_download_callback);
} else {
WVLOG_I("[DOWNLOAD] had RegisterDownloadCallback.");
}
}
void WebDownloadManager::RemoveDownloadDelegate(WebDownloadDelegate *delegate)
{
auto iterator = g_web_download_delegate_map.begin();
while (iterator != g_web_download_delegate_map.end()) {
if (iterator->second == delegate) {
g_web_download_delegate_map.erase(iterator++);
} else {
iterator++;
}
}
}
void WebDownloadManager::AddDownloadDelegateForWeb(int32_t nwebId, WebDownloadDelegate *delegate)
{
NWebHelper::Instance().LoadNWebSDK();
g_web_download_delegate_map.insert_or_assign(nwebId, delegate);
RegisterDownloadCallback();
}
void WebDownloadManager::RemoveDownloadDelegateRef(int32_t nwebId)
{
auto iter = g_web_download_delegate_map.find(nwebId);
if (iter != g_web_download_delegate_map.end()) {
iter->second->RemoveSelfRef();
}
}
void WebDownloadManager::SetDownloadDelegate(WebDownloadDelegate *delegate)
{
NWebHelper::Instance().LoadNWebSDK();
if (!g_default_delegate) {
g_default_delegate = std::make_unique<WebDownloadDelegate>(*delegate);
RegisterDownloadCallback();
}
}
bool WebDownloadManager::HasValidDelegate()
{
if (!g_default_delegate) {
return false;
}
return true;
}
void WebDownloadManager::ResumeDownload(const WebDownloadItem *webDownload)
{
WVLOG_D("[DOWNLOAD] WebDownloadManager::ResumeDownload");
if (!webDownload) {
WVLOG_E("webDownload is nullptr");
return;
}
NWebHelper::Instance().LoadNWebSDK();
NWebDownloadItem *downloadItem = nullptr;
WebDownloadItem_CreateWebDownloadItem(&downloadItem);
WebDownloadItem_SetGuid(downloadItem, webDownload->guid.c_str());
WebDownloadItem_SetUrl(downloadItem, webDownload->url.c_str());
WebDownloadItem_SetFullPath(downloadItem, webDownload->fullPath.c_str());
WebDownloadItem_SetETag(downloadItem, webDownload->etag.c_str());
WebDownloadItem_SetMimeType(downloadItem, webDownload->mimeType.c_str());
WebDownloadItem_SetReceivedBytes(downloadItem, webDownload->receivedBytes);
WebDownloadItem_SetTotalBytes(downloadItem, webDownload->totalBytes);
WebDownloadItem_SetReceivedSlices(downloadItem, webDownload->receivedSlices.c_str());
WebDownloadItem_SetLastModified(downloadItem, webDownload->lastModified.c_str());
WebDownloadItem_SetOriginalUrl(downloadItem, webDownload->originalUrl.c_str());
WebDownloadItem_SetReferrerUrl(downloadItem, webDownload->referrerUrl.c_str());
if (!webDownload->urlChain.empty()) {
std::vector<char*> urlChainArray;
for (const auto& url : webDownload->urlChain) {
urlChainArray.push_back(const_cast<char*>(url.c_str()));
}
WebDownloadItem_SetUrlChain(downloadItem, urlChainArray.data(), urlChainArray.size());
}
WebDownloader_ResumeDownloadStatic(downloadItem);
return;
}
}
}