13
13
See the License for the specific language governing permissions and
14
14
limitations under the License.
15
15
*/
16
- import { ConfigurationChangeEvent , env , workspace } from "vscode" ;
16
+ import { ConfigurationChangeEvent , env , workspace , Disposable } from "vscode" ;
17
17
import { getConfigurationValue , inspectConfiguration , updateConfigurationValue } from "../../configurations/handlers" ;
18
18
import { configKeys } from "../../configurations/configuration" ;
19
19
import { appendPrefixToCommand } from "../../utils" ;
20
+ import { ExtensionContextInfo } from "../../extensionContextInfo" ;
21
+ import { TelemetryPreference } from "../types" ;
22
+ import { cacheService } from "./cacheServiceImpl" ;
23
+ import { TELEMETRY_CONSENT_POPUP_TIME_KEY , TELEMETRY_CONSENT_VERSION_SCHEMA_KEY , TELEMETRY_SETTING_VALUE_KEY } from "../constants" ;
24
+ import { TelemetryConfiguration } from "../config" ;
25
+ import { LOGGER } from "../../logger" ;
20
26
21
- export class TelemetryPrefs {
22
- public isExtTelemetryEnabled : boolean ;
27
+ export class TelemetrySettings {
28
+ private isTelemetryEnabled : boolean ;
29
+ private extensionPrefs : ExtensionTelemetryPreference ;
30
+ private vscodePrefs : VscodeTelemetryPreference ;
31
+
32
+ constructor (
33
+ extensionContext : ExtensionContextInfo ,
34
+ private onTelemetryEnableCallback : ( ) => void ,
35
+ private onTelemetryDisableCallback : ( ) => void ,
36
+ private triggerPopup : ( ) => void ) {
37
+
38
+ this . extensionPrefs = new ExtensionTelemetryPreference ( ) ;
39
+ this . vscodePrefs = new VscodeTelemetryPreference ( ) ;
40
+
41
+ extensionContext . pushSubscription (
42
+ this . extensionPrefs . onChangeTelemetrySetting ( this . onChangeTelemetrySettingCallback )
43
+ ) ;
44
+ extensionContext . pushSubscription (
45
+ this . vscodePrefs . onChangeTelemetrySetting ( this . onChangeTelemetrySettingCallback )
46
+ ) ;
47
+
48
+ this . isTelemetryEnabled = this . checkTelemetryStatus ( ) ;
49
+ this . updateGlobalState ( ) ;
50
+ this . checkConsentVersion ( ) ;
51
+ }
52
+
53
+ private checkTelemetryStatus = ( ) : boolean => this . extensionPrefs . getIsTelemetryEnabled ( ) && this . vscodePrefs . getIsTelemetryEnabled ( ) ;
54
+
55
+ private onChangeTelemetrySettingCallback = ( ) => {
56
+ const newTelemetryStatus = this . checkTelemetryStatus ( ) ;
57
+ if ( newTelemetryStatus !== this . isTelemetryEnabled ) {
58
+ this . isTelemetryEnabled = newTelemetryStatus ;
59
+ cacheService . put ( TELEMETRY_SETTING_VALUE_KEY , newTelemetryStatus . toString ( ) ) ;
60
+
61
+ if ( newTelemetryStatus ) {
62
+ this . onTelemetryEnableCallback ( ) ;
63
+ } else {
64
+ this . onTelemetryDisableCallback ( ) ;
65
+ }
66
+ } else if ( this . vscodePrefs . getIsTelemetryEnabled ( ) && ! this . extensionPrefs . isTelemetrySettingSet ( ) ) {
67
+ this . triggerPopup ( ) ;
68
+ }
69
+ }
70
+
71
+ public getIsTelemetryEnabled = ( ) : boolean => this . isTelemetryEnabled ;
72
+
73
+ public isConsentPopupToBeTriggered = ( ) : boolean => {
74
+ const isExtensionSettingSet = this . extensionPrefs . isTelemetrySettingSet ( ) ;
75
+ const isVscodeSettingEnabled = this . vscodePrefs . getIsTelemetryEnabled ( ) ;
76
+
77
+ const showPopup = ! isExtensionSettingSet && isVscodeSettingEnabled ;
78
+
79
+ if ( showPopup ) {
80
+ cacheService . put ( TELEMETRY_CONSENT_POPUP_TIME_KEY , Date . now ( ) . toString ( ) ) ;
81
+ }
82
+
83
+ return showPopup ;
84
+ }
85
+
86
+ public updateTelemetrySetting = ( value : boolean | undefined ) : void => {
87
+ this . extensionPrefs . updateTelemetryConfig ( value ) ;
88
+ }
89
+
90
+ private updateGlobalState ( ) : void {
91
+ const cachedValue = cacheService . get ( TELEMETRY_SETTING_VALUE_KEY ) ;
92
+
93
+ if ( this . isTelemetryEnabled . toString ( ) !== cachedValue ) {
94
+ cacheService . put ( TELEMETRY_SETTING_VALUE_KEY , this . isTelemetryEnabled . toString ( ) ) ;
95
+ }
96
+ }
97
+
98
+ private checkConsentVersion ( ) : void {
99
+ const cachedVersion = cacheService . get ( TELEMETRY_CONSENT_VERSION_SCHEMA_KEY ) ;
100
+ const currentVersion = TelemetryConfiguration . getInstance ( ) . getTelemetryConfigMetadata ( ) ?. consentSchemaVersion ;
101
+
102
+ if ( cachedVersion !== currentVersion ) {
103
+ cacheService . put ( TELEMETRY_CONSENT_VERSION_SCHEMA_KEY , currentVersion ) ;
104
+ LOGGER . debug ( "Removing telemetry config from user settings" ) ;
105
+ if ( this . extensionPrefs . isTelemetrySettingSet ( ) ) {
106
+ this . updateTelemetrySetting ( undefined ) ;
107
+ }
108
+ this . isTelemetryEnabled = false ;
109
+ }
110
+ }
111
+ }
112
+
113
+ class ExtensionTelemetryPreference implements TelemetryPreference {
114
+ private isTelemetryEnabled : boolean | undefined ;
115
+ private readonly CONFIG = appendPrefixToCommand ( configKeys . telemetryEnabled ) ;
23
116
24
117
constructor ( ) {
25
- this . isExtTelemetryEnabled = this . checkTelemetryStatus ( ) ;
118
+ this . isTelemetryEnabled = getConfigurationValue ( configKeys . telemetryEnabled , false ) ;
26
119
}
27
120
28
- private checkTelemetryStatus = ( ) : boolean => {
29
- return getConfigurationValue ( configKeys . telemetryEnabled , false ) ;
121
+ public getIsTelemetryEnabled = ( ) : boolean => this . isTelemetryEnabled === undefined ? false : this . isTelemetryEnabled ;
122
+
123
+ public onChangeTelemetrySetting = ( callback : ( ) => void ) : Disposable => workspace . onDidChangeConfiguration ( ( e : ConfigurationChangeEvent ) => {
124
+ if ( e . affectsConfiguration ( this . CONFIG ) ) {
125
+ this . isTelemetryEnabled = getConfigurationValue ( configKeys . telemetryEnabled , false ) ;
126
+ callback ( ) ;
127
+ }
128
+ } ) ;
129
+
130
+ public updateTelemetryConfig = ( value : boolean | undefined ) : void => {
131
+ this . isTelemetryEnabled = value ;
132
+ updateConfigurationValue ( configKeys . telemetryEnabled , value , true ) ;
30
133
}
31
134
32
- private configPref = ( configCommand : string ) : boolean => {
33
- const config = inspectConfiguration ( configCommand ) ;
135
+ public isTelemetrySettingSet = ( ) : boolean => {
136
+ if ( this . isTelemetryEnabled === undefined ) return false ;
137
+ const config = inspectConfiguration ( this . CONFIG ) ;
34
138
return (
35
- config ?. workspaceFolderValue !== undefined ||
36
- config ?. workspaceFolderLanguageValue !== undefined ||
37
- config ?. workspaceValue !== undefined ||
38
- config ?. workspaceLanguageValue !== undefined ||
39
139
config ?. globalValue !== undefined ||
40
140
config ?. globalLanguageValue !== undefined
41
141
) ;
42
142
}
143
+ }
43
144
44
- public isExtTelemetryConfigured = ( ) : boolean => {
45
- return this . configPref ( appendPrefixToCommand ( configKeys . telemetryEnabled ) ) ;
46
- }
145
+ class VscodeTelemetryPreference implements TelemetryPreference {
146
+ private isTelemetryEnabled : boolean ;
47
147
48
- public updateTelemetryEnabledConfig = ( value : boolean ) : void => {
49
- this . isExtTelemetryEnabled = value ;
50
- updateConfigurationValue ( configKeys . telemetryEnabled , value , true ) ;
148
+ constructor ( ) {
149
+ this . isTelemetryEnabled = env . isTelemetryEnabled ;
51
150
}
52
151
53
- public didUserDisableVscodeTelemetry = ( ) : boolean => {
54
- return ! env . isTelemetryEnabled ;
55
- }
152
+ public getIsTelemetryEnabled = ( ) : boolean => this . isTelemetryEnabled ;
56
153
57
- public onDidChangeTelemetryEnabled = ( ) => workspace . onDidChangeConfiguration (
58
- ( e : ConfigurationChangeEvent ) => {
59
- if ( e . affectsConfiguration ( appendPrefixToCommand ( configKeys . telemetryEnabled ) ) ) {
60
- this . isExtTelemetryEnabled = this . checkTelemetryStatus ( ) ;
61
- }
62
- }
63
- ) ;
64
- }
154
+ public onChangeTelemetrySetting = ( callback : ( ) => void ) : Disposable => env . onDidChangeTelemetryEnabled ( ( newSetting : boolean ) => {
155
+ this . isTelemetryEnabled = newSetting ;
156
+ callback ( ) ;
157
+ } ) ;
158
+ }
159
+
160
+ // Question:
161
+ // When consent version is changed, we have to show popup to all the users or only those who had accepted earlier?
162
+
163
+ // Test cases:
164
+ // 1. User accepts consent and VSCode telemetry is set to 'all'. Output: enabled telemetry
165
+ // 2. User accepts consent and VSCode telemetry is not set to 'all'. Output: disabled telemetry
166
+ // 3. User rejects consent and VSCode telemetry is set to 'all'. Output: disabled telemetry
167
+ // 4. User rejects consent and VSCode telemetry is not set to 'all'. Output: disabled telemetry
168
+ // 5. User changes from accept to reject consent and VSCode telemetry is set to 'all'. Output: disabled telemetry
169
+ // 6. User changes from accept to reject consent and VSCode telemetry is not set to 'all'. Output: disabled telemetry
170
+ // 7. User changes from reject to accept consent and VSCode telemetry is set to 'all'. Output: enabled telemetry
171
+ // 8. User changes from reject to accept consent and VSCode telemetry is not set to 'all'. Output: disabled telemetry
172
+ // 9. User accepts consent and VSCode telemetry is changed from 'all' to 'error'. Output: disabled telemetry
173
+ // 10. User accepts consent and VSCode telemetry is changed from 'error' to 'all'. Output: enabled telemetry
174
+ // 11. When consent schema version updated, pop up should trigger again.
175
+ // 12. When consent schema version updated, pop up should trigger again, if closed without selecting any value and again reloading the screen, it should pop-up again.: Disabled telemetry in settings
176
+ // 13. When consent schema version updated, pop up should trigger again, if selected yes and again reloading the screen, it shouldn't pop-up again. Output: Enabled telemetry in settings
177
+ // 14. When consent schema version updated, pop up should trigger again, if selected no and again reloading the screen, it shouldn't pop-up again. Output: Disabled telemetry in settings
178
+ // 15. When VSCode setting is changed from reject to accept, our pop-up should come.
0 commit comments