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