feat: enable autostart to use launcher

This commit is contained in:
James Houlahan
2020-12-09 11:29:51 +01:00
parent d2066173f0
commit 839708dcfe
10 changed files with 87 additions and 67 deletions

2
go.mod
View File

@ -49,7 +49,7 @@ require (
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c // indirect github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c // indirect
github.com/hashicorp/go-multierror v1.1.0 github.com/hashicorp/go-multierror v1.1.0
github.com/jaytaylor/html2text v0.0.0-20200412013138-3577fbdbcff7 github.com/jaytaylor/html2text v0.0.0-20200412013138-3577fbdbcff7
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
github.com/keybase/go-keychain v0.0.0-20200502122510-cda31fe0c86d github.com/keybase/go-keychain v0.0.0-20200502122510-cda31fe0c86d
github.com/logrusorgru/aurora v2.0.3+incompatible github.com/logrusorgru/aurora v2.0.3+incompatible
github.com/mattn/go-runewidth v0.0.9 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect

View File

@ -36,6 +36,7 @@ import (
"github.com/Masterminds/semver/v3" "github.com/Masterminds/semver/v3"
"github.com/ProtonMail/go-appdir" "github.com/ProtonMail/go-appdir"
"github.com/ProtonMail/go-autostart"
"github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/ProtonMail/gopenpgp/v2/crypto"
"github.com/ProtonMail/proton-bridge/internal/api" "github.com/ProtonMail/proton-bridge/internal/api"
"github.com/ProtonMail/proton-bridge/internal/config/cache" "github.com/ProtonMail/proton-bridge/internal/config/cache"
@ -70,11 +71,12 @@ type Base struct {
Updater *updater.Updater Updater *updater.Updater
Versioner *versioner.Versioner Versioner *versioner.Versioner
TLS *tls.TLS TLS *tls.TLS
Autostart *autostart.App
name string Name string // the app's name
usage string usage string // the app's usage description
command string // the command used to launch the app (either the exe path or the launcher path)
restart bool restart bool // whether the app is currently set to restart
} }
func New( // nolint[funlen] func New( // nolint[funlen]
@ -156,8 +158,6 @@ func New( // nolint[funlen]
sentryReporter.SetUserAgentProvider(cm) sentryReporter.SetUserAgentProvider(cm)
tls := tls.New(settingsPath)
key, err := crypto.NewKeyFromArmored(updater.DefaultPublicKey) key, err := crypto.NewKeyFromArmored(updater.DefaultPublicKey)
if err != nil { if err != nil {
return nil, err return nil, err
@ -174,9 +174,7 @@ func New( // nolint[funlen]
} }
versioner := versioner.New(updatesDir) versioner := versioner.New(updatesDir)
installer := updater.NewInstaller(versioner) installer := updater.NewInstaller(versioner)
updater := updater.New( updater := updater.New(
cm, cm,
installer, installer,
@ -187,6 +185,19 @@ func New( // nolint[funlen]
runtime.GOOS, runtime.GOOS,
) )
tls := tls.New(settingsPath)
exe, err := os.Executable()
if err != nil {
return nil, err
}
autostart := &autostart.App{
Name: appName,
DisplayName: appName,
Exec: []string{exe},
}
return &Base{ return &Base{
CrashHandler: crashHandler, CrashHandler: crashHandler,
Locations: locations, Locations: locations,
@ -199,16 +210,21 @@ func New( // nolint[funlen]
Updater: updater, Updater: updater,
Versioner: versioner, Versioner: versioner,
TLS: tls, TLS: tls,
Autostart: autostart,
name: appName, Name: appName,
usage: appUsage, usage: appUsage,
// By default, the command is the app's executable.
// This can be changed at runtime by using the "--launcher" flag.
command: exe,
}, nil }, nil
} }
func (b *Base) NewApp(action func(*Base, *cli.Context) error) *cli.App { func (b *Base) NewApp(action func(*Base, *cli.Context) error) *cli.App {
app := cli.NewApp() app := cli.NewApp()
app.Name = b.name app.Name = b.Name
app.Usage = b.usage app.Usage = b.usage
app.Version = constants.Version app.Version = constants.Version
app.Action = b.run(action) app.Action = b.run(action)
@ -258,6 +274,12 @@ func (b *Base) run(appMainLoop func(*Base, *cli.Context) error) cli.ActionFunc {
defer b.CrashHandler.HandlePanic() defer b.CrashHandler.HandlePanic()
defer func() { _ = b.Lock.Close() }() defer func() { _ = b.Lock.Close() }()
// If launcher was used to start the app, use that for restart/autostart.
if launcher := c.String("launcher"); launcher != "" {
b.Autostart.Exec = []string{launcher}
b.command = launcher
}
if doCPUProfile := c.Bool("cpu-prof"); doCPUProfile { if doCPUProfile := c.Bool("cpu-prof"); doCPUProfile {
startCPUProfile() startCPUProfile()
defer pprof.StopCPUProfile() defer pprof.StopCPUProfile()
@ -270,7 +292,7 @@ func (b *Base) run(appMainLoop func(*Base, *cli.Context) error) cli.ActionFunc {
logging.SetLevel(c.String("log-level")) logging.SetLevel(c.String("log-level"))
logrus. logrus.
WithField("appName", b.name). WithField("appName", b.Name).
WithField("version", constants.Version). WithField("version", constants.Version).
WithField("revision", constants.Revision). WithField("revision", constants.Revision).
WithField("build", constants.BuildTime). WithField("build", constants.BuildTime).
@ -287,7 +309,7 @@ func (b *Base) run(appMainLoop func(*Base, *cli.Context) error) cli.ActionFunc {
return nil return nil
} }
return restartApp(c.String("launcher"), true) return b.restartApp(true)
}) })
if err := appMainLoop(b, c); err != nil { if err := appMainLoop(b, c); err != nil {
@ -295,7 +317,7 @@ func (b *Base) run(appMainLoop func(*Base, *cli.Context) error) cli.ActionFunc {
} }
if b.restart { if b.restart {
return restartApp(c.String("launcher"), false) return b.restartApp(false)
} }
if err := b.Versioner.RemoveOldVersions(); err != nil { if err := b.Versioner.RemoveOldVersions(); err != nil {

View File

@ -28,16 +28,7 @@ import (
// maxAllowedRestarts controls after how many crashes the app will give up restarting. // maxAllowedRestarts controls after how many crashes the app will give up restarting.
const maxAllowedRestarts = 10 const maxAllowedRestarts = 10
func restartApp(path string, crash bool) error { func (b *Base) restartApp(crash bool) error {
if path == "" {
exe, err := os.Executable()
if err != nil {
return err
}
path = exe
}
var args []string var args []string
if crash { if crash {
@ -47,11 +38,11 @@ func restartApp(path string, crash bool) error {
} }
logrus. logrus.
WithField("path", path). WithField("command", b.command).
WithField("args", args). WithField("args", args).
Warn("Restarting") Warn("Restarting")
return exec.Command(path, args...).Start() // nolint[gosec] return exec.Command(b.command, args...).Start() // nolint[gosec]
} }
// incrementRestartFlag increments the value of the restart flag. // incrementRestartFlag increments the value of the restart flag.

View File

@ -105,9 +105,13 @@ func run(b *base.Base, c *cli.Context) error { // nolint[funlen]
return nil return nil
} }
// Bridge supports no-window option which we should use for autostart.
b.Autostart.Exec = append(b.Autostart.Exec, "--no-window")
f := frontend.New( f := frontend.New(
constants.Version, constants.Version,
constants.BuildVersion, constants.BuildVersion,
b.Name,
frontendMode, frontendMode,
!c.Bool("no-window"), !c.Bool("no-window"),
b.CrashHandler, b.CrashHandler,
@ -117,6 +121,7 @@ func run(b *base.Base, c *cli.Context) error { // nolint[funlen]
b.Updater, b.Updater,
bridge, bridge,
smtpBackend, smtpBackend,
b.Autostart,
b, b,
) )

View File

@ -57,6 +57,7 @@ func run(b *base.Base, c *cli.Context) error {
f := frontend.NewImportExport( f := frontend.NewImportExport(
constants.Version, constants.Version,
constants.BuildVersion, constants.BuildVersion,
b.Name,
frontendMode, frontendMode,
b.CrashHandler, b.CrashHandler,
b.Locations, b.Locations,

View File

@ -19,6 +19,7 @@
package frontend package frontend
import ( import (
"github.com/ProtonMail/go-autostart"
"github.com/ProtonMail/proton-bridge/internal/bridge" "github.com/ProtonMail/proton-bridge/internal/bridge"
"github.com/ProtonMail/proton-bridge/internal/config/settings" "github.com/ProtonMail/proton-bridge/internal/config/settings"
"github.com/ProtonMail/proton-bridge/internal/frontend/cli" "github.com/ProtonMail/proton-bridge/internal/frontend/cli"
@ -49,6 +50,7 @@ type Frontend interface {
func New( func New(
version, version,
buildVersion, buildVersion,
programName,
frontendType string, frontendType string,
showWindowOnStart bool, showWindowOnStart bool,
panicHandler types.PanicHandler, panicHandler types.PanicHandler,
@ -58,12 +60,14 @@ func New(
updater types.Updater, updater types.Updater,
bridge *bridge.Bridge, bridge *bridge.Bridge,
noEncConfirmator types.NoEncConfirmator, noEncConfirmator types.NoEncConfirmator,
autostart *autostart.App,
restarter types.Restarter, restarter types.Restarter,
) Frontend { ) Frontend {
bridgeWrap := types.NewBridgeWrap(bridge) bridgeWrap := types.NewBridgeWrap(bridge)
return newBridgeFrontend( return newBridgeFrontend(
version, version,
buildVersion, buildVersion,
programName,
frontendType, frontendType,
showWindowOnStart, showWindowOnStart,
panicHandler, panicHandler,
@ -73,6 +77,7 @@ func New(
updater, updater,
bridgeWrap, bridgeWrap,
noEncConfirmator, noEncConfirmator,
autostart,
restarter, restarter,
) )
} }
@ -80,6 +85,7 @@ func New(
func newBridgeFrontend( func newBridgeFrontend(
version, version,
buildVersion, buildVersion,
programName,
frontendType string, frontendType string,
showWindowOnStart bool, showWindowOnStart bool,
panicHandler types.PanicHandler, panicHandler types.PanicHandler,
@ -89,6 +95,7 @@ func newBridgeFrontend(
updater types.Updater, updater types.Updater,
bridge types.Bridger, bridge types.Bridger,
noEncConfirmator types.NoEncConfirmator, noEncConfirmator types.NoEncConfirmator,
autostart *autostart.App,
restarter types.Restarter, restarter types.Restarter,
) Frontend { ) Frontend {
switch frontendType { switch frontendType {
@ -106,6 +113,7 @@ func newBridgeFrontend(
return qt.New( return qt.New(
version, version,
buildVersion, buildVersion,
programName,
showWindowOnStart, showWindowOnStart,
panicHandler, panicHandler,
locations, locations,
@ -114,6 +122,7 @@ func newBridgeFrontend(
updater, updater,
bridge, bridge,
noEncConfirmator, noEncConfirmator,
autostart,
restarter, restarter,
) )
} }
@ -123,6 +132,7 @@ func newBridgeFrontend(
func NewImportExport( func NewImportExport(
version, version,
buildVersion, buildVersion,
programName,
frontendType string, frontendType string,
panicHandler types.PanicHandler, panicHandler types.PanicHandler,
locations *locations.Locations, locations *locations.Locations,
@ -136,6 +146,7 @@ func NewImportExport(
return newIEFrontend( return newIEFrontend(
version, version,
buildVersion, buildVersion,
programName,
frontendType, frontendType,
panicHandler, panicHandler,
locations, locations,
@ -150,6 +161,7 @@ func NewImportExport(
func newIEFrontend( func newIEFrontend(
version, version,
buildVersion, buildVersion,
programName,
frontendType string, frontendType string,
panicHandler types.PanicHandler, panicHandler types.PanicHandler,
locations *locations.Locations, locations *locations.Locations,
@ -173,6 +185,7 @@ func newIEFrontend(
return qtie.New( return qtie.New(
version, version,
buildVersion, buildVersion,
programName,
panicHandler, panicHandler,
locations, locations,
settings, settings,

View File

@ -62,7 +62,7 @@ type FrontendQt struct {
Qml *GoQMLInterface // Object accessible from both Go and QML for methods and signals Qml *GoQMLInterface // Object accessible from both Go and QML for methods and signals
Accounts qtcommon.Accounts // Providing data for accounts ListView Accounts qtcommon.Accounts // Providing data for accounts ListView
programName string // Program name programName string // App name
programVersion string // Program version programVersion string // Program version
buildVersion string // Program build version buildVersion string // Program build version
@ -80,7 +80,7 @@ type FrontendQt struct {
// New is constructor for Import-Export Qt-Go interface // New is constructor for Import-Export Qt-Go interface
func New( func New(
version, buildVersion string, version, buildVersion, programName string,
panicHandler types.PanicHandler, panicHandler types.PanicHandler,
locations *locations.Locations, locations *locations.Locations,
settings *settings.Settings, settings *settings.Settings,
@ -93,7 +93,7 @@ func New(
panicHandler: panicHandler, panicHandler: panicHandler,
locations: locations, locations: locations,
settings: settings, settings: settings,
programName: "ProtonMail Import-Export", programName: programName,
programVersion: "v" + version, programVersion: "v" + version,
eventListener: eventListener, eventListener: eventListener,
updater: updater, updater: updater,

View File

@ -54,7 +54,7 @@ func (s *FrontendHeadless) NotifySilentUpdateError(err error) {
} }
func New( func New(
version, buildVersion string, version, buildVersion, appName string,
panicHandler types.PanicHandler, panicHandler types.PanicHandler,
locations *locations.Locations, locations *locations.Locations,
settings *settings.Settings, settings *settings.Settings,

View File

@ -49,7 +49,6 @@ import (
"github.com/ProtonMail/proton-bridge/pkg/pmapi" "github.com/ProtonMail/proton-bridge/pkg/pmapi"
"github.com/ProtonMail/proton-bridge/pkg/ports" "github.com/ProtonMail/proton-bridge/pkg/ports"
"github.com/ProtonMail/proton-bridge/pkg/useragent" "github.com/ProtonMail/proton-bridge/pkg/useragent"
"github.com/kardianos/osext"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/skratchdot/open-golang/open" "github.com/skratchdot/open-golang/open"
"github.com/therecipe/qt/core" "github.com/therecipe/qt/core"
@ -68,6 +67,7 @@ var accountMutex = &sync.Mutex{}
type FrontendQt struct { type FrontendQt struct {
version string version string
buildVersion string buildVersion string
programName string
showWindowOnStart bool showWindowOnStart bool
panicHandler types.PanicHandler panicHandler types.PanicHandler
locations *locations.Locations locations *locations.Locations
@ -77,19 +77,18 @@ type FrontendQt struct {
bridge types.Bridger bridge types.Bridger
noEncConfirmator types.NoEncConfirmator noEncConfirmator types.NoEncConfirmator
App *widgets.QApplication // Main Application pointer. App *widgets.QApplication // Main Application pointer.
View *qml.QQmlApplicationEngine // QML engine pointer. View *qml.QQmlApplicationEngine // QML engine pointer.
MainWin *core.QObject // Pointer to main window inside QML. MainWin *core.QObject // Pointer to main window inside QML.
Qml *GoQMLInterface // Object accessible from both Go and QML for methods and signals. Qml *GoQMLInterface // Object accessible from both Go and QML for methods and signals.
Accounts *AccountsModel // Providing data for accounts ListView. Accounts *AccountsModel // Providing data for accounts ListView.
programName string // Program name (shown in taskbar). programVer string // Program version (shown in help).
programVer string // Program version (shown in help).
authClient pmapi.Client authClient pmapi.Client
auth *pmapi.Auth auth *pmapi.Auth
AutostartEntry *autostart.App autostart *autostart.App
// expand userID when added // expand userID when added
userIDAdded string userIDAdded string
@ -103,7 +102,8 @@ type FrontendQt struct {
// New returns a new Qt frontend for the bridge. // New returns a new Qt frontend for the bridge.
func New( func New(
version, version,
buildVersion string, buildVersion,
programName string,
showWindowOnStart bool, showWindowOnStart bool,
panicHandler types.PanicHandler, panicHandler types.PanicHandler,
locations *locations.Locations, locations *locations.Locations,
@ -112,12 +112,13 @@ func New(
updater types.Updater, updater types.Updater,
bridge types.Bridger, bridge types.Bridger,
noEncConfirmator types.NoEncConfirmator, noEncConfirmator types.NoEncConfirmator,
autostart *autostart.App,
restarter types.Restarter, restarter types.Restarter,
) *FrontendQt { ) *FrontendQt {
prgName := "ProtonMail Bridge"
tmp := &FrontendQt{ tmp := &FrontendQt{
version: version, version: version,
buildVersion: buildVersion, buildVersion: buildVersion,
programName: programName,
showWindowOnStart: showWindowOnStart, showWindowOnStart: showWindowOnStart,
panicHandler: panicHandler, panicHandler: panicHandler,
locations: locations, locations: locations,
@ -126,24 +127,9 @@ func New(
updater: updater, updater: updater,
bridge: bridge, bridge: bridge,
noEncConfirmator: noEncConfirmator, noEncConfirmator: noEncConfirmator,
programVer: "v" + version,
programName: prgName, autostart: autostart,
programVer: "v" + version, restarter: restarter,
AutostartEntry: &autostart.App{
Name: prgName,
DisplayName: prgName,
Exec: []string{"", "--no-window"},
},
restarter: restarter,
}
// Handle autostart if wanted.
if p, err := osext.Executable(); err == nil {
tmp.AutostartEntry.Exec[0] = p
log.Info("Autostart ", p)
} else {
log.Error("Cannot get current executable path: ", err)
} }
// Nicer string for OS. // Nicer string for OS.
@ -344,15 +330,15 @@ func (s *FrontendQt) qtExecute(Procedure func(*FrontendQt) error) error {
// Autostart. // Autostart.
if s.Qml.IsFirstStart() { if s.Qml.IsFirstStart() {
if s.AutostartEntry.IsEnabled() { if s.autostart.IsEnabled() {
if err := s.AutostartEntry.Disable(); err != nil { if err := s.autostart.Disable(); err != nil {
log.Error("First disable ", err) log.Error("First disable ", err)
s.autostartError(err) s.autostartError(err)
} }
} }
s.toggleAutoStart() s.toggleAutoStart()
} }
if s.AutostartEntry.IsEnabled() { if s.autostart.IsEnabled() {
s.Qml.SetIsAutoStart(true) s.Qml.SetIsAutoStart(true)
} else { } else {
s.Qml.SetIsAutoStart(false) s.Qml.SetIsAutoStart(false)
@ -526,16 +512,16 @@ func (s *FrontendQt) configureAppleMail(iAccount, iAddress int) {
func (s *FrontendQt) toggleAutoStart() { func (s *FrontendQt) toggleAutoStart() {
defer s.Qml.ProcessFinished() defer s.Qml.ProcessFinished()
var err error var err error
if s.AutostartEntry.IsEnabled() { if s.autostart.IsEnabled() {
err = s.AutostartEntry.Disable() err = s.autostart.Disable()
} else { } else {
err = s.AutostartEntry.Enable() err = s.autostart.Enable()
} }
if err != nil { if err != nil {
log.Error("Enable autostart: ", err) log.Error("Enable autostart: ", err)
s.autostartError(err) s.autostartError(err)
} }
if s.AutostartEntry.IsEnabled() { if s.autostart.IsEnabled() {
s.Qml.SetIsAutoStart(true) s.Qml.SetIsAutoStart(true)
} else { } else {
s.Qml.SetIsAutoStart(false) s.Qml.SetIsAutoStart(false)

View File

@ -23,6 +23,7 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"github.com/ProtonMail/go-autostart"
"github.com/ProtonMail/proton-bridge/internal/config/settings" "github.com/ProtonMail/proton-bridge/internal/config/settings"
"github.com/ProtonMail/proton-bridge/internal/frontend/types" "github.com/ProtonMail/proton-bridge/internal/frontend/types"
"github.com/ProtonMail/proton-bridge/internal/locations" "github.com/ProtonMail/proton-bridge/internal/locations"
@ -57,7 +58,7 @@ func (s *FrontendHeadless) InstanceExistAlert() {}
func New( func New(
version, version,
buildVersion string, buildVersion, appName string,
showWindowOnStart bool, showWindowOnStart bool,
panicHandler types.PanicHandler, panicHandler types.PanicHandler,
locations *locations.Locations, locations *locations.Locations,
@ -66,6 +67,7 @@ func New(
updater types.Updater, updater types.Updater,
bridge types.Bridger, bridge types.Bridger,
noEncConfirmator types.NoEncConfirmator, noEncConfirmator types.NoEncConfirmator,
autostart *autostart.App,
restarter types.Restarter, restarter types.Restarter,
) *FrontendHeadless { ) *FrontendHeadless {
return &FrontendHeadless{} return &FrontendHeadless{}