SEBWIN-301: Changed service procedure so that the service initiates a system configuration update on command from the runtime. Added functionality to terminate the application on service connection loss.
This commit is contained in:
parent
39b63218fb
commit
6f0b0d0fb2
21 changed files with 327 additions and 126 deletions
|
@ -18,7 +18,7 @@ namespace SafeExamBrowser.Client.Communication
|
||||||
{
|
{
|
||||||
internal class ClientHost : BaseHost, IClientHost
|
internal class ClientHost : BaseHost, IClientHost
|
||||||
{
|
{
|
||||||
private bool allowConnection = true;
|
private bool allowConnection;
|
||||||
private int processId;
|
private int processId;
|
||||||
|
|
||||||
public Guid AuthenticationToken { private get; set; }
|
public Guid AuthenticationToken { private get; set; }
|
||||||
|
@ -37,6 +37,7 @@ namespace SafeExamBrowser.Client.Communication
|
||||||
int processId,
|
int processId,
|
||||||
int timeout_ms) : base(address, factory, logger, timeout_ms)
|
int timeout_ms) : base(address, factory, logger, timeout_ms)
|
||||||
{
|
{
|
||||||
|
this.allowConnection = true;
|
||||||
this.processId = processId;
|
this.processId = processId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,14 +7,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.ServiceModel;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
using Moq;
|
using Moq;
|
||||||
using SafeExamBrowser.Contracts.Communication.Data;
|
|
||||||
using SafeExamBrowser.Contracts.Communication.Proxies;
|
|
||||||
using SafeExamBrowser.Contracts.Logging;
|
|
||||||
using SafeExamBrowser.Communication.Proxies;
|
using SafeExamBrowser.Communication.Proxies;
|
||||||
using SafeExamBrowser.Contracts.Communication;
|
using SafeExamBrowser.Contracts.Communication;
|
||||||
|
using SafeExamBrowser.Contracts.Communication.Data;
|
||||||
|
using SafeExamBrowser.Contracts.Communication.Proxies;
|
||||||
|
using SafeExamBrowser.Contracts.Configuration;
|
||||||
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Communication.UnitTests.Proxies
|
namespace SafeExamBrowser.Communication.UnitTests.Proxies
|
||||||
{
|
{
|
||||||
|
@ -39,18 +39,19 @@ namespace SafeExamBrowser.Communication.UnitTests.Proxies
|
||||||
proxyObjectFactory = new Mock<IProxyObjectFactory>();
|
proxyObjectFactory = new Mock<IProxyObjectFactory>();
|
||||||
proxy = new Mock<IProxyObject>();
|
proxy = new Mock<IProxyObject>();
|
||||||
|
|
||||||
proxy.Setup(p => p.Connect(It.IsAny<Guid>())).Returns(response);
|
proxy.Setup(p => p.Connect(null)).Returns(response);
|
||||||
proxy.Setup(o => o.State).Returns(CommunicationState.Opened);
|
proxy.Setup(o => o.State).Returns(System.ServiceModel.CommunicationState.Opened);
|
||||||
proxyObjectFactory.Setup(f => f.CreateObject(It.IsAny<string>())).Returns(proxy.Object);
|
proxyObjectFactory.Setup(f => f.CreateObject(It.IsAny<string>())).Returns(proxy.Object);
|
||||||
|
|
||||||
sut = new ServiceProxy("net.pipe://random/address/here", proxyObjectFactory.Object, logger.Object, default(Interlocutor));
|
sut = new ServiceProxy("net.pipe://random/address/here", proxyObjectFactory.Object, logger.Object, default(Interlocutor));
|
||||||
|
sut.Connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void MustIgnoreConnectIfUnavailable()
|
public void MustIgnoreConnectIfUnavailable()
|
||||||
{
|
{
|
||||||
sut.Ignore = true;
|
sut.Ignore = true;
|
||||||
sut.Connect(Guid.NewGuid());
|
sut.Connect();
|
||||||
|
|
||||||
proxy.Verify(p => p.Connect(It.IsAny<Guid>()), Times.Never);
|
proxy.Verify(p => p.Connect(It.IsAny<Guid>()), Times.Never);
|
||||||
}
|
}
|
||||||
|
@ -64,6 +65,61 @@ namespace SafeExamBrowser.Communication.UnitTests.Proxies
|
||||||
proxy.Verify(p => p.Disconnect(It.IsAny<DisconnectionMessage>()), Times.Never);
|
proxy.Verify(p => p.Disconnect(It.IsAny<DisconnectionMessage>()), Times.Never);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void MustCorrectlySendSystemConfigurationUpdate()
|
||||||
|
{
|
||||||
|
proxy.Setup(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.UpdateSystemConfiguration))).Returns(new SimpleResponse(SimpleResponsePurport.Acknowledged));
|
||||||
|
|
||||||
|
var communication = sut.RunSystemConfigurationUpdate();
|
||||||
|
|
||||||
|
proxy.Verify(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.UpdateSystemConfiguration)), Times.Once);
|
||||||
|
|
||||||
|
Assert.IsTrue(communication.Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void MustFailIfSystemConfigurationUpdateNotAcknowledged()
|
||||||
|
{
|
||||||
|
proxy.Setup(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.UpdateSystemConfiguration))).Returns<Response>(null);
|
||||||
|
|
||||||
|
var communication = sut.RunSystemConfigurationUpdate();
|
||||||
|
|
||||||
|
Assert.IsFalse(communication.Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void MustIgnoreSystemConfigurationUpdateIfUnavailable()
|
||||||
|
{
|
||||||
|
sut.Ignore = true;
|
||||||
|
sut.RunSystemConfigurationUpdate();
|
||||||
|
|
||||||
|
proxy.Verify(p => p.Send(It.IsAny<Message>()), Times.Never);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void MustCorrectlyStartSession()
|
||||||
|
{
|
||||||
|
var configuration = new ServiceConfiguration { SessionId = Guid.NewGuid() };
|
||||||
|
|
||||||
|
proxy.Setup(p => p.Send(It.IsAny<SessionStartMessage>())).Returns(new SimpleResponse(SimpleResponsePurport.Acknowledged));
|
||||||
|
|
||||||
|
var communication = sut.StartSession(configuration);
|
||||||
|
|
||||||
|
proxy.Verify(p => p.Send(It.Is<SessionStartMessage>(m => m.Configuration.SessionId == configuration.SessionId)), Times.Once);
|
||||||
|
|
||||||
|
Assert.IsTrue(communication.Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void MustFailIfSessionStartNotAcknowledged()
|
||||||
|
{
|
||||||
|
proxy.Setup(p => p.Send(It.IsAny<SessionStartMessage>())).Returns<Response>(null);
|
||||||
|
|
||||||
|
var communication = sut.StartSession(new ServiceConfiguration());
|
||||||
|
|
||||||
|
Assert.IsFalse(communication.Success);
|
||||||
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void MustIgnoreStartSessionIfUnavaiable()
|
public void MustIgnoreStartSessionIfUnavaiable()
|
||||||
{
|
{
|
||||||
|
@ -75,6 +131,30 @@ namespace SafeExamBrowser.Communication.UnitTests.Proxies
|
||||||
proxy.Verify(p => p.Send(It.IsAny<Message>()), Times.Never);
|
proxy.Verify(p => p.Send(It.IsAny<Message>()), Times.Never);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void MustCorrectlyStopSession()
|
||||||
|
{
|
||||||
|
var sessionId = Guid.NewGuid();
|
||||||
|
|
||||||
|
proxy.Setup(p => p.Send(It.IsAny<SessionStopMessage>())).Returns(new SimpleResponse(SimpleResponsePurport.Acknowledged));
|
||||||
|
|
||||||
|
var communication = sut.StopSession(sessionId);
|
||||||
|
|
||||||
|
proxy.Verify(p => p.Send(It.Is<SessionStopMessage>(m => m.SessionId == sessionId)), Times.Once);
|
||||||
|
|
||||||
|
Assert.IsTrue(communication.Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void MustFailIfSessionStopNotAcknowledged()
|
||||||
|
{
|
||||||
|
proxy.Setup(p => p.Send(It.IsAny<SessionStopMessage>())).Returns<Response>(null);
|
||||||
|
|
||||||
|
var communication = sut.StopSession(Guid.Empty);
|
||||||
|
|
||||||
|
Assert.IsFalse(communication.Success);
|
||||||
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void MustIgnoreStopSessionIfUnavaiable()
|
public void MustIgnoreStopSessionIfUnavaiable()
|
||||||
{
|
{
|
||||||
|
|
|
@ -46,6 +46,37 @@ namespace SafeExamBrowser.Communication.Proxies
|
||||||
return base.Disconnect();
|
return base.Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CommunicationResult RunSystemConfigurationUpdate()
|
||||||
|
{
|
||||||
|
if (IgnoreOperation(nameof(RunSystemConfigurationUpdate)))
|
||||||
|
{
|
||||||
|
return new CommunicationResult(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var response = Send(SimpleMessagePurport.UpdateSystemConfiguration);
|
||||||
|
var success = IsAcknowledged(response);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
Logger.Debug("Service acknowledged system configuration update.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.Error($"Service did not acknowledge system configuration update! Received: {ToString(response)}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CommunicationResult(success);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Logger.Error($"Failed to perform '{nameof(RunSystemConfigurationUpdate)}'", e);
|
||||||
|
|
||||||
|
return new CommunicationResult(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public CommunicationResult StartSession(ServiceConfiguration configuration)
|
public CommunicationResult StartSession(ServiceConfiguration configuration)
|
||||||
{
|
{
|
||||||
if (IgnoreOperation(nameof(StartSession)))
|
if (IgnoreOperation(nameof(StartSession)))
|
||||||
|
|
|
@ -44,6 +44,11 @@ namespace SafeExamBrowser.Contracts.Communication.Data
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sent form the runtime to the client to command the latter to shut itself down.
|
/// Sent form the runtime to the client to command the latter to shut itself down.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Shutdown
|
Shutdown,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sent from the runtime to the service to command the latter to update the system configuration.
|
||||||
|
/// </summary>
|
||||||
|
UpdateSystemConfiguration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,6 @@ namespace SafeExamBrowser.Contracts.Communication.Hosts
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IServiceHost : ICommunicationHost
|
public interface IServiceHost : ICommunicationHost
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Determines whether another application component may establish a connection with the host.
|
|
||||||
/// </summary>
|
|
||||||
bool AllowConnection { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event fired when the runtime requested to start a new session.
|
/// Event fired when the runtime requested to start a new session.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -29,5 +24,10 @@ namespace SafeExamBrowser.Contracts.Communication.Hosts
|
||||||
/// Event fired when the runtime requested to stop a running session.
|
/// Event fired when the runtime requested to stop a running session.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event CommunicationEventHandler<SessionStopEventArgs> SessionStopRequested;
|
event CommunicationEventHandler<SessionStopEventArgs> SessionStopRequested;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event fired when the runtime requested to update the system configuration.
|
||||||
|
/// </summary>
|
||||||
|
event CommunicationEventHandler SystemConfigurationUpdateRequested;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,11 @@ namespace SafeExamBrowser.Contracts.Communication.Proxies
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool Ignore { set; }
|
bool Ignore { set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Instructs the service to start a system configuration update.
|
||||||
|
/// </summary>
|
||||||
|
CommunicationResult RunSystemConfigurationUpdate();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Instructs the service to start a new session according to the given configuration.
|
/// Instructs the service to start a new session according to the given configuration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -91,7 +91,6 @@ namespace SafeExamBrowser.Contracts.I18n
|
||||||
OperationStatus_StopWindowMonitoring,
|
OperationStatus_StopWindowMonitoring,
|
||||||
OperationStatus_TerminateBrowser,
|
OperationStatus_TerminateBrowser,
|
||||||
OperationStatus_TerminateShell,
|
OperationStatus_TerminateShell,
|
||||||
OperationStatus_UpdateSystemConfiguration,
|
|
||||||
OperationStatus_WaitExplorerStartup,
|
OperationStatus_WaitExplorerStartup,
|
||||||
OperationStatus_WaitExplorerTermination,
|
OperationStatus_WaitExplorerTermination,
|
||||||
OperationStatus_WaitRuntimeDisconnection,
|
OperationStatus_WaitRuntimeDisconnection,
|
||||||
|
|
|
@ -231,9 +231,6 @@
|
||||||
<Entry key="OperationStatus_TerminateShell">
|
<Entry key="OperationStatus_TerminateShell">
|
||||||
Terminating user interface
|
Terminating user interface
|
||||||
</Entry>
|
</Entry>
|
||||||
<Entry key="OperationStatus_UpdateSystemConfiguration">
|
|
||||||
Updating system configuration
|
|
||||||
</Entry>
|
|
||||||
<Entry key="OperationStatus_WaitExplorerStartup">
|
<Entry key="OperationStatus_WaitExplorerStartup">
|
||||||
Waiting for Windows explorer to start up
|
Waiting for Windows explorer to start up
|
||||||
</Entry>
|
</Entry>
|
||||||
|
|
|
@ -15,7 +15,6 @@ using SafeExamBrowser.Contracts.Communication.Proxies;
|
||||||
using SafeExamBrowser.Contracts.Configuration;
|
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.Lockdown;
|
|
||||||
using SafeExamBrowser.Contracts.Logging;
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
using SafeExamBrowser.Contracts.SystemComponents;
|
using SafeExamBrowser.Contracts.SystemComponents;
|
||||||
using SafeExamBrowser.Contracts.UserInterface.MessageBox;
|
using SafeExamBrowser.Contracts.UserInterface.MessageBox;
|
||||||
|
@ -35,7 +34,6 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
private SessionConfiguration session;
|
private SessionConfiguration session;
|
||||||
private SessionContext sessionContext;
|
private SessionContext sessionContext;
|
||||||
private Settings settings;
|
private Settings settings;
|
||||||
private Mock<ISystemConfigurationUpdate> systemConfigurationUpdate;
|
|
||||||
private Mock<IUserInfo> userInfo;
|
private Mock<IUserInfo> userInfo;
|
||||||
private ServiceOperation sut;
|
private ServiceOperation sut;
|
||||||
|
|
||||||
|
@ -52,7 +50,6 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
session = new SessionConfiguration();
|
session = new SessionConfiguration();
|
||||||
sessionContext = new SessionContext();
|
sessionContext = new SessionContext();
|
||||||
settings = new Settings();
|
settings = new Settings();
|
||||||
systemConfigurationUpdate = new Mock<ISystemConfigurationUpdate>();
|
|
||||||
userInfo = new Mock<IUserInfo>();
|
userInfo = new Mock<IUserInfo>();
|
||||||
|
|
||||||
appConfig.ServiceEventName = serviceEventName;
|
appConfig.ServiceEventName = serviceEventName;
|
||||||
|
@ -63,7 +60,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
session.Settings = settings;
|
session.Settings = settings;
|
||||||
settings.Service.Policy = ServicePolicy.Mandatory;
|
settings.Service.Policy = ServicePolicy.Mandatory;
|
||||||
|
|
||||||
sut = new ServiceOperation(logger.Object, runtimeHost.Object, service.Object, sessionContext, systemConfigurationUpdate.Object, 0, userInfo.Object);
|
sut = new ServiceOperation(logger.Object, runtimeHost.Object, service.Object, sessionContext, 0, userInfo.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
|
@ -92,7 +89,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
var result = sut.Perform();
|
var result = sut.Perform();
|
||||||
|
|
||||||
service.Verify(s => s.StartSession(It.IsAny<ServiceConfiguration>()), Times.Once);
|
service.Verify(s => s.StartSession(It.IsAny<ServiceConfiguration>()), Times.Once);
|
||||||
systemConfigurationUpdate.Verify(u => u.Execute(), Times.Once);
|
service.Verify(s => s.RunSystemConfigurationUpdate(), Times.Never);
|
||||||
userInfo.Verify(u => u.GetUserName(), Times.Once);
|
userInfo.Verify(u => u.GetUserName(), Times.Once);
|
||||||
userInfo.Verify(u => u.GetUserSid(), Times.Once);
|
userInfo.Verify(u => u.GetUserSid(), Times.Once);
|
||||||
|
|
||||||
|
@ -125,7 +122,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
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<ServiceConfiguration>())).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, systemConfigurationUpdate.Object, TIMEOUT, userInfo.Object);
|
sut = new ServiceOperation(logger.Object, runtimeHost.Object, service.Object, sessionContext, TIMEOUT, userInfo.Object);
|
||||||
|
|
||||||
before = DateTime.Now;
|
before = DateTime.Now;
|
||||||
var result = sut.Perform();
|
var result = sut.Perform();
|
||||||
|
@ -158,7 +155,6 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
var result = sut.Perform();
|
var result = sut.Perform();
|
||||||
|
|
||||||
service.Verify(s => s.StartSession(It.IsAny<ServiceConfiguration>()), Times.Once);
|
service.Verify(s => s.StartSession(It.IsAny<ServiceConfiguration>()), Times.Once);
|
||||||
systemConfigurationUpdate.Verify(u => u.Execute(), Times.Never);
|
|
||||||
|
|
||||||
Assert.AreEqual(OperationResult.Failed, result);
|
Assert.AreEqual(OperationResult.Failed, result);
|
||||||
}
|
}
|
||||||
|
@ -213,7 +209,6 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
{
|
{
|
||||||
service.Setup(s => s.StopSession(It.IsAny<Guid>())).Returns(new CommunicationResult(true)).Callback(() => serviceEvent.Set());
|
service.Setup(s => s.StopSession(It.IsAny<Guid>())).Returns(new CommunicationResult(true)).Callback(() => serviceEvent.Set());
|
||||||
PerformNormally();
|
PerformNormally();
|
||||||
systemConfigurationUpdate.Reset();
|
|
||||||
|
|
||||||
var result = sut.Repeat();
|
var result = sut.Repeat();
|
||||||
|
|
||||||
|
@ -221,7 +216,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
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<ServiceConfiguration>()), 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);
|
||||||
systemConfigurationUpdate.Verify(u => u.Execute(), Times.Exactly(2));
|
service.Verify(s => s.RunSystemConfigurationUpdate(), Times.Never);
|
||||||
|
|
||||||
Assert.AreEqual(OperationResult.Success, result);
|
Assert.AreEqual(OperationResult.Success, result);
|
||||||
}
|
}
|
||||||
|
@ -268,7 +263,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
var before = default(DateTime);
|
var before = default(DateTime);
|
||||||
|
|
||||||
service.Setup(s => s.StopSession(It.IsAny<Guid>())).Returns(new CommunicationResult(true));
|
service.Setup(s => s.StopSession(It.IsAny<Guid>())).Returns(new CommunicationResult(true));
|
||||||
sut = new ServiceOperation(logger.Object, runtimeHost.Object, service.Object, sessionContext, systemConfigurationUpdate.Object, TIMEOUT, userInfo.Object);
|
sut = new ServiceOperation(logger.Object, runtimeHost.Object, service.Object, sessionContext, TIMEOUT, userInfo.Object);
|
||||||
|
|
||||||
PerformNormally();
|
PerformNormally();
|
||||||
|
|
||||||
|
@ -288,6 +283,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
{
|
{
|
||||||
service.Setup(s => s.Disconnect()).Returns(true);
|
service.Setup(s => s.Disconnect()).Returns(true);
|
||||||
service.Setup(s => s.StopSession(It.IsAny<Guid>())).Returns(new CommunicationResult(true)).Callback(() => serviceEvent.Set());
|
service.Setup(s => s.StopSession(It.IsAny<Guid>())).Returns(new CommunicationResult(true)).Callback(() => serviceEvent.Set());
|
||||||
|
service.Setup(s => s.RunSystemConfigurationUpdate()).Returns(new CommunicationResult(true));
|
||||||
|
|
||||||
PerformNormally();
|
PerformNormally();
|
||||||
|
|
||||||
|
@ -303,14 +299,15 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
{
|
{
|
||||||
service.Setup(s => s.Disconnect()).Returns(true);
|
service.Setup(s => s.Disconnect()).Returns(true);
|
||||||
service.Setup(s => s.StopSession(It.IsAny<Guid>())).Returns(new CommunicationResult(true)).Callback(() => serviceEvent.Set());
|
service.Setup(s => s.StopSession(It.IsAny<Guid>())).Returns(new CommunicationResult(true)).Callback(() => serviceEvent.Set());
|
||||||
|
service.Setup(s => s.RunSystemConfigurationUpdate()).Returns(new CommunicationResult(true));
|
||||||
|
|
||||||
PerformNormally();
|
PerformNormally();
|
||||||
systemConfigurationUpdate.Reset();
|
|
||||||
|
|
||||||
var result = sut.Revert();
|
var result = sut.Revert();
|
||||||
|
|
||||||
service.Verify(s => s.StopSession(It.IsAny<Guid>()), Times.Once);
|
service.Verify(s => s.StopSession(It.IsAny<Guid>()), Times.Once);
|
||||||
service.Verify(s => s.Disconnect(), Times.Once);
|
service.Verify(s => s.Disconnect(), Times.Once);
|
||||||
systemConfigurationUpdate.Verify(u => u.Execute(), Times.Once);
|
service.Verify(s => s.RunSystemConfigurationUpdate(), Times.Once);
|
||||||
|
|
||||||
Assert.AreEqual(OperationResult.Success, result);
|
Assert.AreEqual(OperationResult.Success, result);
|
||||||
}
|
}
|
||||||
|
@ -319,14 +316,31 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
public void Revert_MustHandleCommunicationFailureWhenStoppingSession()
|
public void Revert_MustHandleCommunicationFailureWhenStoppingSession()
|
||||||
{
|
{
|
||||||
service.Setup(s => s.StopSession(It.IsAny<Guid>())).Returns(new CommunicationResult(false));
|
service.Setup(s => s.StopSession(It.IsAny<Guid>())).Returns(new CommunicationResult(false));
|
||||||
|
|
||||||
PerformNormally();
|
PerformNormally();
|
||||||
systemConfigurationUpdate.Reset();
|
|
||||||
|
|
||||||
var result = sut.Revert();
|
var result = sut.Revert();
|
||||||
|
|
||||||
service.Verify(s => s.StopSession(It.IsAny<Guid>()), Times.Once);
|
service.Verify(s => s.StopSession(It.IsAny<Guid>()), Times.Once);
|
||||||
service.Verify(s => s.Disconnect(), Times.Once);
|
service.Verify(s => s.Disconnect(), Times.Once);
|
||||||
systemConfigurationUpdate.Verify(u => u.Execute(), Times.Never);
|
service.Verify(s => s.RunSystemConfigurationUpdate(), Times.Never);
|
||||||
|
|
||||||
|
Assert.AreEqual(OperationResult.Failed, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Revert_MustHandleCommunicationFailureWhenInitiatingSystemConfigurationUpdate()
|
||||||
|
{
|
||||||
|
service.Setup(s => s.StopSession(It.IsAny<Guid>())).Returns(new CommunicationResult(true)).Callback(() => serviceEvent.Set());
|
||||||
|
service.Setup(s => s.RunSystemConfigurationUpdate()).Returns(new CommunicationResult(false));
|
||||||
|
|
||||||
|
PerformNormally();
|
||||||
|
|
||||||
|
var result = sut.Revert();
|
||||||
|
|
||||||
|
service.Verify(s => s.StopSession(It.IsAny<Guid>()), Times.Once);
|
||||||
|
service.Verify(s => s.Disconnect(), Times.Once);
|
||||||
|
service.Verify(s => s.RunSystemConfigurationUpdate(), Times.Once);
|
||||||
|
|
||||||
Assert.AreEqual(OperationResult.Failed, result);
|
Assert.AreEqual(OperationResult.Failed, result);
|
||||||
}
|
}
|
||||||
|
@ -340,6 +354,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
|
|
||||||
var result = sut.Revert();
|
var result = sut.Revert();
|
||||||
|
|
||||||
|
service.Verify(s => s.RunSystemConfigurationUpdate(), Times.Never);
|
||||||
|
|
||||||
Assert.AreEqual(OperationResult.Failed, result);
|
Assert.AreEqual(OperationResult.Failed, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,7 +368,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
var before = default(DateTime);
|
var before = default(DateTime);
|
||||||
|
|
||||||
service.Setup(s => s.StopSession(It.IsAny<Guid>())).Returns(new CommunicationResult(true));
|
service.Setup(s => s.StopSession(It.IsAny<Guid>())).Returns(new CommunicationResult(true));
|
||||||
sut = new ServiceOperation(logger.Object, runtimeHost.Object, service.Object, sessionContext, systemConfigurationUpdate.Object, TIMEOUT, userInfo.Object);
|
sut = new ServiceOperation(logger.Object, runtimeHost.Object, service.Object, sessionContext, TIMEOUT, userInfo.Object);
|
||||||
|
|
||||||
PerformNormally();
|
PerformNormally();
|
||||||
|
|
||||||
|
@ -362,6 +378,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
|
|
||||||
service.Verify(s => s.StopSession(It.IsAny<Guid>()), Times.Once);
|
service.Verify(s => s.StopSession(It.IsAny<Guid>()), Times.Once);
|
||||||
service.Verify(s => s.Disconnect(), Times.Once);
|
service.Verify(s => s.Disconnect(), Times.Once);
|
||||||
|
service.Verify(s => s.RunSystemConfigurationUpdate(), Times.Never);
|
||||||
|
|
||||||
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));
|
||||||
|
|
|
@ -389,6 +389,42 @@ namespace SafeExamBrowser.Runtime.UnitTests
|
||||||
runtimeWindow.Verify(s => s.UpdateStatus(It.Is<TextKey>(k => k == key), It.IsAny<bool>()), Times.Once);
|
runtimeWindow.Verify(s => s.UpdateStatus(It.Is<TextKey>(k => k == key), It.IsAny<bool>()), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ServiceProxy_MustShutdownWhenConnectionLostAndMandatory()
|
||||||
|
{
|
||||||
|
currentSettings.Service.Policy = ServicePolicy.Mandatory;
|
||||||
|
|
||||||
|
StartSession();
|
||||||
|
service.Raise(c => c.ConnectionLost += null);
|
||||||
|
|
||||||
|
messageBox.Verify(m => m.Show(
|
||||||
|
It.IsAny<TextKey>(),
|
||||||
|
It.IsAny<TextKey>(),
|
||||||
|
It.IsAny<MessageBoxAction>(),
|
||||||
|
It.Is<MessageBoxIcon>(i => i == MessageBoxIcon.Error),
|
||||||
|
It.IsAny<IWindow>()), Times.Once);
|
||||||
|
sessionSequence.Verify(s => s.TryRevert(), Times.Once);
|
||||||
|
shutdown.Verify(s => s(), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ServiceProxy_MustNotShutdownWhenConnectionLostAndNotMandatory()
|
||||||
|
{
|
||||||
|
currentSettings.Service.Policy = ServicePolicy.Optional;
|
||||||
|
|
||||||
|
StartSession();
|
||||||
|
service.Raise(c => c.ConnectionLost += null);
|
||||||
|
|
||||||
|
messageBox.Verify(m => m.Show(
|
||||||
|
It.IsAny<TextKey>(),
|
||||||
|
It.IsAny<TextKey>(),
|
||||||
|
It.IsAny<MessageBoxAction>(),
|
||||||
|
It.Is<MessageBoxIcon>(i => i == MessageBoxIcon.Error),
|
||||||
|
It.IsAny<IWindow>()), Times.Never);
|
||||||
|
sessionSequence.Verify(s => s.TryRevert(), Times.Never);
|
||||||
|
shutdown.Verify(s => s(), Times.Never);
|
||||||
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Shutdown_MustRevertSessionThenBootstrapSequence()
|
public void Shutdown_MustRevertSessionThenBootstrapSequence()
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,7 +27,6 @@ using SafeExamBrowser.Contracts.SystemComponents;
|
||||||
using SafeExamBrowser.Core.OperationModel;
|
using SafeExamBrowser.Core.OperationModel;
|
||||||
using SafeExamBrowser.Core.Operations;
|
using SafeExamBrowser.Core.Operations;
|
||||||
using SafeExamBrowser.I18n;
|
using SafeExamBrowser.I18n;
|
||||||
using SafeExamBrowser.Lockdown;
|
|
||||||
using SafeExamBrowser.Logging;
|
using SafeExamBrowser.Logging;
|
||||||
using SafeExamBrowser.Runtime.Communication;
|
using SafeExamBrowser.Runtime.Communication;
|
||||||
using SafeExamBrowser.Runtime.Operations;
|
using SafeExamBrowser.Runtime.Operations;
|
||||||
|
@ -71,7 +70,6 @@ namespace SafeExamBrowser.Runtime
|
||||||
var runtimeHost = new RuntimeHost(appConfig.RuntimeAddress, new HostObjectFactory(), ModuleLogger(nameof(RuntimeHost)), FIVE_SECONDS);
|
var runtimeHost = new RuntimeHost(appConfig.RuntimeAddress, new HostObjectFactory(), ModuleLogger(nameof(RuntimeHost)), FIVE_SECONDS);
|
||||||
var serviceProxy = new ServiceProxy(appConfig.ServiceAddress, new ProxyObjectFactory(), ModuleLogger(nameof(ServiceProxy)), Interlocutor.Runtime);
|
var serviceProxy = new ServiceProxy(appConfig.ServiceAddress, new ProxyObjectFactory(), ModuleLogger(nameof(ServiceProxy)), Interlocutor.Runtime);
|
||||||
var sessionContext = new SessionContext();
|
var sessionContext = new SessionContext();
|
||||||
var systemConfigurationUpdate = new SystemConfigurationUpdate(ModuleLogger(nameof(SystemConfigurationUpdate)));
|
|
||||||
var uiFactory = new UserInterfaceFactory(text);
|
var uiFactory = new UserInterfaceFactory(text);
|
||||||
var userInfo = new UserInfo();
|
var userInfo = new UserInfo();
|
||||||
|
|
||||||
|
@ -83,7 +81,7 @@ namespace SafeExamBrowser.Runtime
|
||||||
|
|
||||||
sessionOperations.Enqueue(new SessionInitializationOperation(configuration, logger, runtimeHost, sessionContext));
|
sessionOperations.Enqueue(new SessionInitializationOperation(configuration, logger, runtimeHost, sessionContext));
|
||||||
sessionOperations.Enqueue(new ConfigurationOperation(args, configuration, new HashAlgorithm(), logger, sessionContext));
|
sessionOperations.Enqueue(new ConfigurationOperation(args, configuration, new HashAlgorithm(), logger, sessionContext));
|
||||||
sessionOperations.Enqueue(new ServiceOperation(logger, runtimeHost, serviceProxy, sessionContext, systemConfigurationUpdate, THIRTY_SECONDS, userInfo));
|
sessionOperations.Enqueue(new ServiceOperation(logger, runtimeHost, serviceProxy, sessionContext, THIRTY_SECONDS, userInfo));
|
||||||
sessionOperations.Enqueue(new ClientTerminationOperation(logger, processFactory, proxyFactory, runtimeHost, sessionContext, THIRTY_SECONDS));
|
sessionOperations.Enqueue(new ClientTerminationOperation(logger, processFactory, proxyFactory, runtimeHost, sessionContext, THIRTY_SECONDS));
|
||||||
sessionOperations.Enqueue(new KioskModeOperation(desktopFactory, explorerShell, logger, processFactory, sessionContext));
|
sessionOperations.Enqueue(new KioskModeOperation(desktopFactory, explorerShell, logger, processFactory, sessionContext));
|
||||||
sessionOperations.Enqueue(new ClientOperation(logger, processFactory, proxyFactory, runtimeHost, sessionContext, THIRTY_SECONDS));
|
sessionOperations.Enqueue(new ClientOperation(logger, processFactory, proxyFactory, runtimeHost, sessionContext, THIRTY_SECONDS));
|
||||||
|
|
|
@ -16,7 +16,6 @@ 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.Lockdown;
|
|
||||||
using SafeExamBrowser.Contracts.Logging;
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
using SafeExamBrowser.Contracts.SystemComponents;
|
using SafeExamBrowser.Contracts.SystemComponents;
|
||||||
using SafeExamBrowser.Contracts.UserInterface.MessageBox;
|
using SafeExamBrowser.Contracts.UserInterface.MessageBox;
|
||||||
|
@ -29,7 +28,6 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
private ILogger logger;
|
private ILogger logger;
|
||||||
private IRuntimeHost runtimeHost;
|
private IRuntimeHost runtimeHost;
|
||||||
private IServiceProxy service;
|
private IServiceProxy service;
|
||||||
private ISystemConfigurationUpdate systemConfigurationUpdate;
|
|
||||||
private int timeout_ms;
|
private int timeout_ms;
|
||||||
private IUserInfo userInfo;
|
private IUserInfo userInfo;
|
||||||
|
|
||||||
|
@ -41,14 +39,12 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
IRuntimeHost runtimeHost,
|
IRuntimeHost runtimeHost,
|
||||||
IServiceProxy service,
|
IServiceProxy service,
|
||||||
SessionContext sessionContext,
|
SessionContext sessionContext,
|
||||||
ISystemConfigurationUpdate systemConfigurationUpdate,
|
|
||||||
int timeout_ms,
|
int timeout_ms,
|
||||||
IUserInfo userInfo) : base(sessionContext)
|
IUserInfo userInfo) : base(sessionContext)
|
||||||
{
|
{
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.runtimeHost = runtimeHost;
|
this.runtimeHost = runtimeHost;
|
||||||
this.service = service;
|
this.service = service;
|
||||||
this.systemConfigurationUpdate = systemConfigurationUpdate;
|
|
||||||
this.timeout_ms = timeout_ms;
|
this.timeout_ms = timeout_ms;
|
||||||
this.userInfo = userInfo;
|
this.userInfo = userInfo;
|
||||||
}
|
}
|
||||||
|
@ -103,7 +99,7 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
{
|
{
|
||||||
if (Context.Current != null)
|
if (Context.Current != null)
|
||||||
{
|
{
|
||||||
success &= TryStopSession();
|
success &= TryStopSession(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
success &= TryTerminateConnection();
|
success &= TryTerminateConnection();
|
||||||
|
@ -192,21 +188,18 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
{
|
{
|
||||||
logger.Error($"Failed to start new service session within {timeout_ms / 1000} seconds!");
|
logger.Error($"Failed to start new service session within {timeout_ms / 1000} seconds!");
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusChanged?.Invoke(TextKey.OperationStatus_UpdateSystemConfiguration);
|
|
||||||
systemConfigurationUpdate.Execute();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger.Error("Failed to communicate session start to service!");
|
logger.Error("Failed to communicate session start command to service!");
|
||||||
}
|
}
|
||||||
|
|
||||||
return started;
|
return started;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryStopSession()
|
private bool TryStopSession(bool isFinalSession = false)
|
||||||
{
|
{
|
||||||
var stopped = false;
|
var success = false;
|
||||||
|
|
||||||
logger.Info("Stopping current service session...");
|
logger.Info("Stopping current service session...");
|
||||||
|
|
||||||
|
@ -214,9 +207,9 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
|
|
||||||
if (communication.Success)
|
if (communication.Success)
|
||||||
{
|
{
|
||||||
stopped = TryWaitForServiceEvent(Context.Current.AppConfig.ServiceEventName);
|
success = TryWaitForServiceEvent(Context.Current.AppConfig.ServiceEventName);
|
||||||
|
|
||||||
if (stopped)
|
if (success)
|
||||||
{
|
{
|
||||||
logger.Info("Successfully stopped service session.");
|
logger.Info("Successfully stopped service session.");
|
||||||
}
|
}
|
||||||
|
@ -224,16 +217,28 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
{
|
{
|
||||||
logger.Error($"Failed to stop service session within {timeout_ms / 1000} seconds!");
|
logger.Error($"Failed to stop service session within {timeout_ms / 1000} seconds!");
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusChanged?.Invoke(TextKey.OperationStatus_UpdateSystemConfiguration);
|
|
||||||
systemConfigurationUpdate.Execute();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger.Error("Failed to communicate session stop to service!");
|
logger.Error("Failed to communicate session stop command to service!");
|
||||||
}
|
}
|
||||||
|
|
||||||
return stopped;
|
if (success && isFinalSession)
|
||||||
|
{
|
||||||
|
communication = service.RunSystemConfigurationUpdate();
|
||||||
|
success = communication.Success;
|
||||||
|
|
||||||
|
if (communication.Success)
|
||||||
|
{
|
||||||
|
logger.Info("Instructed service to perform system configuration update.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.Error("Failed to communicate system configuration update command to service!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryWaitForServiceEvent(string eventName)
|
private bool TryWaitForServiceEvent(string eventName)
|
||||||
|
|
|
@ -260,6 +260,7 @@ namespace SafeExamBrowser.Runtime
|
||||||
runtimeHost.ClientConfigurationNeeded += RuntimeHost_ClientConfigurationNeeded;
|
runtimeHost.ClientConfigurationNeeded += RuntimeHost_ClientConfigurationNeeded;
|
||||||
runtimeHost.ReconfigurationRequested += RuntimeHost_ReconfigurationRequested;
|
runtimeHost.ReconfigurationRequested += RuntimeHost_ReconfigurationRequested;
|
||||||
runtimeHost.ShutdownRequested += RuntimeHost_ShutdownRequested;
|
runtimeHost.ShutdownRequested += RuntimeHost_ShutdownRequested;
|
||||||
|
service.ConnectionLost += ServiceProxy_ConnectionLost;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DeregisterEvents()
|
private void DeregisterEvents()
|
||||||
|
@ -267,6 +268,7 @@ namespace SafeExamBrowser.Runtime
|
||||||
runtimeHost.ClientConfigurationNeeded -= RuntimeHost_ClientConfigurationNeeded;
|
runtimeHost.ClientConfigurationNeeded -= RuntimeHost_ClientConfigurationNeeded;
|
||||||
runtimeHost.ReconfigurationRequested -= RuntimeHost_ReconfigurationRequested;
|
runtimeHost.ReconfigurationRequested -= RuntimeHost_ReconfigurationRequested;
|
||||||
runtimeHost.ShutdownRequested -= RuntimeHost_ShutdownRequested;
|
runtimeHost.ShutdownRequested -= RuntimeHost_ShutdownRequested;
|
||||||
|
service.ConnectionLost -= ServiceProxy_ConnectionLost;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RegisterSessionEvents()
|
private void RegisterSessionEvents()
|
||||||
|
@ -358,6 +360,21 @@ namespace SafeExamBrowser.Runtime
|
||||||
shutdown.Invoke();
|
shutdown.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ServiceProxy_ConnectionLost()
|
||||||
|
{
|
||||||
|
if (SessionIsRunning && Session.Settings.Service.Policy == ServicePolicy.Mandatory)
|
||||||
|
{
|
||||||
|
logger.Error("Lost connection to the service component!");
|
||||||
|
StopSession();
|
||||||
|
messageBox.Show(TextKey.MessageBox_ApplicationError, TextKey.MessageBox_ApplicationErrorTitle, icon: MessageBoxIcon.Error, parent: runtimeWindow);
|
||||||
|
shutdown.Invoke();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.Warn("Lost connection to the service component!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void SessionSequence_ActionRequired(ActionRequiredEventArgs args)
|
private void SessionSequence_ActionRequired(ActionRequiredEventArgs args)
|
||||||
{
|
{
|
||||||
switch (args)
|
switch (args)
|
||||||
|
|
|
@ -155,10 +155,6 @@
|
||||||
<Project>{10c62628-8e6a-45aa-9d97-339b119ad21d}</Project>
|
<Project>{10c62628-8e6a-45aa-9d97-339b119ad21d}</Project>
|
||||||
<Name>SafeExamBrowser.I18n</Name>
|
<Name>SafeExamBrowser.I18n</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\SafeExamBrowser.Lockdown\SafeExamBrowser.Lockdown.csproj">
|
|
||||||
<Project>{386b6042-3e12-4753-9fc6-c88ea4f97030}</Project>
|
|
||||||
<Name>SafeExamBrowser.Lockdown</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\SafeExamBrowser.Logging\SafeExamBrowser.Logging.csproj">
|
<ProjectReference Include="..\SafeExamBrowser.Logging\SafeExamBrowser.Logging.csproj">
|
||||||
<Project>{e107026c-2011-4552-a7d8-3a0d37881df6}</Project>
|
<Project>{e107026c-2011-4552-a7d8-3a0d37881df6}</Project>
|
||||||
<Name>SafeExamBrowser.Logging</Name>
|
<Name>SafeExamBrowser.Logging</Name>
|
||||||
|
|
|
@ -48,7 +48,6 @@ namespace SafeExamBrowser.Service.UnitTests.Communication
|
||||||
var response3 = sut.Connect();
|
var response3 = sut.Connect();
|
||||||
|
|
||||||
Assert.IsTrue(response.ConnectionEstablished);
|
Assert.IsTrue(response.ConnectionEstablished);
|
||||||
Assert.IsFalse(sut.AllowConnection);
|
|
||||||
Assert.IsFalse(response2.ConnectionEstablished);
|
Assert.IsFalse(response2.ConnectionEstablished);
|
||||||
Assert.IsFalse(response3.ConnectionEstablished);
|
Assert.IsFalse(response3.ConnectionEstablished);
|
||||||
}
|
}
|
||||||
|
@ -59,15 +58,33 @@ namespace SafeExamBrowser.Service.UnitTests.Communication
|
||||||
var connect = sut.Connect();
|
var connect = sut.Connect();
|
||||||
var disconnect = sut.Disconnect(new DisconnectionMessage { CommunicationToken = connect.CommunicationToken.Value, Interlocutor = Interlocutor.Runtime });
|
var disconnect = sut.Disconnect(new DisconnectionMessage { CommunicationToken = connect.CommunicationToken.Value, Interlocutor = Interlocutor.Runtime });
|
||||||
|
|
||||||
Assert.IsTrue(sut.AllowConnection);
|
|
||||||
Assert.IsTrue(disconnect.ConnectionTerminated);
|
Assert.IsTrue(disconnect.ConnectionTerminated);
|
||||||
|
|
||||||
var connect2 = sut.Connect();
|
var connect2 = sut.Connect();
|
||||||
|
|
||||||
Assert.IsFalse(sut.AllowConnection);
|
|
||||||
Assert.IsTrue(connect2.ConnectionEstablished);
|
Assert.IsTrue(connect2.ConnectionEstablished);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Send_MustHandleSystemConfigurationUpdate()
|
||||||
|
{
|
||||||
|
var sync = new AutoResetEvent(false);
|
||||||
|
var systemConfigurationUpdateRequested = false;
|
||||||
|
|
||||||
|
sut.SystemConfigurationUpdateRequested += () => { systemConfigurationUpdateRequested = true; sync.Set(); };
|
||||||
|
|
||||||
|
var token = sut.Connect().CommunicationToken.Value;
|
||||||
|
var message = new SimpleMessage(SimpleMessagePurport.UpdateSystemConfiguration) { CommunicationToken = token };
|
||||||
|
var response = sut.Send(message);
|
||||||
|
|
||||||
|
sync.WaitOne();
|
||||||
|
|
||||||
|
Assert.IsTrue(systemConfigurationUpdateRequested);
|
||||||
|
Assert.IsNotNull(response);
|
||||||
|
Assert.IsInstanceOfType(response, typeof(SimpleResponse));
|
||||||
|
Assert.AreEqual(SimpleResponsePurport.Acknowledged, (response as SimpleResponse)?.Purport);
|
||||||
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Send_MustHandleSessionStartRequest()
|
public void Send_MustHandleSessionStartRequest()
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,7 +11,6 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
using Moq;
|
using Moq;
|
||||||
using SafeExamBrowser.Contracts.Communication.Hosts;
|
|
||||||
using SafeExamBrowser.Contracts.Configuration;
|
using SafeExamBrowser.Contracts.Configuration;
|
||||||
using SafeExamBrowser.Contracts.Configuration.Settings;
|
using SafeExamBrowser.Contracts.Configuration.Settings;
|
||||||
using SafeExamBrowser.Contracts.Core.OperationModel;
|
using SafeExamBrowser.Contracts.Core.OperationModel;
|
||||||
|
@ -26,7 +25,6 @@ namespace SafeExamBrowser.Service.UnitTests.Operations
|
||||||
{
|
{
|
||||||
private Mock<IAutoRestoreMechanism> autoRestoreMechanism;
|
private Mock<IAutoRestoreMechanism> autoRestoreMechanism;
|
||||||
private Mock<ILogger> logger;
|
private Mock<ILogger> logger;
|
||||||
private Mock<IServiceHost> serviceHost;
|
|
||||||
private Mock<Func<string, EventWaitHandle>> serviceEventFactory;
|
private Mock<Func<string, EventWaitHandle>> serviceEventFactory;
|
||||||
private SessionContext sessionContext;
|
private SessionContext sessionContext;
|
||||||
private SessionInitializationOperation sut;
|
private SessionInitializationOperation sut;
|
||||||
|
@ -36,7 +34,6 @@ namespace SafeExamBrowser.Service.UnitTests.Operations
|
||||||
{
|
{
|
||||||
autoRestoreMechanism = new Mock<IAutoRestoreMechanism>();
|
autoRestoreMechanism = new Mock<IAutoRestoreMechanism>();
|
||||||
logger = new Mock<ILogger>();
|
logger = new Mock<ILogger>();
|
||||||
serviceHost = new Mock<IServiceHost>();
|
|
||||||
serviceEventFactory = new Mock<Func<string, EventWaitHandle>>();
|
serviceEventFactory = new Mock<Func<string, EventWaitHandle>>();
|
||||||
sessionContext = new SessionContext();
|
sessionContext = new SessionContext();
|
||||||
|
|
||||||
|
@ -48,17 +45,7 @@ namespace SafeExamBrowser.Service.UnitTests.Operations
|
||||||
Settings = new Settings()
|
Settings = new Settings()
|
||||||
};
|
};
|
||||||
|
|
||||||
sut = new SessionInitializationOperation(logger.Object, serviceEventFactory.Object, serviceHost.Object, sessionContext);
|
sut = new SessionInitializationOperation(logger.Object, serviceEventFactory.Object, sessionContext);
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void Perform_MustDisableNewConnections()
|
|
||||||
{
|
|
||||||
var result = sut.Perform();
|
|
||||||
|
|
||||||
serviceHost.VerifySet(h => h.AllowConnection = false, Times.Once);
|
|
||||||
|
|
||||||
Assert.AreEqual(OperationResult.Success, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
|
@ -97,17 +84,6 @@ namespace SafeExamBrowser.Service.UnitTests.Operations
|
||||||
Assert.IsNull(sessionContext.Configuration);
|
Assert.IsNull(sessionContext.Configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void Revert_MustEnableNewConnections()
|
|
||||||
{
|
|
||||||
sessionContext.ServiceEvent = new EventStub();
|
|
||||||
|
|
||||||
var result = sut.Revert();
|
|
||||||
|
|
||||||
serviceHost.VerifySet(h => h.AllowConnection = true, Times.Once);
|
|
||||||
Assert.AreEqual(OperationResult.Success, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Revert_MustSetServiceEvent()
|
public void Revert_MustSetServiceEvent()
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Threading;
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
using Moq;
|
using Moq;
|
||||||
using SafeExamBrowser.Contracts.Communication.Events;
|
using SafeExamBrowser.Contracts.Communication.Events;
|
||||||
|
@ -14,6 +15,7 @@ using SafeExamBrowser.Contracts.Communication.Hosts;
|
||||||
using SafeExamBrowser.Contracts.Configuration;
|
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.Lockdown;
|
||||||
using SafeExamBrowser.Contracts.Logging;
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Service.UnitTests
|
namespace SafeExamBrowser.Service.UnitTests
|
||||||
|
@ -27,6 +29,7 @@ namespace SafeExamBrowser.Service.UnitTests
|
||||||
private SessionContext sessionContext;
|
private SessionContext sessionContext;
|
||||||
private Mock<IOperationSequence> sessionSequence;
|
private Mock<IOperationSequence> sessionSequence;
|
||||||
private Mock<IServiceHost> serviceHost;
|
private Mock<IServiceHost> serviceHost;
|
||||||
|
private Mock<ISystemConfigurationUpdate> systemConfigurationUpdate;
|
||||||
private ServiceController sut;
|
private ServiceController sut;
|
||||||
|
|
||||||
[TestInitialize]
|
[TestInitialize]
|
||||||
|
@ -38,10 +41,18 @@ namespace SafeExamBrowser.Service.UnitTests
|
||||||
sessionContext = new SessionContext();
|
sessionContext = new SessionContext();
|
||||||
sessionSequence = new Mock<IOperationSequence>();
|
sessionSequence = new Mock<IOperationSequence>();
|
||||||
serviceHost = new Mock<IServiceHost>();
|
serviceHost = new Mock<IServiceHost>();
|
||||||
|
systemConfigurationUpdate = new Mock<ISystemConfigurationUpdate>();
|
||||||
|
|
||||||
logWriterFactory.Setup(f => f.Invoke(It.IsAny<string>())).Returns(new Mock<ILogObserver>().Object);
|
logWriterFactory.Setup(f => f.Invoke(It.IsAny<string>())).Returns(new Mock<ILogObserver>().Object);
|
||||||
|
|
||||||
sut = new ServiceController(logger.Object, logWriterFactory.Object, bootstrapSequence.Object, sessionSequence.Object, serviceHost.Object, sessionContext);
|
sut = new ServiceController(
|
||||||
|
logger.Object,
|
||||||
|
logWriterFactory.Object,
|
||||||
|
bootstrapSequence.Object,
|
||||||
|
sessionSequence.Object,
|
||||||
|
serviceHost.Object,
|
||||||
|
sessionContext,
|
||||||
|
systemConfigurationUpdate.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
|
@ -160,6 +171,23 @@ namespace SafeExamBrowser.Service.UnitTests
|
||||||
sessionSequence.Verify(s => s.TryRevert(), Times.Never);
|
sessionSequence.Verify(s => s.TryRevert(), Times.Never);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Communication_MustStartSystemConfigurationUpdate()
|
||||||
|
{
|
||||||
|
var sync = new AutoResetEvent(false);
|
||||||
|
|
||||||
|
bootstrapSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success);
|
||||||
|
systemConfigurationUpdate.Setup(u => u.ExecuteAsync()).Callback(() => sync.Set());
|
||||||
|
|
||||||
|
sut.TryStart();
|
||||||
|
serviceHost.Raise(h => h.SystemConfigurationUpdateRequested += null);
|
||||||
|
|
||||||
|
sync.WaitOne();
|
||||||
|
|
||||||
|
systemConfigurationUpdate.Verify(u => u.Execute(), Times.Never);
|
||||||
|
systemConfigurationUpdate.Verify(u => u.ExecuteAsync(), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Start_MustOnlyPerformBootstrapSequence()
|
public void Start_MustOnlyPerformBootstrapSequence()
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,47 +18,34 @@ namespace SafeExamBrowser.Service.Communication
|
||||||
{
|
{
|
||||||
internal class ServiceHost : BaseHost, IServiceHost
|
internal class ServiceHost : BaseHost, IServiceHost
|
||||||
{
|
{
|
||||||
private readonly object @lock = new object();
|
|
||||||
|
|
||||||
private bool allowConnection;
|
private bool allowConnection;
|
||||||
|
|
||||||
public bool AllowConnection
|
|
||||||
{
|
|
||||||
get { lock (@lock) { return allowConnection; } }
|
|
||||||
set { lock (@lock) { allowConnection = value; } }
|
|
||||||
}
|
|
||||||
|
|
||||||
public event CommunicationEventHandler<SessionStartEventArgs> SessionStartRequested;
|
public event CommunicationEventHandler<SessionStartEventArgs> SessionStartRequested;
|
||||||
public event CommunicationEventHandler<SessionStopEventArgs> SessionStopRequested;
|
public event CommunicationEventHandler<SessionStopEventArgs> SessionStopRequested;
|
||||||
|
public event CommunicationEventHandler SystemConfigurationUpdateRequested;
|
||||||
|
|
||||||
internal ServiceHost(string address, IHostObjectFactory factory, ILogger logger, int timeout_ms) : base(address, factory, logger, timeout_ms)
|
internal ServiceHost(string address, IHostObjectFactory factory, ILogger logger, int timeout_ms) : base(address, factory, logger, timeout_ms)
|
||||||
{
|
{
|
||||||
AllowConnection = true;
|
allowConnection = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnConnect(Guid? token)
|
protected override bool OnConnect(Guid? token)
|
||||||
{
|
{
|
||||||
lock (@lock)
|
var allow = allowConnection;
|
||||||
|
|
||||||
|
if (allow)
|
||||||
{
|
{
|
||||||
var allow = AllowConnection;
|
allowConnection = false;
|
||||||
|
|
||||||
if (allow)
|
|
||||||
{
|
|
||||||
AllowConnection = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return allow;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return allow;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDisconnect(Interlocutor interlocutor)
|
protected override void OnDisconnect(Interlocutor interlocutor)
|
||||||
{
|
{
|
||||||
if (interlocutor == Interlocutor.Runtime)
|
if (interlocutor == Interlocutor.Runtime)
|
||||||
{
|
{
|
||||||
lock (@lock)
|
allowConnection = true;
|
||||||
{
|
|
||||||
AllowConnection = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,6 +66,13 @@ namespace SafeExamBrowser.Service.Communication
|
||||||
|
|
||||||
protected override Response OnReceive(SimpleMessagePurport message)
|
protected override Response OnReceive(SimpleMessagePurport message)
|
||||||
{
|
{
|
||||||
|
switch (message)
|
||||||
|
{
|
||||||
|
case SimpleMessagePurport.UpdateSystemConfiguration:
|
||||||
|
SystemConfigurationUpdateRequested?.InvokeAsync();
|
||||||
|
return new SimpleResponse(SimpleResponsePurport.Acknowledged);
|
||||||
|
}
|
||||||
|
|
||||||
return new SimpleResponse(SimpleResponsePurport.UnknownMessage);
|
return new SimpleResponse(SimpleResponsePurport.UnknownMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,14 +57,14 @@ namespace SafeExamBrowser.Service
|
||||||
bootstrapOperations.Enqueue(new CommunicationHostOperation(serviceHost, logger));
|
bootstrapOperations.Enqueue(new CommunicationHostOperation(serviceHost, logger));
|
||||||
bootstrapOperations.Enqueue(new ServiceEventCleanupOperation(logger, sessionContext));
|
bootstrapOperations.Enqueue(new ServiceEventCleanupOperation(logger, sessionContext));
|
||||||
|
|
||||||
sessionOperations.Enqueue(new SessionInitializationOperation(logger, ServiceEventFactory, serviceHost, sessionContext));
|
sessionOperations.Enqueue(new SessionInitializationOperation(logger, ServiceEventFactory, sessionContext));
|
||||||
sessionOperations.Enqueue(new LockdownOperation(featureBackup, featureFactory, logger, sessionContext));
|
sessionOperations.Enqueue(new LockdownOperation(featureBackup, featureFactory, logger, sessionContext));
|
||||||
sessionOperations.Enqueue(new SessionActivationOperation(logger, sessionContext));
|
sessionOperations.Enqueue(new SessionActivationOperation(logger, sessionContext));
|
||||||
|
|
||||||
var bootstrapSequence = new OperationSequence(logger, bootstrapOperations);
|
var bootstrapSequence = new OperationSequence(logger, bootstrapOperations);
|
||||||
var sessionSequence = new OperationSequence(logger, sessionOperations);
|
var sessionSequence = new OperationSequence(logger, sessionOperations);
|
||||||
|
|
||||||
ServiceController = new ServiceController(logger, LogWriterFactory, bootstrapSequence, sessionSequence, serviceHost, sessionContext);
|
ServiceController = new ServiceController(logger, LogWriterFactory, bootstrapSequence, sessionSequence, serviceHost, sessionContext, systemConfigurationUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string BuildBackupFilePath()
|
private string BuildBackupFilePath()
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using SafeExamBrowser.Contracts.Communication.Hosts;
|
|
||||||
using SafeExamBrowser.Contracts.Core.OperationModel;
|
using SafeExamBrowser.Contracts.Core.OperationModel;
|
||||||
using SafeExamBrowser.Contracts.Logging;
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
|
|
||||||
|
@ -18,17 +17,11 @@ namespace SafeExamBrowser.Service.Operations
|
||||||
{
|
{
|
||||||
private ILogger logger;
|
private ILogger logger;
|
||||||
private Func<string, EventWaitHandle> serviceEventFactory;
|
private Func<string, EventWaitHandle> serviceEventFactory;
|
||||||
private IServiceHost serviceHost;
|
|
||||||
|
|
||||||
public SessionInitializationOperation(
|
public SessionInitializationOperation(ILogger logger, Func<string, EventWaitHandle> serviceEventFactory, SessionContext sessionContext) : base(sessionContext)
|
||||||
ILogger logger,
|
|
||||||
Func<string, EventWaitHandle> serviceEventFactory,
|
|
||||||
IServiceHost serviceHost,
|
|
||||||
SessionContext sessionContext) : base(sessionContext)
|
|
||||||
{
|
{
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.serviceEventFactory = serviceEventFactory;
|
this.serviceEventFactory = serviceEventFactory;
|
||||||
this.serviceHost = serviceHost;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override OperationResult Perform()
|
public override OperationResult Perform()
|
||||||
|
@ -41,9 +34,6 @@ namespace SafeExamBrowser.Service.Operations
|
||||||
logger.Info("Stopping auto-restore mechanism...");
|
logger.Info("Stopping auto-restore mechanism...");
|
||||||
Context.AutoRestoreMechanism.Stop();
|
Context.AutoRestoreMechanism.Stop();
|
||||||
|
|
||||||
logger.Info("Disabling service host...");
|
|
||||||
serviceHost.AllowConnection = false;
|
|
||||||
|
|
||||||
InitializeServiceEvent();
|
InitializeServiceEvent();
|
||||||
|
|
||||||
return OperationResult.Success;
|
return OperationResult.Success;
|
||||||
|
@ -72,9 +62,6 @@ namespace SafeExamBrowser.Service.Operations
|
||||||
logger.Info("Starting auto-restore mechanism...");
|
logger.Info("Starting auto-restore mechanism...");
|
||||||
Context.AutoRestoreMechanism.Start();
|
Context.AutoRestoreMechanism.Start();
|
||||||
|
|
||||||
logger.Info("Enabling service host...");
|
|
||||||
serviceHost.AllowConnection = true;
|
|
||||||
|
|
||||||
logger.Info("Clearing session data...");
|
logger.Info("Clearing session data...");
|
||||||
Context.Configuration = null;
|
Context.Configuration = null;
|
||||||
Context.IsRunning = false;
|
Context.IsRunning = false;
|
||||||
|
|
|
@ -11,6 +11,7 @@ using SafeExamBrowser.Contracts.Communication.Events;
|
||||||
using SafeExamBrowser.Contracts.Communication.Hosts;
|
using SafeExamBrowser.Contracts.Communication.Hosts;
|
||||||
using SafeExamBrowser.Contracts.Configuration;
|
using SafeExamBrowser.Contracts.Configuration;
|
||||||
using SafeExamBrowser.Contracts.Core.OperationModel;
|
using SafeExamBrowser.Contracts.Core.OperationModel;
|
||||||
|
using SafeExamBrowser.Contracts.Lockdown;
|
||||||
using SafeExamBrowser.Contracts.Logging;
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
using SafeExamBrowser.Contracts.Service;
|
using SafeExamBrowser.Contracts.Service;
|
||||||
|
|
||||||
|
@ -24,6 +25,7 @@ namespace SafeExamBrowser.Service
|
||||||
private IOperationSequence sessionSequence;
|
private IOperationSequence sessionSequence;
|
||||||
private IServiceHost serviceHost;
|
private IServiceHost serviceHost;
|
||||||
private SessionContext sessionContext;
|
private SessionContext sessionContext;
|
||||||
|
private ISystemConfigurationUpdate systemConfigurationUpdate;
|
||||||
private ILogObserver sessionWriter;
|
private ILogObserver sessionWriter;
|
||||||
|
|
||||||
private ServiceConfiguration Session
|
private ServiceConfiguration Session
|
||||||
|
@ -42,7 +44,8 @@ namespace SafeExamBrowser.Service
|
||||||
IOperationSequence bootstrapSequence,
|
IOperationSequence bootstrapSequence,
|
||||||
IOperationSequence sessionSequence,
|
IOperationSequence sessionSequence,
|
||||||
IServiceHost serviceHost,
|
IServiceHost serviceHost,
|
||||||
SessionContext sessionContext)
|
SessionContext sessionContext,
|
||||||
|
ISystemConfigurationUpdate systemConfigurationUpdate)
|
||||||
{
|
{
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.logWriterFactory = logWriterFactory;
|
this.logWriterFactory = logWriterFactory;
|
||||||
|
@ -50,6 +53,7 @@ namespace SafeExamBrowser.Service
|
||||||
this.sessionSequence = sessionSequence;
|
this.sessionSequence = sessionSequence;
|
||||||
this.serviceHost = serviceHost;
|
this.serviceHost = serviceHost;
|
||||||
this.sessionContext = sessionContext;
|
this.sessionContext = sessionContext;
|
||||||
|
this.systemConfigurationUpdate = systemConfigurationUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryStart()
|
public bool TryStart()
|
||||||
|
@ -141,12 +145,14 @@ namespace SafeExamBrowser.Service
|
||||||
{
|
{
|
||||||
serviceHost.SessionStartRequested += ServiceHost_SessionStartRequested;
|
serviceHost.SessionStartRequested += ServiceHost_SessionStartRequested;
|
||||||
serviceHost.SessionStopRequested += ServiceHost_SessionStopRequested;
|
serviceHost.SessionStopRequested += ServiceHost_SessionStopRequested;
|
||||||
|
serviceHost.SystemConfigurationUpdateRequested += ServiceHost_SystemConfigurationUpdateRequested;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DeregisterEvents()
|
private void DeregisterEvents()
|
||||||
{
|
{
|
||||||
serviceHost.SessionStartRequested -= ServiceHost_SessionStartRequested;
|
serviceHost.SessionStartRequested -= ServiceHost_SessionStartRequested;
|
||||||
serviceHost.SessionStopRequested -= ServiceHost_SessionStopRequested;
|
serviceHost.SessionStopRequested -= ServiceHost_SessionStopRequested;
|
||||||
|
serviceHost.SystemConfigurationUpdateRequested -= ServiceHost_SystemConfigurationUpdateRequested;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ServiceHost_SessionStartRequested(SessionStartEventArgs args)
|
private void ServiceHost_SessionStartRequested(SessionStartEventArgs args)
|
||||||
|
@ -182,6 +188,12 @@ namespace SafeExamBrowser.Service
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ServiceHost_SystemConfigurationUpdateRequested()
|
||||||
|
{
|
||||||
|
logger.Info("Received request to initiate system configuration update.");
|
||||||
|
systemConfigurationUpdate.ExecuteAsync();
|
||||||
|
}
|
||||||
|
|
||||||
private string AppendDivider(string message)
|
private string AppendDivider(string message)
|
||||||
{
|
{
|
||||||
var dashesLeft = new String('-', 48 - message.Length / 2 - message.Length % 2);
|
var dashesLeft = new String('-', 48 - message.Length / 2 - message.Length % 2);
|
||||||
|
|
Loading…
Add table
Reference in a new issue