SEBWIN-301: Switched from interface to data container for session configuration (separated client and service session configuration) and implemented mapping of service policy including the respective message boxes.

This commit is contained in:
dbuechel 2019-06-11 09:53:33 +02:00
parent 73c7e28a33
commit e9d91cb898
45 changed files with 319 additions and 237 deletions

View file

@ -49,7 +49,7 @@ namespace SafeExamBrowser.Client.UnitTests.Communication
{ {
var token = Guid.NewGuid(); var token = Guid.NewGuid();
sut.StartupToken = token; sut.AuthenticationToken = token;
var response = sut.Connect(token); var response = sut.Connect(token);
@ -64,7 +64,7 @@ namespace SafeExamBrowser.Client.UnitTests.Communication
{ {
var token = Guid.NewGuid(); var token = Guid.NewGuid();
sut.StartupToken = token; sut.AuthenticationToken = token;
var response = sut.Connect(Guid.NewGuid()); var response = sut.Connect(Guid.NewGuid());
@ -78,7 +78,7 @@ namespace SafeExamBrowser.Client.UnitTests.Communication
{ {
var token = Guid.NewGuid(); var token = Guid.NewGuid();
sut.StartupToken = token; sut.AuthenticationToken = token;
var response1 = sut.Connect(token); var response1 = sut.Connect(token);
var response2 = sut.Connect(token); var response2 = sut.Connect(token);
@ -102,7 +102,7 @@ namespace SafeExamBrowser.Client.UnitTests.Communication
var token = Guid.NewGuid(); var token = Guid.NewGuid();
sut.RuntimeDisconnected += () => eventFired = true; sut.RuntimeDisconnected += () => eventFired = true;
sut.StartupToken = token; sut.AuthenticationToken = token;
var connectionResponse = sut.Connect(token); var connectionResponse = sut.Connect(token);
var response = sut.Disconnect(new DisconnectionMessage { CommunicationToken = connectionResponse.CommunicationToken.Value }); var response = sut.Disconnect(new DisconnectionMessage { CommunicationToken = connectionResponse.CommunicationToken.Value });
@ -116,11 +116,11 @@ namespace SafeExamBrowser.Client.UnitTests.Communication
[TestMethod] [TestMethod]
public void MustNotAllowReconnectionAfterDisconnection() public void MustNotAllowReconnectionAfterDisconnection()
{ {
var token = sut.StartupToken = Guid.NewGuid(); var token = sut.AuthenticationToken = Guid.NewGuid();
var response = sut.Connect(token); var response = sut.Connect(token);
sut.Disconnect(new DisconnectionMessage { CommunicationToken = response.CommunicationToken.Value }); sut.Disconnect(new DisconnectionMessage { CommunicationToken = response.CommunicationToken.Value });
sut.StartupToken = token = Guid.NewGuid(); sut.AuthenticationToken = token = Guid.NewGuid();
response = sut.Connect(token); response = sut.Connect(token);
@ -130,7 +130,7 @@ namespace SafeExamBrowser.Client.UnitTests.Communication
[TestMethod] [TestMethod]
public void MustHandleAuthenticationRequestCorrectly() public void MustHandleAuthenticationRequestCorrectly()
{ {
sut.StartupToken = Guid.Empty; sut.AuthenticationToken = Guid.Empty;
var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var token = sut.Connect(Guid.Empty).CommunicationToken.Value;
var message = new SimpleMessage(SimpleMessagePurport.Authenticate) { CommunicationToken = token }; var message = new SimpleMessage(SimpleMessagePurport.Authenticate) { CommunicationToken = token };
@ -157,7 +157,7 @@ namespace SafeExamBrowser.Client.UnitTests.Communication
messageBoxRequested = args.Action == action && args.Icon == icon && args.Message == message && args.RequestId == requestId && args.Title == title; messageBoxRequested = args.Action == action && args.Icon == icon && args.Message == message && args.RequestId == requestId && args.Title == title;
resetEvent.Set(); resetEvent.Set();
}; };
sut.StartupToken = Guid.Empty; sut.AuthenticationToken = Guid.Empty;
var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var token = sut.Connect(Guid.Empty).CommunicationToken.Value;
var request = new MessageBoxRequestMessage(action, icon, message, requestId, title) { CommunicationToken = token }; var request = new MessageBoxRequestMessage(action, icon, message, requestId, title) { CommunicationToken = token };
@ -184,7 +184,7 @@ namespace SafeExamBrowser.Client.UnitTests.Communication
passwordRequested = args.Purpose == purpose && args.RequestId == requestId; passwordRequested = args.Purpose == purpose && args.RequestId == requestId;
resetEvent.Set(); resetEvent.Set();
}; };
sut.StartupToken = Guid.Empty; sut.AuthenticationToken = Guid.Empty;
var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var token = sut.Connect(Guid.Empty).CommunicationToken.Value;
var message = new PasswordRequestMessage(purpose, requestId) { CommunicationToken = token }; var message = new PasswordRequestMessage(purpose, requestId) { CommunicationToken = token };
@ -210,7 +210,7 @@ namespace SafeExamBrowser.Client.UnitTests.Communication
reconfigurationDenied = new Uri(args.ConfigurationPath).Equals(new Uri(filePath)); reconfigurationDenied = new Uri(args.ConfigurationPath).Equals(new Uri(filePath));
resetEvent.Set(); resetEvent.Set();
}; };
sut.StartupToken = Guid.Empty; sut.AuthenticationToken = Guid.Empty;
var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var token = sut.Connect(Guid.Empty).CommunicationToken.Value;
var message = new ReconfigurationDeniedMessage(filePath) { CommunicationToken = token }; var message = new ReconfigurationDeniedMessage(filePath) { CommunicationToken = token };
@ -230,7 +230,7 @@ namespace SafeExamBrowser.Client.UnitTests.Communication
var shutdownRequested = false; var shutdownRequested = false;
sut.Shutdown += () => shutdownRequested = true; sut.Shutdown += () => shutdownRequested = true;
sut.StartupToken = Guid.Empty; sut.AuthenticationToken = Guid.Empty;
var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var token = sut.Connect(Guid.Empty).CommunicationToken.Value;
var message = new SimpleMessage(SimpleMessagePurport.Shutdown) { CommunicationToken = token }; var message = new SimpleMessage(SimpleMessagePurport.Shutdown) { CommunicationToken = token };
@ -245,7 +245,7 @@ namespace SafeExamBrowser.Client.UnitTests.Communication
[TestMethod] [TestMethod]
public void MustReturnUnknownMessageAsDefault() public void MustReturnUnknownMessageAsDefault()
{ {
sut.StartupToken = Guid.Empty; sut.AuthenticationToken = Guid.Empty;
var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var token = sut.Connect(Guid.Empty).CommunicationToken.Value;
var message = new TestMessage { CommunicationToken = token } as Message; var message = new TestMessage { CommunicationToken = token } as Message;
@ -266,7 +266,7 @@ namespace SafeExamBrowser.Client.UnitTests.Communication
[TestMethod] [TestMethod]
public void MustNotFailIfNoEventHandlersSubscribed() public void MustNotFailIfNoEventHandlersSubscribed()
{ {
sut.StartupToken = Guid.Empty; sut.AuthenticationToken = Guid.Empty;
var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var token = sut.Connect(Guid.Empty).CommunicationToken.Value;

View file

@ -20,7 +20,7 @@ namespace SafeExamBrowser.Client.Communication
private bool allowConnection = true; private bool allowConnection = true;
private int processId; private int processId;
public Guid StartupToken { private get; set; } public Guid AuthenticationToken { private get; set; }
public bool IsConnected { get; private set; } public bool IsConnected { get; private set; }
public event CommunicationEventHandler<MessageBoxRequestEventArgs> MessageBoxRequested; public event CommunicationEventHandler<MessageBoxRequestEventArgs> MessageBoxRequested;
@ -41,7 +41,7 @@ namespace SafeExamBrowser.Client.Communication
protected override bool OnConnect(Guid? token) protected override bool OnConnect(Guid? token)
{ {
var authenticated = StartupToken == token; var authenticated = AuthenticationToken == token;
var accepted = allowConnection && authenticated; var accepted = allowConnection && authenticated;
if (accepted) if (accepted)

View file

@ -51,11 +51,11 @@ namespace SafeExamBrowser.Client
{ {
internal class CompositionRoot internal class CompositionRoot
{ {
private Guid authenticationToken;
private ClientConfiguration configuration; private ClientConfiguration configuration;
private string logFilePath; private string logFilePath;
private LogLevel logLevel; private LogLevel logLevel;
private string runtimeHostUri; private string runtimeHostUri;
private Guid startupToken;
private UserInterfaceMode uiMode; private UserInterfaceMode uiMode;
private IActionCenter actionCenter; private IActionCenter actionCenter;
@ -110,7 +110,7 @@ namespace SafeExamBrowser.Client
var operations = new Queue<IOperation>(); var operations = new Queue<IOperation>();
operations.Enqueue(new I18nOperation(logger, text, textResource)); operations.Enqueue(new I18nOperation(logger, text, textResource));
operations.Enqueue(new RuntimeConnectionOperation(logger, runtimeProxy, startupToken)); operations.Enqueue(new RuntimeConnectionOperation(logger, runtimeProxy, authenticationToken));
operations.Enqueue(new ConfigurationOperation(configuration, logger, runtimeProxy)); operations.Enqueue(new ConfigurationOperation(configuration, logger, runtimeProxy));
operations.Enqueue(new DelegateOperation(UpdateAppConfig)); operations.Enqueue(new DelegateOperation(UpdateAppConfig));
operations.Enqueue(new LazyInitializationOperation(BuildClientHostOperation)); operations.Enqueue(new LazyInitializationOperation(BuildClientHostOperation));
@ -166,14 +166,14 @@ namespace SafeExamBrowser.Client
var hasLogfilePath = Uri.TryCreate(args[1], UriKind.Absolute, out Uri filePath) && filePath.IsFile; var hasLogfilePath = Uri.TryCreate(args[1], UriKind.Absolute, out Uri filePath) && filePath.IsFile;
var hasLogLevel = Enum.TryParse(args[2], out LogLevel level); var hasLogLevel = Enum.TryParse(args[2], out LogLevel level);
var hasHostUri = Uri.TryCreate(args[3], UriKind.Absolute, out Uri hostUri) && hostUri.IsWellFormedOriginalString(); var hasHostUri = Uri.TryCreate(args[3], UriKind.Absolute, out Uri hostUri) && hostUri.IsWellFormedOriginalString();
var hasToken = Guid.TryParse(args[4], out Guid token); var hasAuthenticationToken = Guid.TryParse(args[4], out Guid token);
if (hasLogfilePath && hasLogLevel && hasHostUri && hasToken) if (hasLogfilePath && hasLogLevel && hasHostUri && hasAuthenticationToken)
{ {
logFilePath = args[1]; logFilePath = args[1];
logLevel = level; logLevel = level;
runtimeHostUri = args[3]; runtimeHostUri = args[3];
startupToken = token; authenticationToken = token;
uiMode = args.Length == 6 && Enum.TryParse(args[5], out uiMode) ? uiMode : UserInterfaceMode.Desktop; uiMode = args.Length == 6 && Enum.TryParse(args[5], out uiMode) ? uiMode : UserInterfaceMode.Desktop;
return; return;
@ -222,7 +222,7 @@ namespace SafeExamBrowser.Client
var operation = new CommunicationHostOperation(host, logger); var operation = new CommunicationHostOperation(host, logger);
clientHost = host; clientHost = host;
clientHost.StartupToken = startupToken; clientHost.AuthenticationToken = authenticationToken;
return operation; return operation;
} }

View file

@ -68,7 +68,7 @@ namespace SafeExamBrowser.Communication.UnitTests.Proxies
{ {
sut.Ignore = true; sut.Ignore = true;
var communication = sut.StartSession(Guid.Empty, null); var communication = sut.StartSession(null);
Assert.IsTrue(communication.Success); Assert.IsTrue(communication.Success);
proxy.Verify(p => p.Send(It.IsAny<Message>()), Times.Never); proxy.Verify(p => p.Send(It.IsAny<Message>()), Times.Never);

View file

@ -8,7 +8,7 @@
using System; using System;
using SafeExamBrowser.Contracts.Communication.Proxies; using SafeExamBrowser.Contracts.Communication.Proxies;
using SafeExamBrowser.Contracts.Configuration.Settings; using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.Logging;
namespace SafeExamBrowser.Communication.Proxies namespace SafeExamBrowser.Communication.Proxies
@ -45,7 +45,7 @@ namespace SafeExamBrowser.Communication.Proxies
return base.Disconnect(); return base.Disconnect();
} }
public CommunicationResult StartSession(Guid sessionId, Settings settings) public CommunicationResult StartSession(ServiceConfiguration configuration)
{ {
if (IgnoreOperation(nameof(StartSession))) if (IgnoreOperation(nameof(StartSession)))
{ {

View file

@ -275,10 +275,11 @@ namespace SafeExamBrowser.Configuration.UnitTests
var appConfig = sut.InitializeAppConfig(); var appConfig = sut.InitializeAppConfig();
var configuration = sut.InitializeSessionConfiguration(); var configuration = sut.InitializeSessionConfiguration();
Assert.IsInstanceOfType(configuration.AppConfig, typeof(AppConfig));
Assert.IsInstanceOfType(configuration.Id, typeof(Guid));
Assert.IsNull(configuration.Settings); Assert.IsNull(configuration.Settings);
Assert.IsInstanceOfType(configuration.StartupToken, typeof(Guid)); Assert.IsInstanceOfType(configuration.AppConfig, typeof(AppConfig));
Assert.IsInstanceOfType(configuration.ClientAuthenticationToken, typeof(Guid));
Assert.IsInstanceOfType(configuration.ServiceAuthenticationToken, typeof(Guid));
Assert.IsInstanceOfType(configuration.SessionId, typeof(Guid));
} }
[TestMethod] [TestMethod]
@ -309,10 +310,12 @@ namespace SafeExamBrowser.Configuration.UnitTests
var secondSession = sut.InitializeSessionConfiguration(); var secondSession = sut.InitializeSessionConfiguration();
var thirdSession = sut.InitializeSessionConfiguration(); var thirdSession = sut.InitializeSessionConfiguration();
Assert.AreNotEqual(firstSession.Id, secondSession.Id); Assert.AreNotEqual(firstSession.SessionId, secondSession.SessionId);
Assert.AreNotEqual(firstSession.StartupToken, secondSession.StartupToken); Assert.AreNotEqual(firstSession.ClientAuthenticationToken, secondSession.ClientAuthenticationToken);
Assert.AreNotEqual(secondSession.Id, thirdSession.Id); Assert.AreNotEqual(firstSession.ServiceAuthenticationToken, secondSession.ServiceAuthenticationToken);
Assert.AreNotEqual(secondSession.StartupToken, thirdSession.StartupToken); Assert.AreNotEqual(secondSession.SessionId, thirdSession.SessionId);
Assert.AreNotEqual(secondSession.ClientAuthenticationToken, thirdSession.ClientAuthenticationToken);
Assert.AreNotEqual(secondSession.ServiceAuthenticationToken, thirdSession.ServiceAuthenticationToken);
} }
private void RegisterModules() private void RegisterModules()

View file

@ -33,5 +33,16 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
settings.KioskMode = KioskMode.None; settings.KioskMode = KioskMode.None;
} }
} }
private void MapServicePolicy(Settings settings, object value)
{
const int WARN = 1;
const int FORCE = 2;
if (value is int policy)
{
settings.ServicePolicy = policy == FORCE ? ServicePolicy.Mandatory : (policy == WARN ? ServicePolicy.Warn : ServicePolicy.Optional);
}
}
} }
} }

View file

@ -21,6 +21,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
MapConfigurationFileSettings(item.Key, item.Value, settings); MapConfigurationFileSettings(item.Key, item.Value, settings);
MapGeneralSettings(item.Key, item.Value, settings); MapGeneralSettings(item.Key, item.Value, settings);
MapInputSettings(item.Key, item.Value, settings); MapInputSettings(item.Key, item.Value, settings);
MapSecuritySettings(item.Key, item.Value, settings);
MapUserInterfaceSettings(item.Key, item.Value, settings); MapUserInterfaceSettings(item.Key, item.Value, settings);
} }
@ -174,6 +175,16 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
} }
} }
private void MapSecuritySettings(string key, object value, Settings settings)
{
switch (key)
{
case Keys.Security.ServicePolicy:
MapServicePolicy(settings, value);
break;
}
}
private void MapUserInterfaceSettings(string key, object value, Settings settings) private void MapUserInterfaceSettings(string key, object value, Settings settings)
{ {
switch (key) switch (key)

View file

@ -72,7 +72,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
return appConfig; return appConfig;
} }
internal ISessionConfiguration InitializeSessionConfiguration() internal SessionConfiguration InitializeSessionConfiguration()
{ {
var configuration = new SessionConfiguration(); var configuration = new SessionConfiguration();
@ -80,8 +80,9 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
appConfig.ClientAddress = $"{BASE_ADDRESS}/client/{Guid.NewGuid()}"; appConfig.ClientAddress = $"{BASE_ADDRESS}/client/{Guid.NewGuid()}";
configuration.AppConfig = appConfig.Clone(); configuration.AppConfig = appConfig.Clone();
configuration.Id = Guid.NewGuid(); configuration.ClientAuthenticationToken = Guid.NewGuid();
configuration.StartupToken = Guid.NewGuid(); configuration.ServiceAuthenticationToken = Guid.NewGuid();
configuration.SessionId = Guid.NewGuid();
return configuration; return configuration;
} }

View file

@ -116,6 +116,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
{ {
internal const string KioskModeCreateNewDesktop = "createNewDesktop"; internal const string KioskModeCreateNewDesktop = "createNewDesktop";
internal const string KioskModeDisableExplorerShell = "killExplorerShell"; internal const string KioskModeDisableExplorerShell = "killExplorerShell";
internal const string ServicePolicy = "sebServicePolicy";
} }
internal static class UserInterface internal static class UserInterface

View file

@ -94,7 +94,7 @@ namespace SafeExamBrowser.Configuration
return dataValues.InitializeAppConfig(); return dataValues.InitializeAppConfig();
} }
public ISessionConfiguration InitializeSessionConfiguration() public SessionConfiguration InitializeSessionConfiguration()
{ {
return dataValues.InitializeSessionConfiguration(); return dataValues.InitializeSessionConfiguration();
} }

View file

@ -94,7 +94,6 @@
<Compile Include="ConfigurationRepository.cs" /> <Compile Include="ConfigurationRepository.cs" />
<Compile Include="DataResources\FileResourceLoader.cs" /> <Compile Include="DataResources\FileResourceLoader.cs" />
<Compile Include="DataResources\NetworkResourceLoader.cs" /> <Compile Include="DataResources\NetworkResourceLoader.cs" />
<Compile Include="SessionConfiguration.cs" />
<Compile Include="SubStream.cs" /> <Compile Include="SubStream.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -1,22 +0,0 @@
/*
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Configuration.Settings;
namespace SafeExamBrowser.Configuration
{
internal class SessionConfiguration : ISessionConfiguration
{
public AppConfig AppConfig { get; set; }
public Guid Id { get; set; }
public Settings Settings { get; set; }
public Guid StartupToken { get; set; }
}
}

View file

@ -16,16 +16,16 @@ namespace SafeExamBrowser.Contracts.Communication.Hosts
/// </summary> /// </summary>
public interface IClientHost : ICommunicationHost public interface IClientHost : ICommunicationHost
{ {
/// <summary>
/// The token used for initial authentication with the runtime.
/// </summary>
Guid AuthenticationToken { set; }
/// <summary> /// <summary>
/// Indicates whether the runtime has established a connection to this host. /// Indicates whether the runtime has established a connection to this host.
/// </summary> /// </summary>
bool IsConnected { get; } bool IsConnected { get; }
/// <summary>
/// The startup token used for initial authentication.
/// </summary>
Guid StartupToken { set; }
/// <summary> /// <summary>
/// Event fired when the runtime requests a message box input from the user. /// Event fired when the runtime requests a message box input from the user.
/// </summary> /// </summary>

View file

@ -22,9 +22,9 @@ namespace SafeExamBrowser.Contracts.Communication.Hosts
bool AllowConnection { get; set; } bool AllowConnection { get; set; }
/// <summary> /// <summary>
/// The startup token used for initial authentication. /// The token used for initial authentication.
/// </summary> /// </summary>
Guid StartupToken { set; } Guid AuthenticationToken { set; }
/// <summary> /// <summary>
/// Event fired when the client disconnected from the runtime. /// Event fired when the client disconnected from the runtime.

View file

@ -10,6 +10,7 @@ using System;
using System.ServiceModel; using System.ServiceModel;
using SafeExamBrowser.Contracts.Communication.Data; using SafeExamBrowser.Contracts.Communication.Data;
using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Configuration;
using ServiceConfiguration = SafeExamBrowser.Contracts.Configuration.ServiceConfiguration;
namespace SafeExamBrowser.Contracts.Communication namespace SafeExamBrowser.Contracts.Communication
{ {
@ -26,6 +27,7 @@ namespace SafeExamBrowser.Contracts.Communication
[ServiceKnownType(typeof(PasswordRequestMessage))] [ServiceKnownType(typeof(PasswordRequestMessage))]
[ServiceKnownType(typeof(ReconfigurationMessage))] [ServiceKnownType(typeof(ReconfigurationMessage))]
[ServiceKnownType(typeof(ReconfigurationDeniedMessage))] [ServiceKnownType(typeof(ReconfigurationDeniedMessage))]
[ServiceKnownType(typeof(ServiceConfiguration))]
[ServiceKnownType(typeof(SimpleMessage))] [ServiceKnownType(typeof(SimpleMessage))]
[ServiceKnownType(typeof(SimpleResponse))] [ServiceKnownType(typeof(SimpleResponse))]
public interface ICommunication public interface ICommunication

View file

@ -7,7 +7,7 @@
*/ */
using System; using System;
using SafeExamBrowser.Contracts.Configuration.Settings; using SafeExamBrowser.Contracts.Configuration;
namespace SafeExamBrowser.Contracts.Communication.Proxies namespace SafeExamBrowser.Contracts.Communication.Proxies
{ {
@ -28,9 +28,9 @@ namespace SafeExamBrowser.Contracts.Communication.Proxies
bool IsConnected { get; } bool IsConnected { get; }
/// <summary> /// <summary>
/// Instructs the service to start a new session according to the given parameters. /// Instructs the service to start a new session according to the given configuration.
/// </summary> /// </summary>
CommunicationResult StartSession(Guid sessionId, Settings settings); CommunicationResult StartSession(ServiceConfiguration configuration);
/// <summary> /// <summary>
/// Instructs the service to stop the specified session. /// Instructs the service to stop the specified session.

View file

@ -11,7 +11,7 @@ using System;
namespace SafeExamBrowser.Contracts.Configuration namespace SafeExamBrowser.Contracts.Configuration
{ {
/// <summary> /// <summary>
/// Container for the configuration of the client application component. /// The configuration for a session of the client application component.
/// </summary> /// </summary>
[Serializable] [Serializable]
public class ClientConfiguration public class ClientConfiguration

View file

@ -31,7 +31,7 @@ namespace SafeExamBrowser.Contracts.Configuration
/// <summary> /// <summary>
/// Initializes all relevant configuration data for a new session. /// Initializes all relevant configuration data for a new session.
/// </summary> /// </summary>
ISessionConfiguration InitializeSessionConfiguration(); SessionConfiguration InitializeSessionConfiguration();
/// <summary> /// <summary>
/// Loads the default settings. /// Loads the default settings.

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
namespace SafeExamBrowser.Contracts.Configuration
{
/// <summary>
/// The configuration for a session of the service application component.
/// </summary>
[Serializable]
public class ServiceConfiguration
{
/// <summary>
/// The global application configuration.
/// </summary>
public AppConfig AppConfig { get; set; }
/// <summary>
/// The token used for initial authentication with the runtime.
/// </summary>
public Guid AuthenticationToken { get; set; }
/// <summary>
/// The unique identifier for the current session.
/// </summary>
public Guid SessionId { get; set; }
/// <summary>
/// The application settings to be used by the service.
/// </summary>
public Settings.Settings Settings { get; set; }
}
}

View file

@ -11,28 +11,33 @@ using System;
namespace SafeExamBrowser.Contracts.Configuration namespace SafeExamBrowser.Contracts.Configuration
{ {
/// <summary> /// <summary>
/// Holds all session-related configuration data. /// Container holding all session-related configuration data.
/// </summary> /// </summary>
public interface ISessionConfiguration public class SessionConfiguration
{ {
/// <summary> /// <summary>
/// The active application configuration for this session. /// The active application configuration for this session.
/// </summary> /// </summary>
AppConfig AppConfig { get; } public AppConfig AppConfig { get; set; }
/// <summary>
/// The token used for initial communication authentication with the client.
/// </summary>
public Guid ClientAuthenticationToken { get; set; }
/// <summary>
/// The token used for initial communication authentication with the service.
/// </summary>
public Guid ServiceAuthenticationToken { get; set; }
/// <summary> /// <summary>
/// The unique session identifier. /// The unique session identifier.
/// </summary> /// </summary>
Guid Id { get; } public Guid SessionId { get; set; }
/// <summary> /// <summary>
/// The settings used for this session. /// The settings used for this session.
/// </summary> /// </summary>
Settings.Settings Settings { get; set; } public Settings.Settings Settings { get; set; }
/// <summary>
/// The startup token used by the client and runtime components for initial authentication.
/// </summary>
Guid StartupToken { get; }
} }
} }

View file

@ -21,6 +21,11 @@ namespace SafeExamBrowser.Contracts.Configuration.Settings
/// <summary> /// <summary>
/// The service component is optional. If it is not running, all service-related actions are simply skipped. /// The service component is optional. If it is not running, all service-related actions are simply skipped.
/// </summary> /// </summary>
Optional Optional,
/// <summary>
/// The service component should be running. If it is not running, the user will be warned that all service-related actions are skipped.
/// </summary>
Warn
} }
} }

View file

@ -48,6 +48,10 @@ namespace SafeExamBrowser.Contracts.I18n
MessageBox_ReconfigurationQuestionTitle, MessageBox_ReconfigurationQuestionTitle,
MessageBox_ReloadConfirmation, MessageBox_ReloadConfirmation,
MessageBox_ReloadConfirmationTitle, MessageBox_ReloadConfirmationTitle,
MessageBox_ServiceUnavailableError,
MessageBox_ServiceUnavailableErrorTitle,
MessageBox_ServiceUnavailableWarning,
MessageBox_ServiceUnavailableWarningTitle,
MessageBox_SessionStartError, MessageBox_SessionStartError,
MessageBox_SessionStartErrorTitle, MessageBox_SessionStartErrorTitle,
MessageBox_ShutdownError, MessageBox_ShutdownError,

View file

@ -60,6 +60,7 @@
<Compile Include="Communication\Events\MessageBoxReplyEventArgs.cs" /> <Compile Include="Communication\Events\MessageBoxReplyEventArgs.cs" />
<Compile Include="Communication\Events\MessageBoxRequestEventArgs.cs" /> <Compile Include="Communication\Events\MessageBoxRequestEventArgs.cs" />
<Compile Include="Communication\Hosts\IServiceHost.cs" /> <Compile Include="Communication\Hosts\IServiceHost.cs" />
<Compile Include="Configuration\ClientConfiguration.cs" />
<Compile Include="Configuration\Cryptography\EncryptionParameters.cs" /> <Compile Include="Configuration\Cryptography\EncryptionParameters.cs" />
<Compile Include="Configuration\Cryptography\ICertificateStore.cs" /> <Compile Include="Configuration\Cryptography\ICertificateStore.cs" />
<Compile Include="Configuration\Cryptography\IPasswordEncryption.cs" /> <Compile Include="Configuration\Cryptography\IPasswordEncryption.cs" />
@ -76,6 +77,7 @@
<Compile Include="Configuration\DataResources\IResourceLoader.cs" /> <Compile Include="Configuration\DataResources\IResourceLoader.cs" />
<Compile Include="Configuration\DataResources\IResourceSaver.cs" /> <Compile Include="Configuration\DataResources\IResourceSaver.cs" />
<Compile Include="Configuration\SaveStatus.cs" /> <Compile Include="Configuration\SaveStatus.cs" />
<Compile Include="Configuration\ServiceConfiguration.cs" />
<Compile Include="Configuration\Settings\ActionCenterSettings.cs" /> <Compile Include="Configuration\Settings\ActionCenterSettings.cs" />
<Compile Include="Configuration\Settings\BrowserWindowSettings.cs" /> <Compile Include="Configuration\Settings\BrowserWindowSettings.cs" />
<Compile Include="Configuration\Settings\UserInterfaceMode.cs" /> <Compile Include="Configuration\Settings\UserInterfaceMode.cs" />
@ -133,10 +135,9 @@
<Compile Include="Communication\Data\Response.cs" /> <Compile Include="Communication\Data\Response.cs" />
<Compile Include="Communication\Data\SimpleResponsePurport.cs" /> <Compile Include="Communication\Data\SimpleResponsePurport.cs" />
<Compile Include="Communication\Data\SimpleResponse.cs" /> <Compile Include="Communication\Data\SimpleResponse.cs" />
<Compile Include="Configuration\ClientConfiguration.cs" />
<Compile Include="Configuration\LoadStatus.cs" /> <Compile Include="Configuration\LoadStatus.cs" />
<Compile Include="Configuration\AppConfig.cs" /> <Compile Include="Configuration\AppConfig.cs" />
<Compile Include="Configuration\ISessionConfiguration.cs" /> <Compile Include="Configuration\SessionConfiguration.cs" />
<Compile Include="Configuration\Settings\ConfigurationMode.cs" /> <Compile Include="Configuration\Settings\ConfigurationMode.cs" />
<Compile Include="Client\INotificationController.cs" /> <Compile Include="Client\INotificationController.cs" />
<Compile Include="Core\OperationModel\IOperation.cs" /> <Compile Include="Core\OperationModel\IOperation.cs" />

View file

@ -102,6 +102,18 @@
<Entry key="MessageBox_ReloadConfirmationTitle"> <Entry key="MessageBox_ReloadConfirmationTitle">
Reload? Reload?
</Entry> </Entry>
<Entry key="MessageBox_ServiceUnavailableError">
Failed to initialize the Safe Exam Browser service! The application is not allowed to start since the current configuration requires the service to be running.
</Entry>
<Entry key="MessageBox_ServiceUnavailableErrorTitle">
Service Unavailable
</Entry>
<Entry key="MessageBox_ServiceUnavailableWarning">
Failed to initialize the Safe Exam Browser service. The application is allowed to start, but it should be ensured that the service is installed and running.
</Entry>
<Entry key="MessageBox_ServiceUnavailableWarningTitle">
Service Unavailable
</Entry>
<Entry key="MessageBox_SessionStartError"> <Entry key="MessageBox_SessionStartError">
The application failed to start a new session! Please consult the application log for more information... The application failed to start a new session! Please consult the application log for more information...
</Entry> </Entry>

View file

@ -48,7 +48,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication
var token = Guid.NewGuid(); var token = Guid.NewGuid();
sut.AllowConnection = true; sut.AllowConnection = true;
sut.StartupToken = token; sut.AuthenticationToken = token;
var response = sut.Connect(token); var response = sut.Connect(token);
@ -62,7 +62,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication
var token = Guid.NewGuid(); var token = Guid.NewGuid();
sut.AllowConnection = true; sut.AllowConnection = true;
sut.StartupToken = token; sut.AuthenticationToken = token;
var response = sut.Connect(Guid.NewGuid()); var response = sut.Connect(Guid.NewGuid());
@ -76,7 +76,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication
var token = Guid.NewGuid(); var token = Guid.NewGuid();
sut.AllowConnection = true; sut.AllowConnection = true;
sut.StartupToken = token; sut.AuthenticationToken = token;
var response1 = sut.Connect(token); var response1 = sut.Connect(token);
var response2 = sut.Connect(token); var response2 = sut.Connect(token);
@ -100,7 +100,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication
var token = Guid.NewGuid(); var token = Guid.NewGuid();
sut.AllowConnection = true; sut.AllowConnection = true;
sut.StartupToken = token; sut.AuthenticationToken = token;
sut.ClientDisconnected += () => disconnected = true; sut.ClientDisconnected += () => disconnected = true;
var connectionResponse = sut.Connect(token); var connectionResponse = sut.Connect(token);
@ -117,13 +117,13 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication
var token = Guid.NewGuid(); var token = Guid.NewGuid();
sut.AllowConnection = true; sut.AllowConnection = true;
sut.StartupToken = token; sut.AuthenticationToken = token;
var response = sut.Connect(token); var response = sut.Connect(token);
sut.Disconnect(new DisconnectionMessage { CommunicationToken = response.CommunicationToken.Value }); sut.Disconnect(new DisconnectionMessage { CommunicationToken = response.CommunicationToken.Value });
sut.AllowConnection = true; sut.AllowConnection = true;
sut.StartupToken = token = Guid.NewGuid(); sut.AuthenticationToken = token = Guid.NewGuid();
response = sut.Connect(token); response = sut.Connect(token);
@ -137,7 +137,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication
sut.AllowConnection = true; sut.AllowConnection = true;
sut.ClientReady += () => clientReady = true; sut.ClientReady += () => clientReady = true;
sut.StartupToken = Guid.Empty; sut.AuthenticationToken = Guid.Empty;
var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var token = sut.Connect(Guid.Empty).CommunicationToken.Value;
var message = new SimpleMessage(SimpleMessagePurport.ClientIsReady) { CommunicationToken = token }; var message = new SimpleMessage(SimpleMessagePurport.ClientIsReady) { CommunicationToken = token };
@ -157,7 +157,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication
sut.AllowConnection = true; sut.AllowConnection = true;
sut.ClientConfigurationNeeded += (a) => { args = a; args.ClientConfiguration = configuration; }; sut.ClientConfigurationNeeded += (a) => { args = a; args.ClientConfiguration = configuration; };
sut.StartupToken = Guid.Empty; sut.AuthenticationToken = Guid.Empty;
var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var token = sut.Connect(Guid.Empty).CommunicationToken.Value;
var message = new SimpleMessage(SimpleMessagePurport.ConfigurationNeeded) { CommunicationToken = token }; var message = new SimpleMessage(SimpleMessagePurport.ConfigurationNeeded) { CommunicationToken = token };
@ -176,7 +176,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication
sut.AllowConnection = true; sut.AllowConnection = true;
sut.ShutdownRequested += () => shutdownRequested = true; sut.ShutdownRequested += () => shutdownRequested = true;
sut.StartupToken = Guid.Empty; sut.AuthenticationToken = Guid.Empty;
var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var token = sut.Connect(Guid.Empty).CommunicationToken.Value;
var message = new SimpleMessage(SimpleMessagePurport.RequestShutdown) { CommunicationToken = token }; var message = new SimpleMessage(SimpleMessagePurport.RequestShutdown) { CommunicationToken = token };
@ -198,7 +198,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication
sut.AllowConnection = true; sut.AllowConnection = true;
sut.MessageBoxReplyReceived += (a) => { args = a; sync.Set(); }; sut.MessageBoxReplyReceived += (a) => { args = a; sync.Set(); };
sut.StartupToken = Guid.Empty; sut.AuthenticationToken = Guid.Empty;
var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var token = sut.Connect(Guid.Empty).CommunicationToken.Value;
var message = new MessageBoxReplyMessage(requestId, result) { CommunicationToken = token }; var message = new MessageBoxReplyMessage(requestId, result) { CommunicationToken = token };
@ -225,7 +225,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication
sut.AllowConnection = true; sut.AllowConnection = true;
sut.PasswordReceived += (a) => { args = a; sync.Set(); }; sut.PasswordReceived += (a) => { args = a; sync.Set(); };
sut.StartupToken = Guid.Empty; sut.AuthenticationToken = Guid.Empty;
var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var token = sut.Connect(Guid.Empty).CommunicationToken.Value;
var message = new PasswordReplyMessage(requestId, success, password) { CommunicationToken = token }; var message = new PasswordReplyMessage(requestId, success, password) { CommunicationToken = token };
@ -251,7 +251,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication
sut.AllowConnection = true; sut.AllowConnection = true;
sut.ReconfigurationRequested += (a) => { args = a; sync.Set(); }; sut.ReconfigurationRequested += (a) => { args = a; sync.Set(); };
sut.StartupToken = Guid.Empty; sut.AuthenticationToken = Guid.Empty;
var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var token = sut.Connect(Guid.Empty).CommunicationToken.Value;
var message = new ReconfigurationMessage(path) { CommunicationToken = token }; var message = new ReconfigurationMessage(path) { CommunicationToken = token };
@ -270,7 +270,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication
public void MustReturnUnknownMessageAsDefault() public void MustReturnUnknownMessageAsDefault()
{ {
sut.AllowConnection = true; sut.AllowConnection = true;
sut.StartupToken = Guid.Empty; sut.AuthenticationToken = Guid.Empty;
var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var token = sut.Connect(Guid.Empty).CommunicationToken.Value;
var message = new TestMessage { CommunicationToken = token } as Message; var message = new TestMessage { CommunicationToken = token } as Message;
@ -292,7 +292,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication
public void MustNotFailIfNoEventHandlersSubscribed() public void MustNotFailIfNoEventHandlersSubscribed()
{ {
sut.AllowConnection = true; sut.AllowConnection = true;
sut.StartupToken = Guid.Empty; sut.AuthenticationToken = Guid.Empty;
var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var token = sut.Connect(Guid.Empty).CommunicationToken.Value;

View file

@ -34,7 +34,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
private Mock<IProcessFactory> processFactory; private Mock<IProcessFactory> processFactory;
private Mock<IProxyFactory> proxyFactory; private Mock<IProxyFactory> proxyFactory;
private Mock<IRuntimeHost> runtimeHost; private Mock<IRuntimeHost> runtimeHost;
private Mock<ISessionConfiguration> session; private SessionConfiguration session;
private SessionContext sessionContext; private SessionContext sessionContext;
private Settings settings; private Settings settings;
private ClientOperation sut; private ClientOperation sut;
@ -50,7 +50,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
proxy = new Mock<IClientProxy>(); proxy = new Mock<IClientProxy>();
proxyFactory = new Mock<IProxyFactory>(); proxyFactory = new Mock<IProxyFactory>();
runtimeHost = new Mock<IRuntimeHost>(); runtimeHost = new Mock<IRuntimeHost>();
session = new Mock<ISessionConfiguration>(); session = new SessionConfiguration();
sessionContext = new SessionContext(); sessionContext = new SessionContext();
settings = new Settings(); settings = new Settings();
terminated = new Action(() => terminated = new Action(() =>
@ -59,10 +59,10 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
process.Raise(p => p.Terminated += null, 0); process.Raise(p => p.Terminated += null, 0);
}); });
session.SetupGet(s => s.AppConfig).Returns(appConfig); session.AppConfig = appConfig;
session.SetupGet(s => s.Settings).Returns(settings); session.Settings = settings;
sessionContext.Current = session.Object; sessionContext.Current = session;
sessionContext.Next = session.Object; sessionContext.Next = session;
proxyFactory.Setup(f => f.CreateClientProxy(It.IsAny<string>())).Returns(proxy.Object); proxyFactory.Setup(f => f.CreateClientProxy(It.IsAny<string>())).Returns(proxy.Object);
sut = new ClientOperation(logger.Object, processFactory.Object, proxyFactory.Object, runtimeHost.Object, sessionContext, 0); sut = new ClientOperation(logger.Object, processFactory.Object, proxyFactory.Object, runtimeHost.Object, sessionContext, 0);

View file

@ -31,7 +31,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
private Mock<IProcessFactory> processFactory; private Mock<IProcessFactory> processFactory;
private Mock<IProxyFactory> proxyFactory; private Mock<IProxyFactory> proxyFactory;
private Mock<IRuntimeHost> runtimeHost; private Mock<IRuntimeHost> runtimeHost;
private Mock<ISessionConfiguration> session; private SessionConfiguration session;
private SessionContext sessionContext; private SessionContext sessionContext;
private ClientTerminationOperation sut; private ClientTerminationOperation sut;
@ -47,7 +47,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
proxy = new Mock<IClientProxy>(); proxy = new Mock<IClientProxy>();
proxyFactory = new Mock<IProxyFactory>(); proxyFactory = new Mock<IProxyFactory>();
runtimeHost = new Mock<IRuntimeHost>(); runtimeHost = new Mock<IRuntimeHost>();
session = new Mock<ISessionConfiguration>(); session = new SessionConfiguration();
sessionContext = new SessionContext(); sessionContext = new SessionContext();
terminated = new Action(() => terminated = new Action(() =>
{ {
@ -55,11 +55,11 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
process.Raise(p => p.Terminated += null, 0); process.Raise(p => p.Terminated += null, 0);
}); });
session.SetupGet(s => s.AppConfig).Returns(appConfig); session.AppConfig = appConfig;
sessionContext.ClientProcess = process.Object; sessionContext.ClientProcess = process.Object;
sessionContext.ClientProxy = proxy.Object; sessionContext.ClientProxy = proxy.Object;
sessionContext.Current = session.Object; sessionContext.Current = session;
sessionContext.Next = session.Object; sessionContext.Next = session;
proxyFactory.Setup(f => f.CreateClientProxy(It.IsAny<string>())).Returns(proxy.Object); proxyFactory.Setup(f => f.CreateClientProxy(It.IsAny<string>())).Returns(proxy.Object);
sut = new ClientTerminationOperation(logger.Object, processFactory.Object, proxyFactory.Object, runtimeHost.Object, sessionContext, 0); sut = new ClientTerminationOperation(logger.Object, processFactory.Object, proxyFactory.Object, runtimeHost.Object, sessionContext, 0);

View file

@ -30,8 +30,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
private Mock<IHashAlgorithm> hashAlgorithm; private Mock<IHashAlgorithm> hashAlgorithm;
private Mock<ILogger> logger; private Mock<ILogger> logger;
private Mock<IConfigurationRepository> repository; private Mock<IConfigurationRepository> repository;
private Mock<ISessionConfiguration> currentSession; private SessionConfiguration currentSession;
private Mock<ISessionConfiguration> nextSession; private SessionConfiguration nextSession;
private SessionContext sessionContext; private SessionContext sessionContext;
[TestInitialize] [TestInitialize]
@ -41,16 +41,16 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
hashAlgorithm = new Mock<IHashAlgorithm>(); hashAlgorithm = new Mock<IHashAlgorithm>();
logger = new Mock<ILogger>(); logger = new Mock<ILogger>();
repository = new Mock<IConfigurationRepository>(); repository = new Mock<IConfigurationRepository>();
currentSession = new Mock<ISessionConfiguration>(); currentSession = new SessionConfiguration();
nextSession = new Mock<ISessionConfiguration>(); nextSession = new SessionConfiguration();
sessionContext = new SessionContext(); sessionContext = new SessionContext();
appConfig.AppDataFilePath = $@"C:\Not\Really\AppData\File.xml"; appConfig.AppDataFilePath = $@"C:\Not\Really\AppData\File.xml";
appConfig.ProgramDataFilePath = $@"C:\Not\Really\ProgramData\File.xml"; appConfig.ProgramDataFilePath = $@"C:\Not\Really\ProgramData\File.xml";
currentSession.SetupGet(s => s.AppConfig).Returns(appConfig); currentSession.AppConfig = appConfig;
nextSession.SetupGet(s => s.AppConfig).Returns(appConfig); nextSession.AppConfig = appConfig;
sessionContext.Current = currentSession.Object; sessionContext.Current = currentSession;
sessionContext.Next = nextSession.Object; sessionContext.Next = nextSession;
} }
[TestMethod] [TestMethod]
@ -112,7 +112,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
var settings = new Settings { ConfigurationMode = ConfigurationMode.Exam }; var settings = new Settings { ConfigurationMode = ConfigurationMode.Exam };
var url = @"http://www.safeexambrowser.org/whatever.seb"; var url = @"http://www.safeexambrowser.org/whatever.seb";
nextSession.SetupGet(s => s.Settings).Returns(settings); nextSession.Settings = settings;
repository.Setup(r => r.TryLoadSettings(It.IsAny<Uri>(), out settings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.LoadWithBrowser); repository.Setup(r => r.TryLoadSettings(It.IsAny<Uri>(), out settings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.LoadWithBrowser);
var sut = new ConfigurationOperation(new[] { "blubb.exe", url }, repository.Object, hashAlgorithm.Object, logger.Object, sessionContext); var sut = new ConfigurationOperation(new[] { "blubb.exe", url }, repository.Object, hashAlgorithm.Object, logger.Object, sessionContext);
@ -125,20 +125,17 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
[TestMethod] [TestMethod]
public void Perform_MustFallbackToDefaultsAsLastPrio() public void Perform_MustFallbackToDefaultsAsLastPrio()
{ {
var actualSettings = default(Settings);
var defaultSettings = new Settings(); var defaultSettings = new Settings();
repository.Setup(r => r.LoadDefaultSettings()).Returns(defaultSettings); repository.Setup(r => r.LoadDefaultSettings()).Returns(defaultSettings);
nextSession.SetupSet<Settings>(s => s.Settings = It.IsAny<Settings>()).Callback(s => actualSettings = s);
var sut = new ConfigurationOperation(null, repository.Object, hashAlgorithm.Object, logger.Object, sessionContext); var sut = new ConfigurationOperation(null, repository.Object, hashAlgorithm.Object, logger.Object, sessionContext);
var result = sut.Perform(); var result = sut.Perform();
repository.Verify(r => r.LoadDefaultSettings(), Times.Once); repository.Verify(r => r.LoadDefaultSettings(), Times.Once);
nextSession.VerifySet(s => s.Settings = defaultSettings);
Assert.AreEqual(OperationResult.Success, result); Assert.AreEqual(OperationResult.Success, result);
Assert.AreSame(defaultSettings, actualSettings); Assert.AreSame(defaultSettings, nextSession.Settings);
} }
[TestMethod] [TestMethod]
@ -241,26 +238,24 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
[TestMethod] [TestMethod]
public void Perform_MustNotFailWithoutCommandLineArgs() public void Perform_MustNotFailWithoutCommandLineArgs()
{ {
var actualSettings = default(Settings);
var defaultSettings = new Settings(); var defaultSettings = new Settings();
var result = OperationResult.Failed; var result = OperationResult.Failed;
repository.Setup(r => r.LoadDefaultSettings()).Returns(defaultSettings); repository.Setup(r => r.LoadDefaultSettings()).Returns(defaultSettings);
nextSession.SetupSet<Settings>(s => s.Settings = It.IsAny<Settings>()).Callback(s => actualSettings = s);
var sut = new ConfigurationOperation(null, repository.Object, hashAlgorithm.Object, logger.Object, sessionContext); var sut = new ConfigurationOperation(null, repository.Object, hashAlgorithm.Object, logger.Object, sessionContext);
result = sut.Perform(); result = sut.Perform();
repository.Verify(r => r.LoadDefaultSettings(), Times.Once); repository.Verify(r => r.LoadDefaultSettings(), Times.Once);
Assert.AreEqual(OperationResult.Success, result); Assert.AreEqual(OperationResult.Success, result);
Assert.AreSame(defaultSettings, actualSettings); Assert.AreSame(defaultSettings, nextSession.Settings);
sut = new ConfigurationOperation(new string[] { }, repository.Object, hashAlgorithm.Object, logger.Object, sessionContext); sut = new ConfigurationOperation(new string[] { }, repository.Object, hashAlgorithm.Object, logger.Object, sessionContext);
result = sut.Perform(); result = sut.Perform();
repository.Verify(r => r.LoadDefaultSettings(), Times.Exactly(2)); repository.Verify(r => r.LoadDefaultSettings(), Times.Exactly(2));
Assert.AreEqual(OperationResult.Success, result); Assert.AreEqual(OperationResult.Success, result);
Assert.AreSame(defaultSettings, actualSettings); Assert.AreSame(defaultSettings, nextSession.Settings);
} }
[TestMethod] [TestMethod]
@ -285,7 +280,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
repository.Setup(r => r.TryLoadSettings(It.IsAny<Uri>(), out settings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success); repository.Setup(r => r.TryLoadSettings(It.IsAny<Uri>(), out settings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
repository.Setup(r => r.TryLoadSettings(It.Is<Uri>(u => u.LocalPath.Contains(FILE_NAME)), out localSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success); repository.Setup(r => r.TryLoadSettings(It.Is<Uri>(u => u.LocalPath.Contains(FILE_NAME)), out localSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
nextSession.SetupGet(s => s.Settings).Returns(settings); nextSession.Settings = settings;
var sut = new ConfigurationOperation(new[] { "blubb.exe", url }, repository.Object, hashAlgorithm.Object, logger.Object, sessionContext); var sut = new ConfigurationOperation(new[] { "blubb.exe", url }, repository.Object, hashAlgorithm.Object, logger.Object, sessionContext);
sut.ActionRequired += args => sut.ActionRequired += args =>
@ -338,7 +333,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
var nextSettings = new Settings { AdminPasswordHash = "9876", ConfigurationMode = ConfigurationMode.ConfigureClient }; var nextSettings = new Settings { AdminPasswordHash = "9876", ConfigurationMode = ConfigurationMode.ConfigureClient };
var url = @"http://www.safeexambrowser.org/whatever.seb"; var url = @"http://www.safeexambrowser.org/whatever.seb";
nextSession.SetupGet(s => s.Settings).Returns(nextSettings); nextSession.Settings = nextSettings;
hashAlgorithm.Setup(h => h.GenerateHashFor(It.Is<string>(p => p == password))).Returns(currentSettings.AdminPasswordHash); hashAlgorithm.Setup(h => h.GenerateHashFor(It.Is<string>(p => p == password))).Returns(currentSettings.AdminPasswordHash);
repository.Setup(r => r.TryLoadSettings(It.IsAny<Uri>(), out currentSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success); repository.Setup(r => r.TryLoadSettings(It.IsAny<Uri>(), out currentSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
repository.Setup(r => r.TryLoadSettings(It.Is<Uri>(u => u.AbsoluteUri == url), out nextSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success); repository.Setup(r => r.TryLoadSettings(It.Is<Uri>(u => u.AbsoluteUri == url), out nextSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
@ -368,7 +363,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
var nextSettings = new Settings { AdminPasswordHash = "1234", ConfigurationMode = ConfigurationMode.ConfigureClient }; var nextSettings = new Settings { AdminPasswordHash = "1234", ConfigurationMode = ConfigurationMode.ConfigureClient };
var url = @"http://www.safeexambrowser.org/whatever.seb"; var url = @"http://www.safeexambrowser.org/whatever.seb";
nextSession.SetupGet(s => s.Settings).Returns(nextSettings); nextSession.Settings = nextSettings;
repository.Setup(r => r.TryLoadSettings(It.IsAny<Uri>(), out currentSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success); repository.Setup(r => r.TryLoadSettings(It.IsAny<Uri>(), out currentSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
repository.Setup(r => r.TryLoadSettings(It.Is<Uri>(u => u.AbsoluteUri == url), out nextSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success); repository.Setup(r => r.TryLoadSettings(It.Is<Uri>(u => u.AbsoluteUri == url), out nextSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
repository.Setup(r => r.ConfigureClientWith(It.IsAny<Uri>(), It.IsAny<PasswordParameters>())).Returns(SaveStatus.Success); repository.Setup(r => r.ConfigureClientWith(It.IsAny<Uri>(), It.IsAny<PasswordParameters>())).Returns(SaveStatus.Success);
@ -452,7 +447,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
var url = @"http://www.safeexambrowser.org/whatever.seb"; var url = @"http://www.safeexambrowser.org/whatever.seb";
appConfig.AppDataFilePath = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations), "Testdata", FILE_NAME); appConfig.AppDataFilePath = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations), "Testdata", FILE_NAME);
nextSession.SetupGet(s => s.Settings).Returns(nextSettings); nextSession.Settings = nextSettings;
hashAlgorithm.Setup(h => h.GenerateHashFor(It.Is<string>(p => p == password))).Returns(currentSettings.AdminPasswordHash); hashAlgorithm.Setup(h => h.GenerateHashFor(It.Is<string>(p => p == password))).Returns(currentSettings.AdminPasswordHash);
repository.Setup(r => r.TryLoadSettings(It.IsAny<Uri>(), out currentSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success); repository.Setup(r => r.TryLoadSettings(It.IsAny<Uri>(), out currentSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
@ -504,14 +499,13 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
var resource = new Uri(Path.Combine(location, nameof(Operations), "Testdata", FILE_NAME)); var resource = new Uri(Path.Combine(location, nameof(Operations), "Testdata", FILE_NAME));
var settings = new Settings { ConfigurationMode = ConfigurationMode.Exam }; var settings = new Settings { ConfigurationMode = ConfigurationMode.Exam };
currentSession.SetupGet(s => s.Settings).Returns(currentSettings); currentSession.Settings = currentSettings;
sessionContext.ReconfigurationFilePath = resource.LocalPath; sessionContext.ReconfigurationFilePath = resource.LocalPath;
repository.Setup(r => r.TryLoadSettings(It.Is<Uri>(u => u.Equals(resource)), out settings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success); repository.Setup(r => r.TryLoadSettings(It.Is<Uri>(u => u.Equals(resource)), out settings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
var sut = new ConfigurationOperation(null, repository.Object, hashAlgorithm.Object, logger.Object, sessionContext); var sut = new ConfigurationOperation(null, repository.Object, hashAlgorithm.Object, logger.Object, sessionContext);
var result = sut.Repeat(); var result = sut.Repeat();
nextSession.VerifySet(s => s.Settings = settings, Times.Once);
repository.Verify(r => r.TryLoadSettings(It.Is<Uri>(u => u.Equals(resource)), out settings, It.IsAny<PasswordParameters>()), Times.AtLeastOnce); repository.Verify(r => r.TryLoadSettings(It.Is<Uri>(u => u.Equals(resource)), out settings, It.IsAny<PasswordParameters>()), Times.AtLeastOnce);
repository.Verify(r => r.ConfigureClientWith(It.Is<Uri>(u => u.Equals(resource)), It.IsAny<PasswordParameters>()), Times.Never); repository.Verify(r => r.ConfigureClientWith(It.Is<Uri>(u => u.Equals(resource)), It.IsAny<PasswordParameters>()), Times.Never);
@ -526,7 +520,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
var resource = new Uri(Path.Combine(location, nameof(Operations), "Testdata", FILE_NAME)); var resource = new Uri(Path.Combine(location, nameof(Operations), "Testdata", FILE_NAME));
var settings = new Settings { ConfigurationMode = ConfigurationMode.ConfigureClient }; var settings = new Settings { ConfigurationMode = ConfigurationMode.ConfigureClient };
currentSession.SetupGet(s => s.Settings).Returns(currentSettings); currentSession.Settings = currentSettings;
sessionContext.ReconfigurationFilePath = resource.LocalPath; sessionContext.ReconfigurationFilePath = resource.LocalPath;
repository.Setup(r => r.TryLoadSettings(It.Is<Uri>(u => u.Equals(resource)), out settings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success); repository.Setup(r => r.TryLoadSettings(It.Is<Uri>(u => u.Equals(resource)), out settings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
repository.Setup(r => r.ConfigureClientWith(It.Is<Uri>(u => u.Equals(resource)), It.IsAny<PasswordParameters>())).Returns(SaveStatus.Success); repository.Setup(r => r.ConfigureClientWith(It.Is<Uri>(u => u.Equals(resource)), It.IsAny<PasswordParameters>())).Returns(SaveStatus.Success);
@ -534,7 +528,6 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
var sut = new ConfigurationOperation(null, repository.Object, hashAlgorithm.Object, logger.Object, sessionContext); var sut = new ConfigurationOperation(null, repository.Object, hashAlgorithm.Object, logger.Object, sessionContext);
var result = sut.Repeat(); var result = sut.Repeat();
nextSession.VerifySet(s => s.Settings = settings, Times.Once);
repository.Verify(r => r.TryLoadSettings(It.Is<Uri>(u => u.Equals(resource)), out settings, It.IsAny<PasswordParameters>()), Times.AtLeastOnce); repository.Verify(r => r.TryLoadSettings(It.Is<Uri>(u => u.Equals(resource)), out settings, It.IsAny<PasswordParameters>()), Times.AtLeastOnce);
repository.Verify(r => r.ConfigureClientWith(It.Is<Uri>(u => u.Equals(resource)), It.IsAny<PasswordParameters>()), Times.Once); repository.Verify(r => r.ConfigureClientWith(It.Is<Uri>(u => u.Equals(resource)), It.IsAny<PasswordParameters>()), Times.Once);
@ -571,7 +564,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
var resource = new Uri(Path.Combine(location, nameof(Operations), "Testdata", FILE_NAME)); var resource = new Uri(Path.Combine(location, nameof(Operations), "Testdata", FILE_NAME));
var settings = new Settings { ConfigurationMode = ConfigurationMode.ConfigureClient }; var settings = new Settings { ConfigurationMode = ConfigurationMode.ConfigureClient };
currentSession.SetupGet(s => s.Settings).Returns(currentSettings); currentSession.Settings = currentSettings;
sessionContext.ReconfigurationFilePath = resource.LocalPath; sessionContext.ReconfigurationFilePath = resource.LocalPath;
repository.Setup(r => r.TryLoadSettings(It.Is<Uri>(u => u.Equals(resource)), out settings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.PasswordNeeded); repository.Setup(r => r.TryLoadSettings(It.Is<Uri>(u => u.Equals(resource)), out settings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.PasswordNeeded);
@ -590,14 +583,12 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
} }
[TestMethod] [TestMethod]
public void Rever_MustDoNothing() public void Revert_MustDoNothing()
{ {
var sut = new ConfigurationOperation(null, repository.Object, hashAlgorithm.Object, logger.Object, sessionContext); var sut = new ConfigurationOperation(null, repository.Object, hashAlgorithm.Object, logger.Object, sessionContext);
var result = sut.Revert(); var result = sut.Revert();
currentSession.VerifyNoOtherCalls();
hashAlgorithm.VerifyNoOtherCalls(); hashAlgorithm.VerifyNoOtherCalls();
nextSession.VerifyNoOtherCalls();
repository.VerifyNoOtherCalls(); repository.VerifyNoOtherCalls();
Assert.AreEqual(OperationResult.Success, result); Assert.AreEqual(OperationResult.Success, result);

View file

@ -20,12 +20,12 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
[TestClass] [TestClass]
public class KioskModeOperationTests public class KioskModeOperationTests
{ {
private Mock<ISessionConfiguration> currentSession; private SessionConfiguration currentSession;
private Settings currentSettings; private Settings currentSettings;
private Mock<IDesktopFactory> desktopFactory; private Mock<IDesktopFactory> desktopFactory;
private Mock<IExplorerShell> explorerShell; private Mock<IExplorerShell> explorerShell;
private Mock<ILogger> logger; private Mock<ILogger> logger;
private Mock<ISessionConfiguration> nextSession; private SessionConfiguration nextSession;
private Settings nextSettings; private Settings nextSettings;
private Mock<IProcessFactory> processFactory; private Mock<IProcessFactory> processFactory;
private SessionContext sessionContext; private SessionContext sessionContext;
@ -35,20 +35,20 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
[TestInitialize] [TestInitialize]
public void Initialize() public void Initialize()
{ {
currentSession = new Mock<ISessionConfiguration>(); currentSession = new SessionConfiguration();
currentSettings = new Settings(); currentSettings = new Settings();
desktopFactory = new Mock<IDesktopFactory>(); desktopFactory = new Mock<IDesktopFactory>();
explorerShell = new Mock<IExplorerShell>(); explorerShell = new Mock<IExplorerShell>();
logger = new Mock<ILogger>(); logger = new Mock<ILogger>();
nextSession = new Mock<ISessionConfiguration>(); nextSession = new SessionConfiguration();
nextSettings = new Settings(); nextSettings = new Settings();
processFactory = new Mock<IProcessFactory>(); processFactory = new Mock<IProcessFactory>();
sessionContext = new SessionContext(); sessionContext = new SessionContext();
currentSession.SetupGet(s => s.Settings).Returns(currentSettings); currentSession.Settings = currentSettings;
nextSession.SetupGet(s => s.Settings).Returns(nextSettings); nextSession.Settings = nextSettings;
sessionContext.Current = currentSession.Object; sessionContext.Current = currentSession;
sessionContext.Next = nextSession.Object; sessionContext.Next = nextSession;
sut = new KioskModeOperation(desktopFactory.Object, explorerShell.Object, logger.Object, processFactory.Object, sessionContext); sut = new KioskModeOperation(desktopFactory.Object, explorerShell.Object, logger.Object, processFactory.Object, sessionContext);
} }

View file

@ -23,32 +23,32 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
private Mock<IDesktopFactory> desktopFactory; private Mock<IDesktopFactory> desktopFactory;
private Mock<IExplorerShell> explorerShell; private Mock<IExplorerShell> explorerShell;
private Mock<ILogger> logger; private Mock<ILogger> logger;
private Mock<ISessionConfiguration> nextSession; private SessionConfiguration nextSession;
private Settings nextSettings; private Settings nextSettings;
private Mock<IProcessFactory> processFactory; private Mock<IProcessFactory> processFactory;
private SessionContext sessionContext; private SessionContext sessionContext;
private KioskModeTerminationOperation sut; private KioskModeTerminationOperation sut;
private Mock<ISessionConfiguration> currentSession; private SessionConfiguration currentSession;
private Settings currentSettings; private Settings currentSettings;
[TestInitialize] [TestInitialize]
public void Initialize() public void Initialize()
{ {
currentSession = new Mock<ISessionConfiguration>(); currentSession = new SessionConfiguration();
currentSettings = new Settings(); currentSettings = new Settings();
desktopFactory = new Mock<IDesktopFactory>(); desktopFactory = new Mock<IDesktopFactory>();
explorerShell = new Mock<IExplorerShell>(); explorerShell = new Mock<IExplorerShell>();
logger = new Mock<ILogger>(); logger = new Mock<ILogger>();
nextSession = new Mock<ISessionConfiguration>(); nextSession = new SessionConfiguration();
nextSettings = new Settings(); nextSettings = new Settings();
processFactory = new Mock<IProcessFactory>(); processFactory = new Mock<IProcessFactory>();
sessionContext = new SessionContext(); sessionContext = new SessionContext();
currentSession.SetupGet(s => s.Settings).Returns(currentSettings); currentSession.Settings = currentSettings;
nextSession.SetupGet(s => s.Settings).Returns(nextSettings); nextSession.Settings = nextSettings;
sessionContext.Current = currentSession.Object; sessionContext.Current = currentSession;
sessionContext.Next = nextSession.Object; sessionContext.Next = nextSession;
sut = new KioskModeTerminationOperation(desktopFactory.Object, explorerShell.Object, logger.Object, processFactory.Object, sessionContext); sut = new KioskModeTerminationOperation(desktopFactory.Object, explorerShell.Object, logger.Object, processFactory.Object, sessionContext);
} }
@ -58,11 +58,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
{ {
var result = sut.Perform(); var result = sut.Perform();
currentSession.VerifyNoOtherCalls();
desktopFactory.VerifyNoOtherCalls(); desktopFactory.VerifyNoOtherCalls();
explorerShell.VerifyNoOtherCalls(); explorerShell.VerifyNoOtherCalls();
logger.VerifyNoOtherCalls(); logger.VerifyNoOtherCalls();
nextSession.VerifyNoOtherCalls();
processFactory.VerifyNoOtherCalls(); processFactory.VerifyNoOtherCalls();
Assert.AreEqual(OperationResult.Success, result); Assert.AreEqual(OperationResult.Success, result);
@ -178,11 +176,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
{ {
var result = sut.Revert(); var result = sut.Revert();
currentSession.VerifyNoOtherCalls();
desktopFactory.VerifyNoOtherCalls(); desktopFactory.VerifyNoOtherCalls();
explorerShell.VerifyNoOtherCalls(); explorerShell.VerifyNoOtherCalls();
logger.VerifyNoOtherCalls(); logger.VerifyNoOtherCalls();
nextSession.VerifyNoOtherCalls();
processFactory.VerifyNoOtherCalls(); processFactory.VerifyNoOtherCalls();
Assert.AreEqual(OperationResult.Success, result); Assert.AreEqual(OperationResult.Success, result);

View file

@ -25,7 +25,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
private Mock<ILogger> logger; private Mock<ILogger> logger;
private Mock<IRuntimeHost> runtimeHost; private Mock<IRuntimeHost> runtimeHost;
private Mock<IServiceProxy> service; private Mock<IServiceProxy> service;
private Mock<ISessionConfiguration> session; private SessionConfiguration session;
private SessionContext sessionContext; private SessionContext sessionContext;
private Settings settings; private Settings settings;
private ServiceOperation sut; private ServiceOperation sut;
@ -36,13 +36,13 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
logger = new Mock<ILogger>(); logger = new Mock<ILogger>();
runtimeHost = new Mock<IRuntimeHost>(); runtimeHost = new Mock<IRuntimeHost>();
service = new Mock<IServiceProxy>(); service = new Mock<IServiceProxy>();
session = new Mock<ISessionConfiguration>(); session = new SessionConfiguration();
sessionContext = new SessionContext(); sessionContext = new SessionContext();
settings = new Settings(); settings = new Settings();
sessionContext.Current = session.Object; sessionContext.Current = session;
sessionContext.Next = session.Object; sessionContext.Next = session;
session.SetupGet(s => s.Settings).Returns(settings); session.Settings = settings;
settings.ServicePolicy = ServicePolicy.Mandatory; settings.ServicePolicy = ServicePolicy.Mandatory;
sut = new ServiceOperation(logger.Object, runtimeHost.Object, service.Object, sessionContext, 0); sut = new ServiceOperation(logger.Object, runtimeHost.Object, service.Object, sessionContext, 0);
@ -70,13 +70,13 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
service.SetupGet(s => s.IsConnected).Returns(true); service.SetupGet(s => s.IsConnected).Returns(true);
service.Setup(s => s.Connect(null, true)).Returns(true); service.Setup(s => s.Connect(null, true)).Returns(true);
service service
.Setup(s => s.StartSession(It.IsAny<Guid>(), It.IsAny<Settings>())) .Setup(s => s.StartSession(It.IsAny<ServiceConfiguration>()))
.Returns(new CommunicationResult(true)) .Returns(new CommunicationResult(true))
.Callback(() => runtimeHost.Raise(h => h.ServiceSessionStarted += null)); .Callback(() => runtimeHost.Raise(h => h.ServiceSessionStarted += null));
var result = sut.Perform(); var result = sut.Perform();
service.Verify(s => s.StartSession(It.IsAny<Guid>(), It.IsAny<Settings>()), Times.Once); service.Verify(s => s.StartSession(It.IsAny<ServiceConfiguration>()), Times.Once);
Assert.AreEqual(OperationResult.Success, result); Assert.AreEqual(OperationResult.Success, result);
} }
@ -87,13 +87,13 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
service.SetupGet(s => s.IsConnected).Returns(true); service.SetupGet(s => s.IsConnected).Returns(true);
service.Setup(s => s.Connect(null, true)).Returns(true); service.Setup(s => s.Connect(null, true)).Returns(true);
service service
.Setup(s => s.StartSession(It.IsAny<Guid>(), It.IsAny<Settings>())) .Setup(s => s.StartSession(It.IsAny<ServiceConfiguration>()))
.Returns(new CommunicationResult(true)) .Returns(new CommunicationResult(true))
.Callback(() => runtimeHost.Raise(h => h.ServiceFailed += null)); .Callback(() => runtimeHost.Raise(h => h.ServiceFailed += null));
var result = sut.Perform(); var result = sut.Perform();
service.Verify(s => s.StartSession(It.IsAny<Guid>(), It.IsAny<Settings>()), Times.Once); service.Verify(s => s.StartSession(It.IsAny<ServiceConfiguration>()), Times.Once);
Assert.AreEqual(OperationResult.Failed, result); Assert.AreEqual(OperationResult.Failed, result);
} }
@ -108,7 +108,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
service.SetupGet(s => s.IsConnected).Returns(true); service.SetupGet(s => s.IsConnected).Returns(true);
service.Setup(s => s.Connect(null, true)).Returns(true); service.Setup(s => s.Connect(null, true)).Returns(true);
service.Setup(s => s.StartSession(It.IsAny<Guid>(), It.IsAny<Settings>())).Returns(new CommunicationResult(true)); service.Setup(s => s.StartSession(It.IsAny<ServiceConfiguration>())).Returns(new CommunicationResult(true));
sut = new ServiceOperation(logger.Object, runtimeHost.Object, service.Object, sessionContext, TIMEOUT); sut = new ServiceOperation(logger.Object, runtimeHost.Object, service.Object, sessionContext, TIMEOUT);
@ -116,7 +116,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
var result = sut.Perform(); var result = sut.Perform();
after = DateTime.Now; after = DateTime.Now;
service.Verify(s => s.StartSession(It.IsAny<Guid>(), It.IsAny<Settings>()), Times.Once); service.Verify(s => s.StartSession(It.IsAny<ServiceConfiguration>()), Times.Once);
Assert.AreEqual(OperationResult.Failed, result); Assert.AreEqual(OperationResult.Failed, result);
Assert.IsTrue(after - before >= new TimeSpan(0, 0, 0, 0, TIMEOUT)); Assert.IsTrue(after - before >= new TimeSpan(0, 0, 0, 0, TIMEOUT));
@ -130,7 +130,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
sut.Perform(); sut.Perform();
service.Verify(s => s.StartSession(It.IsAny<Guid>(), It.IsAny<Settings>()), Times.Never); service.Verify(s => s.StartSession(It.IsAny<ServiceConfiguration>()), Times.Never);
} }
[TestMethod] [TestMethod]
@ -172,7 +172,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
service.Verify(s => s.Connect(It.IsAny<Guid?>(), It.IsAny<bool>()), Times.Once); service.Verify(s => s.Connect(It.IsAny<Guid?>(), It.IsAny<bool>()), Times.Once);
service.Verify(s => s.StopSession(It.IsAny<Guid>()), Times.Once); service.Verify(s => s.StopSession(It.IsAny<Guid>()), Times.Once);
service.Verify(s => s.StartSession(It.IsAny<Guid>(), It.IsAny<Settings>()), Times.Exactly(2)); service.Verify(s => s.StartSession(It.IsAny<ServiceConfiguration>()), Times.Exactly(2));
service.Verify(s => s.Disconnect(), Times.Never); service.Verify(s => s.Disconnect(), Times.Never);
Assert.AreEqual(OperationResult.Success, result); Assert.AreEqual(OperationResult.Success, result);
@ -188,7 +188,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
var result = sut.Repeat(); var result = sut.Repeat();
service.Verify(s => s.StopSession(It.IsAny<Guid>()), Times.Once); service.Verify(s => s.StopSession(It.IsAny<Guid>()), Times.Once);
service.Verify(s => s.StartSession(It.IsAny<Guid>(), It.IsAny<Settings>()), Times.Once); service.Verify(s => s.StartSession(It.IsAny<ServiceConfiguration>()), Times.Once);
service.Verify(s => s.Disconnect(), Times.Never); service.Verify(s => s.Disconnect(), Times.Never);
Assert.AreEqual(OperationResult.Failed, result); Assert.AreEqual(OperationResult.Failed, result);
@ -320,7 +320,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
service.SetupGet(s => s.IsConnected).Returns(true); service.SetupGet(s => s.IsConnected).Returns(true);
service.Setup(s => s.Connect(null, true)).Returns(true); service.Setup(s => s.Connect(null, true)).Returns(true);
service service
.Setup(s => s.StartSession(It.IsAny<Guid>(), It.IsAny<Settings>())) .Setup(s => s.StartSession(It.IsAny<ServiceConfiguration>()))
.Returns(new CommunicationResult(true)) .Returns(new CommunicationResult(true))
.Callback(() => runtimeHost.Raise(h => h.ServiceSessionStarted += null)); .Callback(() => runtimeHost.Raise(h => h.ServiceSessionStarted += null));

View file

@ -19,9 +19,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
[TestClass] [TestClass]
public class SessionActivationOperationTests public class SessionActivationOperationTests
{ {
private Mock<ISessionConfiguration> currentSession; private SessionConfiguration currentSession;
private Mock<ILogger> logger; private Mock<ILogger> logger;
private Mock<ISessionConfiguration> nextSession; private SessionConfiguration nextSession;
private Settings nextSettings; private Settings nextSettings;
private SessionContext sessionContext; private SessionContext sessionContext;
@ -30,15 +30,15 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
[TestInitialize] [TestInitialize]
public void Initialize() public void Initialize()
{ {
currentSession = new Mock<ISessionConfiguration>(); currentSession = new SessionConfiguration();
logger = new Mock<ILogger>(); logger = new Mock<ILogger>();
nextSession = new Mock<ISessionConfiguration>(); nextSession = new SessionConfiguration();
nextSettings = new Settings(); nextSettings = new Settings();
sessionContext = new SessionContext(); sessionContext = new SessionContext();
nextSession.SetupGet(s => s.Settings).Returns(nextSettings); nextSession.Settings = nextSettings;
sessionContext.Current = currentSession.Object; sessionContext.Current = currentSession;
sessionContext.Next = nextSession.Object; sessionContext.Next = nextSession;
sut = new SessionActivationOperation(logger.Object, sessionContext); sut = new SessionActivationOperation(logger.Object, sessionContext);
} }
@ -50,11 +50,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
var result = sut.Perform(); var result = sut.Perform();
currentSession.VerifyNoOtherCalls();
nextSession.VerifyGet(s => s.Id);
Assert.AreEqual(OperationResult.Success, result); Assert.AreEqual(OperationResult.Success, result);
Assert.AreSame(sessionContext.Current, nextSession.Object); Assert.AreSame(sessionContext.Current, nextSession);
Assert.IsNull(sessionContext.Next); Assert.IsNull(sessionContext.Next);
} }
@ -73,11 +70,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
{ {
var result = sut.Repeat(); var result = sut.Repeat();
currentSession.VerifyGet(s => s.Id);
nextSession.VerifyGet(s => s.Id);
Assert.AreEqual(OperationResult.Success, result); Assert.AreEqual(OperationResult.Success, result);
Assert.AreSame(sessionContext.Current, nextSession.Object); Assert.AreSame(sessionContext.Current, nextSession);
Assert.IsNull(sessionContext.Next); Assert.IsNull(sessionContext.Next);
} }
@ -96,9 +90,6 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
{ {
var result = sut.Revert(); var result = sut.Revert();
currentSession.VerifyNoOtherCalls();
nextSession.VerifyNoOtherCalls();
Assert.AreEqual(OperationResult.Success, result); Assert.AreEqual(OperationResult.Success, result);
} }
} }

View file

@ -23,7 +23,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
private Mock<IConfigurationRepository> configuration; private Mock<IConfigurationRepository> configuration;
private Mock<ILogger> logger; private Mock<ILogger> logger;
private Mock<IRuntimeHost> runtimeHost; private Mock<IRuntimeHost> runtimeHost;
private Mock<ISessionConfiguration> session; private SessionConfiguration session;
private SessionContext sessionContext; private SessionContext sessionContext;
private SessionInitializationOperation sut; private SessionInitializationOperation sut;
@ -35,12 +35,12 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
configuration = new Mock<IConfigurationRepository>(); configuration = new Mock<IConfigurationRepository>();
logger = new Mock<ILogger>(); logger = new Mock<ILogger>();
runtimeHost = new Mock<IRuntimeHost>(); runtimeHost = new Mock<IRuntimeHost>();
session = new Mock<ISessionConfiguration>(); session = new SessionConfiguration();
sessionContext = new SessionContext(); sessionContext = new SessionContext();
configuration.Setup(c => c.InitializeSessionConfiguration()).Returns(session.Object); configuration.Setup(c => c.InitializeSessionConfiguration()).Returns(session);
session.SetupGet(s => s.AppConfig).Returns(appConfig); session.AppConfig = appConfig;
sessionContext.Next = session.Object; sessionContext.Next = session;
sut = new SessionInitializationOperation(configuration.Object, logger.Object, runtimeHost.Object, sessionContext); sut = new SessionInitializationOperation(configuration.Object, logger.Object, runtimeHost.Object, sessionContext);
} }
@ -50,12 +50,12 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
{ {
var token = Guid.NewGuid(); var token = Guid.NewGuid();
session.SetupGet(s => s.StartupToken).Returns(token); session.ClientAuthenticationToken = token;
sut.Perform(); sut.Perform();
configuration.Verify(c => c.InitializeSessionConfiguration(), Times.Once); configuration.Verify(c => c.InitializeSessionConfiguration(), Times.Once);
runtimeHost.VerifySet(r => r.StartupToken = token, Times.Once); runtimeHost.VerifySet(r => r.AuthenticationToken = token, Times.Once);
} }
[TestMethod] [TestMethod]
@ -63,12 +63,12 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
{ {
var token = Guid.NewGuid(); var token = Guid.NewGuid();
session.SetupGet(s => s.StartupToken).Returns(token); session.ClientAuthenticationToken = token;
sut.Repeat(); sut.Repeat();
configuration.Verify(c => c.InitializeSessionConfiguration(), Times.Once); configuration.Verify(c => c.InitializeSessionConfiguration(), Times.Once);
runtimeHost.VerifySet(r => r.StartupToken = token, Times.Once); runtimeHost.VerifySet(r => r.AuthenticationToken = token, Times.Once);
} }
[TestMethod] [TestMethod]

View file

@ -34,11 +34,11 @@ namespace SafeExamBrowser.Runtime.UnitTests
private Mock<IOperationSequence> bootstrapSequence; private Mock<IOperationSequence> bootstrapSequence;
private Mock<IProcess> clientProcess; private Mock<IProcess> clientProcess;
private Mock<IClientProxy> clientProxy; private Mock<IClientProxy> clientProxy;
private Mock<ISessionConfiguration> currentSession; private SessionConfiguration currentSession;
private Settings currentSettings; private Settings currentSettings;
private Mock<ILogger> logger; private Mock<ILogger> logger;
private Mock<IMessageBox> messageBox; private Mock<IMessageBox> messageBox;
private Mock<ISessionConfiguration> nextSession; private SessionConfiguration nextSession;
private Settings nextSettings; private Settings nextSettings;
private Mock<Action> shutdown; private Mock<Action> shutdown;
private Mock<IText> text; private Mock<IText> text;
@ -56,11 +56,11 @@ namespace SafeExamBrowser.Runtime.UnitTests
bootstrapSequence = new Mock<IOperationSequence>(); bootstrapSequence = new Mock<IOperationSequence>();
clientProcess = new Mock<IProcess>(); clientProcess = new Mock<IProcess>();
clientProxy = new Mock<IClientProxy>(); clientProxy = new Mock<IClientProxy>();
currentSession = new Mock<ISessionConfiguration>(); currentSession = new SessionConfiguration();
currentSettings = new Settings(); currentSettings = new Settings();
logger = new Mock<ILogger>(); logger = new Mock<ILogger>();
messageBox = new Mock<IMessageBox>(); messageBox = new Mock<IMessageBox>();
nextSession = new Mock<ISessionConfiguration>(); nextSession = new SessionConfiguration();
nextSettings = new Settings(); nextSettings = new Settings();
runtimeHost = new Mock<IRuntimeHost>(); runtimeHost = new Mock<IRuntimeHost>();
service = new Mock<IServiceProxy>(); service = new Mock<IServiceProxy>();
@ -70,13 +70,13 @@ namespace SafeExamBrowser.Runtime.UnitTests
text = new Mock<IText>(); text = new Mock<IText>();
uiFactory = new Mock<IUserInterfaceFactory>(); uiFactory = new Mock<IUserInterfaceFactory>();
currentSession.SetupGet(s => s.Settings).Returns(currentSettings); currentSession.Settings = currentSettings;
nextSession.SetupGet(s => s.Settings).Returns(nextSettings); nextSession.Settings = nextSettings;
sessionContext.ClientProcess = clientProcess.Object; sessionContext.ClientProcess = clientProcess.Object;
sessionContext.ClientProxy = clientProxy.Object; sessionContext.ClientProxy = clientProxy.Object;
sessionContext.Current = currentSession.Object; sessionContext.Current = currentSession;
sessionContext.Next = nextSession.Object; sessionContext.Next = nextSession;
uiFactory.Setup(u => u.CreateRuntimeWindow(It.IsAny<AppConfig>())).Returns(new Mock<IRuntimeWindow>().Object); uiFactory.Setup(u => u.CreateRuntimeWindow(It.IsAny<AppConfig>())).Returns(new Mock<IRuntimeWindow>().Object);
uiFactory.Setup(u => u.CreateSplashScreen(It.IsAny<AppConfig>())).Returns(new Mock<ISplashScreen>().Object); uiFactory.Setup(u => u.CreateSplashScreen(It.IsAny<AppConfig>())).Returns(new Mock<ISplashScreen>().Object);
@ -135,9 +135,9 @@ namespace SafeExamBrowser.Runtime.UnitTests
var nextSessionId = Guid.NewGuid(); var nextSessionId = Guid.NewGuid();
var nextSettings = new Settings(); var nextSettings = new Settings();
nextSession.SetupGet(s => s.AppConfig).Returns(nextAppConfig); nextSession.AppConfig = nextAppConfig;
nextSession.SetupGet(s => s.Id).Returns(nextSessionId); nextSession.SessionId = nextSessionId;
nextSession.SetupGet(s => s.Settings).Returns(nextSettings); nextSession.Settings = nextSettings;
StartSession(); StartSession();
runtimeHost.Raise(r => r.ClientConfigurationNeeded += null, args); runtimeHost.Raise(r => r.ClientConfigurationNeeded += null, args);
@ -472,7 +472,7 @@ namespace SafeExamBrowser.Runtime.UnitTests
var session = 0; var session = 0;
bootstrapSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success).Callback(() => bootstrap = ++order); bootstrapSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success).Callback(() => bootstrap = ++order);
sessionSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success).Callback(() => { session = ++order; sessionContext.Current = currentSession.Object; }); sessionSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success).Callback(() => { session = ++order; sessionContext.Current = currentSession; });
sessionContext.Current = null; sessionContext.Current = null;
var success = sut.TryStart(); var success = sut.TryStart();
@ -496,7 +496,7 @@ namespace SafeExamBrowser.Runtime.UnitTests
var session = 0; var session = 0;
bootstrapSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Failed).Callback(() => bootstrap = ++order); bootstrapSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Failed).Callback(() => bootstrap = ++order);
sessionSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success).Callback(() => { session = ++order; sessionContext.Current = currentSession.Object; }); sessionSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success).Callback(() => { session = ++order; sessionContext.Current = currentSession; });
sessionContext.Current = null; sessionContext.Current = null;
var success = sut.TryStart(); var success = sut.TryStart();
@ -516,7 +516,7 @@ namespace SafeExamBrowser.Runtime.UnitTests
public void Startup_MustTerminateOnSessionStartFailure() public void Startup_MustTerminateOnSessionStartFailure()
{ {
bootstrapSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success); bootstrapSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success);
sessionSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Failed).Callback(() => sessionContext.Current = currentSession.Object); sessionSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Failed).Callback(() => sessionContext.Current = currentSession);
sessionContext.Current = null; sessionContext.Current = null;
var success = sut.TryStart(); var success = sut.TryStart();
@ -534,7 +534,7 @@ namespace SafeExamBrowser.Runtime.UnitTests
public void Startup_MustNotTerminateOnSessionStartAbortion() public void Startup_MustNotTerminateOnSessionStartAbortion()
{ {
bootstrapSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success); bootstrapSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success);
sessionSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Aborted).Callback(() => sessionContext.Current = currentSession.Object); sessionSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Aborted).Callback(() => sessionContext.Current = currentSession);
sessionContext.Current = null; sessionContext.Current = null;
var success = sut.TryStart(); var success = sut.TryStart();
@ -551,7 +551,7 @@ namespace SafeExamBrowser.Runtime.UnitTests
private void StartSession() private void StartSession()
{ {
bootstrapSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success); bootstrapSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success);
sessionSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success).Callback(() => sessionContext.Current = currentSession.Object); sessionSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success).Callback(() => sessionContext.Current = currentSession);
sessionContext.Current = null; sessionContext.Current = null;
sut.TryStart(); sut.TryStart();

View file

@ -18,7 +18,7 @@ namespace SafeExamBrowser.Runtime.Communication
internal class RuntimeHost : BaseHost, IRuntimeHost internal class RuntimeHost : BaseHost, IRuntimeHost
{ {
public bool AllowConnection { get; set; } public bool AllowConnection { get; set; }
public Guid StartupToken { private get; set; } public Guid AuthenticationToken { private get; set; }
public event CommunicationEventHandler ClientDisconnected; public event CommunicationEventHandler ClientDisconnected;
public event CommunicationEventHandler ClientReady; public event CommunicationEventHandler ClientReady;
@ -38,7 +38,7 @@ namespace SafeExamBrowser.Runtime.Communication
protected override bool OnConnect(Guid? token = null) protected override bool OnConnect(Guid? token = null)
{ {
var authenticated = StartupToken == token; var authenticated = AuthenticationToken == token;
var accepted = AllowConnection && authenticated; var accepted = AllowConnection && authenticated;
if (accepted) if (accepted)

View file

@ -95,11 +95,11 @@ namespace SafeExamBrowser.Runtime.Operations
private bool TryStartClient() private bool TryStartClient()
{ {
var clientExecutable = Context.Next.AppConfig.ClientExecutablePath; var authenticationToken = Context.Next.ClientAuthenticationToken.ToString("D");
var clientLogFile = $"{'"' + Context.Next.AppConfig.ClientLogFilePath + '"'}"; var executablePath = Context.Next.AppConfig.ClientExecutablePath;
var clientLogLevel = Context.Next.Settings.LogLevel.ToString(); var logFilePath = $"{'"' + Context.Next.AppConfig.ClientLogFilePath + '"'}";
var logLevel = Context.Next.Settings.LogLevel.ToString();
var runtimeHostUri = Context.Next.AppConfig.RuntimeAddress; var runtimeHostUri = Context.Next.AppConfig.RuntimeAddress;
var startupToken = Context.Next.StartupToken.ToString("D");
var uiMode = Context.Next.Settings.UserInterfaceMode.ToString(); var uiMode = Context.Next.Settings.UserInterfaceMode.ToString();
var clientReady = false; var clientReady = false;
@ -112,7 +112,7 @@ namespace SafeExamBrowser.Runtime.Operations
logger.Info("Starting new client process..."); logger.Info("Starting new client process...");
runtimeHost.AllowConnection = true; runtimeHost.AllowConnection = true;
runtimeHost.ClientReady += clientReadyEventHandler; runtimeHost.ClientReady += clientReadyEventHandler;
ClientProcess = processFactory.StartNew(clientExecutable, clientLogFile, clientLogLevel, runtimeHostUri, startupToken, uiMode); ClientProcess = processFactory.StartNew(executablePath, logFilePath, logLevel, runtimeHostUri, authenticationToken, uiMode);
ClientProcess.Terminated += clientTerminatedEventHandler; ClientProcess.Terminated += clientTerminatedEventHandler;
logger.Info("Waiting for client to complete initialization..."); logger.Info("Waiting for client to complete initialization...");
@ -147,7 +147,7 @@ namespace SafeExamBrowser.Runtime.Operations
logger.Info("Client has been successfully started and initialized. Creating communication proxy for client host..."); logger.Info("Client has been successfully started and initialized. Creating communication proxy for client host...");
ClientProxy = proxyFactory.CreateClientProxy(Context.Next.AppConfig.ClientAddress); ClientProxy = proxyFactory.CreateClientProxy(Context.Next.AppConfig.ClientAddress);
if (ClientProxy.Connect(Context.Next.StartupToken)) if (ClientProxy.Connect(Context.Next.ClientAuthenticationToken))
{ {
logger.Info("Connection with client has been established. Requesting authentication..."); logger.Info("Connection with client has been established. Requesting authentication...");

View file

@ -10,11 +10,14 @@ using System.Threading;
using SafeExamBrowser.Contracts.Communication.Events; using SafeExamBrowser.Contracts.Communication.Events;
using SafeExamBrowser.Contracts.Communication.Hosts; using SafeExamBrowser.Contracts.Communication.Hosts;
using SafeExamBrowser.Contracts.Communication.Proxies; using SafeExamBrowser.Contracts.Communication.Proxies;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Configuration.Settings; using SafeExamBrowser.Contracts.Configuration.Settings;
using SafeExamBrowser.Contracts.Core.OperationModel; using SafeExamBrowser.Contracts.Core.OperationModel;
using SafeExamBrowser.Contracts.Core.OperationModel.Events; using SafeExamBrowser.Contracts.Core.OperationModel.Events;
using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Contracts.UserInterface.MessageBox;
using SafeExamBrowser.Runtime.Operations.Events;
namespace SafeExamBrowser.Runtime.Operations namespace SafeExamBrowser.Runtime.Operations
{ {
@ -25,7 +28,7 @@ namespace SafeExamBrowser.Runtime.Operations
private IServiceProxy service; private IServiceProxy service;
private int timeout_ms; private int timeout_ms;
public override event ActionRequiredEventHandler ActionRequired { add { } remove { } } public override event ActionRequiredEventHandler ActionRequired;
public override event StatusChangedEventHandler StatusChanged; public override event StatusChangedEventHandler StatusChanged;
public ServiceOperation( public ServiceOperation(
@ -99,6 +102,7 @@ namespace SafeExamBrowser.Runtime.Operations
private bool TryEstablishConnection() private bool TryEstablishConnection()
{ {
var mandatory = Context.Next.Settings.ServicePolicy == ServicePolicy.Mandatory; var mandatory = Context.Next.Settings.ServicePolicy == ServicePolicy.Mandatory;
var warn = Context.Next.Settings.ServicePolicy == ServicePolicy.Warn;
var connected = service.Connect(); var connected = service.Connect();
var success = connected || !mandatory; var success = connected || !mandatory;
@ -106,10 +110,26 @@ namespace SafeExamBrowser.Runtime.Operations
{ {
service.Ignore = !connected; service.Ignore = !connected;
logger.Info($"The service is {(mandatory ? "mandatory" : "optional")} and {(connected ? "connected." : "not connected. All service-related operations will be ignored!")}"); logger.Info($"The service is {(mandatory ? "mandatory" : "optional")} and {(connected ? "connected." : "not connected. All service-related operations will be ignored!")}");
if (!connected && warn)
{
ActionRequired?.Invoke(new MessageEventArgs
{
Icon = MessageBoxIcon.Warning,
Message = TextKey.MessageBox_ServiceUnavailableWarning,
Title = TextKey.MessageBox_ServiceUnavailableWarningTitle
});
}
} }
else else
{ {
logger.Error("The service is mandatory but no connection could be established!"); logger.Error("The service is mandatory but no connection could be established!");
ActionRequired?.Invoke(new MessageEventArgs
{
Icon = MessageBoxIcon.Error,
Message = TextKey.MessageBox_ServiceUnavailableError,
Title = TextKey.MessageBox_ServiceUnavailableErrorTitle
});
} }
return success; return success;
@ -151,6 +171,13 @@ namespace SafeExamBrowser.Runtime.Operations
private bool TryStartSession() private bool TryStartSession()
{ {
var configuration = new ServiceConfiguration
{
AppConfig = Context.Next.AppConfig,
AuthenticationToken = Context.Next.ServiceAuthenticationToken,
SessionId = Context.Next.SessionId,
Settings = Context.Next.Settings
};
var failure = false; var failure = false;
var success = false; var success = false;
var serviceEvent = new AutoResetEvent(false); var serviceEvent = new AutoResetEvent(false);
@ -162,7 +189,7 @@ namespace SafeExamBrowser.Runtime.Operations
logger.Info("Starting new service session..."); logger.Info("Starting new service session...");
var communication = service.StartSession(Context.Next.Id, Context.Next.Settings); var communication = service.StartSession(configuration);
if (communication.Success) if (communication.Success)
{ {
@ -205,7 +232,7 @@ namespace SafeExamBrowser.Runtime.Operations
logger.Info("Stopping current service session..."); logger.Info("Stopping current service session...");
var communication = service.StopSession(Context.Current.Id); var communication = service.StopSession(Context.Current.SessionId);
if (communication.Success) if (communication.Success)
{ {

View file

@ -63,11 +63,11 @@ namespace SafeExamBrowser.Runtime.Operations
if (isFirstSession) if (isFirstSession)
{ {
logger.Info($"Successfully activated first session '{Context.Next.Id}'."); logger.Info($"Successfully activated first session '{Context.Next.SessionId}'.");
} }
else else
{ {
logger.Info($"Successfully terminated old session '{Context.Current.Id}' and activated new session '{Context.Next.Id}'."); logger.Info($"Successfully terminated old session '{Context.Current.SessionId}' and activated new session '{Context.Next.SessionId}'.");
} }
Context.Current = Context.Next; Context.Current = Context.Next;

View file

@ -63,11 +63,11 @@ namespace SafeExamBrowser.Runtime.Operations
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeSession); StatusChanged?.Invoke(TextKey.OperationStatus_InitializeSession);
Context.Next = configuration.InitializeSessionConfiguration(); Context.Next = configuration.InitializeSessionConfiguration();
runtimeHost.StartupToken = Context.Next.StartupToken; runtimeHost.AuthenticationToken = Context.Next.ClientAuthenticationToken;
logger.Info($" -> Client-ID: {Context.Next.AppConfig.ClientId}"); logger.Info($" -> Client-ID: {Context.Next.AppConfig.ClientId}");
logger.Info($" -> Runtime-ID: {Context.Next.AppConfig.RuntimeId}"); logger.Info($" -> Runtime-ID: {Context.Next.AppConfig.RuntimeId}");
logger.Info($" -> Session-ID: {Context.Next.Id}"); logger.Info($" -> Session-ID: {Context.Next.SessionId}");
} }
private void FinalizeSessionConfiguration() private void FinalizeSessionConfiguration()

View file

@ -42,7 +42,7 @@ namespace SafeExamBrowser.Runtime
private IText text; private IText text;
private IUserInterfaceFactory uiFactory; private IUserInterfaceFactory uiFactory;
private ISessionConfiguration Session private SessionConfiguration Session
{ {
get { return sessionContext.Current; } get { return sessionContext.Current; }
} }
@ -329,7 +329,7 @@ namespace SafeExamBrowser.Runtime
args.ClientConfiguration = new ClientConfiguration args.ClientConfiguration = new ClientConfiguration
{ {
AppConfig = sessionContext.Next.AppConfig, AppConfig = sessionContext.Next.AppConfig,
SessionId = sessionContext.Next.Id, SessionId = sessionContext.Next.SessionId,
Settings = sessionContext.Next.Settings Settings = sessionContext.Next.Settings
}; };
} }

View file

@ -36,7 +36,7 @@ namespace SafeExamBrowser.Runtime
/// <summary> /// <summary>
/// The configuration of the currently active session. /// The configuration of the currently active session.
/// </summary> /// </summary>
internal ISessionConfiguration Current { get; set; } internal SessionConfiguration Current { get; set; }
/// <summary> /// <summary>
/// The new desktop, if <see cref="KioskMode.CreateNewDesktop"/> is currently active. /// The new desktop, if <see cref="KioskMode.CreateNewDesktop"/> is currently active.
@ -46,7 +46,7 @@ namespace SafeExamBrowser.Runtime
/// <summary> /// <summary>
/// The configuration of the next session to be activated. /// The configuration of the next session to be activated.
/// </summary> /// </summary>
internal ISessionConfiguration Next { get; set; } internal SessionConfiguration Next { get; set; }
/// <summary> /// <summary>
/// The original desktop, if <see cref="KioskMode.CreateNewDesktop"/> is currently active. /// The original desktop, if <see cref="KioskMode.CreateNewDesktop"/> is currently active.

View file

@ -9,6 +9,7 @@
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq; using Moq;
using SafeExamBrowser.Contracts.Communication.Hosts; using SafeExamBrowser.Contracts.Communication.Hosts;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Core.OperationModel; using SafeExamBrowser.Contracts.Core.OperationModel;
namespace SafeExamBrowser.Service.UnitTests namespace SafeExamBrowser.Service.UnitTests
@ -65,6 +66,7 @@ namespace SafeExamBrowser.Service.UnitTests
bootstrapSequence.Setup(b => b.TryRevert()).Returns(OperationResult.Success).Callback(() => bootstrap = ++order); bootstrapSequence.Setup(b => b.TryRevert()).Returns(OperationResult.Success).Callback(() => bootstrap = ++order);
sessionSequence.Setup(b => b.TryRevert()).Returns(OperationResult.Success).Callback(() => session = ++order); sessionSequence.Setup(b => b.TryRevert()).Returns(OperationResult.Success).Callback(() => session = ++order);
sessionContext.Current = new ServiceConfiguration();
sut.Terminate(); sut.Terminate();

View file

@ -7,6 +7,7 @@
*/ */
using SafeExamBrowser.Contracts.Communication.Hosts; using SafeExamBrowser.Contracts.Communication.Hosts;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Core.OperationModel; using SafeExamBrowser.Contracts.Core.OperationModel;
using SafeExamBrowser.Contracts.Service; using SafeExamBrowser.Contracts.Service;
@ -19,7 +20,7 @@ namespace SafeExamBrowser.Service
private IServiceHost serviceHost; private IServiceHost serviceHost;
private SessionContext sessionContext; private SessionContext sessionContext;
private object Session private ServiceConfiguration Session
{ {
get { return sessionContext.Current; } get { return sessionContext.Current; }
} }

View file

@ -6,6 +6,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
using SafeExamBrowser.Contracts.Configuration;
namespace SafeExamBrowser.Service namespace SafeExamBrowser.Service
{ {
/// <summary> /// <summary>
@ -16,11 +18,11 @@ namespace SafeExamBrowser.Service
/// <summary> /// <summary>
/// The configuration of the currently active session. /// The configuration of the currently active session.
/// </summary> /// </summary>
internal object Current { get; set; } internal ServiceConfiguration Current { get; set; }
/// <summary> /// <summary>
/// The configuration of the next session to be activated. /// The configuration of the next session to be activated.
/// </summary> /// </summary>
internal object Next { get; set; } internal ServiceConfiguration Next { get; set; }
} }
} }