提交 998a65e2 编写于 作者: B Benjamin Pasero

web - best lifecycle support we can do currently

上级 4118892a
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ShutdownReason, ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { ILogService } from 'vs/platform/log/common/log';
import { AbstractLifecycleService } from 'vs/platform/lifecycle/common/lifecycleService';
import { localize } from 'vs/nls';
import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
export class BrowserLifecycleService extends AbstractLifecycleService {
_serviceBrand: ServiceIdentifier<ILifecycleService>;
constructor(
@ILogService readonly logService: ILogService
) {
super(logService);
this.registerListeners();
}
private registerListeners(): void {
window.onbeforeunload = () => this.beforeUnload();
}
private beforeUnload(): string | null {
let veto: boolean = false;
// Before Shutdown
this._onBeforeShutdown.fire({
veto(value) {
if (value === true) {
veto = true;
} else if (value instanceof Promise && !veto) {
console.warn(new Error('Long running onBeforeShutdown currently not supported'));
}
},
reason: ShutdownReason.QUIT
});
// Veto: signal back to browser by returning a non-falsify return value
if (veto) {
return localize('lifecycleVeto', "Changes that you made may not be saved. Please check press 'Cancel' and try again.");
}
// No Veto: continue with Will Shutdown
this._onWillShutdown.fire({
join() {
console.warn(new Error('Long running onWillShutdown currently not supported'));
},
reason: ShutdownReason.QUIT
});
return null;
}
}
\ No newline at end of file
...@@ -9,10 +9,11 @@ import { Disposable } from 'vs/base/common/lifecycle'; ...@@ -9,10 +9,11 @@ import { Disposable } from 'vs/base/common/lifecycle';
import { ILifecycleService, BeforeShutdownEvent, WillShutdownEvent, StartupKind, LifecyclePhase, LifecyclePhaseToString } from 'vs/platform/lifecycle/common/lifecycle'; import { ILifecycleService, BeforeShutdownEvent, WillShutdownEvent, StartupKind, LifecyclePhase, LifecyclePhaseToString } from 'vs/platform/lifecycle/common/lifecycle';
import { ILogService } from 'vs/platform/log/common/log'; import { ILogService } from 'vs/platform/log/common/log';
import { mark } from 'vs/base/common/performance'; import { mark } from 'vs/base/common/performance';
import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
export abstract class AbstractLifecycleService extends Disposable implements ILifecycleService { export abstract class AbstractLifecycleService extends Disposable implements ILifecycleService {
_serviceBrand: any; _serviceBrand: ServiceIdentifier<ILifecycleService>;
protected readonly _onBeforeShutdown = this._register(new Emitter<BeforeShutdownEvent>()); protected readonly _onBeforeShutdown = this._register(new Emitter<BeforeShutdownEvent>());
get onBeforeShutdown(): Event<BeforeShutdownEvent> { return this._onBeforeShutdown.event; } get onBeforeShutdown(): Event<BeforeShutdownEvent> { return this._onBeforeShutdown.event; }
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { toErrorMessage } from 'vs/base/common/errorMessage'; import { toErrorMessage } from 'vs/base/common/errorMessage';
import { ShutdownReason, StartupKind, handleVetos } from 'vs/platform/lifecycle/common/lifecycle'; import { ShutdownReason, StartupKind, handleVetos, ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { ipcRenderer as ipc } from 'electron'; import { ipcRenderer as ipc } from 'electron';
import { IWindowService } from 'vs/platform/windows/common/windows'; import { IWindowService } from 'vs/platform/windows/common/windows';
...@@ -12,12 +12,13 @@ import { ILogService } from 'vs/platform/log/common/log'; ...@@ -12,12 +12,13 @@ import { ILogService } from 'vs/platform/log/common/log';
import { INotificationService } from 'vs/platform/notification/common/notification'; import { INotificationService } from 'vs/platform/notification/common/notification';
import { onUnexpectedError } from 'vs/base/common/errors'; import { onUnexpectedError } from 'vs/base/common/errors';
import { AbstractLifecycleService } from 'vs/platform/lifecycle/common/lifecycleService'; import { AbstractLifecycleService } from 'vs/platform/lifecycle/common/lifecycleService';
import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
export class LifecycleService extends AbstractLifecycleService { export class LifecycleService extends AbstractLifecycleService {
private static readonly LAST_SHUTDOWN_REASON_KEY = 'lifecyle.lastShutdownReason'; private static readonly LAST_SHUTDOWN_REASON_KEY = 'lifecyle.lastShutdownReason';
_serviceBrand: any; _serviceBrand: ServiceIdentifier<ILifecycleService>;
private shutdownReason: ShutdownReason; private shutdownReason: ShutdownReason;
......
...@@ -131,7 +131,7 @@ export const enum LifecycleMainPhase { ...@@ -131,7 +131,7 @@ export const enum LifecycleMainPhase {
export class LifecycleService extends Disposable implements ILifecycleService { export class LifecycleService extends Disposable implements ILifecycleService {
_serviceBrand: any; _serviceBrand: ServiceIdentifier<ILifecycleService>;
private static readonly QUIT_FROM_RESTART_MARKER = 'quit.from.restart'; // use a marker to find out if the session was restarted private static readonly QUIT_FROM_RESTART_MARKER = 'quit.from.restart'; // use a marker to find out if the session was restarted
......
...@@ -75,7 +75,8 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews ...@@ -75,7 +75,8 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews
})); }));
this._register(lifecycleService.onBeforeShutdown(e => { this._register(lifecycleService.onBeforeShutdown(e => {
e.veto(this._onBeforeShutdown()); this._onBeforeShutdown();
e.veto(false); // Don't veto shutdown
}, this)); }, this));
} }
...@@ -217,13 +218,12 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews ...@@ -217,13 +218,12 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews
return `mainThreadWebview-${viewType}`; return `mainThreadWebview-${viewType}`;
} }
private _onBeforeShutdown(): boolean { private _onBeforeShutdown(): void {
this._webviews.forEach((webview) => { this._webviews.forEach((webview) => {
if (!webview.isDisposed() && webview.state && this._revivers.has(webview.state.viewType)) { if (!webview.isDisposed() && webview.state && this._revivers.has(webview.state.viewType)) {
webview.state.state = webview.webviewState; webview.state.state = webview.webviewState;
} }
}); });
return false; // Don't veto shutdown
} }
private createWebviewEventDelegate(handle: WebviewPanelHandle) { private createWebviewEventDelegate(handle: WebviewPanelHandle) {
......
...@@ -21,9 +21,8 @@ import { IPager } from 'vs/base/common/paging'; ...@@ -21,9 +21,8 @@ import { IPager } from 'vs/base/common/paging';
import { IExtensionManifest, ExtensionType, ExtensionIdentifier, IExtension } from 'vs/platform/extensions/common/extensions'; import { IExtensionManifest, ExtensionType, ExtensionIdentifier, IExtension } from 'vs/platform/extensions/common/extensions';
import { IURLHandler, IURLService } from 'vs/platform/url/common/url'; import { IURLHandler, IURLService } from 'vs/platform/url/common/url';
import { ITelemetryService, ITelemetryData, ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry'; import { ITelemetryService, ITelemetryData, ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
import { AbstractLifecycleService } from 'vs/platform/lifecycle/common/lifecycleService'; import { LogLevel, ConsoleLogService } from 'vs/platform/log/common/log';
import { ILogService, LogLevel, ConsoleLogService } from 'vs/platform/log/common/log'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { ShutdownReason, ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { IProductService } from 'vs/platform/product/common/product'; import { IProductService } from 'vs/platform/product/common/product';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { IStorageService, IWorkspaceStorageChangeEvent, StorageScope, IWillSaveStateEvent, WillSaveStateReason } from 'vs/platform/storage/common/storage'; import { IStorageService, IWorkspaceStorageChangeEvent, StorageScope, IWillSaveStateEvent, WillSaveStateReason } from 'vs/platform/storage/common/storage';
...@@ -518,55 +517,6 @@ registerSingleton(IExtensionUrlHandler, SimpleExtensionURLHandler, true); ...@@ -518,55 +517,6 @@ registerSingleton(IExtensionUrlHandler, SimpleExtensionURLHandler, true);
//#endregion //#endregion
//#region Lifecycle
export class SimpleLifecycleService extends AbstractLifecycleService {
_serviceBrand: any;
constructor(
@ILogService readonly logService: ILogService
) {
super(logService);
this.registerListeners();
}
private registerListeners(): void {
window.onbeforeunload = () => this.beforeUnload();
}
private beforeUnload(): string {
// Before Shutdown
this._onBeforeShutdown.fire({
veto(value) {
if (value === true) {
console.warn(new Error('Preventing onBeforeUnload currently not supported'));
} else if (value instanceof Promise) {
console.warn(new Error('Long running onBeforeShutdown currently not supported'));
}
},
reason: ShutdownReason.QUIT
});
// Will Shutdown
this._onWillShutdown.fire({
join() {
console.warn(new Error('Long running onWillShutdown currently not supported'));
},
reason: ShutdownReason.QUIT
});
// @ts-ignore
return null;
}
}
registerSingleton(ILifecycleService, SimpleLifecycleService);
//#endregion
//#region Log //#region Log
export class SimpleLogService extends ConsoleLogService { } export class SimpleLogService extends ConsoleLogService { }
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
import { TextFileService } from 'vs/workbench/services/textfile/common/textFileService'; import { TextFileService } from 'vs/workbench/services/textfile/common/textFileService';
import { ITextFileService, IResourceEncodings, IResourceEncoding } from 'vs/workbench/services/textfile/common/textfiles'; import { ITextFileService, IResourceEncodings, IResourceEncoding } from 'vs/workbench/services/textfile/common/textfiles';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { ShutdownReason } from 'vs/platform/lifecycle/common/lifecycle';
export class BrowserTextFileService extends TextFileService { export class BrowserTextFileService extends TextFileService {
...@@ -14,6 +15,19 @@ export class BrowserTextFileService extends TextFileService { ...@@ -14,6 +15,19 @@ export class BrowserTextFileService extends TextFileService {
return { encoding: 'utf8', hasBOM: false }; return { encoding: 'utf8', hasBOM: false };
} }
}; };
protected beforeShutdown(reason: ShutdownReason): boolean | Promise<boolean> {
const veto = super.beforeShutdown(reason);
// Web: there is no support for long running unload handlers. As such
// we need to return a direct boolean veto when we detect that there
// are dirty files around.
if (veto instanceof Promise) {
return this.getDirty().length > 0;
}
return veto;
}
} }
registerSingleton(ITextFileService, BrowserTextFileService); registerSingleton(ITextFileService, BrowserTextFileService);
\ No newline at end of file
...@@ -119,7 +119,7 @@ export abstract class TextFileService extends Disposable implements ITextFileSer ...@@ -119,7 +119,7 @@ export abstract class TextFileService extends Disposable implements ITextFileSer
})); }));
} }
private beforeShutdown(reason: ShutdownReason): boolean | Promise<boolean> { protected beforeShutdown(reason: ShutdownReason): boolean | Promise<boolean> {
// Dirty files need treatment on shutdown // Dirty files need treatment on shutdown
const dirty = this.getDirty(); const dirty = this.getDirty();
......
...@@ -57,14 +57,16 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { ...@@ -57,14 +57,16 @@ export class WorkspaceEditingService implements IWorkspaceEditingService {
@ILifecycleService readonly lifecycleService: ILifecycleService, @ILifecycleService readonly lifecycleService: ILifecycleService,
@ILabelService readonly labelService: ILabelService @ILabelService readonly labelService: ILabelService
) { ) {
this.registerListeners();
}
lifecycleService.onBeforeShutdown(async e => { private registerListeners(): void {
this.lifecycleService.onBeforeShutdown(async e => {
const saveOperation = this.saveUntitedBeforeShutdown(e.reason); const saveOperation = this.saveUntitedBeforeShutdown(e.reason);
if (saveOperation) { if (saveOperation) {
e.veto(saveOperation); e.veto(saveOperation);
} }
}); });
} }
private async saveUntitedBeforeShutdown(reason: ShutdownReason): Promise<boolean> { private async saveUntitedBeforeShutdown(reason: ShutdownReason): Promise<boolean> {
......
...@@ -68,8 +68,8 @@ import { ContextViewService } from 'vs/platform/contextview/browser/contextViewS ...@@ -68,8 +68,8 @@ import { ContextViewService } from 'vs/platform/contextview/browser/contextViewS
// import { ExtensionGalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService'; // import { ExtensionGalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService';
// import { IRequestService } from 'vs/platform/request/node/request'; // import { IRequestService } from 'vs/platform/request/node/request';
// import { RequestService } from 'vs/platform/request/electron-browser/requestService'; // import { RequestService } from 'vs/platform/request/electron-browser/requestService';
// import { LifecycleService } from 'vs/platform/lifecycle/electron-browser/lifecycleService'; import { BrowserLifecycleService } from 'vs/platform/lifecycle/browser/lifecycleService';
// import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
// import { ILocalizationsService } from 'vs/platform/localizations/common/localizations'; // import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
// import { LocalizationsService } from 'vs/platform/localizations/electron-browser/localizationsService'; // import { LocalizationsService } from 'vs/platform/localizations/electron-browser/localizationsService';
// import { ISharedProcessService, SharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; // import { ISharedProcessService, SharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
...@@ -152,7 +152,7 @@ registerSingleton(IAccessibilityService, BrowserAccessibilityService, true); ...@@ -152,7 +152,7 @@ registerSingleton(IAccessibilityService, BrowserAccessibilityService, true);
registerSingleton(IContextViewService, ContextViewService, true); registerSingleton(IContextViewService, ContextViewService, true);
// registerSingleton(IExtensionGalleryService, ExtensionGalleryService, true); // registerSingleton(IExtensionGalleryService, ExtensionGalleryService, true);
// registerSingleton(IRequestService, RequestService, true); // registerSingleton(IRequestService, RequestService, true);
// registerSingleton(ILifecycleService, LifecycleService); registerSingleton(ILifecycleService, BrowserLifecycleService);
// registerSingleton(ILocalizationsService, LocalizationsService); // registerSingleton(ILocalizationsService, LocalizationsService);
// registerSingleton(ISharedProcessService, SharedProcessService, true); // registerSingleton(ISharedProcessService, SharedProcessService, true);
// registerSingleton(IProductService, ProductService, true); // registerSingleton(IProductService, ProductService, true);
...@@ -238,7 +238,6 @@ import 'vs/workbench/contrib/debug/browser/repl'; ...@@ -238,7 +238,6 @@ import 'vs/workbench/contrib/debug/browser/repl';
import 'vs/workbench/contrib/debug/browser/debugViewlet'; import 'vs/workbench/contrib/debug/browser/debugViewlet';
import 'vs/workbench/contrib/debug/browser/debugHelperService'; import 'vs/workbench/contrib/debug/browser/debugHelperService';
// Markers // Markers
import 'vs/workbench/contrib/markers/browser/markers.contribution'; import 'vs/workbench/contrib/markers/browser/markers.contribution';
...@@ -288,7 +287,6 @@ import { TaskService } from 'vs/workbench/contrib/tasks/browser/taskService'; ...@@ -288,7 +287,6 @@ import { TaskService } from 'vs/workbench/contrib/tasks/browser/taskService';
import { ITaskService } from 'vs/workbench/contrib/tasks/common/taskService'; import { ITaskService } from 'vs/workbench/contrib/tasks/common/taskService';
registerSingleton(ITaskService, TaskService, true); registerSingleton(ITaskService, TaskService, true);
// Remote // Remote
import 'vs/workbench/contrib/remote/common/remote.contribution'; import 'vs/workbench/contrib/remote/common/remote.contribution';
// import 'vs/workbench/contrib/remote/electron-browser/remote.contribution'; // import 'vs/workbench/contrib/remote/electron-browser/remote.contribution';
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册