|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Immutable;
using System.Diagnostics;
using Microsoft.CodeAnalysis.LanguageServer.BrokeredServices.Services;
using Microsoft.ServiceHub.Framework;
using Microsoft.ServiceHub.Framework.Services;
using Microsoft.VisualStudio.Composition;
using Microsoft.VisualStudio.Threading;
using Microsoft.VisualStudio.Utilities.ServiceBroker;
namespace Microsoft.CodeAnalysis.LanguageServer.BrokeredServices;
internal class BrokeredServiceContainer : GlobalBrokeredServiceContainer
{
public BrokeredServiceContainer(TraceSource traceSource)
: base(ImmutableDictionary<ServiceMoniker, ServiceRegistration>.Empty, isClientOfExclusiveServer: false, joinableTaskFactory: null, traceSource)
{
}
public override IReadOnlyDictionary<string, string> LocalUserCredentials
=> ImmutableDictionary<string, string>.Empty;
/// <inheritdoc cref="GlobalBrokeredServiceContainer.RegisterServices(IReadOnlyDictionary{ServiceMoniker, ServiceRegistration})"/>
internal new void RegisterServices(IReadOnlyDictionary<ServiceMoniker, ServiceRegistration> services)
=> base.RegisterServices(services);
/// <inheritdoc cref="GlobalBrokeredServiceContainer.UnregisterServices(IEnumerable{ServiceMoniker})"/>
internal new void UnregisterServices(IEnumerable<ServiceMoniker> services)
=> base.UnregisterServices(services);
internal ImmutableDictionary<ServiceMoniker, ServiceRegistration> GetRegisteredServices()
=> RegisteredServices;
internal static async Task<BrokeredServiceContainer> CreateAsync(ExportProvider exportProvider, CancellationToken cancellationToken)
{
var traceListener = exportProvider.GetExportedValue<BrokeredServiceTraceListener>();
var container = new BrokeredServiceContainer(traceListener.Source);
container.ProfferIntrinsicService(
FrameworkServices.Authorization,
new ServiceRegistration(VisualStudio.Shell.ServiceBroker.ServiceAudience.Local, null, allowGuestClients: true),
(moniker, options, serviceBroker, cancellationToken) => new(new NoOpAuthorizationService()));
var mefServiceBroker = exportProvider.GetExportedValue<MefServiceBrokerOfExportedServices>();
mefServiceBroker.SetContainer(container);
// Register local mef services.
await mefServiceBroker.RegisterAndProfferServicesAsync(cancellationToken);
// Register the desired remote services
container.RegisterServices(Descriptors.RemoteServicesToRegister);
return container;
}
private class NoOpAuthorizationService : IAuthorizationService
{
public event EventHandler? CredentialsChanged;
public event EventHandler? AuthorizationChanged;
public ValueTask<bool> CheckAuthorizationAsync(ProtectedOperation operation, CancellationToken cancellationToken = default)
{
return new(true);
}
public ValueTask<IReadOnlyDictionary<string, string>> GetCredentialsAsync(CancellationToken cancellationToken = default)
{
return new(ImmutableDictionary<string, string>.Empty);
}
protected virtual void OnCredentialsChanged(EventArgs args) => this.CredentialsChanged?.Invoke(this, args);
protected virtual void OnAuthorizationChanged(EventArgs args) => this.AuthorizationChanged?.Invoke(this, args);
}
}
|