diff --git a/internal/frontend/bridge-gui/bridge-gui-tester/main.cpp b/internal/frontend/bridge-gui/bridge-gui-tester/main.cpp index 0801bfb3..9e828eb8 100644 --- a/internal/frontend/bridge-gui/bridge-gui-tester/main.cpp +++ b/internal/frontend/bridge-gui/bridge-gui-tester/main.cpp @@ -19,7 +19,6 @@ #include "MainWindow.h" #include "AppController.h" #include "GRPCServerWorker.h" -#include #include #include @@ -58,35 +57,30 @@ int main(int argc, char **argv) QApplication::setOrganizationDomain("proton.ch"); QApplication::setQuitOnLastWindowClosed(true); - app().log().setEchoInConsole(true); - app().log().info(QString("%1 started.").arg(applicationName)); + Log& log = app().log(); + log.setEchoInConsole(true); + log.info(QString("%1 started.").arg(applicationName)); MainWindow window(nullptr); app().setMainWindow(&window); window.setWindowTitle(QApplication::applicationName()); window.show(); - GRPCServerWorker *serverWorker = new GRPCServerWorker(nullptr); + auto *serverWorker = new GRPCServerWorker(nullptr); QObject::connect(serverWorker, &Worker::started, []() { app().log().info("Server worker started."); }); QObject::connect(serverWorker, &Worker::finished, []() { app().log().info("Server worker finished."); }); - QObject::connect(serverWorker, &Worker::error, [](QString const &message) { - throw Exception(QString("gRPC Server encountered an error: %1").arg(message)); - }); + QObject::connect(serverWorker, &Worker::error, [&](QString const &message) { app().log().error(message); qApp->exit(EXIT_FAILURE); }); UPOverseer overseer = std::make_unique(serverWorker, nullptr); overseer->startWorker(true); qint32 const exitCode = QApplication::exec(); serverWorker->stop(); - while (!overseer->isFinished()) - { - QThread::msleep(10); - } + if (!overseer->wait(5000)) + log.warn("gRPC server took too long to finish."); app().log().info(QString("%1 exiting with code %2.").arg(applicationName).arg(exitCode)); - return exitCode; - } catch (Exception const &e) { diff --git a/internal/frontend/bridge-gui/bridge-gui/AppController.cpp b/internal/frontend/bridge-gui/bridge-gui/AppController.cpp index 0d6fe09d..c383d8ee 100644 --- a/internal/frontend/bridge-gui/bridge-gui/AppController.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/AppController.cpp @@ -18,9 +18,9 @@ #include "AppController.h" #include "QMLBackend.h" -#include "BridgeMonitor.h" #include #include +#include #include @@ -51,14 +51,14 @@ AppController::AppController() //**************************************************************************************************************************************************** /// \return The bridge worker, which can be null if the application was run in 'attach' mode (-a command-line switch). //**************************************************************************************************************************************************** -BridgeMonitor *AppController::bridgeMonitor() const +ProcessMonitor *AppController::bridgeMonitor() const { if (!bridgeOverseer_) return nullptr; // null bridgeOverseer is OK, it means we run in 'attached' mode (app attached to an already runnning instance of Bridge). - // but if bridgeOverseer is not null, its attached worker must be a valid BridgeMonitor instance. - auto *monitor = dynamic_cast(bridgeOverseer_->worker()); + // but if bridgeOverseer is not null, its attached worker must be a valid ProcessMonitor instance. + auto *monitor = dynamic_cast(bridgeOverseer_->worker()); if (!monitor) throw Exception("Could not retrieve bridge monitor"); diff --git a/internal/frontend/bridge-gui/bridge-gui/AppController.h b/internal/frontend/bridge-gui/bridge-gui/AppController.h index 82e93972..6a04470e 100644 --- a/internal/frontend/bridge-gui/bridge-gui/AppController.h +++ b/internal/frontend/bridge-gui/bridge-gui/AppController.h @@ -21,7 +21,6 @@ class QMLBackend; -class BridgeMonitor; namespace bridgepp @@ -29,6 +28,7 @@ namespace bridgepp class Log; class Overseer; class GRPCClient; +class ProcessMonitor; } @@ -50,7 +50,7 @@ public: // member functions. bridgepp::GRPCClient& grpc() { return *grpc_; } ///< Return a reference to the GRPC client. bridgepp::Log& log() { return *log_; } ///< Return a reference to the log. std::unique_ptr& bridgeOverseer() { return bridgeOverseer_; }; ///< Returns a reference the bridge overseer - BridgeMonitor* bridgeMonitor() const; ///< Return the bridge worker. + bridgepp::ProcessMonitor* bridgeMonitor() const; ///< Return the bridge worker. private: // member functions AppController(); ///< Default constructor. diff --git a/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt b/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt index f51b9765..6a8eafc6 100644 --- a/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt +++ b/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt @@ -82,7 +82,6 @@ endif() add_executable(bridge-gui Resources.qrc AppController.cpp AppController.h - BridgeMonitor.cpp BridgeMonitor.h EventStreamWorker.cpp EventStreamWorker.h main.cpp Pch.h diff --git a/internal/frontend/bridge-gui/bridge-gui/EventStreamWorker.cpp b/internal/frontend/bridge-gui/bridge-gui/EventStreamWorker.cpp index 63012df3..ec79dcc4 100644 --- a/internal/frontend/bridge-gui/bridge-gui/EventStreamWorker.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/EventStreamWorker.cpp @@ -31,8 +31,8 @@ using namespace bridgepp; EventStreamReader::EventStreamReader(QObject *parent) : Worker(parent) { - connect(this, &EventStreamReader::started, [&]() { app().log().debug("EventStreamReader started");}); - connect(this, &EventStreamReader::finished, [&]() { app().log().debug("EventStreamReader finished");}); + connect(this, &EventStreamReader::started, [&]() { app().log().debug("EventStreamReader started"); }); + connect(this, &EventStreamReader::finished, [&]() { app().log().debug("EventStreamReader finished"); }); connect(this, &EventStreamReader::error, &app().log(), &Log::error); } diff --git a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp index dde3a11d..ec200c59 100644 --- a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp @@ -73,6 +73,18 @@ void QMLBackend::init() this->retrieveUserList(); } + +//**************************************************************************************************************************************************** +/// \param timeoutMs The timeout after which the function should return false if the event stream reader is not finished. if -1 one, the function +/// never times out. +/// \return false if and only if the timeout delay was reached. +//**************************************************************************************************************************************************** +bool QMLBackend::waitForEventStreamReaderToFinish(qint32 timeoutMs) +{ + return eventStreamOverseer_->wait(timeoutMs); +} + + //**************************************************************************************************************************************************** // //**************************************************************************************************************************************************** @@ -87,6 +99,7 @@ void QMLBackend::connectGrpcEvents() connect(client, &GRPCClient::reportBugFinished, this, &QMLBackend::reportBugFinished); connect(client, &GRPCClient::reportBugSuccess, this, &QMLBackend::bugReportSendSuccess); connect(client, &GRPCClient::reportBugError, this, &QMLBackend::bugReportSendError); + connect(client, &GRPCClient::showMainWindow, this, &QMLBackend::showMainWindow); // cache events connect(client, &GRPCClient::isCacheOnDiskEnabledChanged, this, &QMLBackend::isDiskCacheEnabledChanged); @@ -168,15 +181,6 @@ void QMLBackend::retrieveUserList() } -//**************************************************************************************************************************************************** -// -//**************************************************************************************************************************************************** -void QMLBackend::clearUserList() -{ - users_->reset(); -} - - //**************************************************************************************************************************************************** // //**************************************************************************************************************************************************** @@ -348,4 +352,4 @@ void QMLBackend::onResetFinished() { emit resetFinished(); this->restart(); -} \ No newline at end of file +} diff --git a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h index b31c3d40..03393b8f 100644 --- a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h +++ b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h @@ -42,7 +42,7 @@ public: // member functions. QMLBackend &operator=(QMLBackend const &) = delete; ///< Disabled assignment operator. QMLBackend &operator=(QMLBackend &&) = delete; ///< Disabled move assignment operator. void init(); ///< Initialize the backend. - void clearUserList(); ///< Clear the user list. + bool waitForEventStreamReaderToFinish(qint32 timeoutMs); ///< Wait for the event stream reader to finish. // invokable methods can be called from QML. They generally return a value, which slots cannot do. Q_INVOKABLE static QPoint getCursorPos(); // _ func() *core.QPoint `slot:"getCursorPos"` diff --git a/internal/frontend/bridge-gui/bridge-gui/UserList.cpp b/internal/frontend/bridge-gui/bridge-gui/UserList.cpp index ac0df9cd..b6fc0753 100644 --- a/internal/frontend/bridge-gui/bridge-gui/UserList.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/UserList.cpp @@ -91,6 +91,7 @@ void UserList::reset() this->beginResetModel(); users_.clear(); this->endResetModel(); + emit countChanged(0); } @@ -102,6 +103,7 @@ void UserList::reset(QList const &users) this->beginResetModel(); users_ = users; this->endResetModel(); + emit countChanged(users_.size()); } @@ -114,6 +116,7 @@ void UserList::appendUser(SPUser const &user) this->beginInsertRows(QModelIndex(), size, size); users_.append(user); this->endInsertRows(); + emit countChanged(users_.size()); } @@ -127,6 +130,7 @@ void UserList::removeUserAt(int row) this->beginRemoveRows(QModelIndex(), row, row); users_.removeAt(row); this->endRemoveRows(); + emit countChanged(users_.size()); } diff --git a/internal/frontend/bridge-gui/bridge-gui/Version.h b/internal/frontend/bridge-gui/bridge-gui/Version.h index 05db92d9..da56ee7e 100644 --- a/internal/frontend/bridge-gui/bridge-gui/Version.h +++ b/internal/frontend/bridge-gui/bridge-gui/Version.h @@ -19,6 +19,6 @@ #ifndef BRIDGE_GUI_VERSION_H #define BRIDGE_GUI_VERSION_H -#define PROJECT_VER "2.2.1+git" +#define PROJECT_VER "2.2.2+git" #endif // BRIDGE_GUI_VERSION_H diff --git a/internal/frontend/bridge-gui/bridge-gui/main.cpp b/internal/frontend/bridge-gui/bridge-gui/main.cpp index f90214bf..a9972c51 100644 --- a/internal/frontend/bridge-gui/bridge-gui/main.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/main.cpp @@ -17,11 +17,11 @@ #include "QMLBackend.h" -#include "BridgeMonitor.h" #include "Version.h" #include #include #include +#include using namespace bridgepp; @@ -29,11 +29,30 @@ using namespace bridgepp; namespace { + +/// \brief The file extension for the bridge executable file. +#ifdef Q_OS_WIN32 + QString const exeSuffix = ".exe"; +#else + QString const exeSuffix; +#endif + QString const launcherFlag = "--launcher"; ///< launcher flag parameter used for bridge. QString const bridgeLock = "bridge-gui.lock"; ///< file name used for the lock file. + QString const exeName = "proton-bridge" + exeSuffix; ///< The bridge executable file name.* } +//**************************************************************************************************************************************************** +/// \return The path of the bridge executable. +/// \return A null string if the executable could not be located. +//**************************************************************************************************************************************************** +QString locateBridgeExe() +{ + QFileInfo const fileInfo(QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(exeName)); + return (fileInfo.exists() && fileInfo.isFile() && fileInfo.isExecutable()) ? fileInfo.absoluteFilePath() : QString(); +} + //**************************************************************************************************************************************************** /// // initialize the Qt application. //**************************************************************************************************************************************************** @@ -93,7 +112,7 @@ QQmlComponent *createRootQmlComponent(QQmlApplicationEngine &engine) //**************************************************************************************************************************************************** /// \param[in] lock The lock file to be checked. -/// \return True if the lock can be taken, false otherwize. +/// \return True if the lock can be taken, false otherwise. //**************************************************************************************************************************************************** bool checkSingleInstance(QLockFile &lock) { @@ -168,14 +187,14 @@ void launchBridge(QStringList const &args) UPOverseer& overseer = app().bridgeOverseer(); overseer.reset(); - const QString bridgeExePath = BridgeMonitor::locateBridgeExe(); + const QString bridgeExePath = locateBridgeExe(); if (bridgeExePath.isEmpty()) throw Exception("Could not locate the bridge executable path"); else app().log().debug(QString("Bridge executable path: %1").arg(QDir::toNativeSeparators(bridgeExePath))); - overseer = std::make_unique(new BridgeMonitor(bridgeExePath, args, nullptr), nullptr); + overseer = std::make_unique(new ProcessMonitor(bridgeExePath, args, nullptr), nullptr); overseer->startWorker(true); } @@ -234,16 +253,16 @@ int main(int argc, char *argv[]) if (!rootObject) throw Exception("Could not create root object."); - BridgeMonitor *bridgeMonitor = app().bridgeMonitor(); + ProcessMonitor *bridgeMonitor = app().bridgeMonitor(); bool bridgeExited = false; bool startError = false; QMetaObject::Connection connection; if (bridgeMonitor) { - const BridgeMonitor::MonitorStatus& status = bridgeMonitor->getStatus(); + const ProcessMonitor::MonitorStatus& status = bridgeMonitor->getStatus(); if (!status.running && !attach) { - // BridgeMonitor already stopped meaning we are attached to an orphan Bridge. + // ProcessMonitor already stopped meaning we are attached to an orphan Bridge. // Restart the full process to be sure there is no more bridge orphans app().log().error("Found orphan bridge, need to restart."); app().backend().forceLauncher(launcher); @@ -254,7 +273,7 @@ int main(int argc, char *argv[]) else { app().log().debug(QString("Monitoring Bridge PID : %1").arg(status.pid)); - connection = QObject::connect(bridgeMonitor, &BridgeMonitor::processExited, [&](int returnCode) { + connection = QObject::connect(bridgeMonitor, &ProcessMonitor::processExited, [&](int returnCode) { bridgeExited = true;// clazy:exclude=lambda-in-connect qGuiApp->exit(returnCode); }); @@ -267,6 +286,8 @@ int main(int argc, char *argv[]) QObject::disconnect(connection); app().grpc().stopEventStream(); + if (!app().backend().waitForEventStreamReaderToFinish(5000)) + log.warn("Event stream reader took too long to finish."); // We manually delete the QML components to avoid warnings error due to order of deletion of C++ / JS objects and singletons. rootObject.reset(); @@ -280,7 +301,7 @@ int main(int argc, char *argv[]) } catch (Exception const &e) { - app().log().error(e.qwhat()); + QTextStream(stderr) << e.qwhat() << "\n"; return EXIT_FAILURE; } } diff --git a/internal/frontend/bridge-gui/bridge-gui/qml/ContentWrapper.qml b/internal/frontend/bridge-gui/bridge-gui/qml/ContentWrapper.qml index 65501965..c8468bf9 100644 --- a/internal/frontend/bridge-gui/bridge-gui/qml/ContentWrapper.qml +++ b/internal/frontend/bridge-gui/bridge-gui/qml/ContentWrapper.qml @@ -258,7 +258,7 @@ Item { signIn.username = this.user.username rightContent.showSignIn() } - onShowSetupGuide: { + onShowSetupGuide: function(user, address) { root.showSetupGuide(user,address) } } diff --git a/internal/frontend/bridge-gui/bridge-gui/qml/LocalCacheSettings.qml b/internal/frontend/bridge-gui/bridge-gui/qml/LocalCacheSettings.qml index 1cae357b..6c90ad2a 100644 --- a/internal/frontend/bridge-gui/bridge-gui/qml/LocalCacheSettings.qml +++ b/internal/frontend/bridge-gui/bridge-gui/qml/LocalCacheSettings.qml @@ -45,7 +45,6 @@ SettingsView { type: Label.Body color: root.colorScheme.text_weak Layout.fillWidth: true - Layout.maximumWidth: this.parent.Layout.maximumWidth wrapMode: Text.WordWrap } diff --git a/internal/frontend/bridge-gui/bridge-gui/qml/MainWindow.qml b/internal/frontend/bridge-gui/bridge-gui/qml/MainWindow.qml index e614c881..07b9a29c 100644 --- a/internal/frontend/bridge-gui/bridge-gui/qml/MainWindow.qml +++ b/internal/frontend/bridge-gui/bridge-gui/qml/MainWindow.qml @@ -52,7 +52,7 @@ ApplicationWindow { target: Backend.users function onRowsInserted(parent, first, last) { - // considerring that users are added one-by-one + // considering that users are added one-by-one var user = Backend.users.get(first) if (!user.loggedIn) { @@ -130,7 +130,7 @@ ApplicationWindow { Layout.fillHeight: true Layout.fillWidth: true - onShowSetupGuide: { + onShowSetupGuide: function(user, address) { root.showSetup(user,address) } } diff --git a/internal/frontend/bridge-gui/bridge-gui/qml/SMTPSettings.qml b/internal/frontend/bridge-gui/bridge-gui/qml/SMTPSettings.qml index 7a539129..06b5a46a 100644 --- a/internal/frontend/bridge-gui/bridge-gui/qml/SMTPSettings.qml +++ b/internal/frontend/bridge-gui/bridge-gui/qml/SMTPSettings.qml @@ -40,7 +40,6 @@ SettingsView { type: Label.Body color: root.colorScheme.text_weak Layout.fillWidth: true - Layout.maximumWidth: this.parent.Layout.maximumWidth wrapMode: Text.WordWrap } diff --git a/internal/frontend/bridge-gui/bridgepp/CMakeLists.txt b/internal/frontend/bridge-gui/bridgepp/CMakeLists.txt index 8ab7fb51..3b76a796 100644 --- a/internal/frontend/bridge-gui/bridgepp/CMakeLists.txt +++ b/internal/frontend/bridge-gui/bridgepp/CMakeLists.txt @@ -108,6 +108,7 @@ add_library(bridgepp bridgepp/GRPC/GRPCUtils.cpp bridgepp/GRPC/GRPCUtils.h ${PROTO_CPP_FILE} ${PROTO_H_FILE} ${GRPC_CPP_FILE} ${GRPC_H_FILE} bridgepp/Log/Log.h bridgepp/Log/Log.cpp + bridgepp/ProcessMonitor.cpp bridgepp/ProcessMonitor.h bridgepp/User/User.cpp bridgepp/User/User.h bridgepp/Worker/Worker.h bridgepp/Worker/Overseer.h bridgepp/Worker/Overseer.cpp ) diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeUtils.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeUtils.h index 8dc05854..87f009ad 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeUtils.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeUtils.h @@ -16,14 +16,15 @@ // along with Proton Mail Bridge. If not, see . -#ifndef BRIDGE_GUI_TESTER_BRIDGE_UTILS_H -#define BRIDGE_GUI_TESTER_BRIDGE_UTILS_H +#ifndef BRIDGE_PP_TESTER_BRIDGE_UTILS_H +#define BRIDGE_PP_TESTER_BRIDGE_UTILS_H #include -namespace bridgepp { +namespace bridgepp +{ QString userConfigDir(); ///< Get the path of the user configuration folder. @@ -34,8 +35,8 @@ QString randomFirstName(); ///< Get a random first name from a pre-determined li QString randomLastName(); ///< Get a random first name from a pre-determined list. SPUser randomUser(); ///< Get a random user. + } // namespace - -#endif // BRIDGE_GUI_TESTER_BRIDGE_UTILS_H +#endif // BRIDGE_PP_TESTER_BRIDGE_UTILS_H diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.h index 3f28b7ec..2658c088 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.h @@ -16,8 +16,8 @@ // along with Proton Mail Bridge. If not, see . -#ifndef BRIDGE_GUI_TESTER_EVENT_FACTORY_H -#define BRIDGE_GUI_TESTER_EVENT_FACTORY_H +#ifndef BRIDGE_PP_EVENT_FACTORY_H +#define BRIDGE_PP_EVENT_FACTORY_H #include "bridge.grpc.pb.h" @@ -85,4 +85,4 @@ SPStreamEvent newUserChangedEvent(QString const &userID); ///< Create a new User } // namespace bridgepp -#endif //BRIDGE_GUI_TESTER_EVENT_FACTORY_H +#endif //BRIDGE_PP_EVENT_FACTORY_H diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h index 8010b7e8..89dd4515 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h @@ -16,8 +16,8 @@ // along with Proton Mail Bridge. If not, see . -#ifndef BRIDGE_GUI_RPC_CLIENT_H -#define BRIDGE_GUI_RPC_CLIENT_H +#ifndef BRIDGE_PP_RPC_CLIENT_H +#define BRIDGE_PP_RPC_CLIENT_H #include "../User/User.h" @@ -233,4 +233,4 @@ private: // data members. } -#endif // BRIDGE_GUI_RPC_CLIENT_H +#endif // BRIDGE_PP_RPC_CLIENT_H diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCUtils.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCUtils.h index 5c4ad567..f207a563 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCUtils.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCUtils.h @@ -16,8 +16,8 @@ // along with Proton Mail Bridge. If not, see . -#ifndef BRIDGE_GUI_GRPC_UTILS_H -#define BRIDGE_GUI_GRPC_UTILS_H +#ifndef BRIDGE_PP_GRPC_UTILS_H +#define BRIDGE_PP_GRPC_UTILS_H #include "../User/User.h" @@ -42,4 +42,4 @@ SPUser userFromGRPC(grpc::User const &grpcUser); ///< Create a bridgepp::User fr } -#endif // BRIDGE_GUI_GRPC_UTILS_H +#endif // BRIDGE_PP_GRPC_UTILS_H diff --git a/internal/frontend/bridge-gui/bridge-gui/BridgeMonitor.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/ProcessMonitor.cpp similarity index 62% rename from internal/frontend/bridge-gui/bridge-gui/BridgeMonitor.cpp rename to internal/frontend/bridge-gui/bridgepp/bridgepp/ProcessMonitor.cpp index d69bf8a1..9b901043 100644 --- a/internal/frontend/bridge-gui/bridge-gui/BridgeMonitor.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/ProcessMonitor.cpp @@ -16,62 +16,35 @@ // along with Proton Mail Bridge. If not, see . -#include "BridgeMonitor.h" -#include +#include "ProcessMonitor.h" +#include "Exception/Exception.h" -using namespace bridgepp; - - -namespace +namespace bridgepp { -/// \brief The file extension for the bridge executable file. -#ifdef Q_OS_WIN32 -QString const exeSuffix = ".exe"; -#else -QString const exeSuffix; -#endif - -QString const exeName = "proton-bridge" + exeSuffix; ///< The bridge executable file name.* - - -} - - //**************************************************************************************************************************************************** -/// \return The path of the bridge executable. -/// \return A null string if the executable could not be located. -//**************************************************************************************************************************************************** -QString BridgeMonitor::locateBridgeExe() -{ - QFileInfo const fileInfo(QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(exeName)); - return (fileInfo.exists() && fileInfo.isFile() && fileInfo.isExecutable()) ? fileInfo.absoluteFilePath() : QString(); -} - - -//**************************************************************************************************************************************************** -/// \param[in] exePath The path of the Bridge executable. +/// \param[in] exePath The path of the executable. /// \param[in] parent The parent object of the worker. //**************************************************************************************************************************************************** -BridgeMonitor::BridgeMonitor(QString const &exePath, QStringList const &args, QObject *parent) +ProcessMonitor::ProcessMonitor(QString const &exePath, QStringList const &args, QObject *parent) : Worker(parent) , exePath_(exePath) , args_(args) { QFileInfo fileInfo(exePath); if (!fileInfo.exists()) - throw Exception("Could not locate Bridge executable."); + throw Exception(QString("Could not locate %1 executable.").arg(fileInfo.baseName())); if ((!fileInfo.isFile()) || (!fileInfo.isExecutable())) - throw Exception("Invalid bridge executable"); + throw Exception(QString("Invalid %1 executable").arg(fileInfo.baseName())); } //**************************************************************************************************************************************************** // //**************************************************************************************************************************************************** -void BridgeMonitor::run() +void ProcessMonitor::run() { try { @@ -92,9 +65,9 @@ void BridgeMonitor::run() } status_.running = false; - status_.returnCode = p.exitCode(); + status_.returnCode = p.exitCode(); - emit processExited(status_.returnCode ); + emit processExited(status_.returnCode); emit finished(); } catch (Exception const &e) @@ -103,10 +76,14 @@ void BridgeMonitor::run() } } + //**************************************************************************************************************************************************** /// \return status of the monitored process //**************************************************************************************************************************************************** -const BridgeMonitor::MonitorStatus& BridgeMonitor::getStatus() +const ProcessMonitor::MonitorStatus &ProcessMonitor::getStatus() { return status_; } + + +} // namespace bridgepp \ No newline at end of file diff --git a/internal/frontend/bridge-gui/bridge-gui/BridgeMonitor.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/ProcessMonitor.h similarity index 58% rename from internal/frontend/bridge-gui/bridge-gui/BridgeMonitor.h rename to internal/frontend/bridge-gui/bridgepp/bridgepp/ProcessMonitor.h index 948f4966..aeb37d8e 100644 --- a/internal/frontend/bridge-gui/bridge-gui/BridgeMonitor.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/ProcessMonitor.h @@ -16,48 +16,52 @@ // along with Proton Mail Bridge. If not, see . - -#ifndef BRIDGE_GUI_BRIDGE_MONITOR_H -#define BRIDGE_GUI_BRIDGE_MONITOR_H +#ifndef BRIDGE_PP_PROCESS_MONITOR_H +#define BRIDGE_PP_PROCESS_MONITOR_H -#include +#include "Worker/Worker.h" -//********************************************************************************************************************** -/// \brief Bridge process launcher and monitor class. -//********************************************************************************************************************** -class BridgeMonitor: public bridgepp::Worker +namespace bridgepp { - Q_OBJECT -public: // static member functions - static QString locateBridgeExe(); ///< Try to find the bridge executable path. - struct MonitorStatus { + +//********************************************************************************************************************** +/// \brief Process launcher and monitor class. +//********************************************************************************************************************** +class ProcessMonitor : public Worker +{ +Q_OBJECT +public: // static member functions + struct MonitorStatus + { bool running = false; int returnCode = 0; qint64 pid = 0; }; public: // member functions. - BridgeMonitor(QString const& exePath, QStringList const &args, QObject *parent); ///< Default constructor. - BridgeMonitor(BridgeMonitor const&) = delete; ///< Disabled copy-constructor. - BridgeMonitor(BridgeMonitor&&) = delete; ///< Disabled assignment copy-constructor. - ~BridgeMonitor() override = default; ///< Destructor. - BridgeMonitor& operator=(BridgeMonitor const&) = delete; ///< Disabled assignment operator. - BridgeMonitor& operator=(BridgeMonitor&&) = delete; ///< Disabled move assignment operator. + ProcessMonitor(QString const &exePath, QStringList const &args, QObject *parent); ///< Default constructor. + ProcessMonitor(ProcessMonitor const &) = delete; ///< Disabled copy-constructor. + ProcessMonitor(ProcessMonitor &&) = delete; ///< Disabled assignment copy-constructor. + ~ProcessMonitor() override = default; ///< Destructor. + ProcessMonitor &operator=(ProcessMonitor const &) = delete; ///< Disabled assignment operator. + ProcessMonitor &operator=(ProcessMonitor &&) = delete; ///< Disabled move assignment operator. void run() override; ///< Run the worker. + MonitorStatus const &getStatus(); - const MonitorStatus& getStatus(); signals: void processExited(int code); ///< Slot for the exiting of the process. private: // data members - QString const exePath_; ///< The path to the bridge executable. + QString const exePath_; ///< The path to the executable. QStringList args_; ///< arguments to be passed to the brigde. MonitorStatus status_; ///< Status of the monitoring. }; +} -#endif // BRIDGE_GUI_BRIDGE_MONITOR_H + +#endif //BRIDGE_PP_PROCESS_MONITOR_H diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/User/User.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/User/User.h index 472229e1..604fc3a1 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/User/User.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/User/User.h @@ -16,8 +16,8 @@ // along with Proton Mail Bridge. If not, see . -#ifndef BRIDGE_GUI_USER_H -#define BRIDGE_GUI_USER_H +#ifndef BRIDGE_PP_USER_H +#define BRIDGE_PP_USER_H namespace bridgepp @@ -127,4 +127,4 @@ private: // data members. } // namespace bridgepp -#endif // BRIDGE_GUI_USER_H +#endif // BRIDGE_PP_USER_H diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/Worker/Overseer.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/Worker/Overseer.cpp index 62c9f4e4..6e176669 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/Worker/Overseer.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/Worker/Overseer.cpp @@ -108,6 +108,26 @@ bool Overseer::isFinished() const } +//**************************************************************************************************************************************************** +/// \param timeoutMs The timeout after which the function should return false if the event stream reader is not finished. if -1 one, the function +/// never times out. +/// \return false if and only if the timeout delay was reached. +//**************************************************************************************************************************************************** +bool Overseer::wait(qint32 timeoutMs) const +{ + QElapsedTimer timer; + timer.start(); + + while (!this->isFinished()) { + if ((timeoutMs >= 0) && (timer.elapsed() > timeoutMs)) + return false; + QThread::msleep(10); + } + + return true; +} + + //**************************************************************************************************************************************************** /// \return The worker. //**************************************************************************************************************************************************** diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/Worker/Overseer.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/Worker/Overseer.h index d193289c..cafa3820 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/Worker/Overseer.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/Worker/Overseer.h @@ -41,6 +41,7 @@ public: // member functions. Overseer &operator=(Overseer const &) = delete; ///< Disabled assignment operator. Overseer &operator=(Overseer &&) = delete; ///< Disabled move assignment operator. bool isFinished() const; ///< Check if the worker is finished. + bool wait(qint32 timeoutMs) const; ///< Wait for the worker to finish. Worker *worker() const; ///< Return worker. public slots: diff --git a/internal/frontend/grpc/utils.go b/internal/frontend/grpc/utils.go index 236e2307..f129aeed 100644 --- a/internal/frontend/grpc/utils.go +++ b/internal/frontend/grpc/utils.go @@ -64,7 +64,7 @@ func grpcUserFromBridge(user types.User) *User { Username: user.Username(), AvatarText: getInitials(user.Username()), LoggedIn: user.IsConnected(), - SplitMode: user.IsCombinedAddressMode(), + SplitMode: !user.IsCombinedAddressMode(), SetupGuideSeen: true, // users listed have already seen the setup guide. UsedBytes: user.UsedBytes(), TotalBytes: user.TotalBytes(),