Implement Display Protocol Detection (#208212)

display protocol
This commit is contained in:
Benjamin Christopher Simmonds 2024-03-20 17:00:23 +01:00 committed by GitHub
parent ccdffd394b
commit ab78ff55f4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 93 additions and 2 deletions

View file

@ -0,0 +1,78 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { constants as FSConstants } from 'fs';
import { access } from 'fs/promises';
import { join } from 'vs/base/common/path';
import { env } from 'vs/base/common/process';
const XDG_SESSION_TYPE = 'XDG_SESSION_TYPE';
const WAYLAND_DISPLAY = 'WAYLAND_DISPLAY';
const XDG_RUNTIME_DIR = 'XDG_RUNTIME_DIR';
const enum DisplayProtocolType {
Wayland = 'wayland',
XWayland = 'xwayland',
X11 = 'x11',
Unknown = 'unknown'
}
export async function getDisplayProtocol(errorLogger: (error: any) => void): Promise<DisplayProtocolType> {
const xdgSessionType = env[XDG_SESSION_TYPE];
if (xdgSessionType) {
// If XDG_SESSION_TYPE is set, return its value if it's either 'wayland' or 'x11'.
// We assume that any value other than 'wayland' or 'x11' is an error or unexpected,
// hence 'unknown' is returned.
return xdgSessionType === DisplayProtocolType.Wayland || xdgSessionType === DisplayProtocolType.X11 ? xdgSessionType : DisplayProtocolType.Unknown;
} else {
const waylandDisplay = env[WAYLAND_DISPLAY];
if (!waylandDisplay) {
// If WAYLAND_DISPLAY is empty, then the session is x11.
return DisplayProtocolType.X11;
} else {
const xdgRuntimeDir = env[XDG_RUNTIME_DIR];
if (!xdgRuntimeDir) {
// If XDG_RUNTIME_DIR is empty, then the session can only be guessed.
return DisplayProtocolType.Unknown;
} else {
// Check for the presence of the file $XDG_RUNTIME_DIR/wayland-0.
const waylandServerPipe = join(xdgRuntimeDir, 'wayland-0');
try {
await access(waylandServerPipe, FSConstants.R_OK);
// If the file exists, then the session is wayland.
return DisplayProtocolType.Wayland;
} catch (err) {
// If the file does not exist or an error occurs, we guess 'unknown'
// since WAYLAND_DISPLAY was set but no wayland-0 pipe could be confirmed.
errorLogger(err);
return DisplayProtocolType.Unknown;
}
}
}
}
}
export function getCodeDisplayProtocol(displayProtocol: DisplayProtocolType, ozonePlatform: string | undefined): DisplayProtocolType {
if (!ozonePlatform) {
return displayProtocol === DisplayProtocolType.Wayland ? DisplayProtocolType.XWayland : DisplayProtocolType.X11;
} else {
switch (ozonePlatform) {
case 'auto':
return displayProtocol;
case 'x11':
return displayProtocol === DisplayProtocolType.Wayland ? DisplayProtocolType.XWayland : DisplayProtocolType.X11;
case 'wayland':
return DisplayProtocolType.Wayland;
default:
return DisplayProtocolType.Unknown;
}
}
}

View file

@ -118,6 +118,7 @@ import { NativeEnvironmentService } from 'vs/platform/environment/node/environme
import { SharedProcessRawConnection, SharedProcessLifecycle } from 'vs/platform/sharedProcess/common/sharedProcess';
import { getOSReleaseInfo } from 'vs/base/node/osReleaseInfo';
import { getDesktopEnvironment } from 'vs/base/common/desktopEnvironmentInfo';
import { getCodeDisplayProtocol, getDisplayProtocol } from 'vs/base/node/osDisplayProtocolInfo';
class SharedProcessMain extends Disposable implements IClientConnectionFilter {
@ -465,14 +466,20 @@ class SharedProcessMain extends Disposable implements IClientConnectionFilter {
private async reportClientOSInfo(telemetryService: ITelemetryService, logService: ILogService): Promise<void> {
if (isLinux) {
const releaseInfo = await getOSReleaseInfo(logService.error.bind(logService));
const [releaseInfo, displayProtocol] = await Promise.all([
getOSReleaseInfo(logService.error.bind(logService)),
getDisplayProtocol(logService.error.bind(logService))
]);
const desktopEnvironment = getDesktopEnvironment();
const codeSessionType = getCodeDisplayProtocol(displayProtocol, this.configuration.args['ozone-platform']);
if (releaseInfo) {
type ClientPlatformInfoClassification = {
platformId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'A string identifying the operating system without any version information.' };
platformVersionId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'A string identifying the operating system version excluding any name information or release code.' };
platformIdLike: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'A string identifying the operating system the current OS derivate is closely related to.' };
desktopEnvironment: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'A string identifying the desktop environment the user is using.' };
displayProtocol: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'A string identifying the users display protocol type.' };
codeDisplayProtocol: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'A string identifying the vscode display protocol type.' };
owner: 'benibenj';
comment: 'Provides insight into the distro and desktop environment information on Linux.';
};
@ -481,12 +488,16 @@ class SharedProcessMain extends Disposable implements IClientConnectionFilter {
platformVersionId: string | undefined;
platformIdLike: string | undefined;
desktopEnvironment: string | undefined;
displayProtocol: string | undefined;
codeDisplayProtocol: string | undefined;
};
telemetryService.publicLog2<ClientPlatformInfoEvent, ClientPlatformInfoClassification>('clientPlatformInfo', {
platformId: releaseInfo.id,
platformVersionId: releaseInfo.version_id,
platformIdLike: releaseInfo.id_like,
desktopEnvironment: desktopEnvironment
desktopEnvironment: desktopEnvironment,
displayProtocol: displayProtocol,
codeDisplayProtocol: codeSessionType
});
}
}

View file

@ -140,4 +140,5 @@ export interface NativeParsedArgs {
'log-net-log'?: string;
'vmodule'?: string;
'disable-dev-shm-usage'?: boolean;
'ozone-platform'?: string;
}

View file

@ -204,6 +204,7 @@ export const OPTIONS: OptionDescriptions<Required<NativeParsedArgs>> = {
'_urls': { type: 'string[]' },
'disable-dev-shm-usage': { type: 'boolean' },
'profile-temp': { type: 'boolean' },
'ozone-platform': { type: 'string' },
_: { type: 'string[]' } // main arguments
};