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 
25 namespace OHOS {
26 namespace NWeb {
27 namespace {
28 static std::unique_ptr<OHOS::NWeb::WebDownloadDelegate> g_default_delegate;
29 static std::unordered_map<int32_t, WebDownloadDelegate *> g_web_download_delegate_map;
30 static WebDownloadDelegateCallback *g_download_callback;
31 
GetWebDownloadDelegate(int32_t nwebId)32 WebDownloadDelegate *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 
DownloadBeforeStart(NWebDownloadItem * downloadItem,WebBeforeDownloadCallbackWrapper * wrapper)41 void 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 
DownloadDidUpdate(NWebDownloadItem * downloadItem,WebDownloadItemCallbackWrapper * wrapper)67 void 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
RegisterDownloadCallback()119 void 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
RemoveDownloadDelegate(WebDownloadDelegate * delegate)134 void 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
AddDownloadDelegateForWeb(int32_t nwebId,WebDownloadDelegate * delegate)147 void 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
RemoveDownloadDelegateRef(int32_t nwebId)155 void 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
SetDownloadDelegate(WebDownloadDelegate * delegate)164 void 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
HasValidDelegate()174 bool WebDownloadManager::HasValidDelegate()
175 {
176     if (!g_default_delegate) {
177         return false;
178     }
179 
180     return true;
181 }
182 
183 // static
ResumeDownload(const WebDownloadItem * webDownload)184 void 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