GODT-1667: bridge-gui spawns bridge process. [skip-ci]

Other: renaming of bridge-gui.
WIP: locate bridge exe.
WIP: bridge process launch.
WIP: cleaner closure of bridge.
WIP: grpcClient connection retries.
WIP: clean exit when bridge process is killed.

Fixed issues from MR review. [skip-ci].

WIP: Fixed gRPC case in CMakelists.txt [skip-ci]

It caused issues on Debian.

WIP: update gRPC/protobuf and tweaked CMakeLists.txt. [skip-ci]

WIP: Fixed a bug where splash screen could not be dismissed. [skip-ci]
This commit is contained in:
Xavier Michelon
2022-07-11 11:09:30 +02:00
committed by Jakub
parent 7a633ee8c8
commit 72708d6e2c
155 changed files with 4734 additions and 4199 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,214 @@
// Copyright (c) 2022 Proton AG
//
// This file is part of Proton Mail Bridge.
//
// Proton Mail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#ifndef BRIDGE_QT6_RPC_CLIENT_H
#define BRIDGE_QT6_RPC_CLIENT_H
#include "GRPC/bridge.grpc.pb.h"
#include "grpc++/grpc++.h"
#include "User/User.h"
typedef grpc::Status (grpc::Bridge::Stub::*SimpleMethod)(grpc::ClientContext*, const google::protobuf::Empty&, google::protobuf::Empty*);
typedef grpc::Status (grpc::Bridge::Stub::*BoolSetter)(grpc::ClientContext*, const google::protobuf::BoolValue&, google::protobuf::Empty*);
typedef grpc::Status (grpc::Bridge::Stub::*BoolGetter)(grpc::ClientContext*, const google::protobuf::Empty&, google::protobuf::BoolValue*);
typedef grpc::Status (grpc::Bridge::Stub::*Int32Setter)(grpc::ClientContext*, const google::protobuf::Int32Value&, google::protobuf::Empty*);
typedef grpc::Status (grpc::Bridge::Stub::*Int32Getter)(grpc::ClientContext*, const google::protobuf::Empty&, google::protobuf::Int32Value*);
typedef grpc::Status (grpc::Bridge::Stub::*StringGetter)(grpc::ClientContext*, const google::protobuf::Empty&, google::protobuf::StringValue*);
typedef grpc::Status (grpc::Bridge::Stub::*StringSetter)(grpc::ClientContext*, const google::protobuf::StringValue&, google::protobuf::Empty*);
typedef grpc::Status (grpc::Bridge::Stub::*StringParamMethod)(grpc::ClientContext*, const google::protobuf::StringValue&, google::protobuf::Empty*);
//****************************************************************************************************************************************************
/// \brief gRPC client class. This class encapsulate the gRPC service, abstracting all data type conversions.
//****************************************************************************************************************************************************
class GRPCClient: public QObject
{
Q_OBJECT
public: // member functions.
GRPCClient() = default; ///< Default constructor.
GRPCClient(GRPCClient const&) = delete; ///< Disabled copy-constructor.
GRPCClient(GRPCClient&&) = delete; ///< Disabled assignment copy-constructor.
~GRPCClient() override = default; ///< Destructor.
GRPCClient& operator=(GRPCClient const&) = delete; ///< Disabled assignment operator.
GRPCClient& operator=(GRPCClient&&) = delete; ///< Disabled move assignment operator.
bool connectToServer(QString &outError); ///< Establish connection to the gRPC server.
grpc::Status guiReady(); ///< performs the "GuiReady" gRPC call.
grpc::Status isFirstGUIStart(bool &outIsFirst); ///< performs the "IsFirstGUIStart" gRPC call.
grpc::Status isAutostartOn(bool &outIsOn); ///< Performs the "isAutostartOn" gRPC call.
grpc::Status setIsAutostartOn(bool on); ///< Performs the "setIsAutostartOn" gRPC call.
grpc::Status isBetaEnabled(bool &outEnabled); ///< Performs the "isBetaEnabled" gRPC call.
grpc::Status setisBetaEnabled(bool enabled); ///< Performs the 'setIsBetaEnabled' gRPC call.
grpc::Status colorSchemeName(QString &outName); ///< Performs the "colorSchemeName' gRPC call.
grpc::Status setColorSchemeName(QString const &name); ///< Performs the "setColorSchemeName' gRPC call.
grpc::Status currentEmailClient(QString &outName); ///< Performs the 'currentEmailClient' gRPC call.
grpc::Status quit(); ///< Perform the "Quit" gRPC call.
grpc::Status restart(); ///< Performs the Restart gRPC call.
grpc::Status isPortFree(qint32 port, bool &outFree); ///< Performs the 'IsPortFree' call.
grpc::Status showOnStartup(bool &outValue); ///< Performs the 'ShowOnStartup' call.
grpc::Status showSplashScreen(bool &outValue); ///< Performs the 'ShowSplashScreen' call.
grpc::Status goos(QString &outGoos); ///< Performs the 'GoOs' call.
grpc::Status logsPath(QUrl &outPath); ///< Performs the 'LogsPath' call.
grpc::Status licensePath(QUrl &outPath); ///< Performs the 'LicensePath' call.
grpc::Status dependencyLicensesLink(QUrl &outUrl); ///< Performs the 'DependencyLicensesLink' call.
grpc::Status version(QString &outVersion); ///< Performs the 'Version' call.
grpc::Status hostname(QString &outHostname); ///< Performs the 'Hostname' call.
signals: // app related signals
void internetStatus(bool isOn);
void toggleAutostartFinished();
void resetFinished();
void reportBugFinished();
void reportBugSuccess();
void reportBugError();
void showMainWindow();
// cache related calls
public:
grpc::Status isCacheOnDiskEnabled(bool &outEnabled); ///< Performs the 'isCacheOnDiskEnabled' call.
grpc::Status diskCachePath(QUrl &outPath); ///< Performs the 'diskCachePath' call.
grpc::Status changeLocalCache(bool enabled, QUrl const &path); ///< Performs the 'ChangeLocalCache' call.
signals:
void isCacheOnDiskEnabledChanged(bool enabled);
void diskCachePathChanged(QUrl const&outPath);
void cacheUnavailable(); // _ func() `signal:"cacheUnavailable"`
void cacheCantMove(); // _ func() `signal:"cacheCantMove"`
void cacheLocationChangeSuccess(); // _ func() `signal:"cacheLocationChangeSuccess"`
void diskFull(); // _ func() `signal:"diskFull"`
void changeLocalCacheFinished(); // _ func() `signal:"changeLocalCacheFinished"`
// mail settings related calls
public:
grpc::Status useSSLForSMTP(bool &outUseSSL); ///< Performs the 'useSSLForSMTP' gRPC call
grpc::Status setUseSSLForSMTP(bool useSSL); ///< Performs the 'currentEmailClient' gRPC call.
grpc::Status portIMAP(int &outPort); ///< Performs the 'portImap' gRPC call.
grpc::Status portSMTP(int &outPort); ///< Performs the 'portImap' gRPC call.
grpc::Status changePorts(int portIMAP, int portSMTP); ///< Performs the 'changePorts' gRPC call.
grpc::Status isDoHEnabled(bool &outEnabled); ///< Performs the 'isDoHEnabled' gRPC call.
grpc::Status setIsDoHEnabled(bool enabled); ///< Performs the 'setIsDoHEnabled' gRPC call.
signals:
void portIssueIMAP();
void portIssueSMTP();
void toggleUseSSLFinished();
void changePortFinished();
public: // login related calls
grpc::Status login(QString const &username, QString const& password); ///< Performs the 'login' call.
grpc::Status login2FA(QString const &username, QString const& code); ///< Performs the 'login2FA' call.
grpc::Status login2Passwords(QString const &username, QString const& password); ///< Performs the 'login2Passwords' call.
grpc::Status loginAbort(QString const &username); ///< Performs the 'loginAbort' call.
signals:
void loginUsernamePasswordError(QString const &errMsg); // _ func(errorMsg string) `signal:"loginUsernamePasswordError"`
void loginFreeUserError(); // _ func() `signal:"loginFreeUserError"`
void loginConnectionError(QString const &errMsg); // _ func(errorMsg string) `signal:"loginConnectionError"`
void login2FARequested(QString const &userName); // _ func(username string) `signal:"login2FARequested"`
void login2FAError(QString const& errMsg); // _ func(errorMsg string) `signal:"login2FAError"`
void login2FAErrorAbort(QString const& errMsg); // _ func(errorMsg string) `signal:"login2FAErrorAbort"`
void login2PasswordRequested(); // _ func() `signal:"login2PasswordRequested"`
void login2PasswordError(QString const& errMsg); // _ func(errorMsg string) `signal:"login2PasswordError"`
void login2PasswordErrorAbort(QString const& errMsg); // _ func(errorMsg string) `signal:"login2PasswordErrorAbort"`
void loginFinished(QString const &userID); // _ func(index int) `signal:"loginFinished"`
void loginAlreadyLoggedIn(QString const &userID); // _ func(index int) `signal:"loginAlreadyLoggedIn"`
public: // Update related calls
grpc::Status checkUpdate();
grpc::Status installUpdate();
grpc::Status setIsAutomaticUpdateOn(bool on);
grpc::Status isAutomaticUpdateOn(bool &isOn);
signals:
void updateManualError();
void updateForceError();
void updateSilentError();
void updateManualReady(QString const &version);
void updateManualRestartNeeded();
void updateForce(QString const &version);
void updateSilentRestartNeeded();
void updateIsLatestVersion();
void checkUpdatesFinished();
public: // user related calls
grpc::Status getUserList(QList<SPUser>& outUsers);
grpc::Status getUser(QString const &userID, SPUser& outUser);
grpc::Status logoutUser(QString const &userID); ///< Performs the 'logoutUser' call.
grpc::Status removeUser(QString const &userID); ///< Performs the 'removeUser' call.
grpc::Status configureAppleMail(QString const& userID, QString const &address); ///< Performs the 'configureAppleMail' call.
grpc::Status setUserSplitMode(QString const& userID, bool active); ///< Performs the 'SetUserSplitMode' call.
signals:
void toggleSplitModeFinished(QString const& userID);
void userDisconnected(QString const& username);
void userChanged(QString const& userID);
public: // keychain related calls
grpc::Status availableKeychains(QStringList &outKeychains);
grpc::Status currentKeychain(QString &outKeychain);
grpc::Status setCurrentKeychain(QString const &keychain);
signals:
void changeKeychainFinished();
void hasNoKeychain();
void rebuildKeychain();
signals: // mail releated events
void noActiveKeyForRecipient(QString const &email); // _ func(email string) `signal:noActiveKeyForRecipient`
void addressChanged(QString const &address); // _ func(address string) `signal:addressChanged`
void addressChangedLogout(QString const &address); // _ func(address string) `signal:addressChangedLogout`
void apiCertIssue();
public:
grpc::Status startEventStream(); ///< Retrieve and signal the events in the event stream.
grpc::Status stopEventStream(); ///< Stop the event stream.
private:
grpc::Status simpleMethod(SimpleMethod method); ///< perform a gRPC call to a bool setter.
grpc::Status setBool(BoolSetter setter, bool value); ///< perform a gRPC call to a bool setter.
grpc::Status getBool(BoolGetter getter, bool& outValue); ///< perform a gRPC call to a bool getter.
grpc::Status setInt32(Int32Setter setter, int value); ///< perform a gRPC call to an int setter.
grpc::Status getInt32(Int32Getter getter, int& outValue); ///< perform a gRPC call to an int getter.
grpc::Status setString(StringSetter getter, QString const& value); ///< Perform a gRPC call to a string setter.
grpc::Status getString(StringGetter getter, QString& outValue); ///< Perform a gRPC call to a string getter.
grpc::Status getURLForLocalFile(StringGetter getter, QUrl& outValue); ///< Perform a gRPC call to a string getter, with resulted converted to QUrl for a local file path.
grpc::Status getURL(StringGetter getter, QUrl& outValue); ///< Perform a gRPC call to a string getter, with resulted converted to QUrl.
grpc::Status methodWithStringParam(StringParamMethod method, QString const& str); ///< Perfom a gRPC call that takes a string as a parameter and returns an Empty.
void processAppEvent(grpc::AppEvent const &event); ///< Process an 'App' event.
void processLoginEvent(grpc::LoginEvent const &event); ///< Process a 'Login' event.
void processUpdateEvent(grpc::UpdateEvent const &event); ///< Process an 'Update' event.
void processCacheEvent(grpc::CacheEvent const &event); ///< Process a 'Cache' event.
void processMailSettingsEvent(grpc::MailSettingsEvent const &event); ///< Process a 'MailSettings' event.
void processKeychainEvent(grpc::KeychainEvent const &event); ///< Process a 'Keychain' event.
void processMailEvent(grpc::MailEvent const &event); ///< Process a 'Mail' event.
void processUserEvent(grpc::UserEvent const &event); ///< Process a 'User' event.
private: // data members.
std::shared_ptr<grpc::Channel> channel_ { nullptr }; ///< The gRPC channel.
std::shared_ptr<grpc::Bridge::Stub> stub_ { nullptr }; ///< The gRPC stub (a.k.a. client).
};
#endif // BRIDGE_QT6_RPC_CLIENT_H

View File

@ -0,0 +1,63 @@
// Copyright (c) 2022 Proton AG
//
// This file is part of Proton Mail Bridge.
//
// Proton Mail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#include "GRPCUtils.h"
#include "QMLBackend.h"
//****************************************************************************************************************************************************
/// \param[in] status The status
/// \param[in] callName The call name.
//****************************************************************************************************************************************************
void logGRPCCallStatus(grpc::Status const& status, QString const &callName)
{
if (status.ok())
app().log().debug(QString("%1()").arg(callName));
else
app().log().error(QString("%1() FAILED").arg(callName));
}
//****************************************************************************************************************************************************
/// \param[in] grpcUser the gRPC user struct
/// \return a user.
//****************************************************************************************************************************************************
SPUser parsegrpcUser(grpc::User const &grpcUser)
{
// As we want to use shared pointers here, we do not want to use the Qt ownership system, so we set parent to nil.
// But: From https://doc.qt.io/qt-5/qtqml-cppintegration-data.html:
// " When data is transferred from C++ to QML, the ownership of the data always remains with C++. The exception to this rule
// is when a QObject is returned from an explicit C++ method call: in this case, the QML engine assumes ownership of the object. "
// This is the case here, so we explicitely indicate that the object is owned by C++.
SPUser user = std::make_shared<User>(nullptr);
QQmlEngine::setObjectOwnership(user.get(), QQmlEngine::CppOwnership);
user->setProperty("username", QString::fromStdString(grpcUser.username()));
user->setProperty("avatarText", QString::fromStdString(grpcUser.avatartext()));
user->setProperty("loggedIn", grpcUser.loggedin());
user->setProperty("splitMode", grpcUser.splitmode());
user->setProperty("setupGuideSeen", grpcUser.setupguideseen());
user->setProperty("usedBytes", float(grpcUser.usedbytes()));
user->setProperty("totalBytes", float(grpcUser.totalbytes()));
user->setProperty("password", QString::fromStdString(grpcUser.password()));
QStringList addresses;
for (int j = 0; j < grpcUser.addresses_size(); ++j)
addresses.append(QString::fromStdString(grpcUser.addresses(j)));
user->setProperty("addresses", addresses);
user->setProperty("id", QString::fromStdString(grpcUser.id()));
return user;
}

View File

@ -0,0 +1,30 @@
// Copyright (c) 2022 Proton AG
//
// This file is part of Proton Mail Bridge.
//
// Proton Mail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#ifndef BRIDGE_QT6_GRPCUTILS_H
#define BRIDGE_QT6_GRPCUTILS_H
#include "GRPC/bridge.grpc.pb.h"
#include "grpc++/grpc++.h"
#include "User/User.h"
void logGRPCCallStatus(grpc::Status const& status, QString const &callName); ///< Log the status of a gRPC code.
SPUser parsegrpcUser(grpc::User const& grpcUser); ///< Parse a gRPC user struct and return a User.
#endif // BRIDGE_QT6_GRPCUTILS_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff