-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
gui/main: Clean old Windows Uninstall registry key (#1755)
* core/app: Separate setup from sync start We want to be able to run actions as soon as the app is setup but before we've started synchronizing (or rather, while we start synchronizing) so we don't "waste" time. Besides, when running a manual synchronization, we shouldn't have to re-instantiate the whole app! We can easily separate the app setup from its synchronization start via a new method. We can take this opportunity to better handle configuration issues, especially in the way we alert the user about it. * gui/main: Update systray state before window state The systray icon's state will be the first thing users will see in most situations since the app window is hidden most of the time. Therefore, updating its state first seems more appropriate especially if the window state update is blocking (i.e. requires user interaction like when we detect an invalid configuration). * gui/main: Clean old Windows Uninstall registry key Windows uses Uninstall registry subkeys to know where to find the uninstall executables of applications and list them in its programs management application. In the more recent versions of `electron-builder`, the format of the subkey has changed and `electron-builder` does not clean up old subkeys after an update. This means that users updating Cozy Desktop to v3.16.0 will see 2 Cozy Desktop applications listed in the programs management application and trying to uninstall the oldest version will actually uninstall the most recent (the uninstall paths are the same) and leave the old entry without any way to remove it. We introduce here a registry cleanup during the app startup phase so that our users won't have to manually edit their registry to remove the old subkey.
- Loading branch information
Showing
9 changed files
with
183 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/** | ||
* Windows uses Uninstall registry subkeys to know where to find the | ||
* uninstall executables of applications and list them in its programs | ||
* management application. | ||
* In the more recent versions of `electron-builder`, the format of the | ||
* subkey has changed and `electron-builder` does not clean up old | ||
* subkeys after an update. | ||
* This means that users updating Cozy Desktop to v3.16.0 will see 2 | ||
* Cozy Desktop applications listed in the programs management | ||
* application and trying to uninstall the oldest version will actually | ||
* uninstall the most recent (the uninstall paths are the same) and leave | ||
* the old entry without any way to remove it. | ||
* We introduce here a registry cleanup during the app startup phase so | ||
* that our users won't have to manually edit their registry to remove | ||
* the old subkey. | ||
*/ | ||
|
||
const regedit = require('regedit') | ||
|
||
// Key used prior to v3.16.0 | ||
const OLD_UNINSTALL_KEY = | ||
'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\4e3f3566-be06-5f9a-b012-0cf924cd77aa' | ||
|
||
const REGEDIT_INEXISTANT_PATH_ERROR_CODE = 2 | ||
const REGEDIT_ERROR = 'RegeditError' | ||
function RegeditError(code, msg) { | ||
this.name = REGEDIT_ERROR | ||
this.code = code | ||
this.message = msg | ||
} | ||
|
||
async function removeOldUninstallKey() { | ||
return new Promise((resolve, reject) => { | ||
regedit.deleteKey(OLD_UNINSTALL_KEY, err => { | ||
if (err && err.code !== REGEDIT_INEXISTANT_PATH_ERROR_CODE) { | ||
reject(new RegeditError(err.code, err.message)) | ||
} | ||
resolve() | ||
}) | ||
}) | ||
} | ||
|
||
module.exports = { | ||
RegeditError, | ||
removeOldUninstallKey | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -120,6 +120,11 @@ | |
"Helpers Just now": "Just now", | ||
"Helpers KB": "KB", | ||
"Helpers MB": "MB", | ||
"InvalidConfiguration Invalid configuration": "Invalid configuration", | ||
"InvalidConfiguration The client configuration is invalid": "The client configuration is invalid", | ||
"InvalidConfiguration Please log out and go through the onboarding again or contact us at [email protected]": "Please log out and go through the onboarding again or contact us at [email protected]", | ||
"InvalidConfiguration Log out": "Log out", | ||
"InvalidConfiguration Contact support": "Contact support", | ||
"Password Login": "Login", | ||
"Password Password": "Password", | ||
"Password Wrong cozy address?": "Wrong cozy address?", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -120,6 +120,11 @@ | |
"Helpers Just now": "Juste à l’instant", | ||
"Helpers KB": "Ko", | ||
"Helpers MB": "Mo", | ||
"InvalidConfiguration Invalid configuration": "Configuration invalide", | ||
"InvalidConfiguration The client configuration is invalid": "La configuration du client est invalide", | ||
"InvalidConfiguration Please log out and go through the onboarding again or contact us at [email protected]": "Veuillez vous déconnecter et réinitialiser votre client ou contactez nous sur [email protected]", | ||
"InvalidConfiguration Log out": "Se déconnecter", | ||
"InvalidConfiguration Contact support": "Contacter le support", | ||
"Password Login": "Se connecter", | ||
"Password Password": "Mot de passe", | ||
"Password Wrong cozy address?": "Mauvaise adresse Cozy ?", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,8 @@ const os = require('os') | |
const proxy = require('./js/proxy') | ||
const { COZY_CLIENT_REVOKED_MESSAGE } = require('../core/remote/cozy') | ||
const migrations = require('../core/pouch/migrations') | ||
const config = require('../core/config') | ||
const winRegistry = require('../core/utils/win_registry') | ||
|
||
const autoLaunch = require('./js/autolaunch') | ||
const lastFiles = require('./js/lastfiles') | ||
|
@@ -87,6 +89,7 @@ const showWindow = bounds => { | |
|
||
let revokedAlertShown = false | ||
let syncDirUnlinkedShown = false | ||
let invalidConfigShown = false | ||
|
||
const sendErrorToMainWindow = msg => { | ||
if (msg === COZY_CLIENT_REVOKED_MESSAGE) { | ||
|
@@ -145,6 +148,40 @@ const sendErrorToMainWindow = msg => { | |
.then(() => trayWindow.doRestart()) | ||
.catch(err => log.error(err)) | ||
return // no notification | ||
} else if (msg === config.INVALID_CONFIG_ERROR) { | ||
msg = translate('InvalidConfiguration Invalid configuration') | ||
trayWindow.send('sync-error', msg) | ||
|
||
if (invalidConfigShown) return | ||
invalidConfigShown = true // prevent the alert from appearing twice | ||
|
||
const options = { | ||
type: 'warning', | ||
title: translate('InvalidConfiguration Invalid configuration'), | ||
message: translate( | ||
'InvalidConfiguration The client configuration is invalid' | ||
), | ||
detail: translate( | ||
'InvalidConfiguration Please log out and go through the onboarding again or contact us at [email protected]' | ||
), | ||
buttons: [ | ||
translate('InvalidConfiguration Log out'), | ||
translate('InvalidConfiguration Contact support') | ||
], | ||
defaultId: 0 | ||
} | ||
trayWindow.hide() | ||
const userChoice = dialog.showMessageBox(null, options) | ||
if (userChoice === 0) { | ||
desktop | ||
.removeConfig() | ||
.then(() => log.info('removed')) | ||
.then(() => trayWindow.doRestart()) | ||
.catch(err => log.error(err)) | ||
} else { | ||
helpWindow.show() | ||
} | ||
return // no notification | ||
} else if (msg === 'Cozy is full' || msg === 'No more disk space') { | ||
msg = translate('Error ' + msg) | ||
trayWindow.send('sync-error', msg) | ||
|
@@ -176,28 +213,28 @@ const updateState = (newState, data) => { | |
if (newState === 'online' && state !== 'offline') return | ||
if (newState === 'offline' && state === 'error') return | ||
|
||
// Update window status bar | ||
if (newState === 'online') { | ||
tray.setState('up-to-date') | ||
trayWindow.send('up-to-date') | ||
} else if (newState === 'offline') { | ||
tray.setState('offline') | ||
trayWindow.send('offline') | ||
} else if (newState === 'error') { | ||
tray.setState('error', data) | ||
sendErrorToMainWindow(data) | ||
} else if (newState === 'sync-status') { | ||
tray.setState(data.label === 'uptodate' ? 'up-to-date' : 'syncing') | ||
trayWindow.send('sync-status', data) | ||
} else if (newState === 'syncing' && data && data.filename) { | ||
tray.setState('syncing', data) | ||
trayWindow.send('transfer', data) | ||
} | ||
|
||
if (newState === 'sync-status') { | ||
state = data.label === 'uptodate' ? 'up-to-date' : 'syncing' | ||
} else if (newState === 'uptodate') { | ||
state = 'up-to-date' | ||
} else { | ||
state = newState | ||
} | ||
// Update systray icon and tooltip | ||
tray.setState(state, data) | ||
} | ||
|
||
const addFile = info => { | ||
|
@@ -308,8 +345,33 @@ const startSync = force => { | |
sendErrorToMainWindow('Syncdir has been unlinked') | ||
}) | ||
desktop.events.on('delete-file', removeFile) | ||
|
||
try { | ||
desktop.setup() | ||
} catch (err) { | ||
log.fatal({ err, sentry: true }, 'Could not setup app') | ||
if (err instanceof config.InvalidConfigError) { | ||
updateState('error', err.name) | ||
} else { | ||
updateState('error', err.message) | ||
} | ||
return | ||
} | ||
|
||
// We do it here since Sentry's setup happens in `desktop.setup()` | ||
if (process.platform === 'win32') { | ||
winRegistry.removeOldUninstallKey().catch(err => { | ||
if (err instanceof winRegistry.RegeditError) { | ||
log.error( | ||
{ err, sentry: true }, | ||
'Failed to remove uninstall registry key' | ||
) | ||
} | ||
}) | ||
} | ||
|
||
desktop | ||
.synchronize(desktop.config.fileConfig.mode) | ||
.startSync(desktop.config.fileConfig.mode) | ||
.then(() => sendErrorToMainWindow('stopped')) | ||
.catch(err => { | ||
if (err.status === 402) { | ||
|
@@ -327,13 +389,11 @@ const startSync = force => { | |
trayWindow.send('user-action-required', userActionRequired) | ||
desktop.remote.warningsPoller.switchMode('medium') | ||
return | ||
} else if (err instanceof migrations.MigrationFailedError) { | ||
updateState('error', err.name) | ||
} else { | ||
updateState('error', err.message) | ||
} | ||
|
||
const msg = | ||
err instanceof migrations.MigrationFailedError | ||
? err.name | ||
: err.message | ||
updateState('error', msg) | ||
sendDiskUsage() | ||
}) | ||
sendDiskUsage() | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3278,6 +3278,11 @@ iconv-lite@^0.5.0: | |
dependencies: | ||
safer-buffer ">= 2.1.2 < 3" | ||
|
||
if-async@^3.7.4: | ||
version "3.7.4" | ||
resolved "https://registry.yarnpkg.com/if-async/-/if-async-3.7.4.tgz#55868deb0093d3c67bf7166e745353fb9bcb21a2" | ||
integrity sha1-VYaN6wCT08Z79xZudFNT+5vLIaI= | ||
|
||
ignore@^3.3.5: | ||
version "3.3.10" | ||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" | ||
|
@@ -5836,6 +5841,16 @@ readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stre | |
string_decoder "^1.1.1" | ||
util-deprecate "^1.0.1" | ||
|
||
"readable-stream@>=1.0.33-1 <1.1.0-0": | ||
version "1.0.34" | ||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" | ||
integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= | ||
dependencies: | ||
core-util-is "~1.0.0" | ||
inherits "~2.0.1" | ||
isarray "0.0.1" | ||
string_decoder "~0.10.x" | ||
|
||
readable-stream@~0.0.2: | ||
version "0.0.4" | ||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-0.0.4.tgz#f32d76e3fb863344a548d79923007173665b3b8d" | ||
|
@@ -5872,6 +5887,16 @@ redent@^1.0.0: | |
indent-string "^2.1.0" | ||
strip-indent "^1.0.1" | ||
|
||
regedit@^3.0.3: | ||
version "3.0.3" | ||
resolved "https://registry.yarnpkg.com/regedit/-/regedit-3.0.3.tgz#0c2188e15f670de7d5740c5cea9bbebe99497749" | ||
integrity sha512-SpHmMKOtiEYx0MiRRC48apBsmThoZ4svZNsYoK8leHd5bdUHV1nYb8pk8gh6Moou7/S9EDi1QsjBTpyXVQrPuQ== | ||
dependencies: | ||
debug "^4.1.0" | ||
if-async "^3.7.4" | ||
stream-slicer "0.0.6" | ||
through2 "^0.6.3" | ||
|
||
regenerator-runtime@^0.10.5: | ||
version "0.10.5" | ||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" | ||
|
@@ -6519,6 +6544,11 @@ stealthy-require@^1.1.1: | |
resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" | ||
integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= | ||
|
||
[email protected]: | ||
version "0.0.6" | ||
resolved "https://registry.yarnpkg.com/stream-slicer/-/stream-slicer-0.0.6.tgz#f86b2ac5c2440b7a0a87b71f33665c0788046138" | ||
integrity sha1-+GsqxcJEC3oKh7cfM2ZcB4gEYTg= | ||
|
||
strict-uri-encode@^1.0.0: | ||
version "1.1.0" | ||
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" | ||
|
@@ -6809,6 +6839,14 @@ [email protected]: | |
dependencies: | ||
readable-stream "2 || 3" | ||
|
||
through2@^0.6.3: | ||
version "0.6.5" | ||
resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" | ||
integrity sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg= | ||
dependencies: | ||
readable-stream ">=1.0.33-1 <1.1.0-0" | ||
xtend ">=4.0.0 <4.1.0-0" | ||
|
||
through2@~0.2.3: | ||
version "0.2.3" | ||
resolved "https://registry.yarnpkg.com/through2/-/through2-0.2.3.tgz#eb3284da4ea311b6cc8ace3653748a52abf25a3f" | ||
|
@@ -7362,7 +7400,7 @@ [email protected]: | |
resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943" | ||
integrity sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM= | ||
|
||
xtend@^4.0.0, xtend@^4.0.2, xtend@~4.0.0: | ||
"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@^4.0.2, xtend@~4.0.0: | ||
version "4.0.2" | ||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" | ||
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== | ||
|