From 44bbe1ea36e08681c222fa9a8e88f13a099c92b2 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 29 Aug 2019 16:12:47 -0700 Subject: [PATCH] Add qt+ssl to qt launcher --- cmake/init.cmake | 6 ++- launchers/qt/CMakeLists.txt | 50 +++++++++++++++++-- launchers/qt/resources/qml/Login.qml | 2 + launchers/qt/src/Launcher.cpp | 2 +- launchers/qt/src/LauncherState.cpp | 75 ++++++++++++++++++++++++++++ launchers/qt/src/LauncherState.h | 23 ++++++++- launchers/qt/src/main.cpp | 4 ++ 7 files changed, 154 insertions(+), 8 deletions(-) diff --git a/cmake/init.cmake b/cmake/init.cmake index 3f632b30f8..fb72e828ea 100644 --- a/cmake/init.cmake +++ b/cmake/init.cmake @@ -30,12 +30,14 @@ endif () # CMAKE_CURRENT_SOURCE_DIR is the parent folder here set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/") -set(HF_CMAKE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +set(HF_CMAKE_DIR "${CMAKE_CURRENT_LIST_DIR}") set(MACRO_DIR "${HF_CMAKE_DIR}/macros") set(EXTERNAL_PROJECT_DIR "${HF_CMAKE_DIR}/externals") -file(GLOB HIFI_CUSTOM_MACROS "cmake/macros/*.cmake") +file(GLOB HIFI_CUSTOM_MACROS "${HF_CMAKE_DIR}/macros/*.cmake") +message("CMAKE FILEs: ${CMAKE_CURRENT_LIST_DIR} ${MACRO_DIR} ||") foreach(CUSTOM_MACRO ${HIFI_CUSTOM_MACROS}) + message("CMAKE FILE: ${CUSTOM_MACRO}") include(${CUSTOM_MACRO}) endforeach() unset(HIFI_CUSTOM_MACROS) diff --git a/launchers/qt/CMakeLists.txt b/launchers/qt/CMakeLists.txt index bd19e10341..ad31023cb7 100644 --- a/launchers/qt/CMakeLists.txt +++ b/launchers/qt/CMakeLists.txt @@ -1,14 +1,50 @@ cmake_minimum_required(VERSION 3.11) + project(HQLauncher) + set(CMAKE_CXX_STANDARD_REQUIRED_ON) -include("cmake/init.cmake") -find_package(Qt5 COMPONENTS Core Gui Qml Quick QuickControls2 Network REQUIRED) -find_package(OpenGL) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) #set(CMAKE_AUTOUIC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) + +include("cmake/init.cmake") + +include(ExternalProject) + +if (WIN32) + + ExternalProject_Add( + qtlite + URL "https://hifi-public.s3.amazonaws.com/huffman/launcher/qt-lite-ssl.zip" + URL_HASH MD5=83eeba1565e5727aef11655acf893c15 + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + LOG_DOWNLOAD 1 + ) + + + ExternalProject_Get_Property(qtlite SOURCE_DIR) + ExternalProject_Get_Property(qtlite STAMP_DIR) + + include("${STAMP_DIR}/download-qtlite.cmake") + include("${STAMP_DIR}/extract-qtlite.cmake") + include("${STAMP_DIR}/verify-qtlite.cmake") + + message("${SOURCE_DIR}/lib/cmake") + + list(APPEND CMAKE_PREFIX_PATH ${SOURCE_DIR}/lib/cmake) + + set(SSL_DIR ${SOURCE_DIR}/ssl) + message("SSL dir is ${SSL_DIR}") + +endif () + +find_package(Qt5 COMPONENTS Core Gui Qml Quick QuickControls2 Network REQUIRED) +find_package(OpenGL) + set(CUSTOM_LAUNCHER_QRC_PATHS "") set(RESOURCES_QRC ${CMAKE_CURRENT_BINARY_DIR}/resources.qrc) set(RESOURCES_RCC ${CMAKE_CURRENT_SOURCE_DIR}/resources.rcc) @@ -38,9 +74,12 @@ set(src_files src/LauncherWindow.h src/LauncherWindow.cpp) +set(TARGET_NAME ${PROJECT_NAME}) add_executable(${PROJECT_NAME} ${src_files}) -target_link_libraries(${PROJECT_NAME} PUBLIC +#target_openssl() + +target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Quick Qt5::QuickControls2 @@ -51,6 +90,9 @@ target_link_libraries(${PROJECT_NAME} PUBLIC ${OPENGL_LIBRARIES} ${plugin_libs} wsock32 ws2_32 Winmm version imm32 dwmapi + Crypt32 Iphlpapi + "${SSL_DIR}/lib/libeay32.lib" + "${SSL_DIR}/lib/ssleay32.lib" "${_qt5Core_install_prefix}/lib/qtpcre2.lib" "${_qt5Core_install_prefix}/lib/qtlibpng.lib" "${_qt5Core_install_prefix}/lib/qtfreetype.lib" diff --git a/launchers/qt/resources/qml/Login.qml b/launchers/qt/resources/qml/Login.qml index fb4dd2367b..c6cb949cca 100644 --- a/launchers/qt/resources/qml/Login.qml +++ b/launchers/qt/resources/qml/Login.qml @@ -105,5 +105,7 @@ Item { horizontalCenter: instruction.horizontalCenter topMargin: 48 } + + onClicked: LauncherState.login(username.text, password.text) } } diff --git a/launchers/qt/src/Launcher.cpp b/launchers/qt/src/Launcher.cpp index 10d30a7285..4c430e41ec 100644 --- a/launchers/qt/src/Launcher.cpp +++ b/launchers/qt/src/Launcher.cpp @@ -11,7 +11,7 @@ Launcher::Launcher(int& argc, char**argv) : QGuiApplication(argc, argv) { QString resourceBinaryLocation = QGuiApplication::applicationDirPath() + "/resources.rcc"; QResource::registerResource(resourceBinaryLocation); _launcherState = std::make_shared(); - _launcherState->setUIState(LauncherState::DOWNLOAD_SCREEN); + _launcherState->setUIState(LauncherState::LOGIN_SCREEN); _launcherWindow = std::make_unique(); _launcherWindow->rootContext()->setContextProperty("LauncherState", _launcherState.get()); _launcherWindow->setFlags(Qt::FramelessWindowHint); diff --git a/launchers/qt/src/LauncherState.cpp b/launchers/qt/src/LauncherState.cpp index 73197de9c1..214f587d2c 100644 --- a/launchers/qt/src/LauncherState.cpp +++ b/launchers/qt/src/LauncherState.cpp @@ -2,12 +2,68 @@ #include +#include +#include + +#include +#include +#include +#include + +#include #include static const std::array QML_FILE_FOR_UI_STATE = { { "qrc:/qml/SplashScreen.qml", "qrc:/qml/Login.qml", "qrc:/qml/DisplayName.qml", "qrc:/qml/Download.qml", "qrc:/qml/DownloadFinshed.qml", "qrc:/qml/Error.qml" } }; +LauncherState::LauncherState() { + // TODO Show splash screen until this request is complete + auto request = new QNetworkRequest(QUrl("https://thunder.highfidelity.com/builds/api/tags/latest/?format=json")); + auto reply = _networkAccessManager.get(*request); + QObject::connect(reply, &QNetworkReply::finished, [reply, this]() { + if (reply->error()) { + qDebug() << "Error getting builds from thunder: " << reply->errorString(); + } else { + qDebug() << "Builds reply has been received"; + auto data = reply->readAll(); + QJsonParseError parseError; + auto doc = QJsonDocument::fromJson(data, &parseError); + if (parseError.error) { + qDebug() << "Error parsing response from thunder: " << data; + } else { + auto root = doc.object(); + if (!root.contains("default_tag")) { + return; + } + + _latestBuilds.defaultTag = root["default_tag"].toString(); + + auto results = root["results"]; + if (!results.isArray()) { + return; + } + + for (auto result : results.toArray()) { + auto entry = result.toObject(); + Build build; + build.tag = entry["name"].toString(); + build.latestVersion = entry["latest_version"].toInt(); + build.buildNumber = entry["build_number"].toInt(); +#ifdef Q_OS_WIN + build.installerZipURL = entry["installers"].toObject()["windows"].toObject()["zip_url"].toString(); +#elif defined(Q_OS_MACOS) + build.installerZipURL = entry["installers"].toObject()["mac"].toObject()["zip_url"].toString(); +#else + #error "Launcher is only supported on Windows and Mac OS" +#endif + _latestBuilds.builds.push_back(build); + } + } + } + }); +} + QString LauncherState::getCurrentUISource() const { return QML_FILE_FOR_UI_STATE[getUIState()]; } @@ -31,3 +87,22 @@ void LauncherState::setLastLoginError(LastLoginError lastLoginError) { LauncherState::LastLoginError LauncherState::getLastLoginError() const { return _lastLoginError; } + +void LauncherState::login(QString username, QString password) { + qDebug() << "Got login: " << username << password; + + auto request = new QNetworkRequest(QUrl("https://metaverse.highfidelity.com/oauth/token")); + + request->setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); + QUrlQuery query; + query.addQueryItem("grant_type", "password"); + query.addQueryItem("username", username); + query.addQueryItem("password", password); + query.addQueryItem("scope", "owner"); + + auto reply = _networkAccessManager.post(*request, query.toString().toUtf8()); + + QObject::connect(reply, &QNetworkReply::finished, [reply, this]() { + qDebug() << "Got response for login: " << reply->readAll(); + }); +} diff --git a/launchers/qt/src/LauncherState.h b/launchers/qt/src/LauncherState.h index 081d6acfca..73e512be63 100644 --- a/launchers/qt/src/LauncherState.h +++ b/launchers/qt/src/LauncherState.h @@ -1,11 +1,24 @@ #include #include +#include + +struct Build { + QString tag; + int latestVersion; + int buildNumber; + QString installerZipURL; +}; + +struct LatestBuilds { + QString defaultTag; + std::vector builds; +}; class LauncherState : public QObject { Q_OBJECT public: - LauncherState() = default; + LauncherState(); ~LauncherState() = default; enum UIState { @@ -36,10 +49,18 @@ public: void setLastLoginError(LastLoginError lastLoginError); LastLoginError getLastLoginError() const; + + + // LOGIN + Q_INVOKABLE void login(QString username, QString password); + signals: void updateSourceUrl(QString sourceUrl); private: + QNetworkAccessManager _networkAccessManager; + LatestBuilds _latestBuilds; + UIState _uiState { SPLASH_SCREEN }; LastLoginError _lastLoginError { NONE }; }; diff --git a/launchers/qt/src/main.cpp b/launchers/qt/src/main.cpp index bf4e303e94..50bfb5f59d 100644 --- a/launchers/qt/src/main.cpp +++ b/launchers/qt/src/main.cpp @@ -2,11 +2,13 @@ #include "LauncherWindow.h" #include "Launcher.h" + //Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin); Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin); Q_IMPORT_PLUGIN(QtQuick2Plugin); Q_IMPORT_PLUGIN(QtQuickControls2Plugin); Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); + int main(int argc, char *argv[]) { QString name { "HQLauncher" }; @@ -14,5 +16,7 @@ int main(int argc, char *argv[]) QCoreApplication::setOrganizationName(name); Launcher launcher(argc, argv); + return launcher.exec(); + }