debt - use product service in more places

This commit is contained in:
Benjamin Pasero 2021-03-15 09:47:35 +01:00
parent 0e05a1f21a
commit 640fa1af29
26 changed files with 194 additions and 145 deletions

View file

@ -1,7 +1,7 @@
{
"name": "code-oss-dev",
"version": "1.55.0",
"distro": "89f1579ed6a94b2dd7db7a8c29dddd48065cadc8",
"distro": "eac6088e9101eb5fc1b038b261ce3b08342da884",
"author": {
"name": "Microsoft Corporation"
},
@ -223,4 +223,4 @@
"elliptic": "^6.5.3",
"nwmatcher": "^1.4.4"
}
}
}

View file

@ -7,7 +7,7 @@ import * as fs from 'fs';
import * as path from 'vs/base/common/path';
import * as pfs from 'vs/base/node/pfs';
import { IStringDictionary } from 'vs/base/common/collections';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { onUnexpectedError } from 'vs/base/common/errors';
import { ILogService } from 'vs/platform/log/common/log';
@ -34,7 +34,8 @@ export class LanguagePackCachedDataCleaner extends Disposable {
constructor(
@INativeEnvironmentService private readonly _environmentService: INativeEnvironmentService,
@ILogService private readonly _logService: ILogService
@ILogService private readonly _logService: ILogService,
@IProductService private readonly _productService: IProductService
) {
super();
// We have no Language pack support for dev version (run from source)
@ -48,7 +49,7 @@ export class LanguagePackCachedDataCleaner extends Disposable {
let handle: any = setTimeout(async () => {
handle = undefined;
this._logService.info('Starting to clean up unused language packs.');
const maxAge = product.nameLong.indexOf('Insiders') >= 0
const maxAge = this._productService.nameLong.indexOf('Insiders') >= 0
? 1000 * 60 * 60 * 24 * 7 // roughly 1 week
: 1000 * 60 * 60 * 24 * 30 * 3; // roughly 3 months
try {

View file

@ -184,7 +184,8 @@ class SharedProcessMain extends Disposable {
this._register(toDisposable(() => storageService.flush()));
// Product
services.set(IProductService, { _serviceBrand: undefined, ...product });
const productService = { _serviceBrand: undefined, ...product };
services.set(IProductService, productService);
// Request
services.set(IRequestService, new SyncDescriptor(RequestService));
@ -213,19 +214,19 @@ class SharedProcessMain extends Disposable {
let telemetryService: ITelemetryService;
let telemetryAppender: ITelemetryAppender;
if (!extensionDevelopmentLocationURI && !environmentService.disableTelemetry && product.enableTelemetry) {
if (!extensionDevelopmentLocationURI && !environmentService.disableTelemetry && productService.enableTelemetry) {
telemetryAppender = new TelemetryLogAppender(loggerService, environmentService);
// Application Insights
if (product.aiConfig && product.aiConfig.asimovKey && isBuilt) {
const appInsightsAppender = new AppInsightsAppender('monacoworkbench', null, product.aiConfig.asimovKey);
if (productService.aiConfig && productService.aiConfig.asimovKey && isBuilt) {
const appInsightsAppender = new AppInsightsAppender('monacoworkbench', null, productService.aiConfig.asimovKey);
this._register(toDisposable(() => appInsightsAppender.flush())); // Ensure the AI appender is disposed so that it flushes remaining data
telemetryAppender = combinedAppender(appInsightsAppender, telemetryAppender);
}
telemetryService = new TelemetryService({
appender: telemetryAppender,
commonProperties: resolveCommonProperties(fileService, release(), process.arch, product.commit, product.version, this.configuration.machineId, product.msftInternalDomains, installSourcePath),
commonProperties: resolveCommonProperties(fileService, release(), process.arch, productService.commit, productService.version, this.configuration.machineId, productService.msftInternalDomains, installSourcePath),
sendErrorTelemetry: true,
piiPaths: [appRoot, extensionsPath]
}, configurationService);

View file

@ -33,7 +33,7 @@ import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtil
import { TelemetryAppenderClient } from 'vs/platform/telemetry/common/telemetryIpc';
import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService';
import { resolveCommonProperties } from 'vs/platform/telemetry/common/commonProperties';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
import { ProxyAuthHandler } from 'vs/code/electron-main/auth';
import { FileProtocolHandler } from 'vs/code/electron-main/protocol';
import { Disposable } from 'vs/base/common/lifecycle';
@ -106,7 +106,8 @@ export class CodeApplication extends Disposable {
@ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IStateService private readonly stateService: IStateService,
@IFileService private readonly fileService: IFileService
@IFileService private readonly fileService: IFileService,
@IProductService private readonly productService: IProductService
) {
super();
@ -419,7 +420,7 @@ export class CodeApplication extends Disposable {
// This will help Windows to associate the running program with
// any shortcut that is pinned to the taskbar and prevent showing
// two icons in the taskbar for the same app.
const win32AppUserModelId = product.win32AppUserModelId;
const win32AppUserModelId = this.productService.win32AppUserModelId;
if (isWindows && win32AppUserModelId) {
app.setAppUserModelId(win32AppUserModelId);
}
@ -588,10 +589,10 @@ export class CodeApplication extends Disposable {
services.set(IURLService, new SyncDescriptor(NativeURLService));
// Telemetry
if (!this.environmentMainService.isExtensionDevelopment && !this.environmentMainService.args['disable-telemetry'] && !!product.enableTelemetry) {
if (!this.environmentMainService.isExtensionDevelopment && !this.environmentMainService.args['disable-telemetry'] && !!this.productService.enableTelemetry) {
const channel = getDelayedChannel(sharedProcessReady.then(client => client.getChannel('telemetryAppender')));
const appender = new TelemetryAppenderClient(channel);
const commonProperties = resolveCommonProperties(this.fileService, release(), process.arch, product.commit, product.version, machineId, product.msftInternalDomains, this.environmentMainService.installSourcePath);
const commonProperties = resolveCommonProperties(this.fileService, release(), process.arch, this.productService.commit, this.productService.version, machineId, this.productService.msftInternalDomains, this.environmentMainService.installSourcePath);
const piiPaths = [this.environmentMainService.appRoot, this.environmentMainService.extensionsPath];
const config: ITelemetryServiceConfig = { appender, commonProperties, piiPaths, sendErrorTelemetry: true };
@ -789,7 +790,7 @@ export class CodeApplication extends Disposable {
urlService.registerHandler(new URLHandlerChannelClient(urlHandlerChannel));
// Watch Electron URLs and forward them to the UrlService
this._register(new ElectronURLListener(pendingProtocolLinksToHandle, urlService, windowsMainService, this.environmentMainService));
this._register(new ElectronURLListener(pendingProtocolLinksToHandle, urlService, windowsMainService, this.environmentMainService, this.productService));
// Open our first window
const args = this.environmentMainService.args;
@ -860,14 +861,14 @@ export class CodeApplication extends Disposable {
private shouldBlockURI(uri: URI): boolean {
if (uri.authority === Schemas.file && isWindows) {
const res = dialog.showMessageBoxSync({
title: product.nameLong,
title: this.productService.nameLong,
type: 'question',
buttons: [
mnemonicButtonLabel(localize({ key: 'open', comment: ['&& denotes a mnemonic'] }, "&&Yes")),
mnemonicButtonLabel(localize({ key: 'cancel', comment: ['&& denotes a mnemonic'] }, "&&No")),
],
cancelId: 1,
message: localize('confirmOpenMessage', "An external application wants to open '{0}' in {1}. Do you want to open this file or folder?", getPathLabel(uri.fsPath, this.environmentMainService), product.nameShort),
message: localize('confirmOpenMessage', "An external application wants to open '{0}' in {1}. Do you want to open this file or folder?", getPathLabel(uri.fsPath, this.environmentMainService), this.productService.nameShort),
detail: localize('confirmOpenDetail', "If you did not initiate this request, it may represent an attempted attack on your system. Unless you took an explicit action to initiate this request, you should press 'No'"),
noLink: true
});
@ -962,7 +963,7 @@ export class CodeApplication extends Disposable {
}));
// Windows: install mutex
const win32MutexName = product.win32MutexName;
const win32MutexName = this.productService.win32MutexName;
if (isWindows && win32MutexName) {
try {
const WindowsMutex = (require.__$__nodeRequire('windows-mutex') as typeof import('windows-mutex')).Mutex;
@ -1032,7 +1033,7 @@ export class CodeApplication extends Disposable {
recordingStopped = true; // only once
const path = await contentTracing.stopRecording(joinPath(this.environmentMainService.userHome, `${product.applicationName}-${Math.random().toString(16).slice(-4)}.trace.txt`).fsPath);
const path = await contentTracing.stopRecording(joinPath(this.environmentMainService.userHome, `${this.productService.applicationName}-${Math.random().toString(16).slice(-4)}.trace.txt`).fsPath);
if (!timeout) {
dialogMainService.showMessageBox({

View file

@ -12,7 +12,7 @@ import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows';
import { INativeHostMainService } from 'vs/platform/native/electron-main/nativeHostMainService';
import { IEncryptionMainService } from 'vs/platform/encryption/electron-main/encryptionMainService';
import { generateUuid } from 'vs/base/common/uuid';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
import { CancellationToken } from 'vs/base/common/cancellation';
interface ElectronAuthenticationResponseDetails extends AuthenticationResponseDetails {
@ -56,7 +56,7 @@ enum ProxyAuthState {
export class ProxyAuthHandler extends Disposable {
private static PROXY_CREDENTIALS_SERVICE_KEY = `${product.urlProtocol}.proxy-credentials`;
private readonly PROXY_CREDENTIALS_SERVICE_KEY = `${this.productService.urlProtocol}.proxy-credentials`;
private pendingProxyResolve: Promise<Credentials | undefined> | undefined = undefined;
@ -68,7 +68,8 @@ export class ProxyAuthHandler extends Disposable {
@ILogService private readonly logService: ILogService,
@IWindowsMainService private readonly windowsMainService: IWindowsMainService,
@INativeHostMainService private readonly nativeHostMainService: INativeHostMainService,
@IEncryptionMainService private readonly encryptionMainService: IEncryptionMainService
@IEncryptionMainService private readonly encryptionMainService: IEncryptionMainService,
@IProductService private readonly productService: IProductService
) {
super();
@ -153,7 +154,7 @@ export class ProxyAuthHandler extends Disposable {
let storedUsername: string | undefined = undefined;
let storedPassword: string | undefined = undefined;
try {
const encryptedSerializedProxyCredentials = await this.nativeHostMainService.getPassword(undefined, ProxyAuthHandler.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash);
const encryptedSerializedProxyCredentials = await this.nativeHostMainService.getPassword(undefined, this.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash);
if (encryptedSerializedProxyCredentials) {
const credentials: Credentials = JSON.parse(await this.encryptionMainService.decrypt(encryptedSerializedProxyCredentials));
@ -211,9 +212,9 @@ export class ProxyAuthHandler extends Disposable {
try {
if (reply.remember) {
const encryptedSerializedCredentials = await this.encryptionMainService.encrypt(JSON.stringify(credentials));
await this.nativeHostMainService.setPassword(undefined, ProxyAuthHandler.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash, encryptedSerializedCredentials);
await this.nativeHostMainService.setPassword(undefined, this.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash, encryptedSerializedCredentials);
} else {
await this.nativeHostMainService.deletePassword(undefined, ProxyAuthHandler.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash);
await this.nativeHostMainService.deletePassword(undefined, this.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash);
}
} catch (error) {
this.logService.error(error); // handle gracefully

View file

@ -83,7 +83,7 @@ class CodeMain {
const args = this.resolveArgs();
// Create services
const [instantiationService, instanceEnvironment, environmentService, configurationService, stateService, bufferLogService] = this.createServices(args);
const [instantiationService, instanceEnvironment, environmentService, configurationService, stateService, bufferLogService, productService] = this.createServices(args);
try {
@ -93,7 +93,7 @@ class CodeMain {
} catch (error) {
// Show a dialog for errors that can be resolved by the user
this.handleStartupDataDirError(environmentService, error);
this.handleStartupDataDirError(environmentService, productService.nameLong, error);
throw error;
}
@ -107,7 +107,7 @@ class CodeMain {
// Create the main IPC server by trying to be the server
// If this throws an error it means we are not the first
// instance of VS Code running and so we would quit.
const mainProcessNodeIpcServer = await this.doStartup(args, logService, environmentService, lifecycleMainService, instantiationService, true);
const mainProcessNodeIpcServer = await this.doStartup(args, logService, environmentService, lifecycleMainService, instantiationService, productService, true);
// Delay creation of spdlog for perf reasons (https://github.com/microsoft/vscode/issues/72906)
bufferLogService.logger = new SpdLogLogger('main', join(environmentService.logsPath, 'main.log'), true, bufferLogService.getLevel());
@ -125,7 +125,7 @@ class CodeMain {
}
}
private createServices(args: NativeParsedArgs): [IInstantiationService, IProcessEnvironment, IEnvironmentMainService, ConfigurationService, StateService, BufferLogService] {
private createServices(args: NativeParsedArgs): [IInstantiationService, IProcessEnvironment, IEnvironmentMainService, ConfigurationService, StateService, BufferLogService, IProductService] {
const services = new ServiceCollection();
// Environment
@ -171,12 +171,13 @@ class CodeMain {
services.set(ISignService, new SyncDescriptor(SignService));
// Product
services.set(IProductService, { _serviceBrand: undefined, ...product });
const productService = { _serviceBrand: undefined, ...product };
services.set(IProductService, productService);
// Tunnel
services.set(ITunnelService, new SyncDescriptor(TunnelService));
return [new InstantiationService(services, true), instanceEnvironment, environmentMainService, configurationService, stateService, bufferLogService];
return [new InstantiationService(services, true), instanceEnvironment, environmentMainService, configurationService, stateService, bufferLogService, productService];
}
private patchEnvironment(environmentMainService: IEnvironmentMainService): IProcessEnvironment {
@ -217,7 +218,7 @@ class CodeMain {
return Promise.all([environmentServiceInitialization, configurationServiceInitialization, stateServiceInitialization]);
}
private async doStartup(args: NativeParsedArgs, logService: ILogService, environmentMainService: IEnvironmentMainService, lifecycleMainService: ILifecycleMainService, instantiationService: IInstantiationService, retry: boolean): Promise<NodeIPCServer> {
private async doStartup(args: NativeParsedArgs, logService: ILogService, environmentMainService: IEnvironmentMainService, lifecycleMainService: ILifecycleMainService, instantiationService: IInstantiationService, productService: IProductService, retry: boolean): Promise<NodeIPCServer> {
// Try to setup a server for running. If that succeeds it means
// we are the first instance to startup. Otherwise it is likely
@ -233,7 +234,7 @@ class CodeMain {
if (error.code !== 'EADDRINUSE') {
// Show a dialog for errors that can be resolved by the user
this.handleStartupDataDirError(environmentMainService, error);
this.handleStartupDataDirError(environmentMainService, productService.nameLong, error);
// Any other runtime error is just printed to the console
throw error;
@ -249,8 +250,9 @@ class CodeMain {
if (!retry || isWindows || error.code !== 'ECONNREFUSED') {
if (error.code === 'EPERM') {
this.showStartupWarningDialog(
localize('secondInstanceAdmin', "A second instance of {0} is already running as administrator.", product.nameShort),
localize('secondInstanceAdminDetail', "Please close the other instance and try again.")
localize('secondInstanceAdmin', "A second instance of {0} is already running as administrator.", productService.nameShort),
localize('secondInstanceAdminDetail', "Please close the other instance and try again."),
productService.nameLong
);
}
@ -268,7 +270,7 @@ class CodeMain {
throw error;
}
return this.doStartup(args, logService, environmentMainService, lifecycleMainService, instantiationService, false);
return this.doStartup(args, logService, environmentMainService, lifecycleMainService, instantiationService, productService, false);
}
// Tests from CLI require to be the only instance currently
@ -287,8 +289,9 @@ class CodeMain {
if (!args.wait && !args.status) {
startupWarningDialogHandle = setTimeout(() => {
this.showStartupWarningDialog(
localize('secondInstanceNoResponse', "Another instance of {0} is running but not responding", product.nameShort),
localize('secondInstanceNoResponseDetail', "Please close all other instances and try again.")
localize('secondInstanceNoResponse', "Another instance of {0} is running but not responding", productService.nameShort),
localize('secondInstanceNoResponseDetail', "Please close all other instances and try again."),
productService.nameLong
);
}, 10000);
}
@ -298,7 +301,7 @@ class CodeMain {
// Process Info
if (args.status) {
return instantiationService.invokeFunction(async () => {
const diagnosticsService = new DiagnosticsService(NullTelemetryService);
const diagnosticsService = new DiagnosticsService(NullTelemetryService, productService);
const mainProcessInfo = await launchService.getMainProcessInfo();
const remoteDiagnostics = await launchService.getRemoteDiagnostics({ includeProcesses: true, includeWorkspaceMetadata: true });
const diagnostics = await diagnosticsService.getDiagnostics(mainProcessInfo, remoteDiagnostics);
@ -342,23 +345,24 @@ class CodeMain {
return mainProcessNodeIpcServer;
}
private handleStartupDataDirError(environmentMainService: IEnvironmentMainService, error: NodeJS.ErrnoException): void {
private handleStartupDataDirError(environmentMainService: IEnvironmentMainService, title: string, error: NodeJS.ErrnoException): void {
if (error.code === 'EACCES' || error.code === 'EPERM') {
const directories = coalesce([environmentMainService.userDataPath, environmentMainService.extensionsPath, XDG_RUNTIME_DIR]).map(folder => getPathLabel(folder, environmentMainService));
this.showStartupWarningDialog(
localize('startupDataDirError', "Unable to write program user data."),
localize('startupUserDataAndExtensionsDirErrorDetail', "{0}\n\nPlease make sure the following directories are writeable:\n\n{1}", toErrorMessage(error), directories.join('\n'))
localize('startupUserDataAndExtensionsDirErrorDetail', "{0}\n\nPlease make sure the following directories are writeable:\n\n{1}", toErrorMessage(error), directories.join('\n')),
title
);
}
}
private showStartupWarningDialog(message: string, detail: string): void {
private showStartupWarningDialog(message: string, detail: string, title: string): void {
// use sync variant here because we likely exit after this method
// due to startup issues and otherwise the dialog seems to disappear
// https://github.com/microsoft/vscode/issues/104493
dialog.showMessageBoxSync({
title: product.nameLong,
title,
type: 'warning',
buttons: [mnemonicButtonLabel(localize({ key: 'close', comment: ['&& denotes a mnemonic'] }, "&&Close"))],
message,

View file

@ -131,7 +131,8 @@ class CliMain extends Disposable {
services.set(IStateService, stateService);
// Product
services.set(IProductService, { _serviceBrand: undefined, ...product });
const productService = { _serviceBrand: undefined, ...product };
services.set(IProductService, productService);
const { appRoot, extensionsPath, extensionDevelopmentLocationURI, isBuilt, installSourcePath } = environmentService;
@ -148,15 +149,15 @@ class CliMain extends Disposable {
// Telemetry
const appenders: AppInsightsAppender[] = [];
if (isBuilt && !extensionDevelopmentLocationURI && !environmentService.disableTelemetry && product.enableTelemetry) {
if (product.aiConfig && product.aiConfig.asimovKey) {
appenders.push(new AppInsightsAppender('monacoworkbench', null, product.aiConfig.asimovKey));
if (isBuilt && !extensionDevelopmentLocationURI && !environmentService.disableTelemetry && productService.enableTelemetry) {
if (productService.aiConfig && productService.aiConfig.asimovKey) {
appenders.push(new AppInsightsAppender('monacoworkbench', null, productService.aiConfig.asimovKey));
}
const config: ITelemetryServiceConfig = {
appender: combinedAppender(...appenders),
sendErrorTelemetry: false,
commonProperties: resolveCommonProperties(fileService, release(), process.arch, product.commit, product.version, stateService.getItem('telemetry.machineId'), product.msftInternalDomains, installSourcePath),
commonProperties: resolveCommonProperties(fileService, release(), process.arch, productService.commit, productService.version, stateService.getItem('telemetry.machineId'), productService.msftInternalDomains, installSourcePath),
piiPaths: [appRoot, extensionsPath]
};

View file

@ -9,7 +9,7 @@ import { exists, readFile } from 'fs';
import { join, basename } from 'vs/base/common/path';
import { parse, ParseError, getNodeType } from 'vs/base/common/json';
import { listProcesses } from 'vs/base/node/ps';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
import { isWindows, isLinux } from 'vs/base/common/platform';
import { URI } from 'vs/base/common/uri';
import { ProcessItem } from 'vs/base/common/processes';
@ -213,7 +213,10 @@ export class DiagnosticsService implements IDiagnosticsService {
declare readonly _serviceBrand: undefined;
constructor(@ITelemetryService private readonly telemetryService: ITelemetryService) { }
constructor(
@ITelemetryService private readonly telemetryService: ITelemetryService,
@IProductService private readonly productService: IProductService
) { }
private formatMachineInfo(info: IMachineInfo): string {
const output: string[] = [];
@ -227,7 +230,7 @@ export class DiagnosticsService implements IDiagnosticsService {
private formatEnvironment(info: IMainProcessInfo): string {
const output: string[] = [];
output.push(`Version: ${product.nameShort} ${product.version} (${product.commit || 'Commit unknown'}, ${product.date || 'Date unknown'})`);
output.push(`Version: ${this.productService.nameShort} ${this.productService.version} (${this.productService.commit || 'Commit unknown'}, ${this.productService.date || 'Date unknown'})`);
output.push(`OS Version: ${osLib.type()} ${osLib.arch()} ${osLib.release()}`);
const cpus = osLib.cpus();
if (cpus && cpus.length > 0) {
@ -481,7 +484,7 @@ export class DiagnosticsService implements IDiagnosticsService {
// Format name with indent
let name: string;
if (isRoot) {
name = item.pid === mainPid ? `${product.applicationName} main` : 'remote agent';
name = item.pid === mainPid ? `${this.productService.applicationName} main` : 'remote agent';
} else {
name = `${' '.repeat(indent)} ${item.name}`;

View file

@ -5,7 +5,7 @@
import { localize } from 'vs/nls';
import * as os from 'os';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv';
import { ICommonIssueService, IssueReporterData, IssueReporterFeatures, ProcessExplorerData } from 'vs/platform/issue/common/issue';
import { BrowserWindow, ipcMain, screen, IpcMainEvent, Display } from 'electron';
@ -43,7 +43,8 @@ export class IssueMainService implements ICommonIssueService {
@ILogService private readonly logService: ILogService,
@IDiagnosticsService private readonly diagnosticsService: IDiagnosticsService,
@IDialogMainService private readonly dialogMainService: IDialogMainService,
@INativeHostMainService private readonly nativeHostMainService: INativeHostMainService
@INativeHostMainService private readonly nativeHostMainService: INativeHostMainService,
@IProductService private readonly productService: IProductService
) {
this.registerListeners();
}
@ -410,12 +411,12 @@ export class IssueMainService implements ICommonIssueService {
release: os.release(),
},
product: {
nameShort: product.nameShort,
version: !!product.darwinUniversalAssetId ? `${product.version} (Universal)` : product.version,
commit: product.commit,
date: product.date,
reportIssueUrl: product.reportIssueUrl,
reportMarketplaceIssueUrl: product.reportMarketplaceIssueUrl
nameShort: this.productService.nameShort,
version: !!this.productService.darwinUniversalAssetId ? `${this.productService.version} (Universal)` : this.productService.version,
commit: this.productService.commit,
date: this.productService.date,
reportIssueUrl: this.productService.reportIssueUrl,
reportMarketplaceIssueUrl: this.productService.reportMarketplaceIssueUrl
}
};

View file

@ -11,7 +11,7 @@ import { getTitleBarStyle, INativeRunActionInWindowRequest, INativeRunKeybinding
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IUpdateService, StateType } from 'vs/platform/update/common/update';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
import { RunOnceScheduler } from 'vs/base/common/async';
import { ILogService } from 'vs/platform/log/common/log';
import { mnemonicMenuLabel } from 'vs/base/common/labels';
@ -73,7 +73,8 @@ export class Menubar {
@IStateService private readonly stateService: IStateService,
@ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService,
@ILogService private readonly logService: ILogService,
@INativeHostMainService private readonly nativeHostMainService: INativeHostMainService
@INativeHostMainService private readonly nativeHostMainService: INativeHostMainService,
@IProductService private readonly productService: IProductService
) {
this.menuUpdater = new RunOnceScheduler(() => this.doUpdateMenu(), 0);
@ -123,22 +124,22 @@ export class Menubar {
this.fallbackMenuHandlers['workbench.action.clearRecentFiles'] = () => this.workspacesHistoryMainService.clearRecentlyOpened();
// Help Menu Items
const twitterUrl = product.twitterUrl;
const twitterUrl = this.productService.twitterUrl;
if (twitterUrl) {
this.fallbackMenuHandlers['workbench.action.openTwitterUrl'] = () => this.openUrl(twitterUrl, 'openTwitterUrl');
}
const requestFeatureUrl = product.requestFeatureUrl;
const requestFeatureUrl = this.productService.requestFeatureUrl;
if (requestFeatureUrl) {
this.fallbackMenuHandlers['workbench.action.openRequestFeatureUrl'] = () => this.openUrl(requestFeatureUrl, 'openUserVoiceUrl');
}
const reportIssueUrl = product.reportIssueUrl;
const reportIssueUrl = this.productService.reportIssueUrl;
if (reportIssueUrl) {
this.fallbackMenuHandlers['workbench.action.openIssueReporter'] = () => this.openUrl(reportIssueUrl, 'openReportIssues');
}
const licenseUrl = product.licenseUrl;
const licenseUrl = this.productService.licenseUrl;
if (licenseUrl) {
this.fallbackMenuHandlers['workbench.action.openLicenseUrl'] = () => {
if (language) {
@ -150,7 +151,7 @@ export class Menubar {
};
}
const privacyStatementUrl = product.privacyStatementUrl;
const privacyStatementUrl = this.productService.privacyStatementUrl;
if (privacyStatementUrl && licenseUrl) {
this.fallbackMenuHandlers['workbench.action.openPrivacyStatementUrl'] = () => {
if (language) {
@ -268,7 +269,7 @@ export class Menubar {
let macApplicationMenuItem: MenuItem;
if (isMacintosh) {
const applicationMenu = new Menu();
macApplicationMenuItem = new MenuItem({ label: product.nameShort, submenu: applicationMenu });
macApplicationMenuItem = new MenuItem({ label: this.productService.nameShort, submenu: applicationMenu });
this.setMacApplicationMenu(applicationMenu);
menubar.append(macApplicationMenuItem);
}
@ -362,7 +363,7 @@ export class Menubar {
}
private setMacApplicationMenu(macApplicationMenu: Menu): void {
const about = this.createMenuItem(nls.localize('mAbout', "About {0}", product.nameLong), 'workbench.action.showAboutDialog');
const about = this.createMenuItem(nls.localize('mAbout', "About {0}", this.productService.nameLong), 'workbench.action.showAboutDialog');
const checkForUpdates = this.getUpdateMenuItems();
let preferences;
@ -374,11 +375,11 @@ export class Menubar {
const servicesMenu = new Menu();
const services = new MenuItem({ label: nls.localize('mServices', "Services"), role: 'services', submenu: servicesMenu });
const hide = new MenuItem({ label: nls.localize('mHide', "Hide {0}", product.nameLong), role: 'hide', accelerator: 'Command+H' });
const hide = new MenuItem({ label: nls.localize('mHide', "Hide {0}", this.productService.nameLong), role: 'hide', accelerator: 'Command+H' });
const hideOthers = new MenuItem({ label: nls.localize('mHideOthers', "Hide Others"), role: 'hideOthers', accelerator: 'Command+Alt+H' });
const showAll = new MenuItem({ label: nls.localize('mShowAll', "Show All"), role: 'unhide' });
const quit = new MenuItem(this.likeAction('workbench.action.quit', {
label: nls.localize('miQuit', "Quit {0}", product.nameLong), click: () => {
label: nls.localize('miQuit', "Quit {0}", this.productService.nameLong), click: () => {
const lastActiveWindow = this.windowsMainService.getLastActiveWindow();
if (
this.windowsMainService.getWindowCount() === 0 || // allow to quit when no more windows are open

View file

@ -24,7 +24,7 @@ import { arch, totalmem, release, platform, type, loadavg, freemem, cpus } from
import { virtualMachineHint } from 'vs/base/node/id';
import { ILogService } from 'vs/platform/log/common/log';
import { dirname, join } from 'vs/base/common/path';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
import { memoize } from 'vs/base/common/decorators';
import { Disposable } from 'vs/base/common/lifecycle';
import { ISharedProcess } from 'vs/platform/sharedProcess/node/sharedProcess';
@ -49,7 +49,8 @@ export class NativeHostMainService extends Disposable implements INativeHostMain
@ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService,
@IEnvironmentMainService private readonly environmentMainService: IEnvironmentMainService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
@ILogService private readonly logService: ILogService
@ILogService private readonly logService: ILogService,
@IProductService private readonly productService: IProductService
) {
super();
@ -402,8 +403,8 @@ export class NativeHostMainService extends Disposable implements INativeHostMain
sudoCommand.push('--file-write', `"${source.fsPath}"`, `"${target.fsPath}"`);
const promptOptions = {
name: product.nameLong.replace('-', ''),
icns: (isMacintosh && this.environmentMainService.isBuilt) ? join(dirname(this.environmentMainService.appRoot), `${product.nameShort}.icns`) : undefined
name: this.productService.nameLong.replace('-', ''),
icns: (isMacintosh && this.environmentMainService.isBuilt) ? join(dirname(this.environmentMainService.appRoot), `${this.productService.nameShort}.icns`) : undefined
};
sudoPrompt.exec(sudoCommand.join(' '), promptOptions, (error: string, stdout: string, stderr: string) => {
@ -430,7 +431,7 @@ export class NativeHostMainService extends Disposable implements INativeHostMain
// Windows
if (isWindows) {
if (this.environmentMainService.isBuilt) {
return join(dirname(process.execPath), 'bin', `${product.applicationName}.cmd`);
return join(dirname(process.execPath), 'bin', `${this.productService.applicationName}.cmd`);
}
return join(this.environmentMainService.appRoot, 'scripts', 'code-cli.bat');
@ -439,7 +440,7 @@ export class NativeHostMainService extends Disposable implements INativeHostMain
// Linux
if (isLinux) {
if (this.environmentMainService.isBuilt) {
return join(dirname(process.execPath), 'bin', `${product.applicationName}`);
return join(dirname(process.execPath), 'bin', `${this.productService.applicationName}`);
}
return join(this.environmentMainService.appRoot, 'scripts', 'code-cli.sh');

View file

@ -7,15 +7,15 @@ import { Event, Emitter } from 'vs/base/common/event';
import { timeout } from 'vs/base/common/async';
import { IConfigurationService, getMigratedSettingValue } from 'vs/platform/configuration/common/configuration';
import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
import { IUpdateService, State, StateType, AvailableForDownload, UpdateType } from 'vs/platform/update/common/update';
import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/environmentMainService';
import { ILogService } from 'vs/platform/log/common/log';
import { IRequestService } from 'vs/platform/request/common/request';
import { CancellationToken } from 'vs/base/common/cancellation';
export function createUpdateURL(platform: string, quality: string): string {
return `${product.updateUrl}/api/update/${platform}/${quality}/${product.commit}`;
export function createUpdateURL(platform: string, quality: string, productService: IProductService): string {
return `${productService.updateUrl}/api/update/${platform}/${quality}/${productService.commit}`;
}
export type UpdateNotAvailableClassification = {
@ -49,6 +49,7 @@ export abstract class AbstractUpdateService implements IUpdateService {
@IEnvironmentMainService private readonly environmentMainService: IEnvironmentMainService,
@IRequestService protected requestService: IRequestService,
@ILogService protected logService: ILogService,
@IProductService protected readonly productService: IProductService
) { }
/**
@ -66,7 +67,7 @@ export abstract class AbstractUpdateService implements IUpdateService {
return;
}
if (!product.updateUrl || !product.commit) {
if (!this.productService.updateUrl || !this.productService.commit) {
this.logService.info('update#ctor - updates are disabled as there is no update URL');
return;
}
@ -104,7 +105,7 @@ export abstract class AbstractUpdateService implements IUpdateService {
}
private getProductQuality(updateMode: string): string | undefined {
return updateMode === 'none' ? undefined : product.quality;
return updateMode === 'none' ? undefined : this.productService.quality;
}
private scheduleCheckForUpdates(delay = 60 * 60 * 1000): Promise<void> {

View file

@ -15,7 +15,7 @@ import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/e
import { ILogService } from 'vs/platform/log/common/log';
import { AbstractUpdateService, createUpdateURL, UpdateNotAvailableClassification } from 'vs/platform/update/electron-main/abstractUpdateService';
import { IRequestService } from 'vs/platform/request/common/request';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
export class DarwinUpdateService extends AbstractUpdateService {
@ -34,9 +34,10 @@ export class DarwinUpdateService extends AbstractUpdateService {
@ITelemetryService private readonly telemetryService: ITelemetryService,
@IEnvironmentMainService environmentMainService: IEnvironmentMainService,
@IRequestService requestService: IRequestService,
@ILogService logService: ILogService
@ILogService logService: ILogService,
@IProductService productService: IProductService
) {
super(lifecycleMainService, configurationService, environmentMainService, requestService, logService);
super(lifecycleMainService, configurationService, environmentMainService, requestService, logService, productService);
}
initialize(): void {
@ -58,12 +59,12 @@ export class DarwinUpdateService extends AbstractUpdateService {
protected buildUpdateFeedUrl(quality: string): string | undefined {
let assetID: string;
if (!product.darwinUniversalAssetId) {
if (!this.productService.darwinUniversalAssetId) {
assetID = process.arch === 'x64' ? 'darwin' : 'darwin-arm64';
} else {
assetID = product.darwinUniversalAssetId;
assetID = this.productService.darwinUniversalAssetId;
}
const url = createUpdateURL(assetID, quality);
const url = createUpdateURL(assetID, quality, this.productService);
try {
electron.autoUpdater.setFeedURL({ url });
} catch (e) {

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
import { State, IUpdate, AvailableForDownload, UpdateType } from 'vs/platform/update/common/update';
@ -26,13 +26,14 @@ export class LinuxUpdateService extends AbstractUpdateService {
@IEnvironmentMainService environmentMainService: IEnvironmentMainService,
@IRequestService requestService: IRequestService,
@ILogService logService: ILogService,
@INativeHostMainService private readonly nativeHostMainService: INativeHostMainService
@INativeHostMainService private readonly nativeHostMainService: INativeHostMainService,
@IProductService productService: IProductService
) {
super(lifecycleMainService, configurationService, environmentMainService, requestService, logService);
super(lifecycleMainService, configurationService, environmentMainService, requestService, logService, productService);
}
protected buildUpdateFeedUrl(quality: string): string {
return createUpdateURL(`linux-${process.arch}`, quality);
return createUpdateURL(`linux-${process.arch}`, quality, this.productService);
}
protected doCheckForUpdates(context: any): void {
@ -64,8 +65,8 @@ export class LinuxUpdateService extends AbstractUpdateService {
protected async doDownloadUpdate(state: AvailableForDownload): Promise<void> {
// Use the download URL if available as we don't currently detect the package type that was
// installed and the website download page is more useful than the tarball generally.
if (product.downloadUrl && product.downloadUrl.length > 0) {
this.nativeHostMainService.openExternal(undefined, product.downloadUrl);
if (this.productService.downloadUrl && this.productService.downloadUrl.length > 0) {
this.nativeHostMainService.openExternal(undefined, this.productService.downloadUrl);
} else if (state.update.url) {
this.nativeHostMainService.openExternal(undefined, state.update.url);
}

View file

@ -9,7 +9,7 @@ import * as pfs from 'vs/base/node/pfs';
import { memoize } from 'vs/base/common/decorators';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
import { State, IUpdate, StateType, AvailableForDownload, UpdateType } from 'vs/platform/update/common/update';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/environmentMainService';
@ -55,7 +55,7 @@ export class Win32UpdateService extends AbstractUpdateService {
@memoize
get cachePath(): Promise<string> {
const result = path.join(tmpdir(), `vscode-update-${product.target}-${process.arch}`);
const result = path.join(tmpdir(), `vscode-update-${this.productService.target}-${process.arch}`);
return fs.promises.mkdir(result, { recursive: true }).then(() => result);
}
@ -67,9 +67,10 @@ export class Win32UpdateService extends AbstractUpdateService {
@IRequestService requestService: IRequestService,
@ILogService logService: ILogService,
@IFileService private readonly fileService: IFileService,
@INativeHostMainService private readonly nativeHostMainService: INativeHostMainService
@INativeHostMainService private readonly nativeHostMainService: INativeHostMainService,
@IProductService productService: IProductService
) {
super(lifecycleMainService, configurationService, environmentMainService, requestService, logService);
super(lifecycleMainService, configurationService, environmentMainService, requestService, logService, productService);
}
initialize(): void {
@ -86,7 +87,7 @@ export class Win32UpdateService extends AbstractUpdateService {
"target" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog('update:win32SetupTarget', { target: product.target });
this.telemetryService.publicLog('update:win32SetupTarget', { target: this.productService.target });
}
}
@ -99,11 +100,11 @@ export class Win32UpdateService extends AbstractUpdateService {
if (getUpdateType() === UpdateType.Archive) {
platform += '-archive';
} else if (product.target === 'user') {
} else if (this.productService.target === 'user') {
platform += '-user';
}
return createUpdateURL(platform, quality);
return createUpdateURL(platform, quality, this.productService);
}
protected doCheckForUpdates(context: any): void {
@ -155,7 +156,7 @@ export class Win32UpdateService extends AbstractUpdateService {
this.availableUpdate = { packagePath };
if (fastUpdatesEnabled && update.supportsFastUpdate) {
if (product.target === 'user') {
if (this.productService.target === 'user') {
this.doApplyUpdate();
} else {
this.setState(State.Downloaded(update));
@ -185,11 +186,11 @@ export class Win32UpdateService extends AbstractUpdateService {
private async getUpdatePackagePath(version: string): Promise<string> {
const cachePath = await this.cachePath;
return path.join(cachePath, `CodeSetup-${product.quality}-${version}.exe`);
return path.join(cachePath, `CodeSetup-${this.productService.quality}-${version}.exe`);
}
private async cleanup(exceptVersion: string | null = null): Promise<any> {
const filter = exceptVersion ? (one: string) => !(new RegExp(`${product.quality}-${exceptVersion}\\.exe$`).test(one)) : () => true;
const filter = exceptVersion ? (one: string) => !(new RegExp(`${this.productService.quality}-${exceptVersion}\\.exe$`).test(one)) : () => true;
const cachePath = await this.cachePath;
const versions = await pfs.readdir(cachePath);
@ -219,7 +220,7 @@ export class Win32UpdateService extends AbstractUpdateService {
const cachePath = await this.cachePath;
this.availableUpdate.updateFilePath = path.join(cachePath, `CodeSetup-${product.quality}-${update.version}.flag`);
this.availableUpdate.updateFilePath = path.join(cachePath, `CodeSetup-${this.productService.quality}-${update.version}.flag`);
await pfs.writeFile(this.availableUpdate.updateFilePath, 'flag');
const child = spawn(this.availableUpdate.packagePath, ['/verysilent', `/update="${this.availableUpdate.updateFilePath}"`, '/nocloseapplications', '/mergetasks=runcode,!desktopicon,!quicklaunchicon'], {
@ -233,7 +234,7 @@ export class Win32UpdateService extends AbstractUpdateService {
this.setState(State.Idle(getUpdateType()));
});
const readyMutexName = `${product.win32MutexName}-ready`;
const readyMutexName = `${this.productService.win32MutexName}-ready`;
const mutex = await import('windows-mutex');
// poll for mutex-ready

View file

@ -7,7 +7,7 @@ import { IURLService, IURLHandler, IOpenURLOptions } from 'vs/platform/url/commo
import { URI, UriComponents } from 'vs/base/common/uri';
import { first } from 'vs/base/common/async';
import { toDisposable, IDisposable, Disposable } from 'vs/base/common/lifecycle';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
export abstract class AbstractURLService extends Disposable implements IURLService {
@ -30,6 +30,12 @@ export abstract class AbstractURLService extends Disposable implements IURLServi
export class NativeURLService extends AbstractURLService {
constructor(
@IProductService protected readonly productService: IProductService
) {
super();
}
create(options?: Partial<UriComponents>): URI {
let { authority, path, query, fragment } = options ? options : { authority: undefined, path: undefined, query: undefined, fragment: undefined };
@ -37,6 +43,6 @@ export class NativeURLService extends AbstractURLService {
path = `/${path}`; // URI validation requires a path if there is an authority
}
return URI.from({ scheme: product.urlProtocol, authority, path, query, fragment });
return URI.from({ scheme: this.productService.urlProtocol, authority, path, query, fragment });
}
}

View file

@ -6,7 +6,7 @@
import { Event } from 'vs/base/common/event';
import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/environmentMainService';
import { IURLService } from 'vs/platform/url/common/url';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
import { app, Event as ElectronEvent } from 'electron';
import { URI } from 'vs/base/common/uri';
import { IDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle';
@ -43,7 +43,8 @@ export class ElectronURLListener {
initialUrisToHandle: { uri: URI, url: string }[],
private readonly urlService: IURLService,
windowsMainService: IWindowsMainService,
environmentMainService: IEnvironmentMainService
environmentMainService: IEnvironmentMainService,
productService: IProductService
) {
// the initial set of URIs we need to handle once the window is ready
@ -53,7 +54,7 @@ export class ElectronURLListener {
if (isWindows) {
const windowsParameters = environmentMainService.isBuilt ? [] : [`"${environmentMainService.appRoot}"`];
windowsParameters.push('--open-url', '--');
app.setAsDefaultProtocolClient(product.urlProtocol, process.execPath, windowsParameters);
app.setAsDefaultProtocolClient(productService.urlProtocol, process.execPath, windowsParameters);
}
// macOS: listen to `open-url` events from here on to handle

View file

@ -15,7 +15,7 @@ import { ILogService } from 'vs/platform/log/common/log';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv';
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
import { WindowMinimumSize, IWindowSettings, MenuBarVisibility, getTitleBarStyle, getMenuBarVisibility, zoomLevelToZoomFactor, INativeWindowConfiguration } from 'vs/platform/windows/common/windows';
import { Disposable } from 'vs/base/common/lifecycle';
import { browserCodeLoadingCacheStrategy, isLinux, isMacintosh, isWindows } from 'vs/base/common/platform';
@ -119,7 +119,8 @@ export class CodeWindow extends Disposable implements ICodeWindow {
@ITelemetryService private readonly telemetryService: ITelemetryService,
@IDialogMainService private readonly dialogMainService: IDialogMainService,
@ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService,
@INativeHostMainService private readonly nativeHostMainService: INativeHostMainService
@INativeHostMainService private readonly nativeHostMainService: INativeHostMainService,
@IProductService private readonly productService: IProductService
) {
super();
@ -144,7 +145,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
minWidth: WindowMinimumSize.WIDTH,
minHeight: WindowMinimumSize.HEIGHT,
show: !isFullscreenOrMaximized,
title: product.nameLong,
title: this.productService.nameLong,
webPreferences: {
preload: FileAccess.asFileUri('vs/base/parts/sandbox/electron-browser/preload.js', require).fsPath,
v8CacheOptions: browserCodeLoadingCacheStrategy,
@ -196,7 +197,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
const useNativeTabs = isMacintosh && windowConfig?.nativeTabs === true;
if (useNativeTabs) {
options.tabbingIdentifier = product.nameShort; // this opts in to sierra tabs
options.tabbingIdentifier = this.productService.nameShort; // this opts in to sierra tabs
}
const useCustomTitleStyle = getTitleBarStyle(this.configurationService) === 'custom';
@ -263,7 +264,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
this.createTouchBar();
// Request handling
this.marketplaceHeadersPromise = resolveMarketplaceHeaders(product.version, this.environmentMainService, this.fileService, {
this.marketplaceHeadersPromise = resolveMarketplaceHeaders(this.productService.version, this.environmentMainService, this.fileService, {
get: key => storageMainService.globalStorage.get(key),
store: (key, value) => storageMainService.globalStorage.set(key, value)
});
@ -575,7 +576,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
// Show Dialog
const result = await this.dialogMainService.showMessageBox({
title: product.nameLong,
title: this.productService.nameLong,
type: 'warning',
buttons: [mnemonicButtonLabel(localize({ key: 'reopen', comment: ['&& denotes a mnemonic'] }, "&&Reopen")), mnemonicButtonLabel(localize({ key: 'wait', comment: ['&& denotes a mnemonic'] }, "&&Keep Waiting")), mnemonicButtonLabel(localize({ key: 'close', comment: ['&& denotes a mnemonic'] }, "&&Close"))],
message: localize('appStalled', "The window is no longer responding"),
@ -605,7 +606,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
}
const result = await this.dialogMainService.showMessageBox({
title: product.nameLong,
title: this.productService.nameLong,
type: 'warning',
buttons: [mnemonicButtonLabel(localize({ key: 'reopen', comment: ['&& denotes a mnemonic'] }, "&&Reopen")), mnemonicButtonLabel(localize({ key: 'close', comment: ['&& denotes a mnemonic'] }, "&&Close"))],
message,
@ -731,7 +732,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
this.setRepresentedFilename('');
}
this._win.setTitle(product.nameLong);
this._win.setTitle(this.productService.nameLong);
}
// Load URL

View file

@ -20,7 +20,7 @@ import { ILogService } from 'vs/platform/log/common/log';
import { IWindowSettings, IPath, isFileToOpen, isWorkspaceToOpen, isFolderToOpen, IWindowOpenable, IOpenEmptyWindowOptions, IAddFoldersRequest, IPathsToWaitFor, INativeWindowConfiguration, INativeOpenFileRequest } from 'vs/platform/windows/common/windows';
import { findWindowOnFile, findWindowOnWorkspaceOrFolder, findWindowOnExtensionDevelopmentPath } from 'vs/platform/windows/electron-main/windowsFinder';
import { Emitter } from 'vs/base/common/event';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
import { IWindowsMainService, IOpenConfiguration, IWindowsCountChangedEvent, ICodeWindow, IOpenEmptyConfiguration, OpenContext } from 'vs/platform/windows/electron-main/windows';
import { IWorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService';
import { IProcessEnvironment, isMacintosh } from 'vs/base/common/platform';
@ -149,7 +149,8 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
@IWorkspacesManagementMainService private readonly workspacesManagementMainService: IWorkspacesManagementMainService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IDialogMainService private readonly dialogMainService: IDialogMainService,
@IFileService private readonly fileService: IFileService
@IFileService private readonly fileService: IFileService,
@IProductService private readonly productService: IProductService
) {
super();
@ -665,7 +666,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
const uri = this.resourceFromOpenable(pathToOpen);
const options: MessageBoxOptions = {
title: product.nameLong,
title: this.productService.nameLong,
type: 'info',
buttons: [localize('ok', "OK")],
message: uri.scheme === Schemas.file ? localize('pathNotExistTitle', "Path does not exist") : localize('uriInvalidTitle', "URI can not be opened"),

View file

@ -20,7 +20,7 @@ import { originalFSPath, joinPath, basename, extUriBiasedIgnorePathCase } from '
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { ICodeWindow } from 'vs/platform/windows/electron-main/windows';
import { localize } from 'vs/nls';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
import { MessageBoxOptions, BrowserWindow } from 'electron';
import { withNullAsUndefined } from 'vs/base/common/types';
import { IBackupMainService } from 'vs/platform/backup/electron-main/backup';
@ -77,7 +77,8 @@ export class WorkspacesManagementMainService extends Disposable implements IWork
@IEnvironmentMainService private readonly environmentMainService: IEnvironmentMainService,
@ILogService private readonly logService: ILogService,
@IBackupMainService private readonly backupMainService: IBackupMainService,
@IDialogMainService private readonly dialogMainService: IDialogMainService
@IDialogMainService private readonly dialogMainService: IDialogMainService,
@IProductService private readonly productService: IProductService
) {
super();
}
@ -270,7 +271,7 @@ export class WorkspacesManagementMainService extends Disposable implements IWork
// Prevent overwriting a workspace that is currently opened in another window
if (findWindowOnWorkspaceOrFolder(windows, workspacePath)) {
const options: MessageBoxOptions = {
title: product.nameLong,
title: this.productService.nameLong,
type: 'info',
buttons: [localize('ok', "OK")],
message: localize('workspaceOpenedMessage', "Unable to save workspace '{0}'", basename(workspacePath)),

View file

@ -22,6 +22,7 @@ import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogMain
import { INativeOpenDialogOptions } from 'vs/platform/dialogs/common/dialogs';
import { IBackupMainService, IWorkspaceBackupInfo } from 'vs/platform/backup/electron-main/backup';
import { IEmptyWindowBackupInfo } from 'vs/platform/backup/node/backup';
import product from 'vs/platform/product/common/product';
suite('WorkspacesManagementMainService', () => {
@ -103,7 +104,7 @@ suite('WorkspacesManagementMainService', () => {
}
};
service = new WorkspacesManagementMainService(environmentMainService, new NullLogService(), new TestBackupMainService(), new TestDialogMainService());
service = new WorkspacesManagementMainService(environmentMainService, new NullLogService(), new TestBackupMainService(), new TestDialogMainService(), { _serviceBrand: undefined, ...product });
return fs.promises.mkdir(untitledWorkspacesHomePath, { recursive: true });
});

View file

@ -37,7 +37,6 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/
import { timeout } from 'vs/base/common/async';
import { VSBuffer } from 'vs/base/common/buffer';
import { DisposableStore } from 'vs/base/common/lifecycle';
import product from 'vs/platform/product/common/product';
import { Event } from 'vs/base/common/event';
import { UriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentityService';
import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFilesystemProvider';
@ -76,7 +75,7 @@ suite('WorkspaceContextService - Folder', () => {
const environmentService = TestEnvironmentService;
fileService.registerProvider(Schemas.userData, disposables.add(new FileUserDataProvider(ROOT.scheme, fileSystemProvider, Schemas.userData, new NullLogService())));
testObject = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache() }, environmentService, fileService, new RemoteAgentService(null, environmentService, { _serviceBrand: undefined, ...product }, new RemoteAuthorityResolverService(undefined, undefined), new SignService(undefined), new NullLogService()), new UriIdentityService(fileService), new NullLogService()));
testObject = disposables.add(new WorkspaceService({ configurationCache: new ConfigurationCache() }, environmentService, fileService, new RemoteAgentService(null, environmentService, TestProductService, new RemoteAuthorityResolverService(undefined, undefined), new SignService(undefined), new NullLogService()), new UriIdentityService(fileService), new NullLogService()));
await (<WorkspaceService>testObject).initialize(convertToWorkspacePayload(folder));
});

View file

@ -11,7 +11,7 @@ import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storag
import { ITelemetryData } from 'vs/base/common/actions';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
export const ITASExperimentService = createDecorator<ITASExperimentService>('TASExperimentService');
@ -43,7 +43,10 @@ class MementoKeyValueStorage implements IKeyValueStorage {
class ExperimentServiceTelemetry implements IExperimentationTelemetry {
private _lastAssignmentContext: string | undefined;
constructor(private telemetryService: ITelemetryService) { }
constructor(
private telemetryService: ITelemetryService,
private productService: IProductService
) { }
get assignmentContext(): string[] | undefined {
return this._lastAssignmentContext?.split(';');
@ -52,7 +55,7 @@ class ExperimentServiceTelemetry implements IExperimentationTelemetry {
// __GDPR__COMMON__ "VSCode.ABExp.Features" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "abexp.assignmentcontext" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
setSharedProperty(name: string, value: string): void {
if (name === product.tasConfig?.assignmentContextTelemetryPropertyName) {
if (name === this.productService.tasConfig?.assignmentContextTelemetryPropertyName) {
this._lastAssignmentContext = value;
}
@ -190,9 +193,10 @@ export class ExperimentService implements ITASExperimentService {
@ITelemetryService private telemetryService: ITelemetryService,
@IStorageService private storageService: IStorageService,
@IConfigurationService private configurationService: IConfigurationService,
@IProductService private productService: IProductService
) {
if (product.tasConfig && this.experimentsEnabled && this.telemetryService.isOptedIn) {
if (productService.tasConfig && this.experimentsEnabled && this.telemetryService.isOptedIn) {
this.tasClient = this.setupTASClient();
}
}
@ -244,20 +248,20 @@ export class ExperimentService implements ITASExperimentService {
private async setupTASClient(): Promise<TASClient> {
const startSetup = Date.now();
const telemetryInfo = await this.telemetryService.getTelemetryInfo();
const targetPopulation = telemetryInfo.msftInternal ? TargetPopulation.Internal : (product.quality === 'stable' ? TargetPopulation.Public : TargetPopulation.Insiders);
const targetPopulation = telemetryInfo.msftInternal ? TargetPopulation.Internal : (this.productService.quality === 'stable' ? TargetPopulation.Public : TargetPopulation.Insiders);
const machineId = telemetryInfo.machineId;
const filterProvider = new ExperimentServiceFilterProvider(
product.version,
product.nameLong,
this.productService.version,
this.productService.nameLong,
machineId,
targetPopulation
);
const keyValueStorage = new MementoKeyValueStorage(new Memento(ExperimentService.MEMENTO_ID, this.storageService));
this.telemetry = new ExperimentServiceTelemetry(this.telemetryService);
this.telemetry = new ExperimentServiceTelemetry(this.telemetryService, this.productService);
const tasConfig = product.tasConfig!;
const tasConfig = this.productService.tasConfig!;
const tasClient = new (await import('tas-client-umd')).ExperimentationService({
filterProviders: [filterProvider],
telemetry: this.telemetry,

View file

@ -20,7 +20,7 @@ import { URI } from 'vs/base/common/uri';
import { joinPath } from 'vs/base/common/resources';
import { FileAccess } from 'vs/base/common/network';
import { DefaultIconPath } from 'vs/platform/extensionManagement/common/extensionManagement';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
export const IGettingStartedService = createDecorator<IGettingStartedService>('gettingStartedService');
@ -79,6 +79,7 @@ export class GettingStartedService extends Disposable implements IGettingStarted
@IContextKeyService private readonly contextService: IContextKeyService,
@IUserDataAutoSyncEnablementService readonly userDataAutoSyncEnablementService: IUserDataAutoSyncEnablementService,
@IExtensionService private readonly extensionService: IExtensionService,
@IProductService private readonly productService: IProductService
) {
super();
@ -138,7 +139,7 @@ export class GettingStartedService extends Disposable implements IGettingStarted
if (!this.trackedExtensions.has(ExtensionIdentifier.toKey(extension.identifier))) {
this.trackedExtensions.add(ExtensionIdentifier.toKey(extension.identifier));
if ((extension.contributes?.welcomeCategories || extension.contributes?.welcomeItems) && product.quality === 'stable') {
if ((extension.contributes?.welcomeCategories || extension.contributes?.welcomeItems) && this.productService.quality === 'stable') {
console.warn('Extension', extension.identifier.value, 'contributes welcome page content but this is a Stable build and extension contributions are only available in Insiders. The contributed content will be disregarded.');
return;
}

View file

@ -27,9 +27,9 @@ export class RelayURLService extends NativeURLService implements IURLHandler, IO
@IMainProcessService mainProcessService: IMainProcessService,
@IOpenerService openerService: IOpenerService,
@INativeHostService private readonly nativeHostService: INativeHostService,
@IProductService private readonly productService: IProductService
@IProductService productService: IProductService
) {
super();
super(productService);
this.urlService = ProxyChannel.toService<IURLService>(mainProcessService.getChannel('url'));

View file

@ -46,6 +46,19 @@ export interface IWorkingCopyBackup<MetaType = object> {
content?: ITextSnapshot;
}
/**
* A working copy is an abstract concept to unify handling of
* data that can be worked on (e.g. edited) in an editor.
*
* Every working copy has in common that it is identified by
* a resource `URI` and only one working copy can be registered
* with the same `URI`.
*
* A working copy resource may be the backing store of the data
* (e.g. a file on disk), but that is not a requirement. The
* `URI` is mainly used to uniquely identify a working copy among
* others.
*/
export interface IWorkingCopy {
/**
@ -160,9 +173,11 @@ export interface IWorkingCopyService {
/**
* Register a new working copy with the service. This method will
* throw if you try to register a working copy with a resource
* that was already registered before. There can only be 1 working
* copy per resource registered to the service.
* throw if you try to register a working copy on a resource that
* has already been registered.
*
* Overall there can only ever be 1 working copy with the same
* resource.
*/
registerWorkingCopy(workingCopy: IWorkingCopy): IDisposable;