wip: policy

This commit is contained in:
João Moreno 2022-05-16 17:46:39 +02:00
parent 5eb8bee367
commit d90d07adef
No known key found for this signature in database
GPG key ID: 896B853774D1A575
6 changed files with 187 additions and 7 deletions

View file

@ -248,6 +248,7 @@
"url",
"util",
"v8-inspect-profiler",
"vscode-policy-watcher",
"vscode-proxy-agent",
"vscode-regexpp",
"vscode-textmate",

View file

@ -109,7 +109,10 @@ export class PolicyConfiguration extends Disposable {
}
async reload(): Promise<ConfigurationModel> {
await this.policyService.refresh();
if (this.policyService instanceof FilePolicyService) {
await this.policyService.refresh();
}
this.update(this.defaultConfiguration.configurationModel.keys, false);
return this._configurationModel;
}

View file

@ -12,14 +12,12 @@ export type Policies = Map<PolicyName, PolicyValue>;
export interface IPolicyService {
readonly onDidChange: Event<readonly PolicyName[]>;
initialize(): Promise<void>;
refresh(): Promise<void>;
getPolicyValue(name: PolicyName): PolicyValue | undefined;
}
export class NullPolicyService implements IPolicyService {
readonly onDidChange = Event.None;
async initialize() { }
async refresh() { }
getPolicyValue() { return undefined; }
}
@ -35,10 +33,6 @@ export class MultiPolicyService implements IPolicyService {
await Promise.all(this.policyServices.map(p => p.initialize()));
}
async refresh() {
await Promise.all(this.policyServices.map(p => p.refresh()));
}
getPolicyValue(name: PolicyName) {
for (const policyService of this.policyServices) {
const result = policyService.getPolicyValue(name);

View file

@ -0,0 +1,73 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Emitter, Event } from 'vs/base/common/event';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc';
import { IPolicyService, Policies, PolicyName, PolicyValue } from 'vs/platform/policy/common/policy';
export class PolicyChannel implements IServerChannel {
private readonly disposables = new DisposableStore();
constructor(private service: IPolicyService) { }
listen(_: unknown, event: string): Event<any> {
switch (event) {
case 'onDidChange': return Event.map(
this.service.onDidChange,
names => new Map(
names
.map(name => [name, this.service.getPolicyValue(name)])
.filter(pair => pair[1] !== undefined) as [PolicyName, PolicyValue][]),
this.disposables
);
}
throw new Error(`Event not found: ${event}`);
}
call(_: unknown, command: string): Promise<any> {
switch (command) {
case 'initialize': return this.service.initialize();
}
throw new Error(`Call not found: ${command}`);
}
dispose() {
this.disposables.dispose();
}
}
export class PolicyChannelClient implements IPolicyService {
declare readonly _serviceBrand: undefined;
private policies: Policies = new Map();
private readonly _onDidChange = new Emitter<readonly string[]>();
readonly onDidChange: Event<readonly string[]> = this._onDidChange.event;
constructor(private readonly channel: IChannel) {
this.channel.listen<Policies>('onDidChange')(policies => {
for (const [name, value] of policies) {
if (value === undefined) {
this.policies.delete(name);
} else {
this.policies.set(name, value);
}
}
});
}
initialize(): Promise<void> {
return this.channel.call('initialize');
}
getPolicyValue(name: PolicyName): PolicyValue | undefined {
return this.policies.get(name);
}
}

View file

@ -0,0 +1,30 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
declare module 'vscode-policy-watcher' {
interface Watcher {
dispose(): void;
}
interface Policies {
[policyName: string]: {
type: string
};
}
interface PolicyValues {
[policyName: string]: string | number | boolean;
}
function createWatcher(
productName: string,
policies: Policies,
onDidChange: (update: PolicyValues) => void
): Watcher;
namespace createWatcher { }
export = createWatcher;
}

View file

@ -0,0 +1,79 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Emitter } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { IPolicyService, Policies, PolicyName, PolicyValue } from 'vs/platform/policy/common/policy';
import { IProductService } from 'vs/platform/product/common/productService';
import { Registry } from 'vs/platform/registry/common/platform';
import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry';
import * as createWatcher from 'vscode-policy-watcher';
import { IStringDictionary } from 'vs/base/common/collections';
export class WindowsPolicyService extends Disposable implements IPolicyService {
private policies: Policies = new Map();
private readonly _onDidChange = new Emitter<readonly PolicyName[]>();
readonly onDidChange = this._onDidChange.event;
constructor(
@IProductService private readonly productService: IProductService
) {
super();
}
initialize(): Promise<void> {
return new Promise(c => {
if (!this.productService.win32RegValueName) {
return;
}
const policies: IStringDictionary<{ type: string }> = {};
const configRegistry = Registry.as<IConfigurationRegistry>(Extensions.Configuration);
for (const configuration of configRegistry.getConfigurations()) {
if (configuration.properties) {
for (const key in configuration.properties) {
const config = configuration.properties[key];
const policy = config.policy;
if (policy) {
if (config.type !== 'string' && config.type !== 'number') {
console.warn(`Policy ${policy.name} has unsupported type ${config.type}`);
continue;
}
policies[policy.name] = { type: config.type };
}
}
}
}
let first = true;
this._register(createWatcher(this.productService.win32RegValueName, policies, update => () => {
for (const key in update) {
this.policies.set(key, update[key]);
}
if (first) {
first = false;
c();
} else {
this._onDidChange.fire(Object.keys(update));
}
}));
});
}
async refresh(): Promise<void> {
// NOOP
}
getPolicyValue(name: PolicyName): PolicyValue | undefined {
return this.policies.get(name);
}
}