Skip to content

Commit 3adc475

Browse files
committed
Implement various updater improvements from MPN
1 parent da9e1a6 commit 3adc475

File tree

10 files changed

+345
-255
lines changed

10 files changed

+345
-255
lines changed

Source/Core/Common/HttpRequest.cpp

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,21 @@ class HttpRequest::Impl final
3434
s32 GetLastResponseCode();
3535
Response Fetch(const std::string& url, Method method, const Headers& headers, const u8* payload,
3636
size_t size, AllowedReturnCodes codes = AllowedReturnCodes::Ok_Only,
37-
std::span<Multiform> multiform = {});
37+
const std::vector<Multiform>& multiform = {});
3838

3939
static int CurlProgressCallback(Impl* impl, curl_off_t dltotal, curl_off_t dlnow,
4040
curl_off_t ultotal, curl_off_t ulnow);
4141
std::string EscapeComponent(const std::string& string);
42+
std::string GetFinalUrl() const { return m_final_url; }
4243

44+
void SetProgressCallback(ProgressCallback callback);
4345
private:
4446
static inline std::once_flag s_curl_was_initialized;
4547
ProgressCallback m_callback;
4648
Headers m_response_headers;
4749
std::unique_ptr<CURL, decltype(&curl_easy_cleanup)> m_curl{nullptr, curl_easy_cleanup};
4850
std::string m_error_string;
51+
std::string m_final_url;
4952
};
5053

5154
HttpRequest::HttpRequest(std::chrono::milliseconds timeout_ms, ProgressCallback callback)
@@ -55,6 +58,15 @@ HttpRequest::HttpRequest(std::chrono::milliseconds timeout_ms, ProgressCallback
5558

5659
HttpRequest::~HttpRequest() = default;
5760

61+
void HttpRequest::SetProgressCallback(ProgressCallback callback)
62+
{
63+
m_callback = std::move(callback);
64+
if (m_impl)
65+
{
66+
m_impl->SetProgressCallback(m_callback);
67+
}
68+
}
69+
5870
bool HttpRequest::IsValid() const
5971
{
6072
return m_impl->IsValid();
@@ -115,8 +127,8 @@ int HttpRequest::Impl::CurlProgressCallback(Impl* impl, curl_off_t dltotal, curl
115127
// Call the progress callback with the current download progress
116128
if (impl->m_callback)
117129
{
118-
return !impl->m_callback(static_cast<s64>(dltotal), static_cast<s64>(dlnow),
119-
static_cast<s64>(ultotal), static_cast<s64>(ulnow));
130+
return impl->m_callback(static_cast<s64>(dltotal), static_cast<s64>(dlnow),
131+
static_cast<s64>(ultotal), static_cast<s64>(ulnow)) ? 0 : 1;
120132
}
121133
return 0; // If no callback, continue
122134
}
@@ -183,7 +195,7 @@ void HttpRequest::Impl::UseIPv4()
183195
}
184196

185197
HttpRequest::Response HttpRequest::PostMultiform(const std::string& url,
186-
std::span<Multiform> multiform,
198+
const std::vector<Multiform>& multiform,
187199
const Headers& headers, AllowedReturnCodes codes)
188200
{
189201
return m_impl->Fetch(url, Impl::Method::POST, headers, nullptr, 0, codes, multiform);
@@ -195,6 +207,20 @@ void HttpRequest::Impl::FollowRedirects(long max)
195207
curl_easy_setopt(m_curl.get(), CURLOPT_MAXREDIRS, max);
196208
}
197209

210+
void HttpRequest::Impl::SetProgressCallback(ProgressCallback callback)
211+
{
212+
m_callback = std::move(callback);
213+
if (m_curl)
214+
{
215+
curl_easy_setopt(m_curl.get(), CURLOPT_NOPROGRESS, m_callback == nullptr);
216+
if (m_callback)
217+
{
218+
curl_easy_setopt(m_curl.get(), CURLOPT_PROGRESSDATA, this);
219+
curl_easy_setopt(m_curl.get(), CURLOPT_XFERINFOFUNCTION, CurlProgressCallback);
220+
}
221+
}
222+
}
223+
198224
std::string HttpRequest::Impl::GetHeaderValue(std::string_view name) const
199225
{
200226
for (const auto& [key, value] : m_response_headers)
@@ -241,12 +267,12 @@ static size_t header_callback(char* buffer, size_t size, size_t nitems, void* us
241267
HttpRequest::Response HttpRequest::Impl::Fetch(const std::string& url, Method method,
242268
const Headers& headers, const u8* payload,
243269
size_t size, AllowedReturnCodes codes,
244-
std::span<Multiform> multiform)
270+
const std::vector<Multiform>& multiform)
245271
{
246272
m_response_headers.clear();
247-
curl_easy_setopt(m_curl.get(), CURLOPT_POST, method == Method::POST);
273+
curl_easy_setopt(m_curl.get(), CURLOPT_POST, method == Impl::Method::POST);
248274
curl_easy_setopt(m_curl.get(), CURLOPT_URL, url.c_str());
249-
if (method == Method::POST && multiform.empty())
275+
if (method == Impl::Method::POST && multiform.empty())
250276
{
251277
curl_easy_setopt(m_curl.get(), CURLOPT_POSTFIELDS, payload);
252278
curl_easy_setopt(m_curl.get(), CURLOPT_POSTFIELDSIZE, size);
@@ -273,9 +299,9 @@ HttpRequest::Response HttpRequest::Impl::Fetch(const std::string& url, Method me
273299
{
274300
if (!value)
275301
list = curl_slist_append(list, (name + ':').c_str());
276-
else if (value->empty())
302+
else if (value && value->empty())
277303
list = curl_slist_append(list, (name + ';').c_str());
278-
else
304+
else if (value)
279305
list = curl_slist_append(list, (name + ": " + *value).c_str());
280306
}
281307

@@ -290,14 +316,20 @@ HttpRequest::Response HttpRequest::Impl::Fetch(const std::string& url, Method me
290316
curl_easy_setopt(m_curl.get(), CURLOPT_WRITEFUNCTION, CurlWriteCallback);
291317
curl_easy_setopt(m_curl.get(), CURLOPT_WRITEDATA, &buffer);
292318

293-
const char* type = method == Method::POST ? "POST" : "GET";
319+
const char* type = method == Impl::Method::POST ? "POST" : "GET";
294320
const CURLcode res = curl_easy_perform(m_curl.get());
295321
if (res != CURLE_OK)
296322
{
297323
ERROR_LOG_FMT(COMMON, "Failed to {} {}: {}", type, url, m_error_string);
298324
return {};
299325
}
300326

327+
// Store the final URL after redirects
328+
char* final_url = nullptr;
329+
if (curl_easy_getinfo(m_curl.get(), CURLINFO_EFFECTIVE_URL, &final_url) == CURLE_OK && final_url)
330+
m_final_url = final_url;
331+
else
332+
m_final_url.clear();
301333
if (codes == AllowedReturnCodes::All)
302334
return buffer;
303335

@@ -321,4 +353,10 @@ HttpRequest::Response HttpRequest::Impl::Fetch(const std::string& url, Method me
321353

322354
return buffer;
323355
}
356+
357+
std::string HttpRequest::GetFinalUrl() const
358+
{
359+
return m_impl->GetFinalUrl();
360+
}
361+
324362
} // namespace Common

Source/Core/Common/HttpRequest.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,7 @@ class HttpRequest final
2828
// Return false to abort the request
2929
using ProgressCallback = std::function<bool(s64 dltotal, s64 dlnow, s64 ultotal, s64 ulnow)>;
3030

31-
void SetProgressCallback(ProgressCallback callback) {
32-
m_callback = std::move(callback);
33-
}
34-
31+
void SetProgressCallback(ProgressCallback callback);
3532

3633
explicit HttpRequest(std::chrono::milliseconds timeout_ms = std::chrono::milliseconds{3000},
3734
ProgressCallback callback = nullptr);
@@ -60,10 +57,12 @@ class HttpRequest final
6057
Response Post(const std::string& url, const std::string& payload, const Headers& headers = {},
6158
AllowedReturnCodes codes = AllowedReturnCodes::Ok_Only);
6259

63-
Response PostMultiform(const std::string& url, std::span<Multiform> multiform,
60+
Response PostMultiform(const std::string& url, const std::vector<Multiform>& multiform,
6461
const Headers& headers = {},
6562
AllowedReturnCodes codes = AllowedReturnCodes::Ok_Only);
66-
63+
64+
std::string GetFinalUrl() const;
65+
6766
private:
6867
class Impl;
6968
std::unique_ptr<Impl> m_impl;

Source/Core/DolphinQt/CMakeLists.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,8 +276,6 @@ add_executable(dolphin-emu
276276
Main.cpp
277277
MainWindow.cpp
278278
MainWindow.h
279-
ProjectPlus/DownloadUpdateDialog.cpp
280-
ProjectPlus/DownloadUpdateDialog.h
281279
ProjectPlus/DownloadWorker.cpp
282280
ProjectPlus/DownloadWorker.h
283281
ProjectPlus/InstallUpdateDialog.cpp

Source/Core/DolphinQt/DolphinQt.vcxproj

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,6 @@
187187
<ClCompile Include="InfinityBase/InfinityBaseWindow.cpp" />
188188
<ClCompile Include="Main.cpp" />
189189
<ClCompile Include="MainWindow.cpp" />
190-
<ClCompile Include="ProjectPlus/DownloadUpdateDialog.cpp" />
191190
<ClCompile Include="ProjectPlus/DownloadWorker.cpp" />
192191
<ClCompile Include="ProjectPlus/InstallUpdateDialog.cpp" />
193192
<ClCompile Include="ProjectPlus/UpdateDialog.cpp" />
@@ -408,7 +407,6 @@
408407
<QtMoc Include="HotkeyScheduler.h" />
409408
<QtMoc Include="InfinityBase/InfinityBaseWindow.h" />
410409
<QtMoc Include="MainWindow.h" />
411-
<QtMoc Include="ProjectPlus/DownloadUpdateDialog.h" />
412410
<QtMoc Include="ProjectPlus/DownloadWorker.h" />
413411
<QtMoc Include="ProjectPlus/InstallUpdateDialog.h" />
414412
<QtMoc Include="ProjectPlus/UpdateDialog.h" />
@@ -529,4 +527,4 @@
529527
<Message Text="Copy: @(BinaryFiles) -&gt; $(BinaryOutputDir)" Importance="High" />
530528
<Copy SourceFiles="@(BinaryFiles)" DestinationFolder="$(BinaryOutputDir)" />
531529
</Target>
532-
</Project>
530+
</Project>

Source/Core/DolphinQt/ProjectPlus/DownloadUpdateDialog.cpp

Lines changed: 0 additions & 102 deletions
This file was deleted.

Source/Core/DolphinQt/ProjectPlus/DownloadUpdateDialog.h

Lines changed: 0 additions & 31 deletions
This file was deleted.

Source/Core/DolphinQt/ProjectPlus/DownloadWorker.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#include "DownloadWorker.h"
88
#include "Common/HttpRequest.h"
99
#include <QFile>
10-
#include <QMessageBox>
10+
#include <QDebug>
1111

1212
DownloadWorker::DownloadWorker(const QString& url, const QString& filename)
1313
: url(url), filename(filename) {}
@@ -18,7 +18,11 @@ void DownloadWorker::startDownload()
1818

1919
// Set the progress callback
2020
httpRequest.SetProgressCallback([this](s64 dltotal, s64 dlnow, s64 ultotal, s64 ulnow) {
21-
QMetaObject::invokeMethod(this, "updateProgress", Qt::QueuedConnection, Q_ARG(s64, dlnow), Q_ARG(s64, dltotal));
21+
// Debug output to see if callback is being called
22+
qDebug() << "Progress callback called:" << dlnow << "/" << dltotal << "bytes";
23+
24+
// Emit the progress signal directly instead of calling updateProgress
25+
emit progressUpdated(static_cast<qint64>(dlnow), static_cast<qint64>(dltotal));
2226
return true; // Continue the download
2327
});
2428

@@ -29,7 +33,14 @@ void DownloadWorker::startDownload()
2933

3034
// Perform the GET request
3135
auto response = httpRequest.Get(url.toStdString(), headers);
32-
36+
37+
// Check if the final URL is the expected GitHub objects CDN
38+
std::string final_url = httpRequest.GetFinalUrl();
39+
if (final_url.find("objects.githubusercontent.com") == std::string::npos) {
40+
emit errorOccurred(QStringLiteral("Did not reach the expected GitHub objects URL. Final URL: %1").arg(QString::fromStdString(final_url)));
41+
return;
42+
}
43+
3344
// Check the response
3445
if (response)
3546
{
@@ -53,4 +64,4 @@ void DownloadWorker::startDownload()
5364
void DownloadWorker::updateProgress(qint64 dlnow, qint64 dltotal) // Change s64 to qint64
5465
{
5566
emit progressUpdated(dlnow, dltotal); // Emit progress signal
56-
}
67+
}

0 commit comments

Comments
 (0)