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;
 | 
						|
}
 | 
						|
 | 
						|
}
 |