updateService.darwin.ts 4.8 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 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
import { memoize } from 'vs/base/common/decorators';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain';
import { State, IUpdate, StateType } from 'vs/platform/update/common/update';
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';

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,
		@ILogService logService: ILogService
	) {
		super(lifecycleService, configurationService, environmentService, logService);
39
		this.onRawError(this.onError, this, this.disposables);
40 41 42 43 44
		this.onRawUpdateAvailable(this.onUpdateAvailable, this, this.disposables);
		this.onRawUpdateDownloaded(this.onUpdateDownloaded, this, this.disposables);
		this.onRawUpdateNotAvailable(this.onUpdateNotAvailable, this, this.disposables);
	}

45 46 47 48 49
	private onError(err: string): void {
		this.logService.error('UpdateService error: ', err);
		this.setState(State.Idle);
	}

50 51
	protected setUpdateFeedUrl(quality: string): boolean {
		try {
B
Benjamin Pasero 已提交
52
			electron.autoUpdater.setFeedURL({ url: createUpdateURL('darwin', quality) });
53 54
		} catch (e) {
			// application is very likely not signed
55
			this.logService.error('Failed to set update feed URL', e);
56 57 58 59 60 61
			return false;
		}

		return true;
	}

J
Joao Moreno 已提交
62 63
	protected doCheckForUpdates(context: any): void {
		this.setState(State.CheckingForUpdates(context));
64 65 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
		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 已提交
97
					"explicit" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }
98 99
				}
			*/
J
Joao Moreno 已提交
100
		this.telemetryService.publicLog('update:notAvailable', { explicit: !!this.state.context });
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119

		this.setState(State.Idle);
	}

	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);
	}
}