SEBWIN-219: Finished basic implementation of reconfiguration mechanism.
This commit is contained in:
parent
5bd1d9dea4
commit
993329bd71
27 changed files with 259 additions and 98 deletions
|
@ -13,8 +13,10 @@ using System.Linq;
|
||||||
using CefSharp;
|
using CefSharp;
|
||||||
using SafeExamBrowser.Browser.Handlers;
|
using SafeExamBrowser.Browser.Handlers;
|
||||||
using SafeExamBrowser.Contracts.Behaviour;
|
using SafeExamBrowser.Contracts.Behaviour;
|
||||||
|
using SafeExamBrowser.Contracts.Communication;
|
||||||
using SafeExamBrowser.Contracts.Configuration;
|
using SafeExamBrowser.Contracts.Configuration;
|
||||||
using SafeExamBrowser.Contracts.I18n;
|
using SafeExamBrowser.Contracts.I18n;
|
||||||
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
using SafeExamBrowser.Contracts.UserInterface;
|
using SafeExamBrowser.Contracts.UserInterface;
|
||||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||||
using BrowserSettings = SafeExamBrowser.Contracts.Configuration.Settings.BrowserSettings;
|
using BrowserSettings = SafeExamBrowser.Contracts.Configuration.Settings.BrowserSettings;
|
||||||
|
@ -26,6 +28,8 @@ namespace SafeExamBrowser.Browser
|
||||||
private IApplicationButton button;
|
private IApplicationButton button;
|
||||||
private IList<IApplicationInstance> instances = new List<IApplicationInstance>();
|
private IList<IApplicationInstance> instances = new List<IApplicationInstance>();
|
||||||
private BrowserSettings settings;
|
private BrowserSettings settings;
|
||||||
|
private ILogger logger;
|
||||||
|
private IRuntimeProxy runtime;
|
||||||
private RuntimeInfo runtimeInfo;
|
private RuntimeInfo runtimeInfo;
|
||||||
private IUserInterfaceFactory uiFactory;
|
private IUserInterfaceFactory uiFactory;
|
||||||
private IText text;
|
private IText text;
|
||||||
|
@ -33,9 +37,13 @@ namespace SafeExamBrowser.Browser
|
||||||
public BrowserApplicationController(
|
public BrowserApplicationController(
|
||||||
BrowserSettings settings,
|
BrowserSettings settings,
|
||||||
RuntimeInfo runtimeInfo,
|
RuntimeInfo runtimeInfo,
|
||||||
|
ILogger logger,
|
||||||
|
IRuntimeProxy runtime,
|
||||||
IText text,
|
IText text,
|
||||||
IUserInterfaceFactory uiFactory)
|
IUserInterfaceFactory uiFactory)
|
||||||
{
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
this.runtime = runtime;
|
||||||
this.runtimeInfo = runtimeInfo;
|
this.runtimeInfo = runtimeInfo;
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
this.text = text;
|
this.text = text;
|
||||||
|
@ -112,15 +120,32 @@ namespace SafeExamBrowser.Browser
|
||||||
|
|
||||||
private void Instance_ConfigurationDetected(string url, CancelEventArgs args)
|
private void Instance_ConfigurationDetected(string url, CancelEventArgs args)
|
||||||
{
|
{
|
||||||
// TODO:
|
var result = uiFactory.Show(TextKey.MessageBox_ReconfigurationQuestion, TextKey.MessageBox_ReconfigurationQuestionTitle, MessageBoxAction.YesNo, MessageBoxIcon.Question);
|
||||||
// 1. Ask whether reconfiguration should be attempted
|
var reconfigure = result == MessageBoxResult.Yes;
|
||||||
// 2. Contact runtime and ask whether configuration valid and reconfiguration allowed
|
var allowed = false;
|
||||||
// - If yes, do nothing and wait for shutdown command
|
|
||||||
// - If no, show message box and NAVIGATE TO PREVIOUS PAGE -> but how?
|
|
||||||
|
|
||||||
var result = uiFactory.Show(TextKey.MessageBox_ReconfigureQuestion, TextKey.MessageBox_ReconfigureQuestionTitle, MessageBoxAction.YesNo, MessageBoxIcon.Question);
|
logger.Info($"Detected configuration request for '{url}'. The user chose to {(reconfigure ? "start" : "abort")} the reconfiguration.");
|
||||||
|
|
||||||
args.Cancel = result == MessageBoxResult.No;
|
if (reconfigure)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
allowed = runtime.RequestReconfiguration(url);
|
||||||
|
logger.Info($"The runtime {(allowed ? "accepted" : "denied")} the reconfiguration request.");
|
||||||
|
|
||||||
|
if (!allowed)
|
||||||
|
{
|
||||||
|
uiFactory.Show(TextKey.MessageBox_ReconfigurationDenied, TextKey.MessageBox_ReconfigurationDeniedTitle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.Error("Failed to communicate the reconfiguration request to the runtime!", e);
|
||||||
|
uiFactory.Show(TextKey.MessageBox_ReconfigurationError, TextKey.MessageBox_ReconfigurationErrorTitle, icon: MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
args.Cancel = !allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Instance_Terminated(Guid id)
|
private void Instance_Terminated(Guid id)
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace SafeExamBrowser.Browser.Handlers
|
||||||
{
|
{
|
||||||
public IResourceHandler Create(IBrowser browser, IFrame frame, string schemeName, IRequest request)
|
public IResourceHandler Create(IBrowser browser, IFrame frame, string schemeName, IRequest request)
|
||||||
{
|
{
|
||||||
var page = "<html><body style=\"height: 90%; display: flex; align-items: center; justify-content: center\"><progress /></body></html>";
|
var page = @"<html><body style=""height: 90%; display: flex; align-items: center; justify-content: center""><progress /></body></html>";
|
||||||
var handler = ResourceHandler.FromString(page);
|
var handler = ResourceHandler.FromString(page);
|
||||||
|
|
||||||
return handler;
|
return handler;
|
||||||
|
|
|
@ -48,6 +48,7 @@ namespace SafeExamBrowser.Client
|
||||||
private IClientHost clientHost;
|
private IClientHost clientHost;
|
||||||
private ILogger logger;
|
private ILogger logger;
|
||||||
private INativeMethods nativeMethods;
|
private INativeMethods nativeMethods;
|
||||||
|
private IRuntimeProxy runtimeProxy;
|
||||||
private ISystemInfo systemInfo;
|
private ISystemInfo systemInfo;
|
||||||
private IText text;
|
private IText text;
|
||||||
private IUserInterfaceFactory uiFactory;
|
private IUserInterfaceFactory uiFactory;
|
||||||
|
@ -68,8 +69,8 @@ namespace SafeExamBrowser.Client
|
||||||
|
|
||||||
text = new Text(logger);
|
text = new Text(logger);
|
||||||
uiFactory = new UserInterfaceFactory(text);
|
uiFactory = new UserInterfaceFactory(text);
|
||||||
|
runtimeProxy = new RuntimeProxy(runtimeHostUri, new ModuleLogger(logger, typeof(RuntimeProxy)));
|
||||||
|
|
||||||
var runtimeProxy = new RuntimeProxy(runtimeHostUri, new ModuleLogger(logger, typeof(RuntimeProxy)));
|
|
||||||
var displayMonitor = new DisplayMonitor(new ModuleLogger(logger, typeof(DisplayMonitor)), nativeMethods);
|
var displayMonitor = new DisplayMonitor(new ModuleLogger(logger, typeof(DisplayMonitor)), nativeMethods);
|
||||||
var processMonitor = new ProcessMonitor(new ModuleLogger(logger, typeof(ProcessMonitor)), nativeMethods);
|
var processMonitor = new ProcessMonitor(new ModuleLogger(logger, typeof(ProcessMonitor)), nativeMethods);
|
||||||
var windowMonitor = new WindowMonitor(new ModuleLogger(logger, typeof(WindowMonitor)), nativeMethods);
|
var windowMonitor = new WindowMonitor(new ModuleLogger(logger, typeof(WindowMonitor)), nativeMethods);
|
||||||
|
@ -143,7 +144,8 @@ namespace SafeExamBrowser.Client
|
||||||
|
|
||||||
private IOperation BuildBrowserOperation()
|
private IOperation BuildBrowserOperation()
|
||||||
{
|
{
|
||||||
var browserController = new BrowserApplicationController(configuration.Settings.Browser, configuration.RuntimeInfo, text, uiFactory);
|
var moduleLogger = new ModuleLogger(logger, typeof(BrowserApplicationController));
|
||||||
|
var browserController = new BrowserApplicationController(configuration.Settings.Browser, configuration.RuntimeInfo, moduleLogger, runtimeProxy, text, uiFactory);
|
||||||
var browserInfo = new BrowserApplicationInfo();
|
var browserInfo = new BrowserApplicationInfo();
|
||||||
var operation = new BrowserOperation(browserController, browserInfo, logger, Taskbar, uiFactory);
|
var operation = new BrowserOperation(browserController, browserInfo, logger, Taskbar, uiFactory);
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,9 @@ namespace SafeExamBrowser.Configuration
|
||||||
{
|
{
|
||||||
private RuntimeInfo runtimeInfo;
|
private RuntimeInfo runtimeInfo;
|
||||||
|
|
||||||
public ISession CurrentSession { get; private set; }
|
public ISessionData CurrentSession { get; private set; }
|
||||||
public Settings CurrentSettings { get; private set; }
|
public Settings CurrentSettings { get; private set; }
|
||||||
|
public string ReconfigurationUrl { get; set; }
|
||||||
|
|
||||||
public RuntimeInfo RuntimeInfo
|
public RuntimeInfo RuntimeInfo
|
||||||
{
|
{
|
||||||
|
@ -34,9 +35,9 @@ namespace SafeExamBrowser.Configuration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ISession InitializeSession()
|
public ISessionData InitializeSessionData()
|
||||||
{
|
{
|
||||||
var session = new Session
|
var session = new SessionData
|
||||||
{
|
{
|
||||||
Id = Guid.NewGuid(),
|
Id = Guid.NewGuid(),
|
||||||
StartupToken = Guid.NewGuid()
|
StartupToken = Guid.NewGuid()
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Session.cs" />
|
<Compile Include="SessionData.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="ConfigurationRepository.cs" />
|
<Compile Include="ConfigurationRepository.cs" />
|
||||||
<Compile Include="SystemInfo.cs" />
|
<Compile Include="SystemInfo.cs" />
|
||||||
|
|
|
@ -12,7 +12,7 @@ using SafeExamBrowser.Contracts.WindowsApi;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Configuration
|
namespace SafeExamBrowser.Configuration
|
||||||
{
|
{
|
||||||
public class Session : ISession
|
public class SessionData : ISessionData
|
||||||
{
|
{
|
||||||
public IProcess ClientProcess { get; set; }
|
public IProcess ClientProcess { get; set; }
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
|
@ -18,10 +18,12 @@ namespace SafeExamBrowser.Contracts.Communication
|
||||||
/// Defines the API for all communication between the three application components (runtime, service and client).
|
/// Defines the API for all communication between the three application components (runtime, service and client).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ServiceContract(SessionMode = SessionMode.Required)]
|
[ServiceContract(SessionMode = SessionMode.Required)]
|
||||||
[ServiceKnownType(typeof(SimpleMessage))]
|
|
||||||
[ServiceKnownType(typeof(AuthenticationResponse))]
|
[ServiceKnownType(typeof(AuthenticationResponse))]
|
||||||
[ServiceKnownType(typeof(ConfigurationResponse))]
|
|
||||||
[ServiceKnownType(typeof(ClientConfiguration))]
|
[ServiceKnownType(typeof(ClientConfiguration))]
|
||||||
|
[ServiceKnownType(typeof(ConfigurationResponse))]
|
||||||
|
[ServiceKnownType(typeof(ReconfigurationMessage))]
|
||||||
|
[ServiceKnownType(typeof(ReconfigurationResponse))]
|
||||||
|
[ServiceKnownType(typeof(SimpleMessage))]
|
||||||
[ServiceKnownType(typeof(SimpleResponse))]
|
[ServiceKnownType(typeof(SimpleResponse))]
|
||||||
public interface ICommunication
|
public interface ICommunication
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,6 +30,11 @@ namespace SafeExamBrowser.Contracts.Communication
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event CommunicationEventHandler ClientReady;
|
event CommunicationEventHandler ClientReady;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event fired when the client detected a reconfiguration request.
|
||||||
|
/// </summary>
|
||||||
|
event CommunicationEventHandler ReconfigurationRequested;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event fired when the client requests to shut down the application.
|
/// Event fired when the client requests to shut down the application.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -32,5 +32,12 @@ namespace SafeExamBrowser.Contracts.Communication
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <exception cref="System.ServiceModel.*">If the communication failed.</exception>
|
/// <exception cref="System.ServiceModel.*">If the communication failed.</exception>
|
||||||
void RequestShutdown();
|
void RequestShutdown();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Requests the runtime to reconfigure the application with the configuration from the given location. Returns <c>true</c> if
|
||||||
|
/// the runtime accepted the request, otherwise <c>false</c>.
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="System.ServiceModel.*">If the communication failed.</exception>
|
||||||
|
bool RequestReconfiguration(string url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* 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 System;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Contracts.Communication.Messages
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This message is transmitted to the runtime to request that the application be reconfigured.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public class ReconfigurationMessage : Message
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The locator of the new configuration to be used.
|
||||||
|
/// </summary>
|
||||||
|
public string ConfigurationUrl { get; private set; }
|
||||||
|
|
||||||
|
public ReconfigurationMessage(string url)
|
||||||
|
{
|
||||||
|
ConfigurationUrl = url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* 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 System;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Contracts.Communication.Responses
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The response to a <see cref="Messages.ReconfigurationMessage"/>.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public class ReconfigurationResponse : Response
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the reconfiguration request has been accepted.
|
||||||
|
/// </summary>
|
||||||
|
public bool Accepted { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,10 +16,10 @@ namespace SafeExamBrowser.Contracts.Configuration
|
||||||
public interface IConfigurationRepository
|
public interface IConfigurationRepository
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the current session, i.e. the last one which was initialized. If no session has been initialized yet, this
|
/// Retrieves the current session data, i.e. the last one which was initialized. If no session has been initialized yet, this
|
||||||
/// property will be <c>null</c>!
|
/// property will be <c>null</c>!
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ISession CurrentSession { get; }
|
ISessionData CurrentSession { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the current settings, i.e. the last ones which were loaded. If no settings have been loaded yet, this property will
|
/// Retrieves the current settings, i.e. the last ones which were loaded. If no settings have been loaded yet, this property will
|
||||||
|
@ -27,6 +27,11 @@ namespace SafeExamBrowser.Contracts.Configuration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Settings.Settings CurrentSettings { get; }
|
Settings.Settings CurrentSettings { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The locator of the configuration to be used when reconfiguring the application.
|
||||||
|
/// </summary>
|
||||||
|
string ReconfigurationUrl { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The runtime information for the currently running application instance.
|
/// The runtime information for the currently running application instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -40,7 +45,7 @@ namespace SafeExamBrowser.Contracts.Configuration
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes all relevant data for a new session.
|
/// Initializes all relevant data for a new session.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ISession InitializeSession();
|
ISessionData InitializeSessionData();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attempts to load settings from the specified path.
|
/// Attempts to load settings from the specified path.
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace SafeExamBrowser.Contracts.Configuration
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines all session-related (configuration) data.
|
/// Defines all session-related (configuration) data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ISession
|
public interface ISessionData
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The process information of the client instance associated to this session.
|
/// The process information of the client instance associated to this session.
|
|
@ -18,14 +18,18 @@ namespace SafeExamBrowser.Contracts.I18n
|
||||||
LogWindow_Title,
|
LogWindow_Title,
|
||||||
MessageBox_ApplicationError,
|
MessageBox_ApplicationError,
|
||||||
MessageBox_ApplicationErrorTitle,
|
MessageBox_ApplicationErrorTitle,
|
||||||
MessageBox_ConfigureClientSuccess,
|
MessageBox_ClientConfigurationQuestion,
|
||||||
MessageBox_ConfigureClientSuccessTitle,
|
MessageBox_ClientConfigurationQuestionTitle,
|
||||||
MessageBox_Quit,
|
MessageBox_Quit,
|
||||||
MessageBox_QuitTitle,
|
MessageBox_QuitTitle,
|
||||||
MessageBox_QuitError,
|
MessageBox_QuitError,
|
||||||
MessageBox_QuitErrorTitle,
|
MessageBox_QuitErrorTitle,
|
||||||
MessageBox_ReconfigureQuestion,
|
MessageBox_ReconfigurationDenied,
|
||||||
MessageBox_ReconfigureQuestionTitle,
|
MessageBox_ReconfigurationDeniedTitle,
|
||||||
|
MessageBox_ReconfigurationError,
|
||||||
|
MessageBox_ReconfigurationErrorTitle,
|
||||||
|
MessageBox_ReconfigurationQuestion,
|
||||||
|
MessageBox_ReconfigurationQuestionTitle,
|
||||||
MessageBox_SessionStartError,
|
MessageBox_SessionStartError,
|
||||||
MessageBox_SessionStartErrorTitle,
|
MessageBox_SessionStartErrorTitle,
|
||||||
MessageBox_SessionStopError,
|
MessageBox_SessionStopError,
|
||||||
|
|
|
@ -67,18 +67,20 @@
|
||||||
<Compile Include="Communication\IServiceProxy.cs" />
|
<Compile Include="Communication\IServiceProxy.cs" />
|
||||||
<Compile Include="Communication\Messages\Message.cs" />
|
<Compile Include="Communication\Messages\Message.cs" />
|
||||||
<Compile Include="Communication\Messages\DisconnectionMessage.cs" />
|
<Compile Include="Communication\Messages\DisconnectionMessage.cs" />
|
||||||
|
<Compile Include="Communication\Messages\ReconfigurationMessage.cs" />
|
||||||
<Compile Include="Communication\Messages\SimpleMessagePurport.cs" />
|
<Compile Include="Communication\Messages\SimpleMessagePurport.cs" />
|
||||||
<Compile Include="Communication\Messages\SimpleMessage.cs" />
|
<Compile Include="Communication\Messages\SimpleMessage.cs" />
|
||||||
<Compile Include="Communication\Responses\AuthenticationResponse.cs" />
|
<Compile Include="Communication\Responses\AuthenticationResponse.cs" />
|
||||||
<Compile Include="Communication\Responses\ConfigurationResponse.cs" />
|
<Compile Include="Communication\Responses\ConfigurationResponse.cs" />
|
||||||
<Compile Include="Communication\Responses\ConnectionResponse.cs" />
|
<Compile Include="Communication\Responses\ConnectionResponse.cs" />
|
||||||
<Compile Include="Communication\Responses\DisconnectionResponse.cs" />
|
<Compile Include="Communication\Responses\DisconnectionResponse.cs" />
|
||||||
|
<Compile Include="Communication\Responses\ReconfigurationResponse.cs" />
|
||||||
<Compile Include="Communication\Responses\Response.cs" />
|
<Compile Include="Communication\Responses\Response.cs" />
|
||||||
<Compile Include="Communication\Responses\SimpleResponsePurport.cs" />
|
<Compile Include="Communication\Responses\SimpleResponsePurport.cs" />
|
||||||
<Compile Include="Communication\Responses\SimpleResponse.cs" />
|
<Compile Include="Communication\Responses\SimpleResponse.cs" />
|
||||||
<Compile Include="Configuration\ClientConfiguration.cs" />
|
<Compile Include="Configuration\ClientConfiguration.cs" />
|
||||||
<Compile Include="Configuration\RuntimeInfo.cs" />
|
<Compile Include="Configuration\RuntimeInfo.cs" />
|
||||||
<Compile Include="Configuration\ISession.cs" />
|
<Compile Include="Configuration\ISessionData.cs" />
|
||||||
<Compile Include="Configuration\Settings\ConfigurationMode.cs" />
|
<Compile Include="Configuration\Settings\ConfigurationMode.cs" />
|
||||||
<Compile Include="Behaviour\INotificationController.cs" />
|
<Compile Include="Behaviour\INotificationController.cs" />
|
||||||
<Compile Include="Behaviour\OperationModel\IOperation.cs" />
|
<Compile Include="Behaviour\OperationModel\IOperation.cs" />
|
||||||
|
|
|
@ -26,7 +26,6 @@ namespace SafeExamBrowser.Core.Communication
|
||||||
private readonly object @lock = new object();
|
private readonly object @lock = new object();
|
||||||
|
|
||||||
private string address;
|
private string address;
|
||||||
private ILogger logger;
|
|
||||||
private ServiceHost host;
|
private ServiceHost host;
|
||||||
private Thread hostThread;
|
private Thread hostThread;
|
||||||
|
|
||||||
|
@ -47,7 +46,7 @@ namespace SafeExamBrowser.Core.Communication
|
||||||
public BaseHost(string address, ILogger logger)
|
public BaseHost(string address, ILogger logger)
|
||||||
{
|
{
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.logger = logger;
|
this.Logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract bool OnConnect(Guid? token);
|
protected abstract bool OnConnect(Guid? token);
|
||||||
|
@ -59,7 +58,7 @@ namespace SafeExamBrowser.Core.Communication
|
||||||
{
|
{
|
||||||
lock (@lock)
|
lock (@lock)
|
||||||
{
|
{
|
||||||
logger.Debug($"Received connection request with authentication token '{token}'.");
|
Logger.Debug($"Received connection request with authentication token '{token}'.");
|
||||||
|
|
||||||
var response = new ConnectionResponse();
|
var response = new ConnectionResponse();
|
||||||
var connected = OnConnect(token);
|
var connected = OnConnect(token);
|
||||||
|
@ -70,7 +69,7 @@ namespace SafeExamBrowser.Core.Communication
|
||||||
response.ConnectionEstablished = true;
|
response.ConnectionEstablished = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Debug($"{(connected ? "Accepted" : "Denied")} connection request.");
|
Logger.Debug($"{(connected ? "Accepted" : "Denied")} connection request.");
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
@ -82,7 +81,7 @@ namespace SafeExamBrowser.Core.Communication
|
||||||
{
|
{
|
||||||
var response = new DisconnectionResponse();
|
var response = new DisconnectionResponse();
|
||||||
|
|
||||||
logger.Debug($"Received disconnection request with message '{ToString(message)}'.");
|
Logger.Debug($"Received disconnection request with message '{ToString(message)}'.");
|
||||||
|
|
||||||
if (IsAuthorized(message?.CommunicationToken))
|
if (IsAuthorized(message?.CommunicationToken))
|
||||||
{
|
{
|
||||||
|
@ -118,7 +117,7 @@ namespace SafeExamBrowser.Core.Communication
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Debug($"Received message '{ToString(message)}', sending response '{ToString(response)}'.");
|
Logger.Debug($"Received message '{ToString(message)}', sending response '{ToString(response)}'.");
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
@ -153,7 +152,7 @@ namespace SafeExamBrowser.Core.Communication
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
logger.Debug($"Terminated communication host for endpoint '{address}'.");
|
Logger.Debug($"Terminated communication host for endpoint '{address}'.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -183,7 +182,7 @@ namespace SafeExamBrowser.Core.Communication
|
||||||
host.UnknownMessageReceived += Host_UnknownMessageReceived;
|
host.UnknownMessageReceived += Host_UnknownMessageReceived;
|
||||||
host.Open();
|
host.Open();
|
||||||
|
|
||||||
logger.Debug($"Successfully started communication host for endpoint '{address}'.");
|
Logger.Debug($"Successfully started communication host for endpoint '{address}'.");
|
||||||
|
|
||||||
startedEvent.Set();
|
startedEvent.Set();
|
||||||
}
|
}
|
||||||
|
@ -215,32 +214,32 @@ namespace SafeExamBrowser.Core.Communication
|
||||||
|
|
||||||
private void Host_Closed(object sender, EventArgs e)
|
private void Host_Closed(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
logger.Debug("Communication host has been closed.");
|
Logger.Debug("Communication host has been closed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Host_Closing(object sender, EventArgs e)
|
private void Host_Closing(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
logger.Debug("Communication host is closing...");
|
Logger.Debug("Communication host is closing...");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Host_Faulted(object sender, EventArgs e)
|
private void Host_Faulted(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
logger.Error("Communication host has faulted!");
|
Logger.Error("Communication host has faulted!");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Host_Opened(object sender, EventArgs e)
|
private void Host_Opened(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
logger.Debug("Communication host has been opened.");
|
Logger.Debug("Communication host has been opened.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Host_Opening(object sender, EventArgs e)
|
private void Host_Opening(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
logger.Debug("Communication host is opening...");
|
Logger.Debug("Communication host is opening...");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Host_UnknownMessageReceived(object sender, UnknownMessageReceivedEventArgs e)
|
private void Host_UnknownMessageReceived(object sender, UnknownMessageReceivedEventArgs e)
|
||||||
{
|
{
|
||||||
logger.Warn($"Communication host has received an unknown message: {e?.Message}.");
|
Logger.Warn($"Communication host has received an unknown message: {e?.Message}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private string ToString(Message message)
|
private string ToString(Message message)
|
||||||
|
|
|
@ -51,7 +51,7 @@ namespace SafeExamBrowser.Core.Communication
|
||||||
(channel as ICommunicationObject).Opened += BaseProxy_Opened;
|
(channel as ICommunicationObject).Opened += BaseProxy_Opened;
|
||||||
(channel as ICommunicationObject).Opening += BaseProxy_Opening;
|
(channel as ICommunicationObject).Opening += BaseProxy_Opening;
|
||||||
|
|
||||||
Logger.Debug($"Trying to connect to endpoint {address}{(token.HasValue ? $" with authentication token '{token}'" : string.Empty)}...");
|
Logger.Debug($"Trying to connect to endpoint '{address}'{(token.HasValue ? $" with authentication token '{token}'" : string.Empty)}...");
|
||||||
|
|
||||||
var response = channel.Connect(token);
|
var response = channel.Connect(token);
|
||||||
|
|
||||||
|
@ -125,7 +125,6 @@ namespace SafeExamBrowser.Core.Communication
|
||||||
private void BaseProxy_Faulted(object sender, EventArgs e)
|
private void BaseProxy_Faulted(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Logger.Error("Communication channel has faulted!");
|
Logger.Error("Communication channel has faulted!");
|
||||||
ConnectionLost?.Invoke();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BaseProxy_Opened(object sender, EventArgs e)
|
private void BaseProxy_Opened(object sender, EventArgs e)
|
||||||
|
|
|
@ -46,6 +46,18 @@ namespace SafeExamBrowser.Core.Communication
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool RequestReconfiguration(string url)
|
||||||
|
{
|
||||||
|
var response = Send(new ReconfigurationMessage(url));
|
||||||
|
|
||||||
|
if (response is ReconfigurationResponse reconfiguration)
|
||||||
|
{
|
||||||
|
return reconfiguration.Accepted;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public void RequestShutdown()
|
public void RequestShutdown()
|
||||||
{
|
{
|
||||||
var response = Send(SimpleMessagePurport.RequestShutdown);
|
var response = Send(SimpleMessagePurport.RequestShutdown);
|
||||||
|
|
|
@ -12,10 +12,10 @@
|
||||||
<Entry key="MessageBox_ApplicationErrorTitle">
|
<Entry key="MessageBox_ApplicationErrorTitle">
|
||||||
Application Error
|
Application Error
|
||||||
</Entry>
|
</Entry>
|
||||||
<Entry key="MessageBox_ConfigureClientSuccess">
|
<Entry key="MessageBox_ClientConfigurationQuestion">
|
||||||
The client configuration has been saved and will be used when you start the application the next time. Do you want to quit for now?
|
The client configuration has been saved and will be used when you start the application the next time. Do you want to quit for now?
|
||||||
</Entry>
|
</Entry>
|
||||||
<Entry key="MessageBox_ConfigureClientSuccessTitle">
|
<Entry key="MessageBox_ClientConfigurationQuestionTitle">
|
||||||
Configuration Successful
|
Configuration Successful
|
||||||
</Entry>
|
</Entry>
|
||||||
<Entry key="MessageBox_Quit">
|
<Entry key="MessageBox_Quit">
|
||||||
|
@ -25,15 +25,27 @@
|
||||||
Quit?
|
Quit?
|
||||||
</Entry>
|
</Entry>
|
||||||
<Entry key="MessageBox_QuitError">
|
<Entry key="MessageBox_QuitError">
|
||||||
The client failed to communicate the shutdown request to the runtime! Please try again...
|
The client failed to communicate the shutdown request to the runtime!
|
||||||
</Entry>
|
</Entry>
|
||||||
<Entry key="MessageBox_QuitErrorTitle">
|
<Entry key="MessageBox_QuitErrorTitle">
|
||||||
Quit Error
|
Quit Error
|
||||||
</Entry>
|
</Entry>
|
||||||
<Entry key="MessageBox_ReconfigureQuestion">
|
<Entry key="MessageBox_ReconfigurationDenied">
|
||||||
|
You are not allowed to reconfigure the application.
|
||||||
|
</Entry>
|
||||||
|
<Entry key="MessageBox_ReconfigurationDeniedTitle">
|
||||||
|
Reconfiguration Denied
|
||||||
|
</Entry>
|
||||||
|
<Entry key="MessageBox_ReconfigurationError">
|
||||||
|
The client failed to communicate the reconfiguration request to the runtime!
|
||||||
|
</Entry>
|
||||||
|
<Entry key="MessageBox_ReconfigurationErrorTitle">
|
||||||
|
Reconfiguration Error
|
||||||
|
</Entry>
|
||||||
|
<Entry key="MessageBox_ReconfigurationQuestion">
|
||||||
Would you like to reconfigure the application?
|
Would you like to reconfigure the application?
|
||||||
</Entry>
|
</Entry>
|
||||||
<Entry key="MessageBox_ReconfigureQuestionTitle">
|
<Entry key="MessageBox_ReconfigurationQuestionTitle">
|
||||||
Configuration Detected
|
Configuration Detected
|
||||||
</Entry>
|
</Entry>
|
||||||
<Entry key="MessageBox_SessionStartError">
|
<Entry key="MessageBox_SessionStartError">
|
||||||
|
|
|
@ -127,8 +127,8 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
||||||
|
|
||||||
private bool IsConfigurationSufficient()
|
private bool IsConfigurationSufficient()
|
||||||
{
|
{
|
||||||
var message = text.Get(TextKey.MessageBox_ConfigureClientSuccess);
|
var message = text.Get(TextKey.MessageBox_ClientConfigurationQuestion);
|
||||||
var title = text.Get(TextKey.MessageBox_ConfigureClientSuccessTitle);
|
var title = text.Get(TextKey.MessageBox_ClientConfigurationQuestionTitle);
|
||||||
var abort = uiFactory.Show(message, title, MessageBoxAction.YesNo, MessageBoxIcon.Question);
|
var abort = uiFactory.Show(message, title, MessageBoxAction.YesNo, MessageBoxIcon.Question);
|
||||||
|
|
||||||
return abort == MessageBoxResult.Yes;
|
return abort == MessageBoxResult.Yes;
|
||||||
|
|
|
@ -7,38 +7,39 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using SafeExamBrowser.Contracts.Behaviour.OperationModel;
|
using SafeExamBrowser.Contracts.Behaviour.OperationModel;
|
||||||
using SafeExamBrowser.Contracts.Communication;
|
using SafeExamBrowser.Contracts.UserInterface;
|
||||||
using SafeExamBrowser.Contracts.Configuration;
|
|
||||||
using SafeExamBrowser.Contracts.Logging;
|
|
||||||
using SafeExamBrowser.Contracts.WindowsApi;
|
|
||||||
|
|
||||||
namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
||||||
{
|
{
|
||||||
internal class SessionSequenceEndOperation : SessionSequenceOperation
|
internal class SessionSequenceEndOperation : IOperation
|
||||||
{
|
{
|
||||||
public SessionSequenceEndOperation(
|
private SessionController controller;
|
||||||
IClientProxy client,
|
|
||||||
IConfigurationRepository configuration,
|
public IProgressIndicator ProgressIndicator { private get; set; }
|
||||||
ILogger logger,
|
|
||||||
IProcessFactory processFactory,
|
public SessionSequenceEndOperation(SessionController controller)
|
||||||
IRuntimeHost runtimeHost,
|
|
||||||
IServiceProxy service) : base(client, configuration, logger, processFactory, runtimeHost, service)
|
|
||||||
{
|
{
|
||||||
|
this.controller = controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override OperationResult Perform()
|
public OperationResult Perform()
|
||||||
{
|
{
|
||||||
return StartSession();
|
controller.ProgressIndicator = ProgressIndicator;
|
||||||
|
|
||||||
|
return controller.StartSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override OperationResult Repeat()
|
public OperationResult Repeat()
|
||||||
{
|
{
|
||||||
return StartSession();
|
controller.ProgressIndicator = ProgressIndicator;
|
||||||
|
|
||||||
|
return controller.StartSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Revert()
|
public void Revert()
|
||||||
{
|
{
|
||||||
StopSession();
|
controller.ProgressIndicator = ProgressIndicator;
|
||||||
|
controller.StopSession();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,36 +7,34 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using SafeExamBrowser.Contracts.Behaviour.OperationModel;
|
using SafeExamBrowser.Contracts.Behaviour.OperationModel;
|
||||||
using SafeExamBrowser.Contracts.Communication;
|
using SafeExamBrowser.Contracts.UserInterface;
|
||||||
using SafeExamBrowser.Contracts.Configuration;
|
|
||||||
using SafeExamBrowser.Contracts.Logging;
|
|
||||||
using SafeExamBrowser.Contracts.WindowsApi;
|
|
||||||
|
|
||||||
namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
||||||
{
|
{
|
||||||
internal class SessionSequenceStartOperation : SessionSequenceOperation
|
internal class SessionSequenceStartOperation : IOperation
|
||||||
{
|
{
|
||||||
public SessionSequenceStartOperation(
|
private SessionController controller;
|
||||||
IClientProxy client,
|
|
||||||
IConfigurationRepository configuration,
|
public IProgressIndicator ProgressIndicator { private get; set; }
|
||||||
ILogger logger,
|
|
||||||
IProcessFactory processFactory,
|
public SessionSequenceStartOperation(SessionController controller)
|
||||||
IRuntimeHost runtimeHost,
|
|
||||||
IServiceProxy service) : base(client, configuration, logger, processFactory, runtimeHost, service)
|
|
||||||
{
|
{
|
||||||
|
this.controller = controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override OperationResult Perform()
|
public OperationResult Perform()
|
||||||
{
|
{
|
||||||
return OperationResult.Success;
|
return OperationResult.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override OperationResult Repeat()
|
public OperationResult Repeat()
|
||||||
{
|
{
|
||||||
return StopSession();
|
controller.ProgressIndicator = ProgressIndicator;
|
||||||
|
|
||||||
|
return controller.StopSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Revert()
|
public void Revert()
|
||||||
{
|
{
|
||||||
// Nothing to do here...
|
// Nothing to do here...
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,6 +134,7 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
{
|
{
|
||||||
runtimeWindow.Show();
|
runtimeWindow.Show();
|
||||||
runtimeWindow.BringToForeground();
|
runtimeWindow.BringToForeground();
|
||||||
|
runtimeWindow.ShowProgressBar();
|
||||||
logger.Info(">>>--- Initiating session procedure ---<<<");
|
logger.Info(">>>--- Initiating session procedure ---<<<");
|
||||||
|
|
||||||
if (sessionRunning)
|
if (sessionRunning)
|
||||||
|
@ -170,6 +171,7 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
|
|
||||||
if (!initial)
|
if (!initial)
|
||||||
{
|
{
|
||||||
|
logger.Info("Terminating application...");
|
||||||
shutdown.Invoke();
|
shutdown.Invoke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,6 +203,7 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
private void RegisterEvents()
|
private void RegisterEvents()
|
||||||
{
|
{
|
||||||
client.ConnectionLost += Client_ConnectionLost;
|
client.ConnectionLost += Client_ConnectionLost;
|
||||||
|
runtimeHost.ReconfigurationRequested += RuntimeHost_ReconfigurationRequested;
|
||||||
runtimeHost.ShutdownRequested += RuntimeHost_ShutdownRequested;
|
runtimeHost.ShutdownRequested += RuntimeHost_ShutdownRequested;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,6 +215,7 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
private void DeregisterEvents()
|
private void DeregisterEvents()
|
||||||
{
|
{
|
||||||
client.ConnectionLost -= Client_ConnectionLost;
|
client.ConnectionLost -= Client_ConnectionLost;
|
||||||
|
runtimeHost.ReconfigurationRequested -= RuntimeHost_ReconfigurationRequested;
|
||||||
runtimeHost.ShutdownRequested -= RuntimeHost_ShutdownRequested;
|
runtimeHost.ShutdownRequested -= RuntimeHost_ShutdownRequested;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,6 +242,12 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
shutdown.Invoke();
|
shutdown.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void RuntimeHost_ReconfigurationRequested()
|
||||||
|
{
|
||||||
|
logger.Info($"Starting reconfiguration...");
|
||||||
|
StartSession();
|
||||||
|
}
|
||||||
|
|
||||||
private void RuntimeHost_ShutdownRequested()
|
private void RuntimeHost_ShutdownRequested()
|
||||||
{
|
{
|
||||||
logger.Info("Received shutdown request from the client application.");
|
logger.Info("Received shutdown request from the client application.");
|
||||||
|
|
|
@ -15,9 +15,9 @@ using SafeExamBrowser.Contracts.Logging;
|
||||||
using SafeExamBrowser.Contracts.UserInterface;
|
using SafeExamBrowser.Contracts.UserInterface;
|
||||||
using SafeExamBrowser.Contracts.WindowsApi;
|
using SafeExamBrowser.Contracts.WindowsApi;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
{
|
{
|
||||||
internal abstract class SessionSequenceOperation : IOperation
|
internal class SessionController
|
||||||
{
|
{
|
||||||
private const int TEN_SECONDS = 10000;
|
private const int TEN_SECONDS = 10000;
|
||||||
|
|
||||||
|
@ -28,11 +28,11 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
||||||
private IProcessFactory processFactory;
|
private IProcessFactory processFactory;
|
||||||
private IRuntimeHost runtimeHost;
|
private IRuntimeHost runtimeHost;
|
||||||
private IServiceProxy service;
|
private IServiceProxy service;
|
||||||
private ISession session;
|
private ISessionData session;
|
||||||
|
|
||||||
public IProgressIndicator ProgressIndicator { private get; set; }
|
internal IProgressIndicator ProgressIndicator { private get; set; }
|
||||||
|
|
||||||
public SessionSequenceOperation(
|
internal SessionController(
|
||||||
IClientProxy client,
|
IClientProxy client,
|
||||||
IConfigurationRepository configuration,
|
IConfigurationRepository configuration,
|
||||||
ILogger logger,
|
ILogger logger,
|
||||||
|
@ -48,16 +48,12 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
||||||
this.service = service;
|
this.service = service;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract OperationResult Perform();
|
internal OperationResult StartSession()
|
||||||
public abstract OperationResult Repeat();
|
|
||||||
public abstract void Revert();
|
|
||||||
|
|
||||||
protected OperationResult StartSession()
|
|
||||||
{
|
{
|
||||||
logger.Info("Starting new session...");
|
logger.Info("Starting new session...");
|
||||||
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StartSession, true);
|
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StartSession, true);
|
||||||
|
|
||||||
session = configuration.InitializeSession();
|
session = configuration.InitializeSessionData();
|
||||||
runtimeHost.StartupToken = session.StartupToken;
|
runtimeHost.StartupToken = session.StartupToken;
|
||||||
|
|
||||||
logger.Info("Initializing service session...");
|
logger.Info("Initializing service session...");
|
||||||
|
@ -78,7 +74,7 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
||||||
return OperationResult.Success;
|
return OperationResult.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected OperationResult StopSession()
|
internal OperationResult StopSession()
|
||||||
{
|
{
|
||||||
if (sessionRunning)
|
if (sessionRunning)
|
||||||
{
|
{
|
|
@ -7,10 +7,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using SafeExamBrowser.Contracts.Communication;
|
using SafeExamBrowser.Contracts.Communication;
|
||||||
using SafeExamBrowser.Contracts.Communication.Messages;
|
using SafeExamBrowser.Contracts.Communication.Messages;
|
||||||
using SafeExamBrowser.Contracts.Communication.Responses;
|
using SafeExamBrowser.Contracts.Communication.Responses;
|
||||||
using SafeExamBrowser.Contracts.Configuration;
|
using SafeExamBrowser.Contracts.Configuration;
|
||||||
|
using SafeExamBrowser.Contracts.Configuration.Settings;
|
||||||
using SafeExamBrowser.Contracts.Logging;
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
using SafeExamBrowser.Core.Communication;
|
using SafeExamBrowser.Core.Communication;
|
||||||
|
|
||||||
|
@ -25,6 +27,7 @@ namespace SafeExamBrowser.Runtime.Communication
|
||||||
|
|
||||||
public event CommunicationEventHandler ClientDisconnected;
|
public event CommunicationEventHandler ClientDisconnected;
|
||||||
public event CommunicationEventHandler ClientReady;
|
public event CommunicationEventHandler ClientReady;
|
||||||
|
public event CommunicationEventHandler ReconfigurationRequested;
|
||||||
public event CommunicationEventHandler ShutdownRequested;
|
public event CommunicationEventHandler ShutdownRequested;
|
||||||
|
|
||||||
public RuntimeHost(string address, IConfigurationRepository configuration, ILogger logger) : base(address, logger)
|
public RuntimeHost(string address, IConfigurationRepository configuration, ILogger logger) : base(address, logger)
|
||||||
|
@ -48,10 +51,17 @@ namespace SafeExamBrowser.Runtime.Communication
|
||||||
protected override void OnDisconnect()
|
protected override void OnDisconnect()
|
||||||
{
|
{
|
||||||
ClientDisconnected?.Invoke();
|
ClientDisconnected?.Invoke();
|
||||||
|
allowConnection = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Response OnReceive(Message message)
|
protected override Response OnReceive(Message message)
|
||||||
{
|
{
|
||||||
|
switch (message)
|
||||||
|
{
|
||||||
|
case ReconfigurationMessage reconfigurationMessage:
|
||||||
|
return Handle(reconfigurationMessage);
|
||||||
|
}
|
||||||
|
|
||||||
return new SimpleResponse(SimpleResponsePurport.UnknownMessage);
|
return new SimpleResponse(SimpleResponsePurport.UnknownMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,5 +81,22 @@ namespace SafeExamBrowser.Runtime.Communication
|
||||||
|
|
||||||
return new SimpleResponse(SimpleResponsePurport.UnknownMessage);
|
return new SimpleResponse(SimpleResponsePurport.UnknownMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Response Handle(ReconfigurationMessage message)
|
||||||
|
{
|
||||||
|
var isExam = configuration.CurrentSettings.ConfigurationMode == ConfigurationMode.Exam;
|
||||||
|
var isValidUri = Uri.TryCreate(message.ConfigurationUrl, UriKind.Absolute, out _);
|
||||||
|
var allowed = !isExam && isValidUri;
|
||||||
|
|
||||||
|
Logger.Info($"Received reconfiguration request for '{message.ConfigurationUrl}', {(allowed ? "accepted" : "denied")} it.");
|
||||||
|
|
||||||
|
if (allowed)
|
||||||
|
{
|
||||||
|
configuration.ReconfigurationUrl = message.ConfigurationUrl;
|
||||||
|
Task.Run(() => ReconfigurationRequested?.Invoke());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ReconfigurationResponse { Accepted = allowed };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ namespace SafeExamBrowser.Runtime
|
||||||
var clientProxy = new ClientProxy(runtimeInfo.ClientAddress, new ModuleLogger(logger, typeof(ClientProxy)));
|
var clientProxy = new ClientProxy(runtimeInfo.ClientAddress, new ModuleLogger(logger, typeof(ClientProxy)));
|
||||||
var runtimeHost = new RuntimeHost(runtimeInfo.RuntimeAddress, configuration, new ModuleLogger(logger, typeof(RuntimeHost)));
|
var runtimeHost = new RuntimeHost(runtimeInfo.RuntimeAddress, configuration, new ModuleLogger(logger, typeof(RuntimeHost)));
|
||||||
var serviceProxy = new ServiceProxy(runtimeInfo.ServiceAddress, new ModuleLogger(logger, typeof(ServiceProxy)));
|
var serviceProxy = new ServiceProxy(runtimeInfo.ServiceAddress, new ModuleLogger(logger, typeof(ServiceProxy)));
|
||||||
|
var sessionController = new SessionController(clientProxy, configuration, logger, processFactory, runtimeHost, serviceProxy);
|
||||||
|
|
||||||
var bootstrapOperations = new Queue<IOperation>();
|
var bootstrapOperations = new Queue<IOperation>();
|
||||||
var sessionOperations = new Queue<IOperation>();
|
var sessionOperations = new Queue<IOperation>();
|
||||||
|
@ -59,11 +60,11 @@ namespace SafeExamBrowser.Runtime
|
||||||
bootstrapOperations.Enqueue(new I18nOperation(logger, text));
|
bootstrapOperations.Enqueue(new I18nOperation(logger, text));
|
||||||
bootstrapOperations.Enqueue(new CommunicationOperation(runtimeHost, logger));
|
bootstrapOperations.Enqueue(new CommunicationOperation(runtimeHost, logger));
|
||||||
|
|
||||||
sessionOperations.Enqueue(new SessionSequenceStartOperation(clientProxy, configuration, logger, processFactory, runtimeHost, serviceProxy));
|
sessionOperations.Enqueue(new SessionSequenceStartOperation(sessionController));
|
||||||
sessionOperations.Enqueue(new ConfigurationOperation(configuration, logger, runtimeInfo, text, uiFactory, args));
|
sessionOperations.Enqueue(new ConfigurationOperation(configuration, logger, runtimeInfo, text, uiFactory, args));
|
||||||
sessionOperations.Enqueue(new ServiceConnectionOperation(configuration, logger, serviceProxy, text));
|
sessionOperations.Enqueue(new ServiceConnectionOperation(configuration, logger, serviceProxy, text));
|
||||||
sessionOperations.Enqueue(new KioskModeOperation(logger, configuration));
|
sessionOperations.Enqueue(new KioskModeOperation(logger, configuration));
|
||||||
sessionOperations.Enqueue(new SessionSequenceEndOperation(clientProxy, configuration, logger, processFactory, runtimeHost, serviceProxy));
|
sessionOperations.Enqueue(new SessionSequenceEndOperation(sessionController));
|
||||||
|
|
||||||
var boostrapSequence = new OperationSequence(logger, bootstrapOperations);
|
var boostrapSequence = new OperationSequence(logger, bootstrapOperations);
|
||||||
var sessionSequence = new OperationSequence(logger, sessionOperations);
|
var sessionSequence = new OperationSequence(logger, sessionOperations);
|
||||||
|
|
|
@ -91,7 +91,7 @@
|
||||||
<Compile Include="Behaviour\Operations\KioskModeOperation.cs" />
|
<Compile Include="Behaviour\Operations\KioskModeOperation.cs" />
|
||||||
<Compile Include="Behaviour\Operations\ServiceConnectionOperation.cs" />
|
<Compile Include="Behaviour\Operations\ServiceConnectionOperation.cs" />
|
||||||
<Compile Include="Behaviour\Operations\SessionSequenceEndOperation.cs" />
|
<Compile Include="Behaviour\Operations\SessionSequenceEndOperation.cs" />
|
||||||
<Compile Include="Behaviour\Operations\SessionSequenceOperation.cs" />
|
<Compile Include="Behaviour\SessionController.cs" />
|
||||||
<Compile Include="Behaviour\Operations\SessionSequenceStartOperation.cs" />
|
<Compile Include="Behaviour\Operations\SessionSequenceStartOperation.cs" />
|
||||||
<Compile Include="Communication\RuntimeHost.cs" />
|
<Compile Include="Communication\RuntimeHost.cs" />
|
||||||
<Compile Include="CompositionRoot.cs" />
|
<Compile Include="CompositionRoot.cs" />
|
||||||
|
|
Loading…
Reference in a new issue