178 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			178 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* Copyright 2013-2021 MultiMC Contributors
 | |
|  *
 | |
|  * 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 "DownloadTask.h"
 | |
| 
 | |
| #include "updater/UpdateChecker.h"
 | |
| #include "GoUpdate.h"
 | |
| #include "net/NetJob.h"
 | |
| 
 | |
| #include <QFile>
 | |
| #include <QTemporaryDir>
 | |
| #include <QCryptographicHash>
 | |
| 
 | |
| namespace GoUpdate
 | |
| {
 | |
| 
 | |
| DownloadTask::DownloadTask(
 | |
|     shared_qobject_ptr<QNetworkAccessManager> network,
 | |
|     Status status,
 | |
|     QString target,
 | |
|     QObject *parent
 | |
| ) : Task(parent), m_updateFilesDir(target), m_network(network)
 | |
| {
 | |
|     m_status = status;
 | |
| 
 | |
|     m_updateFilesDir.setAutoRemove(false);
 | |
| }
 | |
| 
 | |
| void DownloadTask::executeTask()
 | |
| {
 | |
|     loadVersionInfo();
 | |
| }
 | |
| 
 | |
| void DownloadTask::loadVersionInfo()
 | |
| {
 | |
|     setStatus(tr("Loading version information..."));
 | |
| 
 | |
|     NetJob *netJob = new NetJob("Version Info", m_network);
 | |
| 
 | |
|     // Find the index URL.
 | |
|     QUrl newIndexUrl = QUrl(m_status.newRepoUrl).resolved(QString::number(m_status.newVersionId) + ".json");
 | |
|     qDebug() << m_status.newRepoUrl << " turns into " << newIndexUrl;
 | |
| 
 | |
|     netJob->addNetAction(m_newVersionFileListDownload = Net::Download::makeByteArray(newIndexUrl, &newVersionFileListData));
 | |
| 
 | |
|     // If we have a current version URL, get that one too.
 | |
|     if (!m_status.currentRepoUrl.isEmpty())
 | |
|     {
 | |
|         QUrl cIndexUrl = QUrl(m_status.currentRepoUrl).resolved(QString::number(m_status.currentVersionId) + ".json");
 | |
|         netJob->addNetAction(m_currentVersionFileListDownload = Net::Download::makeByteArray(cIndexUrl, ¤tVersionFileListData));
 | |
|         qDebug() << m_status.currentRepoUrl << " turns into " << cIndexUrl;
 | |
|     }
 | |
| 
 | |
|     // connect signals and start the job
 | |
|     connect(netJob, &NetJob::succeeded, this, &DownloadTask::processDownloadedVersionInfo);
 | |
|     connect(netJob, &NetJob::failed, this, &DownloadTask::vinfoDownloadFailed);
 | |
|     m_vinfoNetJob.reset(netJob);
 | |
|     netJob->start();
 | |
| }
 | |
| 
 | |
| void DownloadTask::vinfoDownloadFailed()
 | |
| {
 | |
|     // Something failed. We really need the second download (current version info), so parse
 | |
|     // downloads anyways as long as the first one succeeded.
 | |
|     if (m_newVersionFileListDownload->wasSuccessful())
 | |
|     {
 | |
|         processDownloadedVersionInfo();
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     // TODO: Give a more detailed error message.
 | |
|     qCritical() << "Failed to download version info files.";
 | |
|     emitFailed(tr("Failed to download version info files."));
 | |
| }
 | |
| 
 | |
| void DownloadTask::processDownloadedVersionInfo()
 | |
| {
 | |
|     VersionFileList m_currentVersionFileList;
 | |
|     VersionFileList m_newVersionFileList;
 | |
| 
 | |
|     setStatus(tr("Reading file list for new version..."));
 | |
|     qDebug() << "Reading file list for new version...";
 | |
|     QString error;
 | |
|     if (!parseVersionInfo(newVersionFileListData, m_newVersionFileList, error))
 | |
|     {
 | |
|         qCritical() << error;
 | |
|         emitFailed(error);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     // if we have the current version info, use it.
 | |
|     if (m_currentVersionFileListDownload && m_currentVersionFileListDownload->wasSuccessful())
 | |
|     {
 | |
|         setStatus(tr("Reading file list for current version..."));
 | |
|         qDebug() << "Reading file list for current version...";
 | |
|         // if this fails, it's not a complete loss.
 | |
|         QString error;
 | |
|         if(!parseVersionInfo( currentVersionFileListData, m_currentVersionFileList, error))
 | |
|         {
 | |
|             qDebug() << error << "This is not a fatal error.";
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // We don't need this any more.
 | |
|     m_currentVersionFileListDownload.reset();
 | |
|     m_newVersionFileListDownload.reset();
 | |
|     m_vinfoNetJob.reset();
 | |
| 
 | |
|     setStatus(tr("Processing file lists - figuring out how to install the update..."));
 | |
| 
 | |
|     // make a new netjob for the actual update files
 | |
|     NetJob::Ptr netJob = new NetJob("Update Files", m_network);
 | |
| 
 | |
|     // fill netJob and operationList
 | |
|     if (!processFileLists(m_currentVersionFileList, m_newVersionFileList, m_status.rootPath, m_updateFilesDir.path(), netJob, m_operations))
 | |
|     {
 | |
|         emitFailed(tr("Failed to process update lists..."));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     // Now start the download.
 | |
|     QObject::connect(netJob.get(), &NetJob::succeeded, this, &DownloadTask::fileDownloadFinished);
 | |
|     QObject::connect(netJob.get(), &NetJob::progress, this, &DownloadTask::fileDownloadProgressChanged);
 | |
|     QObject::connect(netJob.get(), &NetJob::failed, this, &DownloadTask::fileDownloadFailed);
 | |
| 
 | |
|     if(netJob->size() == 1) // Translation issues... see https://github.com/MultiMC/Launcher/issues/1701
 | |
|     {
 | |
|         setStatus(tr("Downloading one update file."));
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         setStatus(tr("Downloading %1 update files.").arg(QString::number(netJob->size())));
 | |
|     }
 | |
|     qDebug() << "Begin downloading update files to" << m_updateFilesDir.path();
 | |
|     m_filesNetJob = netJob;
 | |
|     m_filesNetJob->start();
 | |
| }
 | |
| 
 | |
| void DownloadTask::fileDownloadFinished()
 | |
| {
 | |
|     emitSucceeded();
 | |
| }
 | |
| 
 | |
| void DownloadTask::fileDownloadFailed(QString reason)
 | |
| {
 | |
|     qCritical() << "Failed to download update files:" << reason;
 | |
|     emitFailed(tr("Failed to download update files: %1").arg(reason));
 | |
| }
 | |
| 
 | |
| void DownloadTask::fileDownloadProgressChanged(qint64 current, qint64 total)
 | |
| {
 | |
|     setProgress(current, total);
 | |
| }
 | |
| 
 | |
| QString DownloadTask::updateFilesDir()
 | |
| {
 | |
|     return m_updateFilesDir.path();
 | |
| }
 | |
| 
 | |
| OperationList DownloadTask::operations()
 | |
| {
 | |
|     return m_operations;
 | |
| }
 | |
| 
 | |
| }
 |