From c26f7fc4fb55df38cbd42a9d4379664b48af34c5 Mon Sep 17 00:00:00 2001 From: Tyler Leonhardt Date: Tue, 5 Sep 2023 11:21:46 -0700 Subject: [PATCH 1/4] Remove CredentialsService & keytar ref https://github.com/microsoft/vscode/issues/115215 fixes https://github.com/microsoft/vscode/issues/143395 --- .github/workflows/ci.yml | 3 +- build/.moduleignore | 7 - build/darwin/create-universal-app.ts | 2 +- .../src/common/keychain.ts | 2 - .../extension-browser.webpack.config.js | 3 - .../extension.webpack.config.js | 5 +- .../languagedetection.test.ts | 1 - package.json | 2 - remote/package.json | 1 - remote/yarn.lock | 214 +------------- src/tsconfig.json | 1 - src/vs/code/electron-main/app.ts | 9 - src/vs/code/electron-main/auth.ts | 58 ++-- .../credentials/common/credentials.ts | 84 ------ .../common/credentialsMainService.ts | 264 ------------------ .../electron-main/credentialsMainService.ts | 49 ---- .../node/credentialsMainService.ts | 51 ---- .../node/nativeModules.integrationTest.ts | 24 +- src/vs/server/node/serverServices.ts | 9 +- .../api/browser/extensionHost.contribution.ts | 1 - .../workbench/api/browser/mainThreadKeytar.ts | 41 --- .../api/browser/mainThreadSecretState.ts | 225 +-------------- .../workbench/api/common/extHost.protocol.ts | 9 - .../api/common/extHostRequireInterceptor.ts | 26 +- .../parts/activitybar/activitybarActions.ts | 4 +- src/vs/workbench/browser/web.api.ts | 7 - src/vs/workbench/browser/web.main.ts | 12 +- .../browser/editSessionsStorageService.ts | 6 +- .../browser/authenticationService.ts | 7 +- .../credentials/browser/credentialsService.ts | 82 ------ .../electron-sandbox/credentialsService.ts | 9 - .../test/browser/credentialsService.test.ts | 61 ---- .../userDataSync/browser/userDataSyncInit.ts | 4 +- .../browser/userDataSyncWorkbenchService.ts | 4 +- yarn.lock | 94 +------ 35 files changed, 56 insertions(+), 1325 deletions(-) delete mode 100644 src/vs/platform/credentials/common/credentials.ts delete mode 100644 src/vs/platform/credentials/common/credentialsMainService.ts delete mode 100644 src/vs/platform/credentials/electron-main/credentialsMainService.ts delete mode 100644 src/vs/platform/credentials/node/credentialsMainService.ts delete mode 100644 src/vs/workbench/api/browser/mainThreadKeytar.ts delete mode 100644 src/vs/workbench/services/credentials/browser/credentialsService.ts delete mode 100644 src/vs/workbench/services/credentials/electron-sandbox/credentialsService.ts delete mode 100644 src/vs/workbench/services/credentials/test/browser/credentialsService.test.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cd32a2b50b9c5..4d49c5b204f9e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -221,8 +221,7 @@ jobs: - name: Compile Integration Tests run: yarn --cwd test/integration/browser compile - # This is required for keytar unittests, otherwise we hit - # https://github.com/atom/node-keytar/issues/76 + # This is required for SecretStorage unittests - name: Create temporary keychain run: | security create-keychain -p pwd $RUNNER_TEMP/buildagent.keychain diff --git a/build/.moduleignore b/build/.moduleignore index e4a19bbb76280..d92dedf90f92d 100644 --- a/build/.moduleignore +++ b/build/.moduleignore @@ -79,13 +79,6 @@ kerberos/src/** kerberos/node_modules/** !kerberos/**/*.node -keytar/binding.gyp -keytar/build/** -keytar/src/** -keytar/script/** -keytar/node_modules/** -!keytar/**/*.node - node-pty/binding.gyp node-pty/build/** node-pty/src/** diff --git a/build/darwin/create-universal-app.ts b/build/darwin/create-universal-app.ts index 7b10af8af667c..ffba8952cd8e9 100644 --- a/build/darwin/create-universal-app.ts +++ b/build/darwin/create-universal-app.ts @@ -51,7 +51,7 @@ async function main(buildDir?: string) { fs.writeFileSync(productJsonPath, JSON.stringify(productJson, null, '\t')); // Verify if native module architecture is correct - const findOutput = await spawn('find', [outAppPath, '-name', 'keytar.node']); + const findOutput = await spawn('find', [outAppPath, '-name', 'kerberos.node']); const lipoOutput = await spawn('lipo', ['-archs', findOutput.replace(/\n$/, '')]); if (lipoOutput.replace(/\n$/, '') !== 'x86_64 arm64') { throw new Error(`Invalid arch, got : ${lipoOutput}`); diff --git a/extensions/github-authentication/src/common/keychain.ts b/extensions/github-authentication/src/common/keychain.ts index c7b36d9621273..977dade571b88 100644 --- a/extensions/github-authentication/src/common/keychain.ts +++ b/extensions/github-authentication/src/common/keychain.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -// keytar depends on a native module shipped in vscode, so this is -// how we load it import * as vscode from 'vscode'; import { Log } from './logger'; diff --git a/extensions/microsoft-authentication/extension-browser.webpack.config.js b/extensions/microsoft-authentication/extension-browser.webpack.config.js index c32a44124a2c7..2513c7d0f9c9a 100644 --- a/extensions/microsoft-authentication/extension-browser.webpack.config.js +++ b/extensions/microsoft-authentication/extension-browser.webpack.config.js @@ -20,9 +20,6 @@ module.exports = withBrowserDefaults({ entry: { extension: './src/extension.ts', }, - externals: { - 'keytar': 'commonjs keytar', - }, resolve: { alias: { './node/crypto': path.resolve(__dirname, 'src/browser/crypto'), diff --git a/extensions/microsoft-authentication/extension.webpack.config.js b/extensions/microsoft-authentication/extension.webpack.config.js index a513ac5c3b511..45600607fc5b4 100644 --- a/extensions/microsoft-authentication/extension.webpack.config.js +++ b/extensions/microsoft-authentication/extension.webpack.config.js @@ -12,9 +12,6 @@ const withDefaults = require('../shared.webpack.config'); module.exports = withDefaults({ context: __dirname, entry: { - extension: './src/extension.ts', - }, - externals: { - 'keytar': 'commonjs keytar' + extension: './src/extension.ts' } }); diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/languagedetection.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/languagedetection.test.ts index ce6f675b5f6aa..900eb25649e5d 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/languagedetection.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/languagedetection.test.ts @@ -36,7 +36,6 @@ suite('vscode - automatic language detection', () => { "outDir": "../out/vs", "target": "es2020", "types": [ - "keytar", "mocha", "semver", "sinon", diff --git a/package.json b/package.json index 2814401b7f9e6..555d3445d362f 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,6 @@ "https-proxy-agent": "^2.2.3", "jschardet": "3.0.0", "kerberos": "^2.0.1", - "keytar": "7.9.0", "minimist": "^1.2.6", "native-is-elevated": "0.7.0", "native-keymap": "^3.3.4", @@ -118,7 +117,6 @@ "@types/gulp-svgmin": "^1.2.1", "@types/http-proxy-agent": "^2.0.1", "@types/kerberos": "^1.1.2", - "@types/keytar": "^4.4.0", "@types/minimist": "^1.2.1", "@types/mocha": "^9.1.1", "@types/node": "18.x", diff --git a/remote/package.json b/remote/package.json index 8fe0e55c1dedb..f064462fc2793 100644 --- a/remote/package.json +++ b/remote/package.json @@ -19,7 +19,6 @@ "https-proxy-agent": "^2.2.3", "jschardet": "3.0.0", "kerberos": "^2.0.1", - "keytar": "7.9.0", "minimist": "^1.2.6", "native-watchdog": "^1.4.1", "node-pty": "1.1.0-beta1", diff --git a/remote/yarn.lock b/remote/yarn.lock index 4716df355d54d..e2a07ab9843c5 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -141,29 +141,6 @@ agent-base@^7.0.1, agent-base@^7.0.2, agent-base@^7.1.0: dependencies: debug "^4.3.4" -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - -are-we-there-yet@~1.1.2: - version "1.1.7" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146" - integrity sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -210,26 +187,11 @@ chownr@^1.1.1: resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= - -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - cookie@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== -core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - debug@3.1.0, debug@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" @@ -263,21 +225,11 @@ deep-extend@^0.6.0: resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - detect-libc@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd" integrity sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w== -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - end-of-stream@^1.1.0, end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" @@ -326,20 +278,6 @@ fs-constants@^1.0.0: resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - github-from-package@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" @@ -350,11 +288,6 @@ graceful-fs@4.2.11: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - http-proxy-agent@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" @@ -400,7 +333,7 @@ ieee754@^1.1.13: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: +inherits@^2.0.3, inherits@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -420,18 +353,6 @@ is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - is-glob@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" @@ -444,11 +365,6 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - jschardet@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-3.0.0.tgz#898d2332e45ebabbdb6bf2feece9feea9a99e882" @@ -463,14 +379,6 @@ kerberos@^2.0.1: node-addon-api "^4.3.0" prebuild-install "7.1.1" -keytar@7.9.0: - version "7.9.0" - resolved "https://registry.yarnpkg.com/keytar/-/keytar-7.9.0.tgz#4c6225708f51b50cbf77c5aae81721964c2918cb" - integrity sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ== - dependencies: - node-addon-api "^4.3.0" - prebuild-install "^7.0.1" - lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -567,26 +475,6 @@ node-pty@1.1.0-beta1: dependencies: nan "^2.17.0" -npmlog@^4.0.1: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= - -object-assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -622,30 +510,6 @@ prebuild-install@7.1.1: tar-fs "^2.0.0" tunnel-agent "^0.6.0" -prebuild-install@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.0.1.tgz#c10075727c318efe72412f333e0ef625beaf3870" - integrity sha512-QBSab31WqkyxpnMWQxubYAHR5S9B2+r81ucocew34Fkl98FhvKIF50jIJnNOBmAZfyNV7vE5T6gd3hTVWgY6tg== - dependencies: - detect-libc "^2.0.0" - expand-template "^2.0.3" - github-from-package "0.0.0" - minimist "^1.2.3" - mkdirp-classic "^0.5.3" - napi-build-utils "^1.0.1" - node-abi "^3.3.0" - npmlog "^4.0.1" - pump "^3.0.0" - rc "^1.2.7" - simple-get "^4.0.0" - tar-fs "^2.0.0" - tunnel-agent "^0.6.0" - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" @@ -669,19 +533,6 @@ rc@^1.2.7: minimist "^1.2.0" strip-json-comments "~2.0.1" -readable-stream@^2.0.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - readable-stream@^3.1.1, readable-stream@^3.4.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" @@ -696,11 +547,6 @@ safe-buffer@^5.0.1, safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - semver@^7.3.5: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" @@ -708,16 +554,6 @@ semver@^7.3.5: dependencies: lru-cache "^6.0.0" -set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - -signal-exit@^3.0.0: - version "3.0.6" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" - integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== - simple-concat@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" @@ -754,24 +590,6 @@ socks@^2.7.1: ip "^2.0.0" smart-buffer "^4.2.0" -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -"string-width@^1.0.2 || 2 || 3 || 4": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -779,27 +597,6 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" @@ -845,7 +642,7 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" -util-deprecate@^1.0.1, util-deprecate@~1.0.1: +util-deprecate@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= @@ -865,13 +662,6 @@ vscode-textmate@9.0.0: resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-9.0.0.tgz#313c6c8792b0507aef35aeb81b6b370b37c44d6c" integrity sha512-Cl65diFGxz7gpwbav10HqiY/eVYTO1sjQpmRmV991Bj7wAoOAjGQ97PpQcXorDE2Uc4hnGWLY17xme+5t6MlSg== -wide-align@^1.1.0: - version "1.1.5" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" - integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== - dependencies: - string-width "^1.0.2 || 2 || 3 || 4" - wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" diff --git a/src/tsconfig.json b/src/tsconfig.json index df96ed712470c..56ca209276ba9 100644 --- a/src/tsconfig.json +++ b/src/tsconfig.json @@ -8,7 +8,6 @@ "resolveJsonModule": true, "outDir": "../out/vs", "types": [ - "keytar", "mocha", "semver", "sinon", diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 49f3c2703cd5a..9fcc3ce6f1072 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -31,7 +31,6 @@ import { localize } from 'vs/nls'; import { IBackupMainService } from 'vs/platform/backup/electron-main/backup'; import { BackupMainService } from 'vs/platform/backup/electron-main/backupMainService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ICredentialsMainService } from 'vs/platform/credentials/common/credentials'; import { ElectronExtensionHostDebugBroadcastChannel } from 'vs/platform/debug/electron-main/extensionHostDebugIpc'; import { IDiagnosticsService } from 'vs/platform/diagnostics/common/diagnostics'; import { DiagnosticsMainService, IDiagnosticsMainService } from 'vs/platform/diagnostics/electron-main/diagnosticsMainService'; @@ -97,7 +96,6 @@ import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; import { IWorkspacesHistoryMainService, WorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService'; import { WorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService'; import { IWorkspacesManagementMainService, WorkspacesManagementMainService } from 'vs/platform/workspaces/electron-main/workspacesManagementMainService'; -import { CredentialsNativeMainService } from 'vs/platform/credentials/electron-main/credentialsMainService'; import { IPolicyService } from 'vs/platform/policy/common/policy'; import { PolicyChannel } from 'vs/platform/policy/common/policyIpc'; import { IUserDataProfilesMainService } from 'vs/platform/userDataProfile/electron-main/userDataProfile'; @@ -964,9 +962,6 @@ export class CodeApplication extends Disposable { // Native Host services.set(INativeHostMainService, new SyncDescriptor(NativeHostMainService, undefined, false /* proxied to other processes */)); - // Credentials - services.set(ICredentialsMainService, new SyncDescriptor(CredentialsNativeMainService)); - // Webview Manager services.set(IWebviewManagerService, new SyncDescriptor(WebviewMainService)); @@ -1095,10 +1090,6 @@ export class CodeApplication extends Disposable { const encryptionChannel = ProxyChannel.fromService(accessor.get(IEncryptionMainService)); mainProcessElectronServer.registerChannel('encryption', encryptionChannel); - // Credentials - const credentialsChannel = ProxyChannel.fromService(accessor.get(ICredentialsMainService)); - mainProcessElectronServer.registerChannel('credentials', credentialsChannel); - // Signing const signChannel = ProxyChannel.fromService(accessor.get(ISignService)); mainProcessElectronServer.registerChannel('sign', signChannel); diff --git a/src/vs/code/electron-main/auth.ts b/src/vs/code/electron-main/auth.ts index 9e6793fd489d5..bf2a99f601c69 100644 --- a/src/vs/code/electron-main/auth.ts +++ b/src/vs/code/electron-main/auth.ts @@ -9,10 +9,8 @@ import { Event } from 'vs/base/common/event'; import { hash } from 'vs/base/common/hash'; import { Disposable } from 'vs/base/common/lifecycle'; import { generateUuid } from 'vs/base/common/uuid'; -import { ICredentialsMainService } from 'vs/platform/credentials/common/credentials'; import { IEncryptionMainService } from 'vs/platform/encryption/common/encryptionService'; import { ILogService } from 'vs/platform/log/common/log'; -import { IProductService } from 'vs/platform/product/common/productService'; import { StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IApplicationStorageMainService } from 'vs/platform/storage/electron-main/storageMainService'; import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows'; @@ -58,7 +56,6 @@ enum ProxyAuthState { export class ProxyAuthHandler extends Disposable { - private readonly OLD_PROXY_CREDENTIALS_SERVICE_KEY = `${this.productService.urlProtocol}.proxy-credentials`; private readonly PROXY_CREDENTIALS_SERVICE_KEY = 'proxy-credentials://'; private pendingProxyResolve: Promise | undefined = undefined; @@ -70,10 +67,8 @@ export class ProxyAuthHandler extends Disposable { constructor( @ILogService private readonly logService: ILogService, @IWindowsMainService private readonly windowsMainService: IWindowsMainService, - @ICredentialsMainService private readonly credentialsService: ICredentialsMainService, @IEncryptionMainService private readonly encryptionMainService: IEncryptionMainService, - @IApplicationStorageMainService private readonly applicationStorageMainService: IApplicationStorageMainService, - @IProductService private readonly productService: IProductService + @IApplicationStorageMainService private readonly applicationStorageMainService: IApplicationStorageMainService ) { super(); @@ -145,34 +140,6 @@ export class ProxyAuthHandler extends Disposable { return undefined; } - // TODO: remove this migration in a release or two. - private async getAndMigrateProxyCredentials(authInfoHash: string): Promise<{ storedUsername: string | undefined; storedPassword: string | undefined }> { - // Find any previously stored credentials - try { - let encryptedSerializedProxyCredentials = this.applicationStorageMainService.get(this.PROXY_CREDENTIALS_SERVICE_KEY + authInfoHash, StorageScope.APPLICATION); - let decryptedSerializedProxyCredentials: string | undefined; - if (!encryptedSerializedProxyCredentials) { - encryptedSerializedProxyCredentials = await this.credentialsService.getPassword(this.OLD_PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash) ?? undefined; - if (encryptedSerializedProxyCredentials) { - // re-encrypt to force new encryption algorithm to apply - decryptedSerializedProxyCredentials = await this.encryptionMainService.decrypt(encryptedSerializedProxyCredentials); - encryptedSerializedProxyCredentials = await this.encryptionMainService.encrypt(decryptedSerializedProxyCredentials); - this.applicationStorageMainService.store(this.PROXY_CREDENTIALS_SERVICE_KEY + authInfoHash, encryptedSerializedProxyCredentials, StorageScope.APPLICATION, StorageTarget.MACHINE); - // Remove it from the old location since it's in the new location. - await this.credentialsService.deletePassword(this.OLD_PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash); - } - } - if (encryptedSerializedProxyCredentials) { - const credentials: Credentials = JSON.parse(decryptedSerializedProxyCredentials ?? await this.encryptionMainService.decrypt(encryptedSerializedProxyCredentials)); - - return { storedUsername: credentials.username, storedPassword: credentials.password }; - } - } catch (error) { - this.logService.error(error); // handle errors by asking user for login via dialog - } - return { storedUsername: undefined, storedPassword: undefined }; - } - private async doResolveProxyCredentials(authInfo: AuthInfo): Promise { this.logService.trace('auth#doResolveProxyCredentials - enter', authInfo); @@ -181,7 +148,20 @@ export class ProxyAuthHandler extends Disposable { // given the properties of the auth request // (see https://github.com/microsoft/vscode/issues/109497) const authInfoHash = String(hash({ scheme: authInfo.scheme, host: authInfo.host, port: authInfo.port })); - const { storedUsername, storedPassword } = await this.getAndMigrateProxyCredentials(authInfoHash); + + let storedUsername: string | undefined; + let storedPassword: string | undefined; + try { + // Try to find stored credentials for the given auth info + const encryptedValue = this.applicationStorageMainService.get(this.PROXY_CREDENTIALS_SERVICE_KEY + authInfoHash, StorageScope.APPLICATION); + if (encryptedValue) { + const credentials: Credentials = JSON.parse(await this.encryptionMainService.decrypt(encryptedValue)); + storedUsername = credentials.username; + storedPassword = credentials.password; + } + } catch (error) { + this.logService.error(error); // handle errors by asking user for login via dialog + } // Reply with stored credentials unless we used them already. // In that case we need to show a login dialog again because @@ -230,7 +210,13 @@ export class ProxyAuthHandler extends Disposable { try { if (reply.remember) { const encryptedSerializedCredentials = await this.encryptionMainService.encrypt(JSON.stringify(credentials)); - this.applicationStorageMainService.store(this.PROXY_CREDENTIALS_SERVICE_KEY + authInfoHash, encryptedSerializedCredentials, StorageScope.APPLICATION, StorageTarget.MACHINE); + this.applicationStorageMainService.store( + this.PROXY_CREDENTIALS_SERVICE_KEY + authInfoHash, + encryptedSerializedCredentials, + StorageScope.APPLICATION, + // Always store in machine scope because we do not want these values to be synced + StorageTarget.MACHINE + ); } else { this.applicationStorageMainService.remove(this.PROXY_CREDENTIALS_SERVICE_KEY + authInfoHash, StorageScope.APPLICATION); } diff --git a/src/vs/platform/credentials/common/credentials.ts b/src/vs/platform/credentials/common/credentials.ts deleted file mode 100644 index 889b0a2ac12bc..0000000000000 --- a/src/vs/platform/credentials/common/credentials.ts +++ /dev/null @@ -1,84 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Event } from 'vs/base/common/event'; -import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; - -export const ICredentialsService = createDecorator('credentialsService'); - -export interface ICredentialsProvider { - getPassword(service: string, account: string): Promise; - setPassword(service: string, account: string, password: string): Promise; - deletePassword(service: string, account: string): Promise; - findPassword(service: string): Promise; - findCredentials(service: string): Promise>; - clear?(): Promise; -} - -export interface ICredentialsChangeEvent { - service?: string; - account: string; -} - -export interface ICredentialsService extends ICredentialsProvider { - readonly _serviceBrand: undefined; - readonly onDidChangePassword: Event; - - /* - * Each CredentialsService must provide a prefix that will be used - * by the SecretStorage API when storing secrets. - * This is a method that returns a Promise so that it can be defined in - * the main process and proxied on the renderer side. - */ - getSecretStoragePrefix(): Promise; -} - -export const ICredentialsMainService = createDecorator('credentialsMainService'); - -export interface ICredentialsMainService extends ICredentialsService { } - -interface ISecretVault { - [service: string]: { [account: string]: string } | undefined; -} - -export class InMemoryCredentialsProvider implements ICredentialsProvider { - private secretVault: ISecretVault = {}; - - async getPassword(service: string, account: string): Promise { - return this.secretVault[service]?.[account] ?? null; - } - - async setPassword(service: string, account: string, password: string): Promise { - this.secretVault[service] = this.secretVault[service] ?? {}; - this.secretVault[service]![account] = password; - } - - async deletePassword(service: string, account: string): Promise { - if (!this.secretVault[service]?.[account]) { - return false; - } - delete this.secretVault[service]![account]; - if (Object.keys(this.secretVault[service]!).length === 0) { - delete this.secretVault[service]; - } - return true; - } - - async findPassword(service: string): Promise { - return JSON.stringify(this.secretVault[service]) ?? null; - } - - async findCredentials(service: string): Promise> { - const credentials: { account: string; password: string }[] = []; - for (const account of Object.keys(this.secretVault[service] || {})) { - credentials.push({ account, password: this.secretVault[service]![account] }); - } - return credentials; - } - - async clear(): Promise { - this.secretVault = {}; - } -} diff --git a/src/vs/platform/credentials/common/credentialsMainService.ts b/src/vs/platform/credentials/common/credentialsMainService.ts deleted file mode 100644 index 80e3c89b3dd84..0000000000000 --- a/src/vs/platform/credentials/common/credentialsMainService.ts +++ /dev/null @@ -1,264 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ICredentialsChangeEvent, ICredentialsMainService, InMemoryCredentialsProvider } from 'vs/platform/credentials/common/credentials'; -import { Emitter } from 'vs/base/common/event'; -import { Disposable } from 'vs/base/common/lifecycle'; -import { ILogService } from 'vs/platform/log/common/log'; -import { isWindows } from 'vs/base/common/platform'; -import { retry, SequencerByKey } from 'vs/base/common/async'; - -interface ChunkedPassword { - content: string; - hasNextChunk: boolean; -} - -export type KeytarModule = typeof import('keytar'); - -export abstract class BaseCredentialsMainService extends Disposable implements ICredentialsMainService { - - private static readonly MAX_PASSWORD_LENGTH = 2500; - private static readonly PASSWORD_CHUNK_SIZE = BaseCredentialsMainService.MAX_PASSWORD_LENGTH - 100; - declare readonly _serviceBrand: undefined; - - private _onDidChangePassword: Emitter = this._register(new Emitter()); - readonly onDidChangePassword = this._onDidChangePassword.event; - - protected _keytarCache: KeytarModule | undefined; - - private _sequencer = new SequencerByKey(); - - constructor( - @ILogService protected readonly logService: ILogService, - ) { - super(); - } - - //#region abstract - - public abstract getSecretStoragePrefix(): Promise; - protected abstract withKeytar(): Promise; - /** - * An optional method that subclasses can implement to assist in surfacing - * Keytar load errors to the user in a friendly way. - */ - protected abstract surfaceKeytarLoadError?: (err: any) => void; - - //#endregion - - async getPassword(service: string, account: string): Promise { - this.logService.trace('Going to get password from keytar:', service, account); - let keytar: KeytarModule; - try { - keytar = await this.withKeytar(); - } catch (e) { - // for get operations, we don't want to surface errors to the user - return null; - } - - return await this._sequencer.queue(service + account, () => this.doGetPassword(keytar, service, account)); - } - - private async doGetPassword(keytar: KeytarModule, service: string, account: string): Promise { - this.logService.trace('Doing get password from keytar:', service, account); - const password = await retry(() => keytar.getPassword(service, account), 50, 3); - if (!password) { - this.logService.trace('Did not get a password from keytar for account:', account); - return password; - } - - let content: string | undefined; - let hasNextChunk: boolean | undefined; - try { - const parsed: ChunkedPassword = JSON.parse(password); - content = parsed.content; - hasNextChunk = parsed.hasNextChunk; - } catch { - // Ignore this similar to how we ignore parse errors in the delete - // because on non-windows this will not be a JSON string. - } - - if (!content || !hasNextChunk) { - this.logService.trace('Got password from keytar for account:', account); - return password; - } - - try { - let index = 1; - while (hasNextChunk) { - const nextChunk = await retry(() => keytar.getPassword(service, `${account}-${index}`), 50, 3); - const result: ChunkedPassword = JSON.parse(nextChunk!); - content += result.content; - hasNextChunk = result.hasNextChunk; - index++; - } - - this.logService.trace(`Got ${index}-chunked password from keytar for account:`, account); - return content; - } catch (e) { - this.logService.error(e); - return password; - } - } - - async setPassword(service: string, account: string, password: string): Promise { - this.logService.trace('Going to set password using keytar:', service, account); - let keytar: KeytarModule; - try { - keytar = await this.withKeytar(); - } catch (e) { - this.surfaceKeytarLoadError?.(e); - throw e; - } - - await this._sequencer.queue(service + account, () => this.doSetPassword(keytar, service, account, password)); - this._onDidChangePassword.fire({ service, account }); - } - - private async doSetPassword(keytar: KeytarModule, service: string, account: string, password: string): Promise { - this.logService.trace('Doing set password from keytar:', service, account); - if (!isWindows) { - await retry(() => keytar.setPassword(service, account, password), 50, 3); - this.logService.trace('Set password from keytar for account:', account); - return; - } - - // On Windows, we sometimes have to chunk the password because the Windows Credential Manager only allows passwords of a max length. - // So to make sure we can store passwords of any length, we chunk the longer passwords and store it as multiple passwords. - // To ensure we store any password correctly, we first delete any existing password, chunks and all, and then store the new ones. - - await this.doDeletePassword(keytar, service, account); - - // if it's a short password, just store it - if (password.length <= BaseCredentialsMainService.PASSWORD_CHUNK_SIZE) { - await retry(() => keytar.setPassword(service, account, password), 50, 3); - this.logService.trace('Set password from keytar for account:', account); - return; - } - - // otherwise, chunk it and store it - let index = 0; - let chunk = 0; - let hasNextChunk = true; - while (hasNextChunk) { - const passwordChunk = password.substring(index, index + BaseCredentialsMainService.PASSWORD_CHUNK_SIZE); - index += BaseCredentialsMainService.PASSWORD_CHUNK_SIZE; - hasNextChunk = password.length - index > 0; - - const content: ChunkedPassword = { - content: passwordChunk, - hasNextChunk: hasNextChunk - }; - await retry(() => keytar.setPassword(service, chunk ? `${account}-${chunk}` : account, JSON.stringify(content)), 50, 3); - chunk++; - } - - this.logService.trace(`Set${chunk ? ` ${chunk}-chunked` : ''} password from keytar for account:`, account); - } - - async deletePassword(service: string, account: string): Promise { - this.logService.trace('Going to delete password using keytar:', service, account); - let keytar: KeytarModule; - try { - keytar = await this.withKeytar(); - } catch (e) { - this.surfaceKeytarLoadError?.(e); - throw e; - } - - const result = await this._sequencer.queue(service + account, () => this.doDeletePassword(keytar, service, account)); - if (result) { - this._onDidChangePassword.fire({ service, account }); - } - return result; - } - - private async doDeletePassword(keytar: KeytarModule, service: string, account: string): Promise { - this.logService.trace('Doing delete password from keytar:', service, account); - const password = await keytar.getPassword(service, account); - if (!password) { - this.logService.trace('Did not get a password to delete from keytar for account:', account); - return false; - } - - let content: string | undefined; - let hasNextChunk: boolean | undefined; - try { - const possibleChunk = JSON.parse(password); - content = possibleChunk.content; - hasNextChunk = possibleChunk.hasNextChunk; - } catch { - // When the password is saved the entire JSON payload is encrypted then stored, thus the result from getPassword might not be valid JSON - // https://github.com/microsoft/vscode/blob/c22cb87311b5eb1a3bf5600d18733f7485355dc0/src/vs/workbench/api/browser/mainThreadSecretState.ts#L83 - // However in the chunked case we JSONify each chunk after encryption so for the chunked case we do expect valid JSON here - // https://github.com/microsoft/vscode/blob/708cb0c507d656b760f9d08115b8ebaf8964fd73/src/vs/platform/credentials/common/credentialsMainService.ts#L128 - // Empty catch here just as in getPassword because we expect to handle both JSON cases and non JSON cases here it's not an error case to fail to parse - // https://github.com/microsoft/vscode/blob/708cb0c507d656b760f9d08115b8ebaf8964fd73/src/vs/platform/credentials/common/credentialsMainService.ts#L76 - } - - let index = 0; - if (content && hasNextChunk) { - try { - // need to delete additional chunks - index++; - while (hasNextChunk) { - const accountWithIndex = `${account}-${index}`; - const nextChunk = await keytar.getPassword(service, accountWithIndex); - await keytar.deletePassword(service, accountWithIndex); - - const result: ChunkedPassword = JSON.parse(nextChunk!); - hasNextChunk = result.hasNextChunk; - index++; - } - } catch (e) { - this.logService.error(e); - } - } - - // Delete the first account to determine deletion success - if (await keytar.deletePassword(service, account)) { - this.logService.trace(`Deleted${index ? ` ${index}-chunked` : ''} password from keytar for account:`, account); - return true; - } - - this.logService.trace(`Keytar failed to delete${index ? ` ${index}-chunked` : ''} password for account:`, account); - return false; - } - - async findPassword(service: string): Promise { - let keytar: KeytarModule; - try { - keytar = await this.withKeytar(); - } catch (e) { - // for get operations, we don't want to surface errors to the user - return null; - } - - return await keytar.findPassword(service); - } - - async findCredentials(service: string): Promise> { - let keytar: KeytarModule; - try { - keytar = await this.withKeytar(); - } catch (e) { - // for get operations, we don't want to surface errors to the user - return []; - } - - return await keytar.findCredentials(service); - } - - public clear(): Promise { - if (this._keytarCache instanceof InMemoryCredentialsProvider) { - return this._keytarCache.clear(); - } - - // We don't know how to properly clear Keytar because we don't know - // what services have stored credentials. For reference, a "service" is an extension. - // TODO: should we clear credentials for the built-in auth extensions? - return Promise.resolve(); - } -} diff --git a/src/vs/platform/credentials/electron-main/credentialsMainService.ts b/src/vs/platform/credentials/electron-main/credentialsMainService.ts deleted file mode 100644 index f62719408c18d..0000000000000 --- a/src/vs/platform/credentials/electron-main/credentialsMainService.ts +++ /dev/null @@ -1,49 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { InMemoryCredentialsProvider } from 'vs/platform/credentials/common/credentials'; -import { ILogService } from 'vs/platform/log/common/log'; -import { INativeEnvironmentService } from 'vs/platform/environment/common/environment'; -import { IProductService } from 'vs/platform/product/common/productService'; -import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows'; -import { BaseCredentialsMainService, KeytarModule } from 'vs/platform/credentials/common/credentialsMainService'; - -export class CredentialsNativeMainService extends BaseCredentialsMainService { - - constructor( - @ILogService logService: ILogService, - @INativeEnvironmentService private readonly environmentMainService: INativeEnvironmentService, - @IProductService private readonly productService: IProductService, - @IWindowsMainService private readonly windowsMainService: IWindowsMainService, - ) { - super(logService); - } - - // If the credentials service is running on the server, we add a suffix -server to differentiate from the location that the - // client would store the credentials. - public override async getSecretStoragePrefix() { return Promise.resolve(this.productService.urlProtocol); } - - protected async withKeytar(): Promise { - if (this._keytarCache) { - return this._keytarCache; - } - - if (this.environmentMainService.disableKeytar) { - this.logService.info('Keytar is disabled. Using in-memory credential store instead.'); - this._keytarCache = new InMemoryCredentialsProvider(); - return this._keytarCache; - } - - const keytarCache = await import('keytar'); - // Try using keytar to see if it throws or not. - await keytarCache.findCredentials('test-keytar-loads'); - this._keytarCache = keytarCache; - return this._keytarCache; - } - - protected override surfaceKeytarLoadError = (err: any) => { - this.windowsMainService.sendToFocused('vscode:showCredentialsError', err.message ?? err); - }; -} diff --git a/src/vs/platform/credentials/node/credentialsMainService.ts b/src/vs/platform/credentials/node/credentialsMainService.ts deleted file mode 100644 index cc2156d22cd92..0000000000000 --- a/src/vs/platform/credentials/node/credentialsMainService.ts +++ /dev/null @@ -1,51 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { InMemoryCredentialsProvider } from 'vs/platform/credentials/common/credentials'; -import { ILogService } from 'vs/platform/log/common/log'; -import { INativeEnvironmentService } from 'vs/platform/environment/common/environment'; -import { IProductService } from 'vs/platform/product/common/productService'; -import { BaseCredentialsMainService, KeytarModule } from 'vs/platform/credentials/common/credentialsMainService'; - -export class CredentialsWebMainService extends BaseCredentialsMainService { - // Since we fallback to the in-memory credentials provider, we do not need to surface any Keytar load errors - // to the user. - protected surfaceKeytarLoadError?: (err: any) => void; - - constructor( - @ILogService logService: ILogService, - @INativeEnvironmentService private readonly environmentMainService: INativeEnvironmentService, - @IProductService private readonly productService: IProductService, - ) { - super(logService); - } - - // If the credentials service is running on the server, we add a suffix -server to differentiate from the location that the - // client would store the credentials. - public override async getSecretStoragePrefix() { return Promise.resolve(`${this.productService.urlProtocol}-server`); } - - protected async withKeytar(): Promise { - if (this._keytarCache) { - return this._keytarCache; - } - - if (this.environmentMainService.disableKeytar) { - this.logService.info('Keytar is disabled. Using in-memory credential store instead.'); - this._keytarCache = new InMemoryCredentialsProvider(); - return this._keytarCache; - } - - try { - this._keytarCache = await import('keytar'); - // Try using keytar to see if it throws or not. - await this._keytarCache.findCredentials('test-keytar-loads'); - } catch (e) { - this.logService.warn( - `Using the in-memory credential store as the operating system's credential store could not be accessed. Please see https://aka.ms/vscode-server-keyring on how to set this up. Details: ${e.message ?? e}`); - this._keytarCache = new InMemoryCredentialsProvider(); - } - return this._keytarCache; - } -} diff --git a/src/vs/platform/environment/test/node/nativeModules.integrationTest.ts b/src/vs/platform/environment/test/node/nativeModules.integrationTest.ts index 4148b9dc540e4..68128a214fd5e 100644 --- a/src/vs/platform/environment/test/node/nativeModules.integrationTest.ts +++ b/src/vs/platform/environment/test/node/nativeModules.integrationTest.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { isLinux, isWindows } from 'vs/base/common/platform'; +import { isWindows } from 'vs/base/common/platform'; import { flakySuite } from 'vs/base/test/common/testUtils'; function testErrorMessage(module: string): string { @@ -74,28 +74,6 @@ flakySuite('Native Modules (all platforms)', () => { }); }); -(isLinux ? suite.skip : suite)('Native Modules (Windows, macOS)', () => { - - test('keytar', async () => { - const keytar = await import('keytar'); - const name = `VSCode Test ${Math.floor(Math.random() * 1e9)}`; - try { - await keytar.setPassword(name, 'foo', 'bar'); - assert.strictEqual(await keytar.findPassword(name), 'bar'); - assert.strictEqual((await keytar.findCredentials(name)).length, 1); - assert.strictEqual(await keytar.getPassword(name, 'foo'), 'bar'); - await keytar.deletePassword(name, 'foo'); - assert.strictEqual(await keytar.getPassword(name, 'foo'), null); - } catch (err) { - try { - await keytar.deletePassword(name, 'foo'); // try to clean up - } catch { } - - throw err; - } - }); -}); - (!isWindows ? suite.skip : suite)('Native Modules (Windows)', () => { (process.type === 'renderer' ? test.skip /* TODO@electron module is not context aware yet and thus cannot load in Electron renderer used by tests */ : test)('@vscode/windows-mutex', async () => { diff --git a/src/vs/server/node/serverServices.ts b/src/vs/server/node/serverServices.ts index 7e568185997ae..422370324f777 100644 --- a/src/vs/server/node/serverServices.ts +++ b/src/vs/server/node/serverServices.ts @@ -11,12 +11,10 @@ import * as path from 'vs/base/common/path'; import { IURITransformer } from 'vs/base/common/uriIpc'; import { getMachineId } from 'vs/base/node/id'; import { Promises } from 'vs/base/node/pfs'; -import { ClientConnectionEvent, IMessagePassingProtocol, IPCServer, ProxyChannel, StaticRouter } from 'vs/base/parts/ipc/common/ipc'; +import { ClientConnectionEvent, IMessagePassingProtocol, IPCServer, StaticRouter } from 'vs/base/parts/ipc/common/ipc'; import { ProtocolConstants } from 'vs/base/parts/ipc/common/ipc.net'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ConfigurationService } from 'vs/platform/configuration/common/configurationService'; -import { ICredentialsMainService } from 'vs/platform/credentials/common/credentials'; -import { CredentialsWebMainService } from 'vs/platform/credentials/node/credentialsMainService'; import { ExtensionHostDebugBroadcastChannel } from 'vs/platform/debug/common/extensionHostDebugIpc'; import { IDownloadService } from 'vs/platform/download/common/download'; import { DownloadServiceChannelClient } from 'vs/platform/download/common/downloadIpc'; @@ -201,8 +199,6 @@ export async function setupServerServices(connectionToken: ServerConnectionToken const ptyHostService = instantiationService.createInstance(PtyHostService, ptyHostStarter); services.set(IPtyService, ptyHostService); - services.set(ICredentialsMainService, new SyncDescriptor(CredentialsWebMainService)); - instantiationService.invokeFunction(accessor => { const extensionManagementService = accessor.get(INativeServerExtensionManagementService); const extensionsScannerService = accessor.get(IExtensionsScannerService); @@ -227,9 +223,6 @@ export async function setupServerServices(connectionToken: ServerConnectionToken const channel = new ExtensionManagementChannel(extensionManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority)); socketServer.registerChannel('extensions', channel); - const credentialsChannel = ProxyChannel.fromService(accessor.get(ICredentialsMainService)); - socketServer.registerChannel('credentials', credentialsChannel); - // clean up extensions folder remoteExtensionsScanner.whenExtensionsReady().then(() => extensionManagementService.cleanUp()); diff --git a/src/vs/workbench/api/browser/extensionHost.contribution.ts b/src/vs/workbench/api/browser/extensionHost.contribution.ts index 9217613b50a6b..abb8b45a8ad40 100644 --- a/src/vs/workbench/api/browser/extensionHost.contribution.ts +++ b/src/vs/workbench/api/browser/extensionHost.contribution.ts @@ -42,7 +42,6 @@ import './mainThreadErrors'; import './mainThreadExtensionService'; import './mainThreadFileSystem'; import './mainThreadFileSystemEventService'; -import './mainThreadKeytar'; import './mainThreadLanguageFeatures'; import './mainThreadLanguages'; import './mainThreadLogService'; diff --git a/src/vs/workbench/api/browser/mainThreadKeytar.ts b/src/vs/workbench/api/browser/mainThreadKeytar.ts deleted file mode 100644 index 8b7649ada1f4b..0000000000000 --- a/src/vs/workbench/api/browser/mainThreadKeytar.ts +++ /dev/null @@ -1,41 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { extHostNamedCustomer, IExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers'; -import { MainContext, MainThreadKeytarShape } from 'vs/workbench/api/common/extHost.protocol'; -import { ICredentialsService } from 'vs/platform/credentials/common/credentials'; - -@extHostNamedCustomer(MainContext.MainThreadKeytar) -export class MainThreadKeytar implements MainThreadKeytarShape { - - constructor( - _extHostContext: IExtHostContext, - @ICredentialsService private readonly _credentialsService: ICredentialsService, - ) { } - - async $getPassword(service: string, account: string): Promise { - return this._credentialsService.getPassword(service, account); - } - - async $setPassword(service: string, account: string, password: string): Promise { - return this._credentialsService.setPassword(service, account, password); - } - - async $deletePassword(service: string, account: string): Promise { - return this._credentialsService.deletePassword(service, account); - } - - async $findPassword(service: string): Promise { - return this._credentialsService.findPassword(service); - } - - async $findCredentials(service: string): Promise> { - return this._credentialsService.findCredentials(service); - } - - dispose(): void { - // - } -} diff --git a/src/vs/workbench/api/browser/mainThreadSecretState.ts b/src/vs/workbench/api/browser/mainThreadSecretState.ts index d8fa95ac53885..2c70d06f1ac36 100644 --- a/src/vs/workbench/api/browser/mainThreadSecretState.ts +++ b/src/vs/workbench/api/browser/mainThreadSecretState.ts @@ -5,146 +5,28 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { extHostNamedCustomer, IExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers'; -import { ICredentialsService } from 'vs/platform/credentials/common/credentials'; import { ExtHostContext, ExtHostSecretStateShape, MainContext, MainThreadSecretStateShape } from '../common/extHost.protocol'; import { ILogService } from 'vs/platform/log/common/log'; import { SequencerByKey } from 'vs/base/common/async'; import { ISecretStorageService } from 'vs/platform/secrets/common/secrets'; import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService'; -import { IEncryptionService } from 'vs/platform/encryption/common/encryptionService'; - -class OldMainThreadSecretState extends Disposable implements MainThreadSecretStateShape { - - private secretStoragePrefix = this.credentialsService.getSecretStoragePrefix(); - - constructor( - private readonly _proxy: ExtHostSecretStateShape, - private readonly credentialsService: ICredentialsService, - private readonly encryptionService: IEncryptionService, - private readonly logService: ILogService, - ) { - super(); - this._register(this.credentialsService.onDidChangePassword(async e => { - const extensionId = e.service?.substring((await this.secretStoragePrefix).length); - if (extensionId) { - this._proxy.$onDidChangePassword({ extensionId, key: e.account }); - } - })); - } - - private async getFullKey(extensionId: string): Promise { - return `${await this.secretStoragePrefix}${extensionId}`; - } - - async $getPassword(extensionId: string, key: string): Promise { - this.logService.trace(`MainThreadSecretState#getPassword: Getting password for ${extensionId} extension: `, key); - const fullKey = await this.getFullKey(extensionId); - const password = await this.credentialsService.getPassword(fullKey, key); - if (!password) { - this.logService.trace('MainThreadSecretState#getPassword: No password found for: ', key); - return undefined; - } - - let decrypted: string | null; - try { - this.logService.trace('MainThreadSecretState#getPassword: Decrypting password for: ', key); - decrypted = await this.encryptionService.decrypt(password); - } catch (e) { - this.logService.error(e); - this.logService.trace('MainThreadSecretState#getPassword: Trying migration for: ', key); - - // If we are on a platform that newly started encrypting secrets before storing them, - // then passwords previously stored were stored un-encrypted (NOTE: but still being stored in a secure keyring). - // When we try to decrypt a password that wasn't encrypted previously, the encryption service will throw. - // To recover gracefully, we first try to encrypt & store the password (essentially migrating the secret to the new format) - // and then we try to read it and decrypt again. - const encryptedForSet = await this.encryptionService.encrypt(password); - await this.credentialsService.setPassword(fullKey, key, encryptedForSet); - const passwordEncrypted = await this.credentialsService.getPassword(fullKey, key); - decrypted = passwordEncrypted && await this.encryptionService.decrypt(passwordEncrypted); - } - - if (decrypted) { - try { - const value = JSON.parse(decrypted); - if (value.extensionId === extensionId) { - this.logService.trace('MainThreadSecretState#getPassword: Password found for: ', key); - return value.content; - } - } catch (parseError) { - // We may not be able to parse it, but we keep the secret in the keychain anyway just in case - // it decrypts correctly in the future. - this.logService.error(parseError); - throw new Error('Unable to parse decrypted password'); - } - } - - this.logService.trace('MainThreadSecretState#getPassword: No password found for: ', key); - return undefined; - } - - async $setPassword(extensionId: string, key: string, value: string): Promise { - this.logService.trace(`MainThreadSecretState#setPassword: Setting password for ${extensionId} extension: `, key); - const fullKey = await this.getFullKey(extensionId); - const toEncrypt = JSON.stringify({ - extensionId, - content: value - }); - this.logService.trace('MainThreadSecretState#setPassword: Encrypting password for: ', key); - const encrypted = await this.encryptionService.encrypt(toEncrypt); - this.logService.trace('MainThreadSecretState#setPassword: Storing password for: ', key); - return await this.credentialsService.setPassword(fullKey, key, encrypted); - } - - async $deletePassword(extensionId: string, key: string): Promise { - try { - const fullKey = await this.getFullKey(extensionId); - await this.credentialsService.deletePassword(fullKey, key); - } catch (_) { - throw new Error('Cannot delete password'); - } - } -} @extHostNamedCustomer(MainContext.MainThreadSecretState) export class MainThreadSecretState extends Disposable implements MainThreadSecretStateShape { private readonly _proxy: ExtHostSecretStateShape; - // TODO: Remove this when all known embedders implement a secret storage provider - private readonly _oldMainThreadSecretState: OldMainThreadSecretState | undefined; - private readonly _sequencer = new SequencerByKey(); - // TODO: Remove this when we remove the old API - private secretStoragePrefix = this.credentialsService.getSecretStoragePrefix(); - constructor( extHostContext: IExtHostContext, @ISecretStorageService private readonly secretStorageService: ISecretStorageService, @ILogService private readonly logService: ILogService, - // TODO: Remove this when we remove the old API - @ICredentialsService private readonly credentialsService: ICredentialsService, - // TODO: Remove this when we remove the old API - @IEncryptionService private readonly encryptionService: IEncryptionService, - @IBrowserWorkbenchEnvironmentService environmentService: IBrowserWorkbenchEnvironmentService, + @IBrowserWorkbenchEnvironmentService environmentService: IBrowserWorkbenchEnvironmentService ) { super(); this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostSecretState); - // If the embedder doesn't implement a secret storage provider, then we need to use the old API - // to ensure that secrets are still stored in a secure way. This is only temporary until all - // embedders implement a secret storage provider. - // TODO: Remove this when all known embedders implement a secret storage provider - if (environmentService.options?.credentialsProvider && !environmentService.options?.secretStorageProvider) { - this._oldMainThreadSecretState = this._register(new OldMainThreadSecretState( - this._proxy, - credentialsService, - encryptionService, - logService - )); - } - this._register(this.secretStorageService.onDidChangeSecret((e: string) => { try { const { extensionId, key } = this.parseKey(e); @@ -163,23 +45,9 @@ export class MainThreadSecretState extends Disposable implements MainThreadSecre } private async doGetPassword(extensionId: string, key: string): Promise { - // TODO: Remove this when all known embedders implement a secret storage provider - if (this._oldMainThreadSecretState) { - return await this._oldMainThreadSecretState.$getPassword(extensionId, key); - } - const fullKey = this.getKey(extensionId, key); - const password = await this.secretStorageService.get(fullKey); - if (!password) { - this.logService.trace('[mainThreadSecretState] No password found for: ', extensionId, key); - - // TODO: Remove this when we remove the old API - const password = await this.getAndDeleteOldPassword(extensionId, key); - return password; - } - - this.logService.trace('[mainThreadSecretState] Password found for: ', extensionId, key); + this.logService.trace(`[mainThreadSecretState] ${password ? 'P' : 'No p'}assword found for: `, extensionId, key); return password; } @@ -189,11 +57,6 @@ export class MainThreadSecretState extends Disposable implements MainThreadSecre } private async doSetPassword(extensionId: string, key: string, value: string): Promise { - // TODO: Remove this when all known embedders implement a secret storage provider - if (this._oldMainThreadSecretState) { - return await this._oldMainThreadSecretState.$setPassword(extensionId, key, value); - } - const fullKey = this.getKey(extensionId, key); await this.secretStorageService.set(fullKey, value); this.logService.trace('[mainThreadSecretState] Password set for: ', extensionId, key); @@ -205,11 +68,6 @@ export class MainThreadSecretState extends Disposable implements MainThreadSecre } private async doDeletePassword(extensionId: string, key: string): Promise { - // TODO: Remove this when all known embedders implement a secret storage provider - if (this._oldMainThreadSecretState) { - return await this._oldMainThreadSecretState.$deletePassword(extensionId, key); - } - const fullKey = this.getKey(extensionId, key); await this.secretStorageService.delete(fullKey); this.logService.trace('[mainThreadSecretState] Password deleted for: ', extensionId, key); @@ -222,83 +80,4 @@ export class MainThreadSecretState extends Disposable implements MainThreadSecre private parseKey(key: string): { extensionId: string; key: string } { return JSON.parse(key); } - - //#region Old API - - // Delete this all when we remove the old API - - private async getAndDeleteOldPassword(extensionId: string, key: string): Promise { - const password = await this.getOldPassword(extensionId, key); - if (password) { - const fullKey = this.getKey(extensionId, key); - this.logService.trace('[mainThreadSecretState] Setting old password to new location for: ', extensionId, key); - await this.secretStorageService.set(fullKey, password); - this.logService.trace('[mainThreadSecretState] Old Password set to new location for: ', extensionId, key); - if (this.secretStorageService.type === 'persisted') { - this.logService.trace('[mainThreadSecretState] Deleting old password for since it was persisted in the new location: ', extensionId, key); - await this.deleteOldPassword(extensionId, key); - } - } - return password; - } - - private async getOldPassword(extensionId: string, key: string): Promise { - this.logService.trace(`[mainThreadSecretState] Getting old password for ${extensionId} extension: `, key); - const fullKey = `${await this.secretStoragePrefix}${extensionId}`; - const password = await this.credentialsService.getPassword(fullKey, key); - if (!password) { - this.logService.trace('[mainThreadSecretState] No old password found for: ', extensionId, key); - return undefined; - } - - let decrypted: string | null; - try { - this.logService.trace('[mainThreadSecretState] Decrypting old password for: ', extensionId, key); - decrypted = await this.encryptionService.decrypt(password); - } catch (e) { - this.logService.error(e); - this.logService.trace('[mainThreadSecretState] Trying old migration for: ', extensionId, key); - - // If we are on a platform that newly started encrypting secrets before storing them, - // then passwords previously stored were stored un-encrypted (NOTE: but still being stored in a secure keyring). - // When we try to decrypt a password that wasn't encrypted previously, the encryption service will throw. - // To recover gracefully, we first try to encrypt & store the password (essentially migrating the secret to the new format) - // and then we try to read it and decrypt again. - const encryptedForSet = await this.encryptionService.encrypt(password); - await this.credentialsService.setPassword(fullKey, key, encryptedForSet); - const passwordEncrypted = await this.credentialsService.getPassword(fullKey, key); - decrypted = passwordEncrypted && await this.encryptionService.decrypt(passwordEncrypted); - } - - if (decrypted) { - try { - const value = JSON.parse(decrypted); - if (value.extensionId === extensionId) { - this.logService.trace('[mainThreadSecretState] Old password found for: ', extensionId, key); - return value.content; - } - } catch (parseError) { - // We may not be able to parse it, but we keep the secret in the keychain anyway just in case - // it decrypts correctly in the future. - this.logService.error(parseError); - return undefined; - } - } - - this.logService.trace('[mainThreadSecretState] No old password found for: ', extensionId, key); - return undefined; - } - - private async deleteOldPassword(extensionId: string, key: string): Promise { - try { - const fullKey = `${await this.secretStoragePrefix}${extensionId}`; - this.logService.trace(`[mainThreadSecretState] Deleting old password for ${extensionId} extension: `, key); - await this.credentialsService.deletePassword(fullKey, key); - this.logService.trace('[mainThreadSecretState] Old password deleted for: ', extensionId, key); - } catch (_) { - throw new Error('Cannot delete password'); - } - } - - //#endregion } diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 3c894ef8694c2..a3063e7159536 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -298,14 +298,6 @@ export interface MainThreadConsoleShape extends IDisposable { $logExtensionHostMessage(msg: IRemoteConsoleLog): void; } -export interface MainThreadKeytarShape extends IDisposable { - $getPassword(service: string, account: string): Promise; - $setPassword(service: string, account: string, password: string): Promise; - $deletePassword(service: string, account: string): Promise; - $findPassword(service: string): Promise; - $findCredentials(service: string): Promise>; -} - export interface IRegExpDto { pattern: string; flags?: string; @@ -2631,7 +2623,6 @@ export const MainContext = { MainThreadErrors: createProxyIdentifier('MainThreadErrors'), MainThreadTreeViews: createProxyIdentifier('MainThreadTreeViews'), MainThreadDownloadService: createProxyIdentifier('MainThreadDownloadService'), - MainThreadKeytar: createProxyIdentifier('MainThreadKeytar'), MainThreadLanguageFeatures: createProxyIdentifier('MainThreadLanguageFeatures'), MainThreadLanguages: createProxyIdentifier('MainThreadLanguages'), MainThreadLogger: createProxyIdentifier('MainThreadLogger'), diff --git a/src/vs/workbench/api/common/extHostRequireInterceptor.ts b/src/vs/workbench/api/common/extHostRequireInterceptor.ts index fb96819767b9e..2123f716aaf95 100644 --- a/src/vs/workbench/api/common/extHostRequireInterceptor.ts +++ b/src/vs/workbench/api/common/extHostRequireInterceptor.ts @@ -213,7 +213,6 @@ class KeytarNodeModuleFactory implements INodeModuleFactory { ) { this._mainThreadTelemetry = rpcService.getProxy(MainContext.MainThreadTelemetry); const { environment } = initData; - const mainThreadKeytar = rpcService.getProxy(MainContext.MainThreadKeytar); if (environment.appRoot) { let appRoot = environment.appRoot.fsPath; @@ -227,21 +226,24 @@ class KeytarNodeModuleFactory implements INodeModuleFactory { this.alternativeNames.add(`${appRoot}/node_modules.asar/keytar`); this.alternativeNames.add(`${appRoot}/node_modules/keytar`); } + + // Use an implementation that does nothing to prevent errors from popping up + // do to VS Code no longer shipping with keytar. this._impl = { - getPassword: (service: string, account: string): Promise => { - return mainThreadKeytar.$getPassword(service, account); + getPassword: (_service: string, _account: string): Promise => { + return Promise.resolve(null); }, - setPassword: (service: string, account: string, password: string): Promise => { - return mainThreadKeytar.$setPassword(service, account, password); + setPassword: (_service: string, _account: string, _password: string): Promise => { + return Promise.resolve(); }, - deletePassword: (service: string, account: string): Promise => { - return mainThreadKeytar.$deletePassword(service, account); + deletePassword: (_service: string, _account: string): Promise => { + return Promise.resolve(true); }, - findPassword: (service: string): Promise => { - return mainThreadKeytar.$findPassword(service); + findPassword: (_service: string): Promise => { + return Promise.resolve(null); }, - findCredentials(service: string): Promise> { - return mainThreadKeytar.$findCredentials(service); + findCredentials(_service: string): Promise> { + return Promise.resolve([]); } }; } @@ -249,7 +251,7 @@ class KeytarNodeModuleFactory implements INodeModuleFactory { public load(_request: string, parent: URI): any { const ext = this._extensionPaths.findSubstr(parent); type ShimmingKeytarClassification = { - owner: 'jrieken'; + owner: 'TylerLeonhardt'; comment: 'Know when the keytar-shim was used'; extension: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The extension is question' }; }; diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index 4f70c6103f8f8..6e8afba3bf558 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -36,7 +36,6 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite'; import { ViewContainerLocation } from 'vs/workbench/common/views'; import { IPaneCompositePart } from 'vs/workbench/browser/parts/paneCompositePart'; -import { ICredentialsService } from 'vs/platform/credentials/common/credentials'; import { IUserDataProfileService } from 'vs/workbench/services/userDataProfile/common/userDataProfile'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { ILogService } from 'vs/platform/log/common/log'; @@ -234,7 +233,7 @@ export class AccountsActivityActionViewItem extends MenuActivityActionViewItem { private readonly problematicProviders: Set = new Set(); private initialized = false; - private sessionFromEmbedder = new Lazy>(() => getCurrentAuthenticationSessionInfo(this.credentialsService, this.secretStorageService, this.productService)); + private sessionFromEmbedder = new Lazy>(() => getCurrentAuthenticationSessionInfo(this.secretStorageService, this.productService)); constructor( action: ActivityAction, @@ -254,7 +253,6 @@ export class AccountsActivityActionViewItem extends MenuActivityActionViewItem { @IStorageService private readonly storageService: IStorageService, @IKeybindingService keybindingService: IKeybindingService, @ISecretStorageService private readonly secretStorageService: ISecretStorageService, - @ICredentialsService private readonly credentialsService: ICredentialsService, @ILogService private readonly logService: ILogService ) { super(MenuId.AccountsContext, action, contextMenuActionsProvider, true, colors, activityHoverOptions, themeService, hoverService, menuService, contextMenuService, contextKeyService, configurationService, environmentService, keybindingService); diff --git a/src/vs/workbench/browser/web.api.ts b/src/vs/workbench/browser/web.api.ts index 8295ab261290a..1d703966a894c 100644 --- a/src/vs/workbench/browser/web.api.ts +++ b/src/vs/workbench/browser/web.api.ts @@ -12,7 +12,6 @@ import type { IUpdateProvider } from 'vs/workbench/services/update/browser/updat import type { Event } from 'vs/base/common/event'; import type { IWorkspaceProvider } from 'vs/workbench/services/host/browser/browserHostService'; import type { IProductConfiguration } from 'vs/base/common/product'; -import type { ICredentialsProvider } from 'vs/platform/credentials/common/credentials'; import type { ISecretStorageProvider } from 'vs/platform/secrets/common/secrets'; import type { TunnelProviderFeatures } from 'vs/platform/tunnel/common/tunnel'; import type { IProgress, IProgressCompositeOptions, IProgressDialogOptions, IProgressNotificationOptions, IProgressOptions, IProgressStep, IProgressWindowOptions } from 'vs/platform/progress/common/progress'; @@ -210,12 +209,6 @@ export interface IWorkbenchConstructionOptions { */ readonly settingsSyncOptions?: ISettingsSyncOptions; - /** - * The credentials provider to store and retrieve secrets. - * TODO: Remove this in favor of the secret storage provider. - */ - readonly credentialsProvider?: ICredentialsProvider; - /** * The secret storage provider to store and retrieve secrets. */ diff --git a/src/vs/workbench/browser/web.main.ts b/src/vs/workbench/browser/web.main.ts index 925403791afae..b464fe5abac07 100644 --- a/src/vs/workbench/browser/web.main.ts +++ b/src/vs/workbench/browser/web.main.ts @@ -62,9 +62,7 @@ import { IWorkspaceTrustEnablementService, IWorkspaceTrustManagementService } fr import { HTMLFileSystemProvider } from 'vs/platform/files/browser/htmlFileSystemProvider'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { mixin, safeStringify } from 'vs/base/common/objects'; -import { ICredentialsService } from 'vs/platform/credentials/common/credentials'; import { IndexedDB } from 'vs/base/browser/indexedDB'; -import { BrowserCredentialsService } from 'vs/workbench/services/credentials/browser/credentialsService'; import { IWorkspace } from 'vs/workbench/services/host/browser/browserHostService'; import { WebFileSystemAccess } from 'vs/platform/files/browser/webFileSystemAccess'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -389,10 +387,6 @@ export class BrowserMain extends Disposable { // // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - // Credentials Service - const credentialsService = new BrowserCredentialsService(environmentService, remoteAgentService, productService); - serviceCollection.set(ICredentialsService, credentialsService); - const encryptionService = new EncryptionService(); serviceCollection.set(IEncryptionService, encryptionService); const secretStorageService = new BrowserSecretStorageService(storageService, encryptionService, environmentService, logService); @@ -400,7 +394,7 @@ export class BrowserMain extends Disposable { // Userdata Initialize Service const userDataInitializers: IUserDataInitializer[] = []; - userDataInitializers.push(new UserDataSyncInitializer(environmentService, secretStorageService, credentialsService, userDataSyncStoreManagementService, fileService, userDataProfilesService, storageService, productService, requestService, logService, uriIdentityService)); + userDataInitializers.push(new UserDataSyncInitializer(environmentService, secretStorageService, userDataSyncStoreManagementService, fileService, userDataProfilesService, storageService, productService, requestService, logService, uriIdentityService)); if (environmentService.options.profile) { userDataInitializers.push(new UserDataProfileInitializer(environmentService, fileService, userDataProfileService, storageService, logService, uriIdentityService, requestService)); } @@ -497,7 +491,6 @@ export class BrowserMain extends Disposable { const dialogService = accessor.get(IDialogService); const hostService = accessor.get(IHostService); const storageService = accessor.get(IStorageService); - const credentialsService = accessor.get(ICredentialsService); const logService = accessor.get(ILogService); const result = await dialogService.confirm({ message: localize('reset user data message', "Would you like to reset your data (settings, keybindings, extensions, snippets and UI State) and reload?") @@ -509,9 +502,6 @@ export class BrowserMain extends Disposable { if (storageService instanceof BrowserStorageService) { await storageService.clear(); } - if (typeof credentialsService.clear === 'function') { - await credentialsService.clear(); - } } catch (error) { logService.error(error); throw error; diff --git a/src/vs/workbench/contrib/editSessions/browser/editSessionsStorageService.ts b/src/vs/workbench/contrib/editSessions/browser/editSessionsStorageService.ts index 040294170b971..00914aa8eff5d 100644 --- a/src/vs/workbench/contrib/editSessions/browser/editSessionsStorageService.ts +++ b/src/vs/workbench/contrib/editSessions/browser/editSessionsStorageService.ts @@ -18,7 +18,6 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten import { EDIT_SESSIONS_SIGNED_IN, EditSession, EDIT_SESSION_SYNC_CATEGORY, IEditSessionsStorageService, EDIT_SESSIONS_SIGNED_IN_KEY, IEditSessionsLogService, SyncResource, EDIT_SESSIONS_PENDING_KEY } from 'vs/workbench/contrib/editSessions/common/editSessions'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { generateUuid } from 'vs/base/common/uuid'; -import { ICredentialsService } from 'vs/platform/credentials/common/credentials'; import { getCurrentAuthenticationSessionInfo } from 'vs/workbench/services/authentication/browser/authenticationService'; import { isWeb } from 'vs/base/common/platform'; import { IUserDataSyncMachinesService, UserDataSyncMachinesService } from 'vs/platform/userDataSync/common/userDataSyncMachines'; @@ -82,8 +81,7 @@ export class EditSessionsWorkbenchService extends Disposable implements IEditSes @IProductService private readonly productService: IProductService, @IContextKeyService private readonly contextKeyService: IContextKeyService, @IDialogService private readonly dialogService: IDialogService, - @ISecretStorageService private readonly secretStorageService: ISecretStorageService, - @ICredentialsService private readonly credentialsService: ICredentialsService + @ISecretStorageService private readonly secretStorageService: ISecretStorageService ) { super(); @@ -280,7 +278,7 @@ export class EditSessionsWorkbenchService extends Disposable implements IEditSes // If settings sync is already enabled, avoid asking again to authenticate if (this.shouldAttemptEditSessionInit()) { this.logService.info(`Reusing user data sync enablement`); - const authenticationSessionInfo = await getCurrentAuthenticationSessionInfo(this.credentialsService, this.secretStorageService, this.productService); + const authenticationSessionInfo = await getCurrentAuthenticationSessionInfo(this.secretStorageService, this.productService); if (authenticationSessionInfo !== undefined) { this.logService.info(`Using current authentication session with ID ${authenticationSessionInfo.id}`); this.existingSessionId = authenticationSessionInfo.id; diff --git a/src/vs/workbench/services/authentication/browser/authenticationService.ts b/src/vs/workbench/services/authentication/browser/authenticationService.ts index f6c2f14685a21..7ad844439c549 100644 --- a/src/vs/workbench/services/authentication/browser/authenticationService.ts +++ b/src/vs/workbench/services/authentication/browser/authenticationService.ts @@ -13,7 +13,6 @@ import * as nls from 'vs/nls'; import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { ICredentialsService } from 'vs/platform/credentials/common/credentials'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { Severity } from 'vs/platform/notification/common/notification'; @@ -80,14 +79,10 @@ export function addAccountUsage(storageService: IStorageService, providerId: str // TODO: pull this out into its own service export type AuthenticationSessionInfo = { readonly id: string; readonly accessToken: string; readonly providerId: string; readonly canSignOut?: boolean }; export async function getCurrentAuthenticationSessionInfo( - // TODO: Remove when all known embedders implement SecretStorageProviders instead of CredentialsProviders - credentialsService: ICredentialsService, secretStorageService: ISecretStorageService, productService: IProductService ): Promise { - const authenticationSessionValue = - await secretStorageService.get(`${productService.urlProtocol}.loginAccount`) - ?? await credentialsService.getPassword(`${productService.urlProtocol}.login`, 'account'); + const authenticationSessionValue = await secretStorageService.get(`${productService.urlProtocol}.loginAccount`); if (authenticationSessionValue) { try { const authenticationSessionInfo: AuthenticationSessionInfo = JSON.parse(authenticationSessionValue); diff --git a/src/vs/workbench/services/credentials/browser/credentialsService.ts b/src/vs/workbench/services/credentials/browser/credentialsService.ts deleted file mode 100644 index 80a551f4cc300..0000000000000 --- a/src/vs/workbench/services/credentials/browser/credentialsService.ts +++ /dev/null @@ -1,82 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ICredentialsService, ICredentialsProvider, ICredentialsChangeEvent, InMemoryCredentialsProvider } from 'vs/platform/credentials/common/credentials'; -import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService'; -import { Emitter } from 'vs/base/common/event'; -import { Disposable } from 'vs/base/common/lifecycle'; -import { IProductService } from 'vs/platform/product/common/productService'; -import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; -import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; - -export class BrowserCredentialsService extends Disposable implements ICredentialsService { - - declare readonly _serviceBrand: undefined; - - private _onDidChangePassword = this._register(new Emitter()); - readonly onDidChangePassword = this._onDidChangePassword.event; - - private credentialsProvider: ICredentialsProvider; - - private _secretStoragePrefix: Promise; - public async getSecretStoragePrefix() { return this._secretStoragePrefix; } - - constructor( - @IBrowserWorkbenchEnvironmentService environmentService: IBrowserWorkbenchEnvironmentService, - @IRemoteAgentService remoteAgentService: IRemoteAgentService, - @IProductService private readonly productService: IProductService - ) { - super(); - - if ( - environmentService.remoteAuthority - && !environmentService.options?.credentialsProvider - && !environmentService.options?.secretStorageProvider - ) { - // If we have a remote authority but the embedder didn't provide a credentialsProvider, - // we can use the CredentialsService on the remote side - const remoteCredentialsService = ProxyChannel.toService(remoteAgentService.getConnection()!.getChannel('credentials')); - this.credentialsProvider = remoteCredentialsService; - this._secretStoragePrefix = remoteCredentialsService.getSecretStoragePrefix(); - } else { - // fall back to InMemoryCredentialsProvider if none was given to us. - this.credentialsProvider = environmentService.options?.credentialsProvider ?? new InMemoryCredentialsProvider(); - this._secretStoragePrefix = Promise.resolve(this.productService.urlProtocol); - } - } - - getPassword(service: string, account: string): Promise { - return this.credentialsProvider.getPassword(service, account); - } - - async setPassword(service: string, account: string, password: string): Promise { - await this.credentialsProvider.setPassword(service, account, password); - - this._onDidChangePassword.fire({ service, account }); - } - - async deletePassword(service: string, account: string): Promise { - const didDelete = await this.credentialsProvider.deletePassword(service, account); - if (didDelete) { - this._onDidChangePassword.fire({ service, account }); - } - - return didDelete; - } - - findPassword(service: string): Promise { - return this.credentialsProvider.findPassword(service); - } - - findCredentials(service: string): Promise> { - return this.credentialsProvider.findCredentials(service); - } - - async clear(): Promise { - if (this.credentialsProvider.clear) { - return this.credentialsProvider.clear(); - } - } -} diff --git a/src/vs/workbench/services/credentials/electron-sandbox/credentialsService.ts b/src/vs/workbench/services/credentials/electron-sandbox/credentialsService.ts deleted file mode 100644 index a382e26301d5d..0000000000000 --- a/src/vs/workbench/services/credentials/electron-sandbox/credentialsService.ts +++ /dev/null @@ -1,9 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ICredentialsService } from 'vs/platform/credentials/common/credentials'; -import { registerMainProcessRemoteService } from 'vs/platform/ipc/electron-sandbox/services'; - -registerMainProcessRemoteService(ICredentialsService, 'credentials'); diff --git a/src/vs/workbench/services/credentials/test/browser/credentialsService.test.ts b/src/vs/workbench/services/credentials/test/browser/credentialsService.test.ts deleted file mode 100644 index 8d1e35b49977c..0000000000000 --- a/src/vs/workbench/services/credentials/test/browser/credentialsService.test.ts +++ /dev/null @@ -1,61 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import { DisposableStore } from 'vs/base/common/lifecycle'; -import { BrowserCredentialsService } from 'vs/workbench/services/credentials/browser/credentialsService'; -import { TestEnvironmentService, TestRemoteAgentService } from 'vs/workbench/test/browser/workbenchTestServices'; -import { TestProductService } from 'vs/workbench/test/common/workbenchTestServices'; - -suite('CredentialsService - web', () => { - const serviceId1 = 'test.credentialsService1'; - const serviceId2 = 'test.credentialsService2'; - const disposables = new DisposableStore(); - let credentialsService: BrowserCredentialsService; - setup(async () => { - credentialsService = disposables.add(new BrowserCredentialsService(TestEnvironmentService, new TestRemoteAgentService(), TestProductService)); - await credentialsService.setPassword(serviceId1, 'me1', '1'); - await credentialsService.setPassword(serviceId1, 'me2', '2'); - await credentialsService.setPassword(serviceId2, 'me3', '3'); - }); - - teardown(() => disposables.clear()); - - test('Gets correct values for service', async () => { - const credentials = await credentialsService.findCredentials(serviceId1); - assert.strictEqual(credentials.length, 2); - assert.strictEqual(credentials[0].password, '1'); - }); - - test('Gets correct value for credential', async () => { - const credentials = await credentialsService.getPassword(serviceId1, 'me1'); - assert.strictEqual(credentials, '1'); - }); - - test('Gets null for no account', async () => { - const credentials = await credentialsService.getPassword(serviceId1, 'doesnotexist'); - assert.strictEqual(credentials, null); - }); - - test('Gets null for no service or a different service', async () => { - let credentials = await credentialsService.getPassword('doesnotexist', 'me1'); - assert.strictEqual(credentials, null); - credentials = await credentialsService.getPassword(serviceId2, 'me1'); - assert.strictEqual(credentials, null); - }); - - test('Delete removes the value', async () => { - const result = await credentialsService.deletePassword(serviceId1, 'me1'); - assert.strictEqual(result, true); - const pass = await credentialsService.getPassword(serviceId1, 'me1'); - assert.strictEqual(pass, null); - }); - - test('Clear removes all values for service', async () => { - await credentialsService.clear(); - const credentials = await credentialsService.findCredentials(serviceId1); - assert.strictEqual(credentials.length, 0); - }); -}); diff --git a/src/vs/workbench/services/userDataSync/browser/userDataSyncInit.ts b/src/vs/workbench/services/userDataSync/browser/userDataSyncInit.ts index ef77a1a411d89..a19eae35e5f42 100644 --- a/src/vs/workbench/services/userDataSync/browser/userDataSyncInit.ts +++ b/src/vs/workbench/services/userDataSync/browser/userDataSyncInit.ts @@ -30,7 +30,6 @@ import { isEqual } from 'vs/base/common/resources'; import { CancellationToken } from 'vs/base/common/cancellation'; import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; import { IExtensionStorageService } from 'vs/platform/extensionManagement/common/extensionStorage'; -import { ICredentialsService } from 'vs/platform/credentials/common/credentials'; import { TasksInitializer } from 'vs/platform/userDataSync/common/tasksSync'; import { IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile'; import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService'; @@ -48,7 +47,6 @@ export class UserDataSyncInitializer implements IUserDataInitializer { constructor( @IBrowserWorkbenchEnvironmentService private readonly environmentService: IBrowserWorkbenchEnvironmentService, @ISecretStorageService private readonly secretStorageService: ISecretStorageService, - @ICredentialsService private readonly credentialsService: ICredentialsService, @IUserDataSyncStoreManagementService private readonly userDataSyncStoreManagementService: IUserDataSyncStoreManagementService, @IFileService private readonly fileService: IFileService, @IUserDataProfilesService private readonly userDataProfilesService: IUserDataProfilesService, @@ -92,7 +90,7 @@ export class UserDataSyncInitializer implements IUserDataInitializer { let authenticationSession; try { - authenticationSession = await getCurrentAuthenticationSessionInfo(this.credentialsService, this.secretStorageService, this.productService); + authenticationSession = await getCurrentAuthenticationSessionInfo(this.secretStorageService, this.productService); } catch (error) { this.logService.error(error); } diff --git a/src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.ts b/src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.ts index d509a21c76c5b..4909ab5d1a48d 100644 --- a/src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.ts +++ b/src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.ts @@ -30,7 +30,6 @@ import { isWeb } from 'vs/base/common/platform'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { UserDataSyncStoreClient } from 'vs/platform/userDataSync/common/userDataSyncStoreService'; import { UserDataSyncStoreTypeSynchronizer } from 'vs/platform/userDataSync/common/globalStateSync'; -import { ICredentialsService } from 'vs/platform/credentials/common/credentials'; import { CancellationError } from 'vs/base/common/errors'; import { raceCancellationError } from 'vs/base/common/async'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; @@ -105,7 +104,6 @@ export class UserDataSyncWorkbenchService extends Disposable implements IUserDat @IProductService private readonly productService: IProductService, @IExtensionService private readonly extensionService: IExtensionService, @IBrowserWorkbenchEnvironmentService private readonly environmentService: IBrowserWorkbenchEnvironmentService, - @ICredentialsService private readonly credentialsService: ICredentialsService, @ISecretStorageService private readonly secretStorageService: ISecretStorageService, @INotificationService private readonly notificationService: INotificationService, @IProgressService private readonly progressService: IProgressService, @@ -172,7 +170,7 @@ export class UserDataSyncWorkbenchService extends Disposable implements IUserDat private async initialize(): Promise { if (isWeb) { - const authenticationSession = await getCurrentAuthenticationSessionInfo(this.credentialsService, this.secretStorageService, this.productService); + const authenticationSession = await getCurrentAuthenticationSessionInfo(this.secretStorageService, this.productService); if (this.currentSessionId === undefined && authenticationSession?.id) { if (this.environmentService.options?.settingsSyncOptions?.authenticationProvider && this.environmentService.options.settingsSyncOptions.enabled) { this.currentSessionId = authenticationSession.id; diff --git a/yarn.lock b/yarn.lock index c49176e5cb669..b6cf12e75a5eb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1006,11 +1006,6 @@ resolved "https://registry.yarnpkg.com/@types/kerberos/-/kerberos-1.1.2.tgz#2a774abd48f727852f697d74241e9de3aea8e646" integrity sha512-cLixfcXjdj7qohLasmC1G4fh+en4e4g7mFZiG38D+K9rS9BRKFlq1JH5dGkQzICckbu4wM+RcwSa4VRHlBg7Rg== -"@types/keytar@^4.4.0": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@types/keytar/-/keytar-4.4.0.tgz#ca24e6ee6d0df10c003aafe26e93113b8faf0d8e" - integrity sha512-cq/NkUUy6rpWD8n7PweNQQBpw2o0cf5v6fbkUVEpOB9VzzIvyPvSEId1/goIj+MciW2v1Lw5mRimKO01XgE9EA== - "@types/keyv@^3.1.4": version "3.1.4" resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6" @@ -1826,11 +1821,6 @@ append-buffer@^1.0.2: dependencies: buffer-equal "^1.0.0" -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - arch@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" @@ -1846,14 +1836,6 @@ are-docs-informative@^0.0.2: resolved "https://registry.yarnpkg.com/are-docs-informative/-/are-docs-informative-0.0.2.tgz#387f0e93f5d45280373d387a59d34c96db321963" integrity sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig== -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - arg@^4.1.0: version "4.1.3" resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" @@ -2847,11 +2829,6 @@ config-chain@^1.1.12: ini "^1.3.4" proto-list "~1.2.1" -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - content-disposition@^0.5.4, content-disposition@~0.5.2: version "0.5.4" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" @@ -4651,20 +4628,6 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -5256,11 +5219,6 @@ has-symbols@^1.0.2: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" @@ -6238,14 +6196,6 @@ keygrip@~1.1.0: dependencies: tsscmp "1.0.6" -keytar@7.9.0: - version "7.9.0" - resolved "https://registry.yarnpkg.com/keytar/-/keytar-7.9.0.tgz#4c6225708f51b50cbf77c5aae81721964c2918cb" - integrity sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ== - dependencies: - node-addon-api "^4.3.0" - prebuild-install "^7.0.1" - keyv@^4.0.0: version "4.5.2" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.2.tgz#0e310ce73bf7851ec702f2eaf46ec4e3805cce56" @@ -7265,16 +7215,6 @@ npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" -npmlog@^4.0.1: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - nth-check@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" @@ -7294,7 +7234,7 @@ number-is-nan@^1.0.0: resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= -object-assign@4.X, object-assign@^4.0.1, object-assign@^4.1.0: +object-assign@4.X, object-assign@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= @@ -8238,25 +8178,6 @@ prebuild-install@7.1.1: tar-fs "^2.0.0" tunnel-agent "^0.6.0" -prebuild-install@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.0.1.tgz#c10075727c318efe72412f333e0ef625beaf3870" - integrity sha512-QBSab31WqkyxpnMWQxubYAHR5S9B2+r81ucocew34Fkl98FhvKIF50jIJnNOBmAZfyNV7vE5T6gd3hTVWgY6tg== - dependencies: - detect-libc "^2.0.0" - expand-template "^2.0.3" - github-from-package "0.0.0" - minimist "^1.2.3" - mkdirp-classic "^0.5.3" - napi-build-utils "^1.0.1" - node-abi "^3.3.0" - npmlog "^4.0.1" - pump "^3.0.0" - rc "^1.2.7" - simple-get "^4.0.0" - tar-fs "^2.0.0" - tunnel-agent "^0.6.0" - prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -8468,7 +8389,7 @@ read-pkg@^3.0.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: +readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -8928,7 +8849,7 @@ serialize-javascript@6.0.0, serialize-javascript@^6.0.0: dependencies: randombytes "^2.1.0" -set-blocking@^2.0.0, set-blocking@~2.0.0: +set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= @@ -9352,7 +9273,7 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2", string-width@^2.1.0: +string-width@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -10644,13 +10565,6 @@ which@^1.2.14, which@^1.2.9: dependencies: isexe "^2.0.0" -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - wildcard@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" From 715801613ff699db64df023d03134ef3ae9dbf82 Mon Sep 17 00:00:00 2001 From: Tyler Leonhardt Date: Tue, 5 Sep 2023 12:01:41 -0700 Subject: [PATCH 2/4] compile --- build/darwin/create-universal-app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/darwin/create-universal-app.js b/build/darwin/create-universal-app.js index a85f394ad757c..a01c222c35e35 100644 --- a/build/darwin/create-universal-app.js +++ b/build/darwin/create-universal-app.js @@ -45,7 +45,7 @@ async function main(buildDir) { }); fs.writeFileSync(productJsonPath, JSON.stringify(productJson, null, '\t')); // Verify if native module architecture is correct - const findOutput = await (0, cross_spawn_promise_1.spawn)('find', [outAppPath, '-name', 'keytar.node']); + const findOutput = await (0, cross_spawn_promise_1.spawn)('find', [outAppPath, '-name', 'kerberos.node']); const lipoOutput = await (0, cross_spawn_promise_1.spawn)('lipo', ['-archs', findOutput.replace(/\n$/, '')]); if (lipoOutput.replace(/\n$/, '') !== 'x86_64 arm64') { throw new Error(`Invalid arch, got : ${lipoOutput}`); @@ -57,4 +57,4 @@ if (require.main === module) { process.exit(1); }); } -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlLXVuaXZlcnNhbC1hcHAuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJjcmVhdGUtdW5pdmVyc2FsLWFwcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztnR0FHZ0c7O0FBRWhHLDZCQUE2QjtBQUM3Qix5QkFBeUI7QUFDekIsdUVBQTREO0FBQzVELHFFQUFvRDtBQUVwRCxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztBQUVuRCxLQUFLLFVBQVUsSUFBSSxDQUFDLFFBQWlCO0lBQ3BDLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLENBQUM7SUFFeEMsSUFBSSxDQUFDLFFBQVEsRUFBRTtRQUNkLE1BQU0sSUFBSSxLQUFLLENBQUMsd0JBQXdCLENBQUMsQ0FBQztLQUMxQztJQUVELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxjQUFjLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3JGLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxRQUFRLEdBQUcsTUFBTSxDQUFDO0lBQzFDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLG1CQUFtQixFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3JFLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLHFCQUFxQixFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3pFLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLG1CQUFtQixDQUFDLENBQUM7SUFDL0YsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsbUJBQW1CLENBQUMsQ0FBQztJQUNuRyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxpQkFBaUIsSUFBSSxFQUFFLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDekUsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsY0FBYyxDQUFDLENBQUM7SUFFakcsTUFBTSxJQUFBLDJDQUFnQixFQUFDO1FBQ3RCLFVBQVU7UUFDVixZQUFZO1FBQ1osV0FBVztRQUNYLGFBQWE7UUFDYixXQUFXLEVBQUU7WUFDWixjQUFjO1lBQ2QsYUFBYTtZQUNiLGVBQWU7WUFDZixlQUFlO1lBQ2YsWUFBWTtZQUNaLGNBQWM7WUFDZCxRQUFRO1NBQ1I7UUFDRCxVQUFVO1FBQ1YsS0FBSyxFQUFFLElBQUk7S0FDWCxDQUFDLENBQUM7SUFFSCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsZUFBZSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDekUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUU7UUFDMUIsc0JBQXNCLEVBQUUsa0JBQWtCO0tBQzFDLENBQUMsQ0FBQztJQUNILEVBQUUsQ0FBQyxhQUFhLENBQUMsZUFBZSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBRTNFLGtEQUFrRDtJQUNsRCxNQUFNLFVBQVUsR0FBRyxNQUFNLElBQUEsMkJBQUssRUFBQyxNQUFNLEVBQUUsQ0FBQyxVQUFVLEVBQUUsT0FBTyxFQUFFLGFBQWEsQ0FBQyxDQUFDLENBQUM7SUFDN0UsTUFBTSxVQUFVLEdBQUcsTUFBTSxJQUFBLDJCQUFLLEVBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNsRixJQUFJLFVBQVUsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLGNBQWMsRUFBRTtRQUNyRCxNQUFNLElBQUksS0FBSyxDQUFDLHVCQUF1QixVQUFVLEVBQUUsQ0FBQyxDQUFDO0tBQ3JEO0FBQ0YsQ0FBQztBQUVELElBQUksT0FBTyxDQUFDLElBQUksS0FBSyxNQUFNLEVBQUU7SUFDNUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUU7UUFDakMsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNuQixPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2pCLENBQUMsQ0FBQyxDQUFDO0NBQ0gifQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlLXVuaXZlcnNhbC1hcHAuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJjcmVhdGUtdW5pdmVyc2FsLWFwcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztnR0FHZ0c7O0FBRWhHLDZCQUE2QjtBQUM3Qix5QkFBeUI7QUFDekIsdUVBQTREO0FBQzVELHFFQUFvRDtBQUVwRCxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztBQUVuRCxLQUFLLFVBQVUsSUFBSSxDQUFDLFFBQWlCO0lBQ3BDLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLENBQUM7SUFFeEMsSUFBSSxDQUFDLFFBQVEsRUFBRTtRQUNkLE1BQU0sSUFBSSxLQUFLLENBQUMsd0JBQXdCLENBQUMsQ0FBQztLQUMxQztJQUVELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxjQUFjLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3JGLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxRQUFRLEdBQUcsTUFBTSxDQUFDO0lBQzFDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLG1CQUFtQixFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3JFLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLHFCQUFxQixFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3pFLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLG1CQUFtQixDQUFDLENBQUM7SUFDL0YsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsbUJBQW1CLENBQUMsQ0FBQztJQUNuRyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxpQkFBaUIsSUFBSSxFQUFFLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDekUsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsY0FBYyxDQUFDLENBQUM7SUFFakcsTUFBTSxJQUFBLDJDQUFnQixFQUFDO1FBQ3RCLFVBQVU7UUFDVixZQUFZO1FBQ1osV0FBVztRQUNYLGFBQWE7UUFDYixXQUFXLEVBQUU7WUFDWixjQUFjO1lBQ2QsYUFBYTtZQUNiLGVBQWU7WUFDZixlQUFlO1lBQ2YsWUFBWTtZQUNaLGNBQWM7WUFDZCxRQUFRO1NBQ1I7UUFDRCxVQUFVO1FBQ1YsS0FBSyxFQUFFLElBQUk7S0FDWCxDQUFDLENBQUM7SUFFSCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsZUFBZSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDekUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUU7UUFDMUIsc0JBQXNCLEVBQUUsa0JBQWtCO0tBQzFDLENBQUMsQ0FBQztJQUNILEVBQUUsQ0FBQyxhQUFhLENBQUMsZUFBZSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBRTNFLGtEQUFrRDtJQUNsRCxNQUFNLFVBQVUsR0FBRyxNQUFNLElBQUEsMkJBQUssRUFBQyxNQUFNLEVBQUUsQ0FBQyxVQUFVLEVBQUUsT0FBTyxFQUFFLGVBQWUsQ0FBQyxDQUFDLENBQUM7SUFDL0UsTUFBTSxVQUFVLEdBQUcsTUFBTSxJQUFBLDJCQUFLLEVBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNsRixJQUFJLFVBQVUsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLGNBQWMsRUFBRTtRQUNyRCxNQUFNLElBQUksS0FBSyxDQUFDLHVCQUF1QixVQUFVLEVBQUUsQ0FBQyxDQUFDO0tBQ3JEO0FBQ0YsQ0FBQztBQUVELElBQUksT0FBTyxDQUFDLElBQUksS0FBSyxNQUFNLEVBQUU7SUFDNUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUU7UUFDakMsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNuQixPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2pCLENBQUMsQ0FBQyxDQUFDO0NBQ0gifQ== \ No newline at end of file From 56eaf874a1a906863a92645b50c84438ef28c173 Mon Sep 17 00:00:00 2001 From: Tyler Leonhardt Date: Tue, 5 Sep 2023 12:49:07 -0700 Subject: [PATCH 3/4] remove imports --- src/vs/workbench/workbench.desktop.main.ts | 1 - src/vs/workbench/workbench.web.main.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/src/vs/workbench/workbench.desktop.main.ts b/src/vs/workbench/workbench.desktop.main.ts index 1e429387e2d9a..01041abd0d5c2 100644 --- a/src/vs/workbench/workbench.desktop.main.ts +++ b/src/vs/workbench/workbench.desktop.main.ts @@ -56,7 +56,6 @@ import 'vs/workbench/services/path/electron-sandbox/pathService'; import 'vs/workbench/services/themes/electron-sandbox/nativeHostColorSchemeService'; import 'vs/workbench/services/extensionManagement/electron-sandbox/extensionManagementService'; import 'vs/workbench/services/extensionManagement/electron-sandbox/extensionUrlTrustService'; -import 'vs/workbench/services/credentials/electron-sandbox/credentialsService'; import 'vs/workbench/services/encryption/electron-sandbox/encryptionService'; import 'vs/workbench/services/secrets/electron-sandbox/secretStorageService'; import 'vs/workbench/services/localization/electron-sandbox/languagePackService'; diff --git a/src/vs/workbench/workbench.web.main.ts b/src/vs/workbench/workbench.web.main.ts index 8306e4eac0f90..649a54cdb8c4a 100644 --- a/src/vs/workbench/workbench.web.main.ts +++ b/src/vs/workbench/workbench.web.main.ts @@ -43,7 +43,6 @@ import 'vs/workbench/services/extensionManagement/browser/webExtensionsScannerSe import 'vs/workbench/services/extensionManagement/common/extensionManagementServerService'; import 'vs/workbench/services/extensionManagement/browser/extensionUrlTrustService'; import 'vs/workbench/services/telemetry/browser/telemetryService'; -import 'vs/workbench/services/credentials/browser/credentialsService'; import 'vs/workbench/services/url/browser/urlService'; import 'vs/workbench/services/update/browser/updateService'; import 'vs/workbench/services/workspaces/browser/workspacesService'; From 72ebe40c6b953220dcf8e448b77a203b2679cee1 Mon Sep 17 00:00:00 2001 From: Tyler Leonhardt Date: Tue, 5 Sep 2023 16:11:01 -0700 Subject: [PATCH 4/4] rip the bandaid --- .../api/common/extHostRequireInterceptor.ts | 95 ------------------- 1 file changed, 95 deletions(-) diff --git a/src/vs/workbench/api/common/extHostRequireInterceptor.ts b/src/vs/workbench/api/common/extHostRequireInterceptor.ts index 2123f716aaf95..bcf03a6a02aa7 100644 --- a/src/vs/workbench/api/common/extHostRequireInterceptor.ts +++ b/src/vs/workbench/api/common/extHostRequireInterceptor.ts @@ -15,7 +15,6 @@ import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ExtensionPaths, IExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService'; -import { platform } from 'vs/base/common/process'; import { ILogService } from 'vs/platform/log/common/log'; import { escapeRegExpCharacters } from 'vs/base/common/strings'; @@ -61,7 +60,6 @@ export abstract class RequireInterceptor { const extensionPaths = await this._extHostExtensionService.getExtensionPathIndex(); this.register(new VSCodeNodeModuleFactory(this._apiFactory, extensionPaths, this._extensionRegistry, configProvider, this._logService)); - this.register(this._instaService.createInstance(KeytarNodeModuleFactory, extensionPaths)); this.register(this._instaService.createInstance(NodeModuleAliasingModuleFactory)); if (this._initData.remote.isRemote) { this.register(this._instaService.createInstance(OpenNodeModuleFactory, extensionPaths, this._initData.environment.appUriScheme)); @@ -187,99 +185,6 @@ class VSCodeNodeModuleFactory implements INodeModuleFactory { //#endregion - -//#region --- keytar-module - -interface IKeytarModule { - getPassword(service: string, account: string): Promise; - setPassword(service: string, account: string, password: string): Promise; - deletePassword(service: string, account: string): Promise; - findPassword(service: string): Promise; - findCredentials(service: string): Promise>; -} - -class KeytarNodeModuleFactory implements INodeModuleFactory { - public readonly nodeModuleName: string = 'keytar'; - - private readonly _mainThreadTelemetry: MainThreadTelemetryShape; - private alternativeNames: Set | undefined; - private _impl: IKeytarModule; - - constructor( - private readonly _extensionPaths: ExtensionPaths, - @IExtHostRpcService rpcService: IExtHostRpcService, - @IExtHostInitDataService initData: IExtHostInitDataService, - - ) { - this._mainThreadTelemetry = rpcService.getProxy(MainContext.MainThreadTelemetry); - const { environment } = initData; - - if (environment.appRoot) { - let appRoot = environment.appRoot.fsPath; - if (platform === 'win32') { - appRoot = appRoot.replace(/\\/g, '/'); - } - if (appRoot[appRoot.length - 1] === '/') { - appRoot = appRoot.substr(0, appRoot.length - 1); - } - this.alternativeNames = new Set(); - this.alternativeNames.add(`${appRoot}/node_modules.asar/keytar`); - this.alternativeNames.add(`${appRoot}/node_modules/keytar`); - } - - // Use an implementation that does nothing to prevent errors from popping up - // do to VS Code no longer shipping with keytar. - this._impl = { - getPassword: (_service: string, _account: string): Promise => { - return Promise.resolve(null); - }, - setPassword: (_service: string, _account: string, _password: string): Promise => { - return Promise.resolve(); - }, - deletePassword: (_service: string, _account: string): Promise => { - return Promise.resolve(true); - }, - findPassword: (_service: string): Promise => { - return Promise.resolve(null); - }, - findCredentials(_service: string): Promise> { - return Promise.resolve([]); - } - }; - } - - public load(_request: string, parent: URI): any { - const ext = this._extensionPaths.findSubstr(parent); - type ShimmingKeytarClassification = { - owner: 'TylerLeonhardt'; - comment: 'Know when the keytar-shim was used'; - extension: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The extension is question' }; - }; - this._mainThreadTelemetry.$publicLog2<{ extension: string }, ShimmingKeytarClassification>('shimming.keytar', { extension: ext?.identifier.value ?? 'unknown_extension' }); - return this._impl; - } - - public alternativeModuleName(name: string): string | undefined { - const length = name.length; - // We need at least something like: `?/keytar` which requires - // more than 7 characters. - if (length <= 7 || !this.alternativeNames) { - return undefined; - } - const sep = length - 7; - if ((name.charAt(sep) === '/' || name.charAt(sep) === '\\') && name.endsWith('keytar')) { - name = name.replace(/\\/g, '/'); - if (this.alternativeNames.has(name)) { - return 'keytar'; - } - } - return undefined; - } -} - -//#endregion - - //#region --- opn/open-module interface OpenOptions {