updateService.darwin.ts 5.0 KB
Newer Older
1 2 3 4 5 6 7 8 9
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

import * as electron from 'electron';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
M
Matt Bierner 已提交
10
import { Event, fromNodeEventEmitter } from 'vs/base/common/event';
11 12 13
import { memoize } from 'vs/base/common/decorators';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain';
J
Joao Moreno 已提交
14
import { State, IUpdate, StateType, UpdateType } from 'vs/platform/update/common/update';
15 16 17 18
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { ILogService } from 'vs/platform/log/common/log';
import { AbstractUpdateService, createUpdateURL } from 'vs/platform/update/electron-main/abstractUpdateService';
19
import { IRequestService } from 'vs/platform/request/node/request';
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36

export class DarwinUpdateService extends AbstractUpdateService {

	_serviceBrand: any;

	private disposables: IDisposable[] = [];

	@memoize private get onRawError(): Event<string> { return fromNodeEventEmitter(electron.autoUpdater, 'error', (_, message) => message); }
	@memoize private get onRawUpdateNotAvailable(): Event<void> { return fromNodeEventEmitter<void>(electron.autoUpdater, 'update-not-available'); }
	@memoize private get onRawUpdateAvailable(): Event<IUpdate> { return fromNodeEventEmitter(electron.autoUpdater, 'update-available', (_, url, version) => ({ url, version, productVersion: version })); }
	@memoize private get onRawUpdateDownloaded(): Event<IUpdate> { return fromNodeEventEmitter(electron.autoUpdater, 'update-downloaded', (_, releaseNotes, version, date) => ({ releaseNotes, version, productVersion: version, date })); }

	constructor(
		@ILifecycleService lifecycleService: ILifecycleService,
		@IConfigurationService configurationService: IConfigurationService,
		@ITelemetryService private telemetryService: ITelemetryService,
		@IEnvironmentService environmentService: IEnvironmentService,
37
		@IRequestService requestService: IRequestService,
38 39
		@ILogService logService: ILogService
	) {
40
		super(lifecycleService, configurationService, environmentService, requestService, logService);
41
		this.onRawError(this.onError, this, this.disposables);
42 43 44 45 46
		this.onRawUpdateAvailable(this.onUpdateAvailable, this, this.disposables);
		this.onRawUpdateDownloaded(this.onUpdateDownloaded, this, this.disposables);
		this.onRawUpdateNotAvailable(this.onUpdateNotAvailable, this, this.disposables);
	}

47 48
	private onError(err: string): void {
		this.logService.error('UpdateService error: ', err);
J
Joao Moreno 已提交
49
		this.setState(State.Idle(UpdateType.Archive));
50 51
	}

52 53
	protected buildUpdateFeedUrl(quality: string): string | undefined {
		const url = createUpdateURL('darwin', quality);
54
		try {
55
			electron.autoUpdater.setFeedURL(url);
56 57
		} catch (e) {
			// application is very likely not signed
58
			this.logService.error('Failed to set update feed URL', e);
59
			return undefined;
60
		}
61
		return url;
62 63
	}

J
Joao Moreno 已提交
64 65
	protected doCheckForUpdates(context: any): void {
		this.setState(State.CheckingForUpdates(context));
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
		electron.autoUpdater.checkForUpdates();
	}

	private onUpdateAvailable(update: IUpdate): void {
		if (this.state.type !== StateType.CheckingForUpdates) {
			return;
		}

		this.setState(State.Downloading(update));
	}

	private onUpdateDownloaded(update: IUpdate): void {
		if (this.state.type !== StateType.Downloading) {
			return;
		}

		/* __GDPR__
			"update:downloaded" : {
				"version" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
			}
		*/
		this.telemetryService.publicLog('update:downloaded', { version: update.version });

		this.setState(State.Ready(update));
	}

	private onUpdateNotAvailable(): void {
		if (this.state.type !== StateType.CheckingForUpdates) {
			return;
		}

		/* __GDPR__
				"update:notAvailable" : {
K
kieferrm 已提交
99
					"explicit" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }
100 101
				}
			*/
J
Joao Moreno 已提交
102
		this.telemetryService.publicLog('update:notAvailable', { explicit: !!this.state.context });
103

J
Joao Moreno 已提交
104
		this.setState(State.Idle(UpdateType.Archive));
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
	}

	protected doQuitAndInstall(): void {
		// for some reason updating on Mac causes the local storage not to be flushed.
		// we workaround this issue by forcing an explicit flush of the storage data.
		// see also https://github.com/Microsoft/vscode/issues/172
		this.logService.trace('update#quitAndInstall(): calling flushStorageData()');
		electron.session.defaultSession.flushStorageData();

		this.logService.trace('update#quitAndInstall(): running raw#quitAndInstall()');
		electron.autoUpdater.quitAndInstall();
	}

	dispose(): void {
		this.disposables = dispose(this.disposables);
	}
}