SEBWIN-219: Found better solution for session operation sequence (got rid of session controller and sequence start resp. end operations).
This commit is contained in:
parent
e750f870c0
commit
6efa7bed81
15 changed files with 270 additions and 246 deletions
|
@ -43,14 +43,14 @@ namespace SafeExamBrowser.Contracts.I18n
|
|||
Notification_AboutTooltip,
|
||||
Notification_LogTooltip,
|
||||
ProgressIndicator_CloseRuntimeConnection,
|
||||
ProgressIndicator_CloseServiceConnection,
|
||||
ProgressIndicator_EmptyClipboard,
|
||||
ProgressIndicator_FinalizeServiceSession,
|
||||
ProgressIndicator_InitializeBrowser,
|
||||
ProgressIndicator_InitializeConfiguration,
|
||||
ProgressIndicator_InitializeKioskMode,
|
||||
ProgressIndicator_InitializeProcessMonitoring,
|
||||
ProgressIndicator_InitializeRuntimeConnection,
|
||||
ProgressIndicator_InitializeServiceConnection,
|
||||
ProgressIndicator_InitializeServiceSession,
|
||||
ProgressIndicator_InitializeTaskbar,
|
||||
ProgressIndicator_InitializeWindowMonitoring,
|
||||
ProgressIndicator_InitializeWorkingArea,
|
||||
|
@ -58,17 +58,18 @@ namespace SafeExamBrowser.Contracts.I18n
|
|||
ProgressIndicator_RestoreWorkingArea,
|
||||
ProgressIndicator_RevertKioskMode,
|
||||
ProgressIndicator_ShutdownProcedure,
|
||||
ProgressIndicator_StartClient,
|
||||
ProgressIndicator_StartCommunicationHost,
|
||||
ProgressIndicator_StartEventHandling,
|
||||
ProgressIndicator_StartKeyboardInterception,
|
||||
ProgressIndicator_StartMouseInterception,
|
||||
ProgressIndicator_StartSession,
|
||||
ProgressIndicator_InitializeSession,
|
||||
ProgressIndicator_StopClient,
|
||||
ProgressIndicator_StopCommunicationHost,
|
||||
ProgressIndicator_StopEventHandling,
|
||||
ProgressIndicator_StopKeyboardInterception,
|
||||
ProgressIndicator_StopMouseInterception,
|
||||
ProgressIndicator_StopProcessMonitoring,
|
||||
ProgressIndicator_StopSession,
|
||||
ProgressIndicator_StopWindowMonitoring,
|
||||
ProgressIndicator_TerminateBrowser,
|
||||
ProgressIndicator_TerminateTaskbar,
|
||||
|
|
|
@ -81,12 +81,12 @@
|
|||
<Entry key="ProgressIndicator_CloseRuntimeConnection">
|
||||
Closing runtime connection
|
||||
</Entry>
|
||||
<Entry key="ProgressIndicator_CloseServiceConnection">
|
||||
Closing service connection
|
||||
</Entry>
|
||||
<Entry key="ProgressIndicator_EmptyClipboard">
|
||||
Emptying clipboard
|
||||
</Entry>
|
||||
<Entry key="ProgressIndicator_FinalizeServiceSession">
|
||||
Finalizing service session
|
||||
</Entry>
|
||||
<Entry key="ProgressIndicator_InitializeBrowser">
|
||||
Initializing browser
|
||||
</Entry>
|
||||
|
@ -102,8 +102,11 @@
|
|||
<Entry key="ProgressIndicator_InitializeRuntimeConnection">
|
||||
Initializing runtime connection
|
||||
</Entry>
|
||||
<Entry key="ProgressIndicator_InitializeServiceConnection">
|
||||
Initializing service connection
|
||||
<Entry key="ProgressIndicator_InitializeServiceSession">
|
||||
Initializing service session
|
||||
</Entry>
|
||||
<Entry key="ProgressIndicator_InitializeSession">
|
||||
Initializing new session
|
||||
</Entry>
|
||||
<Entry key="ProgressIndicator_InitializeTaskbar">
|
||||
Initializing taskbar
|
||||
|
@ -126,6 +129,9 @@
|
|||
<Entry key="ProgressIndicator_ShutdownProcedure">
|
||||
Initiating shutdown procedure
|
||||
</Entry>
|
||||
<Entry key="ProgressIndicator_StartClient">
|
||||
Starting client
|
||||
</Entry>
|
||||
<Entry key="ProgressIndicator_StartCommunicationHost">
|
||||
Starting communication host
|
||||
</Entry>
|
||||
|
@ -138,8 +144,8 @@
|
|||
<Entry key="ProgressIndicator_StartMouseInterception">
|
||||
Starting mouse interception
|
||||
</Entry>
|
||||
<Entry key="ProgressIndicator_StartSession">
|
||||
Starting new session
|
||||
<Entry key="ProgressIndicator_StopClient">
|
||||
Stopping client
|
||||
</Entry>
|
||||
<Entry key="ProgressIndicator_StopCommunicationHost">
|
||||
Stopping communication host
|
||||
|
@ -156,9 +162,6 @@
|
|||
<Entry key="ProgressIndicator_StopProcessMonitoring">
|
||||
Stopping process monitoring
|
||||
</Entry>
|
||||
<Entry key="ProgressIndicator_StopSession">
|
||||
Stopping current session
|
||||
</Entry>
|
||||
<Entry key="ProgressIndicator_StopWindowMonitoring">
|
||||
Stopping window monitoring
|
||||
</Entry>
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
|||
private Mock<IConfigurationRepository> configuration;
|
||||
private Mock<IProgressIndicator> progressIndicator;
|
||||
private Mock<IText> text;
|
||||
private ServiceConnectionOperation sut;
|
||||
private ServiceOperation sut;
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
|
@ -39,7 +39,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
|||
progressIndicator = new Mock<IProgressIndicator>();
|
||||
text = new Mock<IText>();
|
||||
|
||||
sut = new ServiceConnectionOperation(configuration.Object, logger.Object, service.Object, text.Object);
|
||||
sut = new ServiceOperation(configuration.Object, logger.Object, service.Object, text.Object);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018 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 Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
||||
{
|
||||
[TestClass]
|
||||
public class SessionSequenceOperationTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void TODO()
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -83,7 +83,6 @@
|
|||
<Compile Include="Behaviour\Operations\ConfigurationOperationTests.cs" />
|
||||
<Compile Include="Behaviour\Operations\KioskModeOperationTests.cs" />
|
||||
<Compile Include="Behaviour\Operations\ServiceConnectionOperationTests.cs" />
|
||||
<Compile Include="Behaviour\Operations\SessionSequenceOperationTests.cs" />
|
||||
<Compile Include="Behaviour\RuntimeControllerTests.cs" />
|
||||
<Compile Include="Communication\RuntimeHostTests.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
|
|
|
@ -17,104 +17,69 @@ using SafeExamBrowser.Contracts.Logging;
|
|||
using SafeExamBrowser.Contracts.UserInterface;
|
||||
using SafeExamBrowser.Contracts.WindowsApi;
|
||||
|
||||
namespace SafeExamBrowser.Runtime.Behaviour
|
||||
namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
||||
{
|
||||
internal class SessionController
|
||||
internal class ClientOperation : IOperation
|
||||
{
|
||||
private const int TEN_SECONDS = 10000;
|
||||
|
||||
private bool sessionRunning;
|
||||
private IConfigurationRepository configuration;
|
||||
private ILogger logger;
|
||||
private IProcessFactory processFactory;
|
||||
private IProxyFactory proxyFactory;
|
||||
private IRuntimeHost runtimeHost;
|
||||
private IServiceProxy service;
|
||||
protected IConfigurationRepository configuration;
|
||||
protected ILogger logger;
|
||||
protected IProcessFactory processFactory;
|
||||
protected IProxyFactory proxyFactory;
|
||||
protected IRuntimeHost runtimeHost;
|
||||
|
||||
internal IProgressIndicator ProgressIndicator { private get; set; }
|
||||
protected static IProcess ClientProcess { get; private set; }
|
||||
protected static IClientProxy ClientProxy { get; private set; }
|
||||
public IProgressIndicator ProgressIndicator { protected get; set; }
|
||||
|
||||
internal SessionController(
|
||||
public ClientOperation(
|
||||
IConfigurationRepository configuration,
|
||||
ILogger logger,
|
||||
IProcessFactory processFactory,
|
||||
IProxyFactory proxyFactory,
|
||||
IRuntimeHost runtimeHost,
|
||||
IServiceProxy service)
|
||||
IRuntimeHost runtimeHost)
|
||||
{
|
||||
this.configuration = configuration;
|
||||
this.logger = logger;
|
||||
this.processFactory = processFactory;
|
||||
this.proxyFactory = proxyFactory;
|
||||
this.runtimeHost = runtimeHost;
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
internal OperationResult StartSession()
|
||||
public virtual OperationResult Perform()
|
||||
{
|
||||
logger.Info("Starting new session...");
|
||||
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StartSession, true);
|
||||
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StartClient, true);
|
||||
|
||||
InitializeSessionConfiguration();
|
||||
StartServiceSession();
|
||||
sessionRunning = TryStartClient();
|
||||
var success = TryStartClient();
|
||||
|
||||
if (!sessionRunning)
|
||||
if (success)
|
||||
{
|
||||
logger.Info($"Failed to start new session! Reverting service session and aborting procedure...");
|
||||
service.StopSession(configuration.CurrentSession.Id);
|
||||
|
||||
return OperationResult.Failed;
|
||||
logger.Info($"Successfully started new client instance.");
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Error($"Failed to start new client instance! Aborting procedure...");
|
||||
}
|
||||
|
||||
logger.Info($"Successfully started new session.");
|
||||
|
||||
return OperationResult.Success;
|
||||
return success ? OperationResult.Success : OperationResult.Failed;
|
||||
}
|
||||
|
||||
internal OperationResult StopSession()
|
||||
public virtual OperationResult Repeat()
|
||||
{
|
||||
if (sessionRunning)
|
||||
return Perform();
|
||||
}
|
||||
|
||||
public virtual void Revert()
|
||||
{
|
||||
if (ClientProcess != null && !ClientProcess.HasTerminated)
|
||||
{
|
||||
logger.Info($"Stopping session with identifier '{configuration.CurrentSession.Id}'...");
|
||||
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StopSession, true);
|
||||
|
||||
StopServiceSession();
|
||||
|
||||
if (!configuration.CurrentSession.ClientProcess.HasTerminated)
|
||||
{
|
||||
StopClient();
|
||||
}
|
||||
|
||||
sessionRunning = false;
|
||||
logger.Info($"Successfully stopped session.");
|
||||
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StopClient, true);
|
||||
TryStopClient();
|
||||
}
|
||||
|
||||
return OperationResult.Success;
|
||||
}
|
||||
|
||||
private void InitializeSessionConfiguration()
|
||||
{
|
||||
configuration.InitializeSessionConfiguration();
|
||||
runtimeHost.StartupToken = configuration.CurrentSession.StartupToken;
|
||||
|
||||
logger.Info($" -> Client-ID: {configuration.RuntimeInfo.ClientId}");
|
||||
logger.Info($" -> Runtime-ID: {configuration.RuntimeInfo.RuntimeId} (as reference, does not change)");
|
||||
logger.Info($" -> Session-ID: {configuration.CurrentSession.Id}");
|
||||
}
|
||||
|
||||
private void StartServiceSession()
|
||||
{
|
||||
logger.Info("Initializing service session...");
|
||||
service.StartSession(configuration.CurrentSession.Id, configuration.CurrentSettings);
|
||||
}
|
||||
|
||||
private void StopServiceSession()
|
||||
{
|
||||
logger.Info("Stopping service session...");
|
||||
service.StopSession(configuration.CurrentSession.Id);
|
||||
}
|
||||
|
||||
private bool TryStartClient()
|
||||
protected bool TryStartClient()
|
||||
{
|
||||
var clientReady = false;
|
||||
var clientReadyEvent = new AutoResetEvent(false);
|
||||
|
@ -126,7 +91,7 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
|||
|
||||
logger.Info("Starting new client process...");
|
||||
runtimeHost.ClientReady += clientReadyEventHandler;
|
||||
configuration.CurrentSession.ClientProcess = processFactory.StartNew(clientExecutable, clientLogFile, hostUri, token);
|
||||
ClientProcess = processFactory.StartNew(clientExecutable, clientLogFile, hostUri, token);
|
||||
|
||||
logger.Info("Waiting for client to complete initialization...");
|
||||
clientReady = clientReadyEvent.WaitOne(TEN_SECONDS);
|
||||
|
@ -140,20 +105,20 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
|||
}
|
||||
|
||||
logger.Info("Client has been successfully started and initialized. Creating communication proxy for client host...");
|
||||
configuration.CurrentSession.ClientProxy = proxyFactory.CreateClientProxy(configuration.RuntimeInfo.ClientAddress);
|
||||
ClientProxy = proxyFactory.CreateClientProxy(configuration.RuntimeInfo.ClientAddress);
|
||||
|
||||
if (!configuration.CurrentSession.ClientProxy.Connect(configuration.CurrentSession.StartupToken))
|
||||
if (!ClientProxy.Connect(configuration.CurrentSession.StartupToken))
|
||||
{
|
||||
logger.Error("Failed to connect to client!");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
logger.Info("Connection with client has been established.");
|
||||
logger.Info("Connection with client has been established. Requesting authentication...");
|
||||
|
||||
var response = configuration.CurrentSession.ClientProxy.RequestAuthentication();
|
||||
var response = ClientProxy.RequestAuthentication();
|
||||
|
||||
if (configuration.CurrentSession.ClientProcess.Id != response?.ProcessId)
|
||||
if (ClientProcess.Id != response?.ProcessId)
|
||||
{
|
||||
logger.Error("Failed to verify client integrity!");
|
||||
|
||||
|
@ -162,11 +127,16 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
|||
|
||||
logger.Info("Authentication of client has been successful, client is ready to operate.");
|
||||
|
||||
configuration.CurrentSession.ClientProcess = ClientProcess;
|
||||
configuration.CurrentSession.ClientProxy = ClientProxy;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void StopClient()
|
||||
protected bool TryStopClient()
|
||||
{
|
||||
var success = false;
|
||||
|
||||
var disconnected = false;
|
||||
var disconnectedEvent = new AutoResetEvent(false);
|
||||
var disconnectedEventHandler = new CommunicationEventHandler(() => disconnectedEvent.Set());
|
||||
|
@ -176,13 +146,13 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
|||
var terminatedEventHandler = new ProcessTerminatedEventHandler((_) => terminatedEvent.Set());
|
||||
|
||||
runtimeHost.ClientDisconnected += disconnectedEventHandler;
|
||||
configuration.CurrentSession.ClientProcess.Terminated += terminatedEventHandler;
|
||||
ClientProcess.Terminated += terminatedEventHandler;
|
||||
|
||||
logger.Info("Instructing client to initiate shutdown procedure.");
|
||||
configuration.CurrentSession.ClientProxy.InitiateShutdown();
|
||||
ClientProxy.InitiateShutdown();
|
||||
|
||||
logger.Info("Disconnecting from client communication host.");
|
||||
configuration.CurrentSession.ClientProxy.Disconnect();
|
||||
ClientProxy.Disconnect();
|
||||
|
||||
logger.Info("Waiting for client to disconnect from runtime communication host...");
|
||||
disconnected = disconnectedEvent.WaitOne(TEN_SECONDS);
|
||||
|
@ -201,20 +171,29 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
|||
}
|
||||
|
||||
runtimeHost.ClientDisconnected -= disconnectedEventHandler;
|
||||
configuration.CurrentSession.ClientProcess.Terminated -= terminatedEventHandler;
|
||||
ClientProcess.Terminated -= terminatedEventHandler;
|
||||
|
||||
if (disconnected && terminated)
|
||||
{
|
||||
logger.Info("Client has been successfully terminated.");
|
||||
success = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Warn("Attempting to kill client process since graceful termination failed!");
|
||||
KillClient();
|
||||
success = TryKillClient();
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
configuration.CurrentSession.ClientProcess = null;
|
||||
configuration.CurrentSession.ClientProxy = null;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
private void KillClient(int attempt = 0)
|
||||
protected bool TryKillClient(int attempt = 0)
|
||||
{
|
||||
const int MAX_ATTEMPTS = 5;
|
||||
|
||||
|
@ -222,20 +201,23 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
|||
{
|
||||
logger.Error($"Failed to kill client process within {MAX_ATTEMPTS} attempts!");
|
||||
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
logger.Info($"Killing client process with ID = {configuration.CurrentSession.ClientProcess.Id}.");
|
||||
configuration.CurrentSession.ClientProcess.Kill();
|
||||
logger.Info($"Killing client process with ID = {ClientProcess.Id}.");
|
||||
ClientProcess.Kill();
|
||||
|
||||
if (configuration.CurrentSession.ClientProcess.HasTerminated)
|
||||
if (ClientProcess.HasTerminated)
|
||||
{
|
||||
logger.Info("Client process has terminated.");
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Warn("Failed to kill client process. Trying again...");
|
||||
KillClient(attempt++);
|
||||
|
||||
return TryKillClient(attempt++);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2018 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 SafeExamBrowser.Contracts.Behaviour.OperationModel;
|
||||
using SafeExamBrowser.Contracts.Communication.Hosts;
|
||||
using SafeExamBrowser.Contracts.Communication.Proxies;
|
||||
using SafeExamBrowser.Contracts.Configuration;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.WindowsApi;
|
||||
|
||||
namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
||||
{
|
||||
internal class ClientTerminationOperation : ClientOperation
|
||||
{
|
||||
public ClientTerminationOperation(
|
||||
IConfigurationRepository configuration,
|
||||
ILogger logger,
|
||||
IProcessFactory processFactory,
|
||||
IProxyFactory proxyFactory,
|
||||
IRuntimeHost runtimeHost) : base(configuration, logger, processFactory, proxyFactory, runtimeHost)
|
||||
{
|
||||
}
|
||||
|
||||
public override OperationResult Perform()
|
||||
{
|
||||
return OperationResult.Success;
|
||||
}
|
||||
|
||||
public override OperationResult Repeat()
|
||||
{
|
||||
var success = true;
|
||||
|
||||
if (ClientProcess != null && !ClientProcess.HasTerminated)
|
||||
{
|
||||
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StopClient, true);
|
||||
success = TryStopClient();
|
||||
}
|
||||
|
||||
return success ? OperationResult.Success : OperationResult.Failed;
|
||||
}
|
||||
|
||||
public override void Revert()
|
||||
{
|
||||
// Nothing to do here...
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,8 +23,8 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
|||
private IConfigurationRepository repository;
|
||||
private ILogger logger;
|
||||
private IMessageBox messageBox;
|
||||
private RuntimeInfo runtimeInfo;
|
||||
private IText text;
|
||||
private RuntimeInfo runtimeInfo;
|
||||
private string[] commandLineArgs;
|
||||
|
||||
public IProgressIndicator ProgressIndicator { private get; set; }
|
||||
|
@ -50,30 +50,23 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
|||
logger.Info("Initializing application configuration...");
|
||||
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeConfiguration);
|
||||
|
||||
Settings settings;
|
||||
var isValidUri = TryGetSettingsUri(out Uri uri);
|
||||
|
||||
if (isValidUri)
|
||||
{
|
||||
logger.Info($"Loading configuration from '{uri.AbsolutePath}'...");
|
||||
settings = repository.LoadSettings(uri);
|
||||
|
||||
if (settings.ConfigurationMode == ConfigurationMode.ConfigureClient)
|
||||
var abort = LoadSettings(uri);
|
||||
|
||||
if (abort)
|
||||
{
|
||||
var abort = IsConfigurationSufficient();
|
||||
|
||||
logger.Info($"The user chose to {(abort ? "abort" : "continue")} after successful client configuration.");
|
||||
|
||||
if (abort)
|
||||
{
|
||||
return OperationResult.Aborted;
|
||||
}
|
||||
return OperationResult.Aborted;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Info("No valid settings file specified nor found in PROGRAMDATA or APPDATA - loading default settings...");
|
||||
settings = repository.LoadDefaultSettings();
|
||||
repository.LoadDefaultSettings();
|
||||
}
|
||||
|
||||
return OperationResult.Success;
|
||||
|
@ -126,6 +119,21 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
|||
return isValidUri;
|
||||
}
|
||||
|
||||
private bool LoadSettings(Uri uri)
|
||||
{
|
||||
var abort = false;
|
||||
var settings = repository.LoadSettings(uri);
|
||||
|
||||
if (settings.ConfigurationMode == ConfigurationMode.ConfigureClient)
|
||||
{
|
||||
abort = IsConfigurationSufficient();
|
||||
|
||||
logger.Info($"The user chose to {(abort ? "abort" : "continue")} after successful client configuration.");
|
||||
}
|
||||
|
||||
return abort;
|
||||
}
|
||||
|
||||
private bool IsConfigurationSufficient()
|
||||
{
|
||||
var message = text.Get(TextKey.MessageBox_ClientConfigurationQuestion);
|
||||
|
|
|
@ -17,7 +17,7 @@ using SafeExamBrowser.Contracts.UserInterface;
|
|||
|
||||
namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
||||
{
|
||||
internal class ServiceConnectionOperation : IOperation
|
||||
internal class ServiceOperation : IOperation
|
||||
{
|
||||
private bool connected, mandatory;
|
||||
private IConfigurationRepository configuration;
|
||||
|
@ -27,7 +27,7 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
|||
|
||||
public IProgressIndicator ProgressIndicator { private get; set; }
|
||||
|
||||
public ServiceConnectionOperation(IConfigurationRepository configuration, ILogger logger, IServiceProxy service, IText text)
|
||||
public ServiceOperation(IConfigurationRepository configuration, ILogger logger, IServiceProxy service, IText text)
|
||||
{
|
||||
this.configuration = configuration;
|
||||
this.service = service;
|
||||
|
@ -37,8 +37,8 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
|||
|
||||
public OperationResult Perform()
|
||||
{
|
||||
logger.Info($"Initializing service connection...");
|
||||
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeServiceConnection);
|
||||
logger.Info($"Initializing service session...");
|
||||
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeServiceSession);
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -60,23 +60,35 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
|||
service.Ignore = !connected;
|
||||
logger.Info($"The service is {(mandatory ? "mandatory" : "optional")} and {(connected ? "available." : "not available. All service-related operations will be ignored!")}");
|
||||
|
||||
if (connected)
|
||||
{
|
||||
StartServiceSession();
|
||||
}
|
||||
|
||||
return OperationResult.Success;
|
||||
}
|
||||
|
||||
public OperationResult Repeat()
|
||||
{
|
||||
// TODO: Re-check if mandatory, if so, try to connect (if not connected) - otherwise, no action required (except maybe logging of status?)
|
||||
if (connected)
|
||||
{
|
||||
StopServiceSession();
|
||||
StartServiceSession();
|
||||
}
|
||||
|
||||
return OperationResult.Success;
|
||||
}
|
||||
|
||||
public void Revert()
|
||||
{
|
||||
logger.Info("Closing service connection...");
|
||||
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_CloseServiceConnection);
|
||||
logger.Info("Finalizing service session...");
|
||||
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_FinalizeServiceSession);
|
||||
|
||||
if (connected)
|
||||
{
|
||||
StopServiceSession();
|
||||
|
||||
try
|
||||
{
|
||||
service.Disconnect();
|
||||
|
@ -88,6 +100,16 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
|||
}
|
||||
}
|
||||
|
||||
private void StartServiceSession()
|
||||
{
|
||||
service.StartSession(configuration.CurrentSession.Id, configuration.CurrentSettings);
|
||||
}
|
||||
|
||||
private void StopServiceSession()
|
||||
{
|
||||
service.StopSession(configuration.CurrentSession.Id);
|
||||
}
|
||||
|
||||
private void LogException(Exception e)
|
||||
{
|
||||
var message = "Failed to connect to the service component!";
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2018 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 SafeExamBrowser.Contracts.Behaviour.OperationModel;
|
||||
using SafeExamBrowser.Contracts.Communication.Hosts;
|
||||
using SafeExamBrowser.Contracts.Configuration;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.UserInterface;
|
||||
|
||||
namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
||||
{
|
||||
internal class SessionInitializationOperation : IOperation
|
||||
{
|
||||
private IConfigurationRepository configuration;
|
||||
private ILogger logger;
|
||||
private IRuntimeHost runtimeHost;
|
||||
|
||||
public IProgressIndicator ProgressIndicator { private get; set; }
|
||||
|
||||
public SessionInitializationOperation(IConfigurationRepository configuration, ILogger logger, IRuntimeHost runtimeHost)
|
||||
{
|
||||
this.configuration = configuration;
|
||||
this.logger = logger;
|
||||
this.runtimeHost = runtimeHost;
|
||||
}
|
||||
|
||||
public OperationResult Perform()
|
||||
{
|
||||
InitializeSessionConfiguration();
|
||||
|
||||
return OperationResult.Success;
|
||||
}
|
||||
|
||||
public OperationResult Repeat()
|
||||
{
|
||||
InitializeSessionConfiguration();
|
||||
|
||||
return OperationResult.Success;
|
||||
}
|
||||
|
||||
public void Revert()
|
||||
{
|
||||
// Nothing to do here...
|
||||
}
|
||||
|
||||
private void InitializeSessionConfiguration()
|
||||
{
|
||||
logger.Info("Initializing new session configuration...");
|
||||
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeSession, true);
|
||||
|
||||
configuration.InitializeSessionConfiguration();
|
||||
runtimeHost.StartupToken = configuration.CurrentSession.StartupToken;
|
||||
|
||||
logger.Info($" -> Client-ID: {configuration.RuntimeInfo.ClientId}");
|
||||
logger.Info($" -> Runtime-ID: {configuration.RuntimeInfo.RuntimeId} (as reference, does not change)");
|
||||
logger.Info($" -> Session-ID: {configuration.CurrentSession.Id}");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018 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 SafeExamBrowser.Contracts.Behaviour.OperationModel;
|
||||
using SafeExamBrowser.Contracts.UserInterface;
|
||||
|
||||
namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
||||
{
|
||||
internal class SessionSequenceEndOperation : IOperation
|
||||
{
|
||||
private SessionController controller;
|
||||
|
||||
public IProgressIndicator ProgressIndicator { private get; set; }
|
||||
|
||||
public SessionSequenceEndOperation(SessionController controller)
|
||||
{
|
||||
this.controller = controller;
|
||||
}
|
||||
|
||||
public OperationResult Perform()
|
||||
{
|
||||
controller.ProgressIndicator = ProgressIndicator;
|
||||
|
||||
return controller.StartSession();
|
||||
}
|
||||
|
||||
public OperationResult Repeat()
|
||||
{
|
||||
controller.ProgressIndicator = ProgressIndicator;
|
||||
|
||||
return controller.StartSession();
|
||||
}
|
||||
|
||||
public void Revert()
|
||||
{
|
||||
controller.ProgressIndicator = ProgressIndicator;
|
||||
controller.StopSession();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018 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 SafeExamBrowser.Contracts.Behaviour.OperationModel;
|
||||
using SafeExamBrowser.Contracts.UserInterface;
|
||||
|
||||
namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
||||
{
|
||||
internal class SessionSequenceStartOperation : IOperation
|
||||
{
|
||||
private SessionController controller;
|
||||
|
||||
public IProgressIndicator ProgressIndicator { private get; set; }
|
||||
|
||||
public SessionSequenceStartOperation(SessionController controller)
|
||||
{
|
||||
this.controller = controller;
|
||||
}
|
||||
|
||||
public OperationResult Perform()
|
||||
{
|
||||
return OperationResult.Success;
|
||||
}
|
||||
|
||||
public OperationResult Repeat()
|
||||
{
|
||||
controller.ProgressIndicator = ProgressIndicator;
|
||||
|
||||
return controller.StopSession();
|
||||
}
|
||||
|
||||
public void Revert()
|
||||
{
|
||||
// Nothing to do here...
|
||||
}
|
||||
}
|
||||
}
|
|
@ -209,18 +209,18 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
|||
runtimeHost.ShutdownRequested += RuntimeHost_ShutdownRequested;
|
||||
}
|
||||
|
||||
private void RegisterSessionEvents()
|
||||
{
|
||||
configuration.CurrentSession.ClientProcess.Terminated += ClientProcess_Terminated;
|
||||
configuration.CurrentSession.ClientProxy.ConnectionLost += Client_ConnectionLost;
|
||||
}
|
||||
|
||||
private void DeregisterEvents()
|
||||
{
|
||||
runtimeHost.ReconfigurationRequested -= RuntimeHost_ReconfigurationRequested;
|
||||
runtimeHost.ShutdownRequested -= RuntimeHost_ShutdownRequested;
|
||||
}
|
||||
|
||||
private void RegisterSessionEvents()
|
||||
{
|
||||
configuration.CurrentSession.ClientProcess.Terminated += ClientProcess_Terminated;
|
||||
configuration.CurrentSession.ClientProxy.ConnectionLost += Client_ConnectionLost;
|
||||
}
|
||||
|
||||
private void DeregisterSessionEvents()
|
||||
{
|
||||
configuration.CurrentSession.ClientProcess.Terminated -= ClientProcess_Terminated;
|
||||
|
|
|
@ -54,7 +54,6 @@ namespace SafeExamBrowser.Runtime
|
|||
var proxyFactory = new ProxyFactory(new ProxyObjectFactory(), logger);
|
||||
var runtimeHost = new RuntimeHost(runtimeInfo.RuntimeAddress, configuration, new HostObjectFactory(), new ModuleLogger(logger, typeof(RuntimeHost)));
|
||||
var serviceProxy = new ServiceProxy(runtimeInfo.ServiceAddress, new ProxyObjectFactory(), new ModuleLogger(logger, typeof(ServiceProxy)));
|
||||
var sessionController = new SessionController(configuration, logger, processFactory, proxyFactory, runtimeHost, serviceProxy);
|
||||
|
||||
var bootstrapOperations = new Queue<IOperation>();
|
||||
var sessionOperations = new Queue<IOperation>();
|
||||
|
@ -62,16 +61,17 @@ namespace SafeExamBrowser.Runtime
|
|||
bootstrapOperations.Enqueue(new I18nOperation(logger, text));
|
||||
bootstrapOperations.Enqueue(new CommunicationOperation(runtimeHost, logger));
|
||||
|
||||
sessionOperations.Enqueue(new SessionSequenceStartOperation(sessionController));
|
||||
sessionOperations.Enqueue(new ConfigurationOperation(configuration, logger, messageBox, runtimeInfo, text, args));
|
||||
sessionOperations.Enqueue(new ServiceConnectionOperation(configuration, logger, serviceProxy, text));
|
||||
sessionOperations.Enqueue(new SessionInitializationOperation(configuration, logger, runtimeHost));
|
||||
sessionOperations.Enqueue(new ServiceOperation(configuration, logger, serviceProxy, text));
|
||||
sessionOperations.Enqueue(new ClientTerminationOperation(configuration, logger, processFactory, proxyFactory, runtimeHost));
|
||||
sessionOperations.Enqueue(new KioskModeOperation(logger, configuration));
|
||||
sessionOperations.Enqueue(new SessionSequenceEndOperation(sessionController));
|
||||
sessionOperations.Enqueue(new ClientOperation(configuration, logger, processFactory, proxyFactory, runtimeHost));
|
||||
|
||||
var boostrapSequence = new OperationSequence(logger, bootstrapOperations);
|
||||
var bootstrapSequence = new OperationSequence(logger, bootstrapOperations);
|
||||
var sessionSequence = new OperationSequence(logger, sessionOperations);
|
||||
|
||||
RuntimeController = new RuntimeController(configuration, logger, messageBox, boostrapSequence, sessionSequence, runtimeHost, runtimeInfo, serviceProxy, shutdown, uiFactory);
|
||||
RuntimeController = new RuntimeController(configuration, logger, messageBox, bootstrapSequence, sessionSequence, runtimeHost, runtimeInfo, serviceProxy, shutdown, uiFactory);
|
||||
}
|
||||
|
||||
internal void LogStartupInformation()
|
||||
|
|
|
@ -87,12 +87,12 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="App.cs" />
|
||||
<Compile Include="Behaviour\Operations\ClientOperation.cs" />
|
||||
<Compile Include="Behaviour\Operations\ClientTerminationOperation.cs" />
|
||||
<Compile Include="Behaviour\Operations\ConfigurationOperation.cs" />
|
||||
<Compile Include="Behaviour\Operations\KioskModeOperation.cs" />
|
||||
<Compile Include="Behaviour\Operations\ServiceConnectionOperation.cs" />
|
||||
<Compile Include="Behaviour\Operations\SessionSequenceEndOperation.cs" />
|
||||
<Compile Include="Behaviour\SessionController.cs" />
|
||||
<Compile Include="Behaviour\Operations\SessionSequenceStartOperation.cs" />
|
||||
<Compile Include="Behaviour\Operations\ServiceOperation.cs" />
|
||||
<Compile Include="Behaviour\Operations\SessionInitializationOperation.cs" />
|
||||
<Compile Include="Communication\ProxyFactory.cs" />
|
||||
<Compile Include="Communication\RuntimeHost.cs" />
|
||||
<Compile Include="CompositionRoot.cs" />
|
||||
|
|
Loading…
Reference in a new issue