Skip to content

Commit c5daccf

Browse files
committed
Normalizes machineId across VS Code clones
1 parent 02ea44d commit c5daccf

File tree

7 files changed

+73
-5
lines changed

7 files changed

+73
-5
lines changed

src/env/browser/machine.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// This is intentional as the browser environment doesn't have access to MAC addresses
2+
export function getMac(): string | undefined {
3+
return undefined;
4+
}

src/env/node/machine.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { createHash } from 'crypto';
2+
import { networkInterfaces } from 'os';
3+
4+
// Sourced from GKD
5+
const knownBadAppIds = [
6+
// this appId corresponds to the 'iBridge Adapter for the Touchbar' on macbooks
7+
// https://github.com/bevry/getmac/issues/42
8+
// https://discussions.apple.com/thread/7763102
9+
// discovered 3/21/23 with ~28,000 unique users
10+
'8149453d12fde3c987f5ceb011360abe56307d17', // sha1('ac:de:48:00:11:22')
11+
12+
// these appIds correspond to the default VMWARE vnet1 and vmnet8 interface mac address
13+
// https://communities.vmware.com/t5/VMware-Workstation-Pro/Why-are-MAC-addresses-for-vmnet1-and-vmnet8-hardcoded/td-p/1580213
14+
// discovered 3/21/23 with 10250 unique users
15+
'a76a6cbfb93cbb6daa4c4836544564fb777a0803', // sha1('00-50-56-C0-00-01')
16+
// discovered 3/22/23 with 3473 unique users
17+
'4433e1caaca0b97ba94ef3e0772e5931f792fa9b', // sha1('00-50-56-C0-00-08')
18+
19+
// this appId corresponds to the "Forticlient VPN client" adapter mac address
20+
// https://community.fortinet.com/t5/Support-Forum/FortiClient-MAC-Address/m-p/60724
21+
// discovered 3/21/23 with 5655 unique users
22+
'b14e824ad9cd8a3e95493d48e6132ecce40e0e47', // sha1('00-09-0F-FE-00-01')
23+
];
24+
25+
// Sourced from https://github.com/bevry/getmac/blob/master/source/index.ts
26+
// There's issues with importing 'getmac' directly, so we referenced the relevant code here
27+
28+
const zeroRegex = /(?:[0]{1,2}[:-]){5}[0]{1,2}/;
29+
export function getMac(): string | undefined {
30+
const list = networkInterfaces();
31+
32+
for (const parts of Object.values(list)) {
33+
// for some reason beyond me, this is needed to satisfy typescript
34+
// fix https://github.com/bevry/getmac/issues/100
35+
if (!parts) continue;
36+
for (const part of parts) {
37+
if (zeroRegex.test(part.mac) === false) {
38+
const appId = sha1(part.mac);
39+
if (appId != null && !knownBadAppIds.includes(appId)) {
40+
return appId;
41+
}
42+
}
43+
}
44+
}
45+
return undefined;
46+
}
47+
48+
function sha1(data: string): string | undefined {
49+
return createHash('sha1').update(data, 'utf8').digest('hex');
50+
}

src/extension.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { registerPartnerActionRunners } from './partners';
2323
import { executeCommand, registerCommands } from './system/-webview/command';
2424
import { configuration, Configuration } from './system/-webview/configuration';
2525
import { setContext } from './system/-webview/context';
26+
import { getMachineId } from './system/-webview/machine';
2627
import { Storage } from './system/-webview/storage';
2728
import { deviceCohortGroup } from './system/-webview/vscode';
2829
import { isTextDocument } from './system/-webview/vscode/documents';
@@ -56,7 +57,7 @@ export async function activate(context: ExtensionContext): Promise<GitLensApi |
5657
env.appName
5758
} (${codeVersion}) on the ${isWeb ? 'web' : 'desktop'}; language='${
5859
env.language
59-
}', logLevel='${logLevel}', defaultDateLocale='${defaultDateLocale}' (${env.machineId}|${
60+
}', logLevel='${logLevel}', defaultDateLocale='${defaultDateLocale}' (${getMachineId()}|${
6061
env.sessionId
6162
})`,
6263
);
@@ -110,7 +111,7 @@ export async function activate(context: ExtensionContext): Promise<GitLensApi |
110111
log: {
111112
message: ` activating in ${env.appName} (${codeVersion}) on the ${isWeb ? 'web' : 'desktop'}; language='${
112113
env.language
113-
}', logLevel='${logLevel}', defaultDateLocale='${defaultDateLocale}' (${env.uriScheme}|${env.machineId}|${
114+
}', logLevel='${logLevel}', defaultDateLocale='${defaultDateLocale}' (${env.uriScheme}|${getMachineId()}|${
114115
env.sessionId
115116
})`,
116117
//${context.extensionRuntime !== ExtensionRuntime.Node ? ' in a webworker' : ''}

src/plus/gk/subscriptionService.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import type { RepositoriesChangeEvent } from '../../git/gitProviderService';
4848
import { executeCommand, registerCommand } from '../../system/-webview/command';
4949
import { configuration } from '../../system/-webview/configuration';
5050
import { setContext } from '../../system/-webview/context';
51+
import { getMachineId } from '../../system/-webview/machine';
5152
import { openUrl } from '../../system/-webview/vscode/uris';
5253
import { createFromDateDelta, fromNow } from '../../system/date';
5354
import { gate } from '../../system/decorators/-webview/gate';
@@ -1025,7 +1026,7 @@ export class SubscriptionService implements Disposable {
10251026
id: session.account.id,
10261027
platform: getPlatform(),
10271028
gitlensVersion: this.container.version,
1028-
machineId: env.machineId,
1029+
machineId: getMachineId(),
10291030
sessionId: env.sessionId,
10301031
vscodeEdition: env.appName,
10311032
vscodeHost: env.appHost,

src/system/-webview/machine.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { env } from 'vscode';
2+
import { getMac } from '@env/machine';
3+
import { isWeb } from '@env/platform';
4+
5+
export function getMachineId(): string {
6+
if (isWeb) {
7+
return env.machineId;
8+
}
9+
return getMac() ?? env.machineId;
10+
}

src/system/-webview/vscode.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ import { getDistributionGroup } from '../string';
88
import { satisfies } from '../version';
99
import { executeCoreCommand } from './command';
1010
import { configuration } from './configuration';
11+
import { getMachineId } from './machine';
1112
import { exists } from './vscode/uris';
1213

13-
export const deviceCohortGroup = getDistributionGroup(env.machineId);
14+
export const deviceCohortGroup = getDistributionGroup(getMachineId());
1415

1516
let _hostExecutablePath: string | undefined;
1617
export async function getHostExecutablePath(): Promise<string> {

src/telemetry/telemetry.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { getPlatform } from '@env/platform';
66
import type { Source, TelemetryEventData, TelemetryEvents, TelemetryGlobalContext } from '../constants.telemetry';
77
import type { Container } from '../container';
88
import { configuration } from '../system/-webview/configuration';
9+
import { getMachineId } from '../system/-webview/machine';
910

1011
export interface TelemetryContext {
1112
env: string;
@@ -99,7 +100,7 @@ export class TelemetryService implements Disposable {
99100
env: container.env,
100101
extensionId: container.id,
101102
extensionVersion: container.version,
102-
machineId: env.machineId,
103+
machineId: getMachineId(),
103104
sessionId: env.sessionId,
104105
language: env.language,
105106
platform: getPlatform(),

0 commit comments

Comments
 (0)