SEBWIN-405: Implemented mechanism to retrieve server failure action via client.
This commit is contained in:
parent
4d59ee399d
commit
4af0cc0d48
16 changed files with 289 additions and 1 deletions
|
@ -192,6 +192,7 @@ namespace SafeExamBrowser.Client
|
|||
ClientHost.PasswordRequested += ClientHost_PasswordRequested;
|
||||
ClientHost.ReconfigurationAborted += ClientHost_ReconfigurationAborted;
|
||||
ClientHost.ReconfigurationDenied += ClientHost_ReconfigurationDenied;
|
||||
ClientHost.ServerFailureActionRequested += ClientHost_ServerFailureActionRequested;
|
||||
ClientHost.Shutdown += ClientHost_Shutdown;
|
||||
displayMonitor.DisplayChanged += DisplayMonitor_DisplaySettingsChanged;
|
||||
runtime.ConnectionLost += Runtime_ConnectionLost;
|
||||
|
@ -233,6 +234,7 @@ namespace SafeExamBrowser.Client
|
|||
ClientHost.PasswordRequested -= ClientHost_PasswordRequested;
|
||||
ClientHost.ReconfigurationAborted -= ClientHost_ReconfigurationAborted;
|
||||
ClientHost.ReconfigurationDenied -= ClientHost_ReconfigurationDenied;
|
||||
ClientHost.ServerFailureActionRequested -= ClientHost_ServerFailureActionRequested;
|
||||
ClientHost.Shutdown -= ClientHost_Shutdown;
|
||||
}
|
||||
|
||||
|
@ -463,6 +465,17 @@ namespace SafeExamBrowser.Client
|
|||
splashScreen.Hide();
|
||||
}
|
||||
|
||||
private void ClientHost_ServerFailureActionRequested(ServerFailureActionRequestEventArgs args)
|
||||
{
|
||||
logger.Info($"Received server failure action request with id '{args.RequestId}'.");
|
||||
|
||||
var dialog = uiFactory.CreateServerFailureDialog(args.Message, args.ShowFallback);
|
||||
var result = dialog.Show(splashScreen);
|
||||
|
||||
runtime.SubmitServerFailureActionResult(args.RequestId, result.Abort, result.Fallback, result.Retry);
|
||||
logger.Info($"Server failure action request with id '{args.RequestId}' is complete.");
|
||||
}
|
||||
|
||||
private void ClientHost_Shutdown()
|
||||
{
|
||||
shutdown.Invoke();
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace SafeExamBrowser.Client.Communication
|
|||
public event CommunicationEventHandler ReconfigurationAborted;
|
||||
public event CommunicationEventHandler<ReconfigurationEventArgs> ReconfigurationDenied;
|
||||
public event CommunicationEventHandler RuntimeDisconnected;
|
||||
public event CommunicationEventHandler<ServerFailureActionRequestEventArgs> ServerFailureActionRequested;
|
||||
public event CommunicationEventHandler Shutdown;
|
||||
|
||||
public ClientHost(
|
||||
|
@ -82,6 +83,9 @@ namespace SafeExamBrowser.Client.Communication
|
|||
case ReconfigurationDeniedMessage m:
|
||||
ReconfigurationDenied?.InvokeAsync(new ReconfigurationEventArgs { ConfigurationPath = m.FilePath });
|
||||
return new SimpleResponse(SimpleResponsePurport.Acknowledged);
|
||||
case ServerFailureActionRequestMessage m:
|
||||
ServerFailureActionRequested?.InvokeAsync(new ServerFailureActionRequestEventArgs { Message = m.Message, RequestId = m.RequestId, ShowFallback = m.ShowFallback });
|
||||
return new SimpleResponse(SimpleResponsePurport.Acknowledged);
|
||||
}
|
||||
|
||||
return new SimpleResponse(SimpleResponsePurport.UnknownMessage);
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2020 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.Communication.Contracts.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// The reply to a <see cref="ServerFailureActionRequestMessage"/>.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class ServerFailureActionReplyMessage : Message
|
||||
{
|
||||
/// <summary>
|
||||
/// The user chose to abort the operation.
|
||||
/// </summary>
|
||||
public bool Abort { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The user chose to perform a fallback.
|
||||
/// </summary>
|
||||
public bool Fallback { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The user chose to retry the operation.
|
||||
/// </summary>
|
||||
public bool Retry { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the server failure action request.
|
||||
/// </summary>
|
||||
public Guid RequestId { get; set; }
|
||||
|
||||
public ServerFailureActionReplyMessage(bool abort, bool fallback, bool retry, Guid requestId)
|
||||
{
|
||||
Abort = abort;
|
||||
Fallback = fallback;
|
||||
Retry = retry;
|
||||
RequestId = requestId;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2020 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.Communication.Contracts.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// This message is transmitted to the client to request a server failure action selection by the user.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class ServerFailureActionRequestMessage : Message
|
||||
{
|
||||
/// <summary>
|
||||
/// The server failure message, if available.
|
||||
/// </summary>
|
||||
public string Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the fallback option should be shown to the user.
|
||||
/// </summary>
|
||||
public bool ShowFallback { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The unique identifier for the server failure action selection request.
|
||||
/// </summary>
|
||||
public Guid RequestId { get; }
|
||||
|
||||
public ServerFailureActionRequestMessage(string message, bool showFallback, Guid requestId)
|
||||
{
|
||||
Message = message;
|
||||
ShowFallback = showFallback;
|
||||
RequestId = requestId;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2020 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.Communication.Contracts.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// The event arguments used for the server failure action event fired by the <see cref="Hosts.IRuntimeHost"/>.
|
||||
/// </summary>
|
||||
public class ServerFailureActionReplyEventArgs : CommunicationEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// The user chose to abort the operation.
|
||||
/// </summary>
|
||||
public bool Abort { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The user chose to perform a fallback.
|
||||
/// </summary>
|
||||
public bool Fallback { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The user chose to retry the operation.
|
||||
/// </summary>
|
||||
public bool Retry { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the server failure action request.
|
||||
/// </summary>
|
||||
public Guid RequestId { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2020 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.Communication.Contracts.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// The event arguments used for the server failure action request event fired by the <see cref="Hosts.IClientHost"/>.
|
||||
/// </summary>
|
||||
public class ServerFailureActionRequestEventArgs : CommunicationEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// The server failure message, if available.
|
||||
/// </summary>
|
||||
public string Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the fallback option should be shown to the user.
|
||||
/// </summary>
|
||||
public bool ShowFallback { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the server failure action selection request.
|
||||
/// </summary>
|
||||
public Guid RequestId { get; set; }
|
||||
}
|
||||
}
|
|
@ -56,6 +56,11 @@ namespace SafeExamBrowser.Communication.Contracts.Hosts
|
|||
/// </summary>
|
||||
event CommunicationEventHandler RuntimeDisconnected;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the runtime requests a server failure action selection from the user.
|
||||
/// </summary>
|
||||
event CommunicationEventHandler<ServerFailureActionRequestEventArgs> ServerFailureActionRequested;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the runtime commands the client to shutdown.
|
||||
/// </summary>
|
||||
|
|
|
@ -61,6 +61,11 @@ namespace SafeExamBrowser.Communication.Contracts.Hosts
|
|||
/// </summary>
|
||||
event CommunicationEventHandler<ReconfigurationEventArgs> ReconfigurationRequested;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the client submitted a server failure action chosen by the user.
|
||||
/// </summary>
|
||||
event CommunicationEventHandler<ServerFailureActionReplyEventArgs> ServerFailureActionReceived;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the client requests to shut down the application.
|
||||
/// </summary>
|
||||
|
|
|
@ -29,6 +29,8 @@ namespace SafeExamBrowser.Communication.Contracts
|
|||
[ServiceKnownType(typeof(PasswordRequestMessage))]
|
||||
[ServiceKnownType(typeof(ReconfigurationMessage))]
|
||||
[ServiceKnownType(typeof(ReconfigurationDeniedMessage))]
|
||||
[ServiceKnownType(typeof(ServerFailureActionReplyMessage))]
|
||||
[ServiceKnownType(typeof(ServerFailureActionRequestMessage))]
|
||||
[ServiceKnownType(typeof(ServiceConfiguration))]
|
||||
[ServiceKnownType(typeof(SessionStartMessage))]
|
||||
[ServiceKnownType(typeof(SessionStopMessage))]
|
||||
|
|
|
@ -47,6 +47,11 @@ namespace SafeExamBrowser.Communication.Contracts.Proxies
|
|||
/// </summary>
|
||||
CommunicationResult RequestPassword(PasswordRequestPurpose purpose, Guid requestId);
|
||||
|
||||
/// <summary>
|
||||
/// Requests the client to render a server failure action dialog and subsequently return the interaction result as separate message.
|
||||
/// </summary>
|
||||
CommunicationResult RequestServerFailureAction(string message, bool showFallback, Guid requestId);
|
||||
|
||||
/// <summary>
|
||||
/// Requests the client to render a message box and subsequently return the interaction result as separate message.
|
||||
/// </summary>
|
||||
|
|
|
@ -52,5 +52,10 @@ namespace SafeExamBrowser.Communication.Contracts.Proxies
|
|||
/// the password parameter will be <see cref="default(string)"/>!
|
||||
/// </summary>
|
||||
CommunicationResult SubmitPassword(Guid requestId, bool success, string password = default(string));
|
||||
|
||||
/// <summary>
|
||||
/// Submits the result of a server failure action selection previously requested by the runtime.
|
||||
/// </summary>
|
||||
CommunicationResult SubmitServerFailureActionResult(Guid requestId, bool abort, bool fallback, bool retry);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,6 +71,8 @@
|
|||
<Compile Include="Data\ReconfigurationDeniedMessage.cs" />
|
||||
<Compile Include="Data\ReconfigurationMessage.cs" />
|
||||
<Compile Include="Data\Response.cs" />
|
||||
<Compile Include="Data\ServerFailureActionReplyMessage.cs" />
|
||||
<Compile Include="Data\ServerFailureActionRequestMessage.cs" />
|
||||
<Compile Include="Data\SessionStartMessage.cs" />
|
||||
<Compile Include="Data\SessionStopMessage.cs" />
|
||||
<Compile Include="Data\SimpleMessage.cs" />
|
||||
|
@ -87,6 +89,8 @@
|
|||
<Compile Include="Events\PasswordReplyEventArgs.cs" />
|
||||
<Compile Include="Events\PasswordRequestEventArgs.cs" />
|
||||
<Compile Include="Events\ReconfigurationEventArgs.cs" />
|
||||
<Compile Include="Events\ServerFailureActionReplyEventArgs.cs" />
|
||||
<Compile Include="Events\ServerFailureActionRequestEventArgs.cs" />
|
||||
<Compile Include="Events\SessionStartEventArgs.cs" />
|
||||
<Compile Include="Events\SessionStopEventArgs.cs" />
|
||||
<Compile Include="Hosts\IClientHost.cs" />
|
||||
|
|
|
@ -180,6 +180,32 @@ namespace SafeExamBrowser.Communication.Proxies
|
|||
}
|
||||
}
|
||||
|
||||
public CommunicationResult RequestServerFailureAction(string message, bool showFallback, Guid requestId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = Send(new ServerFailureActionRequestMessage(message, showFallback, requestId));
|
||||
var success = IsAcknowledged(response);
|
||||
|
||||
if (success)
|
||||
{
|
||||
Logger.Debug("Client acknowledged server failure action request.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Error($"Client did not acknowledge server failure action request! Received: {ToString(response)}.");
|
||||
}
|
||||
|
||||
return new CommunicationResult(success);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error($"Failed to perform '{nameof(RequestServerFailureAction)}'", e);
|
||||
|
||||
return new CommunicationResult(false);
|
||||
}
|
||||
}
|
||||
|
||||
public CommunicationResult ShowMessage(string message, string title, int action, int icon, Guid requestId)
|
||||
{
|
||||
try
|
||||
|
|
|
@ -204,5 +204,31 @@ namespace SafeExamBrowser.Communication.Proxies
|
|||
return new CommunicationResult(false);
|
||||
}
|
||||
}
|
||||
|
||||
public CommunicationResult SubmitServerFailureActionResult(Guid requestId, bool abort, bool fallback, bool retry)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = Send(new ServerFailureActionReplyMessage(abort, fallback, retry, requestId));
|
||||
var acknowledged = IsAcknowledged(response);
|
||||
|
||||
if (acknowledged)
|
||||
{
|
||||
Logger.Debug("Runtime acknowledged server failure action transmission.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Error($"Runtime did not acknowledge server failure action transmission! Response: {ToString(response)}.");
|
||||
}
|
||||
|
||||
return new CommunicationResult(acknowledged);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error($"Failed to perform '{nameof(SubmitServerFailureActionResult)}'", e);
|
||||
|
||||
return new CommunicationResult(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ namespace SafeExamBrowser.Runtime.Communication
|
|||
public event CommunicationEventHandler<MessageBoxReplyEventArgs> MessageBoxReplyReceived;
|
||||
public event CommunicationEventHandler<PasswordReplyEventArgs> PasswordReceived;
|
||||
public event CommunicationEventHandler<ReconfigurationEventArgs> ReconfigurationRequested;
|
||||
public event CommunicationEventHandler<ServerFailureActionReplyEventArgs> ServerFailureActionReceived;
|
||||
public event CommunicationEventHandler ShutdownRequested;
|
||||
|
||||
public RuntimeHost(string address, IHostObjectFactory factory, ILogger logger, int timeout_ms) : base(address, factory, logger, timeout_ms)
|
||||
|
@ -71,6 +72,9 @@ namespace SafeExamBrowser.Runtime.Communication
|
|||
case ReconfigurationMessage m:
|
||||
ReconfigurationRequested?.InvokeAsync(new ReconfigurationEventArgs { ConfigurationPath = m.ConfigurationPath });
|
||||
return new SimpleResponse(SimpleResponsePurport.Acknowledged);
|
||||
case ServerFailureActionReplyMessage m:
|
||||
ServerFailureActionReceived?.InvokeAsync(new ServerFailureActionReplyEventArgs { Abort = m.Abort, Fallback = m.Fallback, RequestId = m.RequestId, Retry = m.Retry });
|
||||
return new SimpleResponse(SimpleResponsePurport.Acknowledged);
|
||||
}
|
||||
|
||||
return new SimpleResponse(SimpleResponsePurport.UnknownMessage);
|
||||
|
|
|
@ -567,7 +567,37 @@ namespace SafeExamBrowser.Runtime
|
|||
|
||||
private void TryAskForServerFailureActionViaClient(ServerFailureEventArgs args)
|
||||
{
|
||||
// TODO: Implement communication mechanism!
|
||||
var requestId = Guid.NewGuid();
|
||||
var response = default(ServerFailureActionReplyEventArgs);
|
||||
var responseEvent = new AutoResetEvent(false);
|
||||
var responseEventHandler = new CommunicationEventHandler<ServerFailureActionReplyEventArgs>((a) =>
|
||||
{
|
||||
if (a.RequestId == requestId)
|
||||
{
|
||||
response = a;
|
||||
responseEvent.Set();
|
||||
}
|
||||
});
|
||||
|
||||
runtimeHost.ServerFailureActionReceived += responseEventHandler;
|
||||
|
||||
var communication = sessionContext.ClientProxy.RequestServerFailureAction(args.Message, args.ShowFallback, requestId);
|
||||
|
||||
if (communication.Success)
|
||||
{
|
||||
responseEvent.WaitOne();
|
||||
args.Abort = response.Abort;
|
||||
args.Fallback = response.Fallback;
|
||||
args.Retry = response.Retry;
|
||||
}
|
||||
else
|
||||
{
|
||||
args.Abort = true;
|
||||
args.Fallback = false;
|
||||
args.Retry = false;
|
||||
}
|
||||
|
||||
runtimeHost.ServerFailureActionReceived -= responseEventHandler;
|
||||
}
|
||||
|
||||
private void TryGetPasswordViaDialog(PasswordRequiredEventArgs args)
|
||||
|
|
Loading…
Reference in a new issue