diff --git a/core/utils/win_registry.js b/core/utils/win_registry.js new file mode 100644 index 000000000..03a93aca6 --- /dev/null +++ b/core/utils/win_registry.js @@ -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 +} diff --git a/gui/main.js b/gui/main.js index a33abb71d..c2c141002 100644 --- a/gui/main.js +++ b/gui/main.js @@ -11,6 +11,7 @@ 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') @@ -357,6 +358,18 @@ const startSync = force => { 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 .startSync(desktop.config.fileConfig.mode) .then(() => sendErrorToMainWindow('stopped')) diff --git a/package.json b/package.json index 203a0588f..481a3d4dd 100644 --- a/package.json +++ b/package.json @@ -106,6 +106,7 @@ "pouchdb": "^7.0.0", "pouchdb-find": "^7.0.0", "read": "1.0.7", + "regedit": "^3.0.3", "trash": "^5.0.0", "uuid": "^3.3.2", "yargs": "^11.0.0" diff --git a/yarn.lock b/yarn.lock index c326d1ab0..91bbeb652 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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= +stream-slicer@0.0.6: + 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 @@ through2@3.0.1: 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 @@ xregexp@2.0.0: 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==