//-----------------------------------------------------------------------
//
// Copyright (c) Andrew Arnott. All rights reserved.
//
//-----------------------------------------------------------------------
namespace DotNetOpenAuth.OpenId.Extensions.UI {
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Linq;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.Xrds;
///
/// OpenID User Interface extension 1.0 request message.
///
///
/// Implements the extension described by: http://wiki.openid.net/f/openid_ui_extension_draft01.html
/// This extension only applies to checkid_setup requests, since checkid_immediate requests display
/// no UI to the user.
/// For rules about how the popup window should be displayed, please see the documentation of
/// .
/// An RP may determine whether an arbitrary OP supports this extension (and thereby determine
/// whether to use a standard full window redirect or a popup) via the
/// method.
///
[Serializable]
public class UIRequest : IOpenIdMessageExtension, IMessageWithEvents {
///
/// The factory method that may be used in deserialization of this message.
///
internal static readonly StandardOpenIdExtensionFactory.CreateDelegate Factory = (typeUri, data, baseMessage, isProviderRole) => {
if (typeUri == UIConstants.UITypeUri && isProviderRole) {
return new UIRequest();
}
return null;
};
///
/// Additional type URIs that this extension is sometimes known by remote parties.
///
private static readonly string[] additionalTypeUris = new string[] {
UIConstants.LangPrefSupported,
UIConstants.PopupSupported,
UIConstants.IconSupported,
};
///
/// Backing store for .
///
private Dictionary extraData = new Dictionary();
///
/// Initializes a new instance of the class.
///
public UIRequest() {
this.LanguagePreference = new[] { CultureInfo.CurrentUICulture };
this.Mode = UIModes.Popup;
}
///
/// Gets or sets the list of user's preferred languages, sorted in decreasing preferred order.
///
/// The default is the of the thread that created this instance.
///
/// The user's preferred languages as a [BCP 47] language priority list, represented as a comma-separated list of BCP 47 basic language ranges in descending priority order. For instance, the value "fr-CA,fr-FR,en-CA" represents the preference for French spoken in Canada, French spoken in France, followed by English spoken in Canada.
///
[SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "By design.")]
[MessagePart("lang", AllowEmpty = false)]
public CultureInfo[] LanguagePreference { get; set; }
///
/// Gets or sets the style of UI that the RP is hosting the OP's authentication page in.
///
/// Some value from the class. Defaults to .
[MessagePart("mode", AllowEmpty = false, IsRequired = true)]
public string Mode { get; set; }
///
/// Gets or sets a value indicating whether the Relying Party has an icon
/// it would like the Provider to display to the user while asking them
/// whether they would like to log in.
///
/// true if the Provider should display an icon; otherwise, false.
///
/// By default, the Provider displays the relying party's favicon.ico.
///
[MessagePart("icon", AllowEmpty = false, IsRequired = false)]
public bool? Icon { get; set; }
#region IOpenIdMessageExtension Members
///
/// Gets the TypeURI the extension uses in the OpenID protocol and in XRDS advertisements.
///
///
public string TypeUri { get { return UIConstants.UITypeUri; } }
///
/// Gets the additional TypeURIs that are supported by this extension, in preferred order.
/// May be empty if none other than is supported, but
/// should not be null.
///
///
/// Useful for reading in messages with an older version of an extension.
/// The value in the property is always checked before
/// trying this list.
/// If you do support multiple versions of an extension using this method,
/// consider adding a CreateResponse method to your request extension class
/// so that the response can have the context it needs to remain compatible
/// given the version of the extension in the request message.
/// The for an example.
///
public IEnumerable AdditionalSupportedTypeUris { get { return additionalTypeUris; } }
///
/// Gets or sets a value indicating whether this extension was
/// signed by the sender.
///
///
/// true if this instance is signed by the sender; otherwise, false.
///
public bool IsSignedByRemoteParty { get; set; }
#endregion
#region IMessage Properties
///
/// Gets the version of the protocol or extension this message is prepared to implement.
///
/// The value 1.0.
///
/// Implementations of this interface should ensure that this property never returns null.
///
public Version Version {
get { return new Version(1, 0); }
}
///
/// Gets the extra, non-standard Protocol parameters included in the message.
///
///
/// Implementations of this interface should ensure that this property never returns null.
///
public IDictionary ExtraData {
get { return this.extraData; }
}
#endregion
#region IMessage methods
///
/// Checks the message state for conformity to the protocol specification
/// and throws an exception if the message is invalid.
///
///
/// Some messages have required fields, or combinations of fields that must relate to each other
/// in specialized ways. After deserializing a message, this method checks the state of the
/// message to see if it conforms to the protocol.
/// Note that this property should not check signatures or perform any state checks
/// outside this scope of this particular message.
///
/// Thrown if the message is invalid.
public void EnsureValidMessage() {
}
#endregion
#region IMessageWithEvents Members
///
/// Called when the message is about to be transmitted,
/// before it passes through the channel binding elements.
///
public void OnSending() {
}
///
/// Called when the message has been received,
/// after it passes through the channel binding elements.
///
public void OnReceiving() {
if (this.LanguagePreference != null) {
// TODO: see if we can change the CultureInfo.CurrentUICulture somehow
}
}
#endregion
}
}