diff --git a/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs b/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs index b19de5f2..bd48f557 100644 --- a/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs +++ b/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs @@ -214,6 +214,21 @@ namespace SafeExamBrowser.Configuration.ConfigurationData } } + internal static class RemoteProctoring + { + internal const string Enabled = "jitsiMeetEnable"; + + internal static class JitsiMeet + { + + } + + internal static class Zoom + { + + } + } + internal static class Security { internal const string AdminPasswordHash = "hashedAdminPassword"; diff --git a/SafeExamBrowser.I18n.Contracts/TextKey.cs b/SafeExamBrowser.I18n.Contracts/TextKey.cs index c397c098..505822cc 100644 --- a/SafeExamBrowser.I18n.Contracts/TextKey.cs +++ b/SafeExamBrowser.I18n.Contracts/TextKey.cs @@ -98,6 +98,8 @@ namespace SafeExamBrowser.I18n.Contracts MessageBox_NotSupportedConfigurationResource, MessageBox_NotSupportedConfigurationResourceTitle, MessageBox_OkButton, + MessageBox_ProctoringDisclaimer, + MessageBox_ProctoringDisclaimerTitle, MessageBox_Quit, MessageBox_QuitTitle, MessageBox_QuitError, diff --git a/SafeExamBrowser.I18n/Data/en.xml b/SafeExamBrowser.I18n/Data/en.xml index b453e229..b6f7ab89 100644 --- a/SafeExamBrowser.I18n/Data/en.xml +++ b/SafeExamBrowser.I18n/Data/en.xml @@ -252,6 +252,12 @@ OK + + The current session will be remote proctored using a live video and audio stream, which is sent to an individually configured server. Ask your examinator about their privacy policy. SEB itself doesn't connect to any centralized SEB proctoring server, your exam provider decides which proctoring service/server to use. + + + Starting Remote Proctoring + Do you want to quit SEB? diff --git a/SafeExamBrowser.Runtime/CompositionRoot.cs b/SafeExamBrowser.Runtime/CompositionRoot.cs index 6380e1f8..f6b9a410 100644 --- a/SafeExamBrowser.Runtime/CompositionRoot.cs +++ b/SafeExamBrowser.Runtime/CompositionRoot.cs @@ -84,6 +84,7 @@ namespace SafeExamBrowser.Runtime sessionOperations.Enqueue(new SessionInitializationOperation(configuration, fileSystem, logger, runtimeHost, sessionContext)); sessionOperations.Enqueue(new ConfigurationOperation(args, configuration, new FileSystem(), new HashAlgorithm(), logger, sessionContext)); + sessionOperations.Enqueue(new DisclaimerOperation(logger, sessionContext)); sessionOperations.Enqueue(new ServerOperation(args, configuration, fileSystem, logger, sessionContext, server)); sessionOperations.Enqueue(new RemoteSessionOperation(remoteSessionDetector, logger, sessionContext)); sessionOperations.Enqueue(new VirtualMachineOperation(vmDetector, logger, sessionContext)); diff --git a/SafeExamBrowser.Runtime/Operations/DisclaimerOperation.cs b/SafeExamBrowser.Runtime/Operations/DisclaimerOperation.cs new file mode 100644 index 00000000..91c6ee6a --- /dev/null +++ b/SafeExamBrowser.Runtime/Operations/DisclaimerOperation.cs @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2021 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.Core.Contracts.OperationModel; +using SafeExamBrowser.Core.Contracts.OperationModel.Events; +using SafeExamBrowser.I18n.Contracts; +using SafeExamBrowser.Logging.Contracts; +using SafeExamBrowser.Runtime.Operations.Events; +using SafeExamBrowser.UserInterface.Contracts.MessageBox; + +namespace SafeExamBrowser.Runtime.Operations +{ + internal class DisclaimerOperation : SessionOperation + { + private readonly ILogger logger; + + public override event ActionRequiredEventHandler ActionRequired; + public override event StatusChangedEventHandler StatusChanged; + + public DisclaimerOperation(ILogger logger, SessionContext context) : base(context) + { + this.logger = logger; + } + + public override OperationResult Perform() + { + return ShowDisclaimer(); + } + + public override OperationResult Repeat() + { + return ShowDisclaimer(); + } + + public override OperationResult Revert() + { + return OperationResult.Success; + } + + private OperationResult ShowDisclaimer() + { + var args = new MessageEventArgs + { + Icon = MessageBoxIcon.Question, + Message = TextKey.MessageBox_ProctoringDisclaimer, + Title = TextKey.MessageBox_ProctoringDisclaimerTitle + }; + + ActionRequired?.Invoke(args); + + if (args.Result == MessageBoxResult.Ok) + { + logger.Info("The user confirmed the remote proctoring disclaimer."); + + return OperationResult.Success; + } + else + { + logger.Warn("The user did not confirm the remote proctoring disclaimer! Aborting session initialization..."); + + return OperationResult.Aborted; + } + } + } +} diff --git a/SafeExamBrowser.Runtime/Operations/Events/MessageEventArgs.cs b/SafeExamBrowser.Runtime/Operations/Events/MessageEventArgs.cs index 32f9db0f..b80ac8e3 100644 --- a/SafeExamBrowser.Runtime/Operations/Events/MessageEventArgs.cs +++ b/SafeExamBrowser.Runtime/Operations/Events/MessageEventArgs.cs @@ -15,14 +15,17 @@ namespace SafeExamBrowser.Runtime.Operations.Events { internal class MessageEventArgs : ActionRequiredEventArgs { + internal MessageBoxAction Action { get; set; } internal MessageBoxIcon Icon { get; set; } internal TextKey Message { get; set; } + internal MessageBoxResult Result { get; set; } internal TextKey Title { get; set; } internal Dictionary MessagePlaceholders { get; private set; } internal Dictionary TitlePlaceholders { get; private set; } public MessageEventArgs() { + Action = MessageBoxAction.Confirm; MessagePlaceholders = new Dictionary(); TitlePlaceholders = new Dictionary(); } diff --git a/SafeExamBrowser.Runtime/RuntimeController.cs b/SafeExamBrowser.Runtime/RuntimeController.cs index 48ba63a6..3c4ee1bc 100644 --- a/SafeExamBrowser.Runtime/RuntimeController.cs +++ b/SafeExamBrowser.Runtime/RuntimeController.cs @@ -468,11 +468,11 @@ namespace SafeExamBrowser.Runtime if (isStartup || isRunningOnDefaultDesktop) { - messageBox.Show(message, title, MessageBoxAction.Confirm, args.Icon, runtimeWindow); + args.Result = messageBox.Show(message, title, MessageBoxAction.Confirm, args.Icon, runtimeWindow); } else { - ShowMessageBoxViaClient(message, title, MessageBoxAction.Confirm, args.Icon); + args.Result = ShowMessageBoxViaClient(message, title, MessageBoxAction.Confirm, args.Icon); } } diff --git a/SafeExamBrowser.Runtime/SafeExamBrowser.Runtime.csproj b/SafeExamBrowser.Runtime/SafeExamBrowser.Runtime.csproj index ce42538d..76c8f478 100644 --- a/SafeExamBrowser.Runtime/SafeExamBrowser.Runtime.csproj +++ b/SafeExamBrowser.Runtime/SafeExamBrowser.Runtime.csproj @@ -92,6 +92,7 @@ + diff --git a/SafeExamBrowser.UserInterface.Contracts/MessageBox/MessageBoxAction.cs b/SafeExamBrowser.UserInterface.Contracts/MessageBox/MessageBoxAction.cs index 312969f7..49cd3f05 100644 --- a/SafeExamBrowser.UserInterface.Contracts/MessageBox/MessageBoxAction.cs +++ b/SafeExamBrowser.UserInterface.Contracts/MessageBox/MessageBoxAction.cs @@ -14,6 +14,7 @@ namespace SafeExamBrowser.UserInterface.Contracts.MessageBox public enum MessageBoxAction { Confirm, + ConfirmAbort, YesNo } } diff --git a/SafeExamBrowser.UserInterface.Desktop/MessageBoxFactory.cs b/SafeExamBrowser.UserInterface.Desktop/MessageBoxFactory.cs index 7e81bb28..cc2b20a0 100644 --- a/SafeExamBrowser.UserInterface.Desktop/MessageBoxFactory.cs +++ b/SafeExamBrowser.UserInterface.Desktop/MessageBoxFactory.cs @@ -25,15 +25,15 @@ namespace SafeExamBrowser.UserInterface.Desktop public MessageBoxResult Show(string message, string title, MessageBoxAction action = MessageBoxAction.Confirm, MessageBoxIcon icon = MessageBoxIcon.Information, IWindow parent = null) { - var result = default(System.Windows.MessageBoxResult); + var result = System.Windows.MessageBoxResult.None; if (parent is Window window) { - result = window.Dispatcher.Invoke(() => System.Windows.MessageBox.Show(window, message, title, ToButton(action), ToImage(icon))); + result = window.Dispatcher.Invoke(() => MessageBox.Show(window, message, title, ToButton(action), ToImage(icon))); } else { - result = System.Windows.MessageBox.Show(message, title, ToButton(action), ToImage(icon)); + result = MessageBox.Show(message, title, ToButton(action), ToImage(icon)); } return ToResult(result); diff --git a/SafeExamBrowser.UserInterface.Mobile/MessageBoxFactory.cs b/SafeExamBrowser.UserInterface.Mobile/MessageBoxFactory.cs index d43db2c5..8f83d187 100644 --- a/SafeExamBrowser.UserInterface.Mobile/MessageBoxFactory.cs +++ b/SafeExamBrowser.UserInterface.Mobile/MessageBoxFactory.cs @@ -26,7 +26,7 @@ namespace SafeExamBrowser.UserInterface.Mobile public MessageBoxResult Show(string message, string title, MessageBoxAction action = MessageBoxAction.Confirm, MessageBoxIcon icon = MessageBoxIcon.Information, IWindow parent = null) { - var result = default(MessageBoxResult); + var result = MessageBoxResult.None; if (parent is Window window) {