File: System\ServiceModel\Security\InfocardInteractiveChannelInitializer.cs
Project: ndp\cdf\src\WCF\ServiceModel\System.ServiceModel.csproj (System.ServiceModel)
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
 
namespace System.ServiceModel.Security
{
    using System.IdentityModel.Selectors;
    using System.IdentityModel.Tokens;
    using System.Runtime;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Description;
    using System.ServiceModel.Dispatcher;
 
    public class InfocardInteractiveChannelInitializer : IInteractiveChannelInitializer
    {
        ClientCredentials credentials;
        Binding binding;
 
        public InfocardInteractiveChannelInitializer(ClientCredentials credentials, Binding binding)
        {
            this.credentials = credentials;
            this.binding = binding;
        }
 
        public Binding Binding
        {
            get
            {
                return binding;
            }
        }
 
        public virtual IAsyncResult BeginDisplayInitializationUI(IClientChannel channel, AsyncCallback callback, object state)
        {
            return new GetTokenUIAsyncResult(binding, channel, this.credentials, callback, state);
        }
 
        public virtual void EndDisplayInitializationUI(IAsyncResult result)
        {
            GetTokenUIAsyncResult.End(result);
        }
 
    }
 
    internal class GetTokenUIAsyncResult : AsyncResult
    {
 
        IClientChannel proxy;
        ClientCredentials credentials;
        Uri relyingPartyIssuer;
        bool requiresInfoCard;
        Binding binding;
 
 
        static AsyncCallback callback = Fx.ThunkCallback(new AsyncCallback(GetTokenUIAsyncResult.Callback));
 
        internal GetTokenUIAsyncResult(Binding binding,
                                        IClientChannel channel,
                                        ClientCredentials credentials,
                                        AsyncCallback callback,
                                        object state)
            : base(callback, state)
        {
            this.credentials = credentials;
            this.proxy = channel;
            this.binding = binding;
            this.CallBegin(true);
 
        }
 
        void CallBegin(bool completedSynchronously)
        {
 
            IAsyncResult result = null;
            Exception exception = null;
 
            try
            {
                CardSpacePolicyElement[] chain;
                SecurityTokenManager tokenManager = credentials.CreateSecurityTokenManager();
                requiresInfoCard = InfoCardHelper.IsInfocardRequired(binding, credentials, tokenManager, proxy.RemoteAddress, out chain, out relyingPartyIssuer);
                MessageSecurityVersion bindingSecurityVersion = InfoCardHelper.GetBindingSecurityVersionOrDefault(binding);
                WSSecurityTokenSerializer tokenSerializer = WSSecurityTokenSerializer.DefaultInstance;
                result = credentials.GetInfoCardTokenCallback.BeginInvoke(requiresInfoCard, chain, tokenManager.CreateSecurityTokenSerializer(bindingSecurityVersion.SecurityTokenVersion), callback, this);
 
            }
            catch (Exception e)
            {
                if (Fx.IsFatal(e))
                {
                    throw;
                }
 
                exception = e;
            }
            if (exception == null)
            {
                if (!result.CompletedSynchronously)
                {
                    return;
                }
 
                this.CallEnd(result, out exception);
            }
            if (exception != null)
            {
                return;
            }
 
 
            this.CallComplete(completedSynchronously, null);
        }
 
        static void Callback(IAsyncResult result)
        {
            if (result.CompletedSynchronously)
            {
                return;
            }
 
            GetTokenUIAsyncResult outer = (GetTokenUIAsyncResult)result.AsyncState;
            Exception exception = null;
 
            outer.CallEnd(result, out exception);
            outer.CallComplete(false, exception);
 
        }
 
        void CallEnd(IAsyncResult result, out Exception exception)
        {
            try
            {
                SecurityToken token = credentials.GetInfoCardTokenCallback.EndInvoke(result);
 
                ChannelParameterCollection channelParameters =
                           proxy.GetProperty<ChannelParameterCollection>();
 
                if (null != channelParameters)
                {
                    channelParameters.Add(new InfoCardChannelParameter(token, relyingPartyIssuer, requiresInfoCard));
                }
                exception = null;
            }
            catch (Exception e)
            {
                if (Fx.IsFatal(e))
                {
                    throw;
                }
                exception = e;
            }
        }
 
        void CallComplete(bool completedSynchronously, Exception exception)
        {
            this.Complete(completedSynchronously, exception);
        }
 
        internal static void End(IAsyncResult result)
        {
            AsyncResult.End<GetTokenUIAsyncResult>(result);
        }
    }
}