193 lines
6.9 KiB
C#
193 lines
6.9 KiB
C#
/*
|
|
* Copyright (c) 2025 ETH Zürich, IT Services
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
using System;
|
|
using System.Linq;
|
|
using SafeExamBrowser.Client.Contracts;
|
|
using SafeExamBrowser.Communication.Contracts.Data;
|
|
using SafeExamBrowser.Communication.Contracts.Events;
|
|
using SafeExamBrowser.Communication.Contracts.Hosts;
|
|
using SafeExamBrowser.Communication.Contracts.Proxies;
|
|
using SafeExamBrowser.I18n.Contracts;
|
|
using SafeExamBrowser.Logging.Contracts;
|
|
using SafeExamBrowser.Server.Contracts.Data;
|
|
using SafeExamBrowser.UserInterface.Contracts;
|
|
using SafeExamBrowser.UserInterface.Contracts.MessageBox;
|
|
using SafeExamBrowser.UserInterface.Contracts.Windows;
|
|
|
|
namespace SafeExamBrowser.Client.Responsibilities
|
|
{
|
|
internal class CommunicationResponsibility : ClientResponsibility
|
|
{
|
|
private readonly ICoordinator coordinator;
|
|
private readonly IMessageBox messageBox;
|
|
private readonly IRuntimeProxy runtime;
|
|
private readonly Action shutdown;
|
|
private readonly ISplashScreen splashScreen;
|
|
private readonly IText text;
|
|
private readonly IUserInterfaceFactory uiFactory;
|
|
|
|
private IClientHost ClientHost => Context.ClientHost;
|
|
|
|
public CommunicationResponsibility(
|
|
ClientContext context,
|
|
ICoordinator coordinator,
|
|
ILogger logger,
|
|
IMessageBox messageBox,
|
|
IRuntimeProxy runtime,
|
|
Action shutdown,
|
|
ISplashScreen splashScreen,
|
|
IText text,
|
|
IUserInterfaceFactory uiFactory) : base(context, logger)
|
|
{
|
|
this.coordinator = coordinator;
|
|
this.messageBox = messageBox;
|
|
this.runtime = runtime;
|
|
this.shutdown = shutdown;
|
|
this.splashScreen = splashScreen;
|
|
this.text = text;
|
|
this.uiFactory = uiFactory;
|
|
}
|
|
|
|
public override void Assume(ClientTask task)
|
|
{
|
|
switch (task)
|
|
{
|
|
case ClientTask.DeregisterEvents:
|
|
DeregisterEvents();
|
|
break;
|
|
case ClientTask.RegisterEvents:
|
|
RegisterEvents();
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void DeregisterEvents()
|
|
{
|
|
if (ClientHost != default)
|
|
{
|
|
ClientHost.ExamSelectionRequested -= ClientHost_ExamSelectionRequested;
|
|
ClientHost.MessageBoxRequested -= ClientHost_MessageBoxRequested;
|
|
ClientHost.PasswordRequested -= ClientHost_PasswordRequested;
|
|
ClientHost.ReconfigurationAborted -= ClientHost_ReconfigurationAborted;
|
|
ClientHost.ReconfigurationDenied -= ClientHost_ReconfigurationDenied;
|
|
ClientHost.ServerFailureActionRequested -= ClientHost_ServerFailureActionRequested;
|
|
ClientHost.Shutdown -= ClientHost_Shutdown;
|
|
}
|
|
|
|
runtime.ConnectionLost -= Runtime_ConnectionLost;
|
|
}
|
|
|
|
private void RegisterEvents()
|
|
{
|
|
ClientHost.ExamSelectionRequested += ClientHost_ExamSelectionRequested;
|
|
ClientHost.MessageBoxRequested += ClientHost_MessageBoxRequested;
|
|
ClientHost.PasswordRequested += ClientHost_PasswordRequested;
|
|
ClientHost.ReconfigurationAborted += ClientHost_ReconfigurationAborted;
|
|
ClientHost.ReconfigurationDenied += ClientHost_ReconfigurationDenied;
|
|
ClientHost.ServerFailureActionRequested += ClientHost_ServerFailureActionRequested;
|
|
ClientHost.Shutdown += ClientHost_Shutdown;
|
|
|
|
runtime.ConnectionLost += Runtime_ConnectionLost;
|
|
}
|
|
|
|
private void ClientHost_ExamSelectionRequested(ExamSelectionRequestEventArgs args)
|
|
{
|
|
Logger.Info($"Received exam selection request with id '{args.RequestId}'.");
|
|
|
|
var exams = args.Exams.Select(e => new Exam { Id = e.id, LmsName = e.lms, Name = e.name, Url = e.url });
|
|
var dialog = uiFactory.CreateExamSelectionDialog(exams);
|
|
var result = dialog.Show();
|
|
|
|
runtime.SubmitExamSelectionResult(args.RequestId, result.Success, result.SelectedExam?.Id);
|
|
Logger.Info($"Exam selection request with id '{args.RequestId}' is complete.");
|
|
}
|
|
|
|
private void ClientHost_MessageBoxRequested(MessageBoxRequestEventArgs args)
|
|
{
|
|
Logger.Info($"Received message box request with id '{args.RequestId}'.");
|
|
|
|
var action = (MessageBoxAction) args.Action;
|
|
var icon = (MessageBoxIcon) args.Icon;
|
|
var result = messageBox.Show(args.Message, args.Title, action, icon, parent: splashScreen);
|
|
|
|
runtime.SubmitMessageBoxResult(args.RequestId, (int) result);
|
|
Logger.Info($"Message box request with id '{args.RequestId}' yielded result '{result}'.");
|
|
}
|
|
|
|
private void ClientHost_PasswordRequested(PasswordRequestEventArgs args)
|
|
{
|
|
var message = default(TextKey);
|
|
var title = default(TextKey);
|
|
|
|
Logger.Info($"Received input request with id '{args.RequestId}' for the {args.Purpose.ToString().ToLower()} password.");
|
|
|
|
switch (args.Purpose)
|
|
{
|
|
case PasswordRequestPurpose.LocalAdministrator:
|
|
message = TextKey.PasswordDialog_LocalAdminPasswordRequired;
|
|
title = TextKey.PasswordDialog_LocalAdminPasswordRequiredTitle;
|
|
break;
|
|
case PasswordRequestPurpose.LocalSettings:
|
|
message = TextKey.PasswordDialog_LocalSettingsPasswordRequired;
|
|
title = TextKey.PasswordDialog_LocalSettingsPasswordRequiredTitle;
|
|
break;
|
|
case PasswordRequestPurpose.Settings:
|
|
message = TextKey.PasswordDialog_SettingsPasswordRequired;
|
|
title = TextKey.PasswordDialog_SettingsPasswordRequiredTitle;
|
|
break;
|
|
}
|
|
|
|
var dialog = uiFactory.CreatePasswordDialog(text.Get(message), text.Get(title));
|
|
var result = dialog.Show();
|
|
|
|
runtime.SubmitPassword(args.RequestId, result.Success, result.Password);
|
|
Logger.Info($"Password request with id '{args.RequestId}' was {(result.Success ? "successful" : "aborted by the user")}.");
|
|
}
|
|
|
|
private void ClientHost_ReconfigurationAborted()
|
|
{
|
|
Logger.Info("The reconfiguration was aborted by the runtime.");
|
|
splashScreen.Hide();
|
|
coordinator.ReleaseReconfigurationLock();
|
|
}
|
|
|
|
private void ClientHost_ReconfigurationDenied(ReconfigurationEventArgs args)
|
|
{
|
|
Logger.Info($"The reconfiguration request for '{args.ConfigurationPath}' was denied by the runtime!");
|
|
messageBox.Show(TextKey.MessageBox_ReconfigurationDenied, TextKey.MessageBox_ReconfigurationDeniedTitle, parent: splashScreen);
|
|
splashScreen.Hide();
|
|
coordinator.ReleaseReconfigurationLock();
|
|
}
|
|
|
|
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();
|
|
|
|
runtime.SubmitServerFailureActionResult(args.RequestId, result.Abort, result.Fallback, result.Retry);
|
|
Logger.Info($"Server failure action request with id '{args.RequestId}' is complete, the user chose to {(result.Abort ? "abort" : (result.Fallback ? "fallback" : "retry"))}.");
|
|
}
|
|
|
|
private void ClientHost_Shutdown()
|
|
{
|
|
shutdown.Invoke();
|
|
}
|
|
|
|
private void Runtime_ConnectionLost()
|
|
{
|
|
Logger.Error("Lost connection to the runtime!");
|
|
|
|
messageBox.Show(TextKey.MessageBox_ApplicationError, TextKey.MessageBox_ApplicationErrorTitle, icon: MessageBoxIcon.Error);
|
|
shutdown.Invoke();
|
|
}
|
|
}
|
|
}
|