Allow globalState to be synchronized across multiple windows (#61024)

* Allow globalState to be synchronized across multiple windows (fixes #55834)

* address some feedback
This commit is contained in:
Benjamin Pasero
2018-10-16 18:52:50 +02:00
committed by GitHub
parent c8e7e58cd0
commit 2ce9665b30
5 changed files with 74 additions and 20 deletions

View File

@@ -62,6 +62,7 @@ import { ExtHostSearch } from './extHostSearch';
import { ExtHostUrls } from './extHostUrls';
import { localize } from 'vs/nls';
import { ExtHostClipboard } from 'vs/workbench/api/node/extHostClipboard';
import { ExtHostStorage } from 'vs/workbench/api/node/extHostStorage';
export interface IExtensionApiFactory {
(extension: IExtensionDescription): typeof vscode;
@@ -94,7 +95,8 @@ export function createApiFactory(
extHostWorkspace: ExtHostWorkspace,
extHostConfiguration: ExtHostConfiguration,
extensionService: ExtHostExtensionService,
extHostLogService: ExtHostLogService
extHostLogService: ExtHostLogService,
extHostStorage: ExtHostStorage
): IExtensionApiFactory {
let schemeTransformer: ISchemeTransformer | null = null;
@@ -129,6 +131,7 @@ export function createApiFactory(
const extHostProgress = rpcProtocol.set(ExtHostContext.ExtHostProgress, new ExtHostProgress(rpcProtocol.getProxy(MainContext.MainThreadProgress)));
const exthostCommentProviders = rpcProtocol.set(ExtHostContext.ExtHostComments, new ExtHostComments(rpcProtocol, extHostCommands.converter, extHostDocuments));
const extHostOutputService = rpcProtocol.set(ExtHostContext.ExtHostOutputService, new ExtHostOutputService(initData.logsLocation, rpcProtocol));
rpcProtocol.set(ExtHostContext.ExtHostStorage, extHostStorage);
// Check that no named customers are missing
const expected: ProxyIdentifier<any>[] = Object.keys(ExtHostContext).map((key) => (<any>ExtHostContext)[key]);

View File

@@ -430,7 +430,7 @@ export interface MainThreadStatusBarShape extends IDisposable {
export interface MainThreadStorageShape extends IDisposable {
$getValue<T>(shared: boolean, key: string): Thenable<T>;
$setValue(shared: boolean, key: string, value: any): Thenable<void>;
$setValue(shared: boolean, key: string, value: object): Thenable<void>;
}
export interface MainThreadTelemetryShape extends IDisposable {
@@ -1016,6 +1016,10 @@ export interface ExtHostCommentsShape {
$provideWorkspaceComments(handle: number): Thenable<modes.CommentThread[]>;
}
export interface ExtHostStorageShape {
$acceptValue(shared: boolean, key: string, value: object): void;
}
// --- proxy identifiers
export const MainContext = {
@@ -1081,6 +1085,7 @@ export const ExtHostContext = {
ExtHostWebviews: createExtId<ExtHostWebviewsShape>('ExtHostWebviews'),
ExtHostProgress: createMainId<ExtHostProgressShape>('ExtHostProgress'),
ExtHostComments: createMainId<ExtHostCommentsShape>('ExtHostComments'),
ExtHostStorage: createMainId<ExtHostStorageShape>('ExtHostStorage'),
ExtHostUrls: createExtId<ExtHostUrlsShape>('ExtHostUrls'),
ExtHostOutputService: createMainId<ExtHostOutputServiceShape>('ExtHostOutputService'),
};

View File

@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { dispose } from 'vs/base/common/lifecycle';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { join } from 'path';
import { mkdirp, dirExists, realpath, writeFile } from 'vs/base/node/pfs';
import Severity from 'vs/base/common/severity';
@@ -30,6 +30,7 @@ class ExtensionMemento implements IExtensionMemento {
private readonly _init: Thenable<ExtensionMemento>;
private _value: { [n: string]: any; };
private readonly _storageListener: IDisposable;
constructor(id: string, global: boolean, storage: ExtHostStorage) {
this._id = id;
@@ -40,6 +41,12 @@ class ExtensionMemento implements IExtensionMemento {
this._value = value;
return this;
});
this._storageListener = this._storage.onDidChangeStorage(e => {
if (e.shared === this._shared && e.key === this._id) {
this._value = e.value;
}
});
}
get whenReady(): Thenable<ExtensionMemento> {
@@ -60,6 +67,10 @@ class ExtensionMemento implements IExtensionMemento {
.setValue(this._shared, this._id, this._value)
.then(() => true);
}
dispose(): void {
this._storageListener.dispose();
}
}
class ExtensionStoragePath {
@@ -150,7 +161,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
this._activator = null;
// initialize API first (i.e. do not release barrier until the API is initialized)
const apiFactory = createApiFactory(initData, extHostContext, extHostWorkspace, extHostConfiguration, this, this._extHostLogService);
const apiFactory = createApiFactory(initData, extHostContext, extHostWorkspace, extHostConfiguration, this, this._extHostLogService, this._storage);
initializeExtensionApi(this, apiFactory).then(() => {

View File

@@ -3,12 +3,22 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { MainContext, MainThreadStorageShape, IMainContext } from './extHost.protocol';
import { MainContext, MainThreadStorageShape, IMainContext, ExtHostStorageShape } from './extHost.protocol';
import { Emitter } from 'vs/base/common/event';
export class ExtHostStorage {
export interface IStorageChangeEvent {
shared: boolean;
key: string;
value: object;
}
export class ExtHostStorage implements ExtHostStorageShape {
private _proxy: MainThreadStorageShape;
private _onDidChangeStorage = new Emitter<IStorageChangeEvent>();
readonly onDidChangeStorage = this._onDidChangeStorage.event;
constructor(mainContext: IMainContext) {
this._proxy = mainContext.getProxy(MainContext.MainThreadStorage);
}
@@ -17,7 +27,11 @@ export class ExtHostStorage {
return this._proxy.$getValue<T>(shared, key).then(value => value || defaultValue);
}
setValue(shared: boolean, key: string, value: any): Thenable<void> {
setValue(shared: boolean, key: string, value: object): Thenable<void> {
return this._proxy.$setValue(shared, key, value);
}
$acceptValue(shared: boolean, key: string, value: object): void {
this._onDidChangeStorage.fire({ shared, key, value });
}
}