Skip to content

Commit 58729f2

Browse files
committed
fix(telemetry): honor vscode.env.isTelemetryEnabled in webview message handler
1 parent 06bfa8f commit 58729f2

2 files changed

Lines changed: 70 additions & 3 deletions

File tree

src/core/webview/__tests__/webviewMessageHandler.spec.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,16 @@ vi.mock("../rulesMessageHandler", () => ({
5151
handleOpenRulesDirectory: vi.fn(),
5252
}))
5353

54+
vi.mock("@roo-code/telemetry", () => ({
55+
TelemetryService: {
56+
hasInstance: vi.fn().mockReturnValue(false),
57+
instance: {
58+
updateTelemetryState: vi.fn(),
59+
captureTelemetrySettingsChanged: vi.fn(),
60+
},
61+
},
62+
}))
63+
5464
import type { ModelRecord } from "@roo-code/types"
5565

5666
import { webviewMessageHandler } from "../webviewMessageHandler"
@@ -127,6 +137,9 @@ vi.mock("vscode", () => {
127137
commands: {
128138
executeCommand: vi.fn().mockResolvedValue(undefined),
129139
},
140+
env: {
141+
isTelemetryEnabled: true,
142+
},
130143
}
131144
})
132145

@@ -1428,3 +1441,48 @@ describe("zooCodeSignOut", () => {
14281441
)
14291442
})
14301443
})
1444+
1445+
describe("webviewMessageHandler - telemetrySetting", () => {
1446+
beforeEach(() => {
1447+
vi.clearAllMocks()
1448+
vi.mocked(vscode.env).isTelemetryEnabled = true
1449+
})
1450+
1451+
// Regression test: TelemetryService.updateTelemetryState must be gated on
1452+
// vscode.env.isTelemetryEnabled in addition to the stored setting, matching
1453+
// extension.ts's onDidChangeTelemetryEnabled listener. Without this AND, a user
1454+
// clicking Accept in the webview could re-enable telemetry even while VS Code's
1455+
// global telemetry toggle is off.
1456+
it("does not enable telemetry when the user accepts but VS Code's global telemetry toggle is off", async () => {
1457+
const { TelemetryService } = await import("@roo-code/telemetry")
1458+
vi.mocked(TelemetryService.hasInstance).mockReturnValue(true)
1459+
vi.mocked(vscode.env).isTelemetryEnabled = false
1460+
vi.mocked(mockClineProvider.contextProxy.getValue).mockReturnValue(undefined)
1461+
1462+
await webviewMessageHandler(mockClineProvider, { type: "telemetrySetting", text: "enabled" })
1463+
1464+
expect(TelemetryService.instance.updateTelemetryState).toHaveBeenCalledWith(false)
1465+
})
1466+
1467+
it("enables telemetry when the user accepts and VS Code's global telemetry toggle is on", async () => {
1468+
const { TelemetryService } = await import("@roo-code/telemetry")
1469+
vi.mocked(TelemetryService.hasInstance).mockReturnValue(true)
1470+
vi.mocked(vscode.env).isTelemetryEnabled = true
1471+
vi.mocked(mockClineProvider.contextProxy.getValue).mockReturnValue(undefined)
1472+
1473+
await webviewMessageHandler(mockClineProvider, { type: "telemetrySetting", text: "enabled" })
1474+
1475+
expect(TelemetryService.instance.updateTelemetryState).toHaveBeenCalledWith(true)
1476+
})
1477+
1478+
it("keeps telemetry disabled when the user declines, regardless of VS Code's global toggle", async () => {
1479+
const { TelemetryService } = await import("@roo-code/telemetry")
1480+
vi.mocked(TelemetryService.hasInstance).mockReturnValue(true)
1481+
vi.mocked(vscode.env).isTelemetryEnabled = true
1482+
vi.mocked(mockClineProvider.contextProxy.getValue).mockReturnValue(undefined)
1483+
1484+
await webviewMessageHandler(mockClineProvider, { type: "telemetrySetting", text: "disabled" })
1485+
1486+
expect(TelemetryService.instance.updateTelemetryState).toHaveBeenCalledWith(false)
1487+
})
1488+
})

src/core/webview/webviewMessageHandler.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -631,9 +631,14 @@ export const webviewMessageHandler = async (
631631

632632
// Telemetry is on by disclosed default: "unset" (no choice made yet) leaves that
633633
// default in effect, same as "enabled". Only an explicit "disabled" opts out.
634+
// vscode.env.isTelemetryEnabled is ANDed in (matching extension.ts's
635+
// onDidChangeTelemetryEnabled listener) so a webview reload can't re-enable
636+
// telemetry while VS Code's global toggle is off.
634637
provider.getStateToPostToWebview().then((state) => {
635638
const { telemetrySetting } = state
636-
TelemetryService.instance.updateTelemetryState(isTelemetryOptedIn(telemetrySetting))
639+
TelemetryService.instance.updateTelemetryState(
640+
isTelemetryOptedIn(telemetrySetting) && vscode.env.isTelemetryEnabled,
641+
)
637642
})
638643

639644
provider.isViewLaunched = true
@@ -2470,11 +2475,15 @@ export const webviewMessageHandler = async (
24702475
TelemetryService.instance.captureTelemetrySettingsChanged(previousSetting, telemetrySetting)
24712476
}
24722477

2473-
// Update the telemetry state
2478+
// Update the telemetry state. vscode.env.isTelemetryEnabled is ANDed in
2479+
// (matching extension.ts's onDidChangeTelemetryEnabled listener) so this can't
2480+
// re-enable telemetry while VS Code's global toggle is off -- the
2481+
// captureTelemetrySettingsChanged calls above/below still track the user's
2482+
// stored preference transition on its own, independent of that live toggle.
24742483
await updateGlobalState("telemetrySetting", telemetrySetting)
24752484

24762485
if (TelemetryService.hasInstance()) {
2477-
TelemetryService.instance.updateTelemetryState(isOptedIn)
2486+
TelemetryService.instance.updateTelemetryState(isOptedIn && vscode.env.isTelemetryEnabled)
24782487
}
24792488

24802489
// If turning telemetry ON, fire event AFTER enabling

0 commit comments

Comments
 (0)