diff --git a/SafeExamBrowser.Client/ClientController.cs b/SafeExamBrowser.Client/ClientController.cs index 473f5e21..c60d182a 100644 --- a/SafeExamBrowser.Client/ClientController.cs +++ b/SafeExamBrowser.Client/ClientController.cs @@ -217,24 +217,11 @@ namespace SafeExamBrowser.Client if (Server != null) { Server.LockScreenConfirmed += Server_LockScreenConfirmed; - Server.TerminationRequested += Server_TerminationRequested; Server.LockScreenRequested += Server_LockScreenRequested; + Server.TerminationRequested += Server_TerminationRequested; } } - private void Server_LockScreenRequested(string message) - { - logger.Info("Received lock screen event from SEB Server."); - var title = text.Get(TextKey.LockScreen_Title); - ShowLockScreen(message, title, Enumerable.Empty()); - } - - private void Server_LockScreenConfirmed() - { - logger.Info("Closing lock screen as requested by the server..."); - lockScreen?.Cancel(); - } - private void Taskbar_LoseFocusRequested(bool forward) { Browser.Focus(forward); @@ -277,8 +264,8 @@ namespace SafeExamBrowser.Client if (Server != null) { Server.LockScreenConfirmed -= Server_LockScreenConfirmed; - Server.TerminationRequested -= Server_TerminationRequested; Server.LockScreenRequested -= Server_LockScreenRequested; + Server.TerminationRequested -= Server_TerminationRequested; } foreach (var activator in context.Activators.OfType()) @@ -659,6 +646,19 @@ namespace SafeExamBrowser.Client shutdown.Invoke(); } + private void Server_LockScreenConfirmed() + { + logger.Info("Closing lock screen as requested by the server..."); + lockScreen?.Cancel(); + } + + private void Server_LockScreenRequested(string message) + { + logger.Info("Received lock screen event from SEB Server."); + var title = text.Get(TextKey.LockScreen_Title); + ShowLockScreen(message, title, Enumerable.Empty()); + } + private void Server_TerminationRequested() { logger.Info("Attempting to shutdown as requested by the server..."); @@ -787,11 +787,11 @@ namespace SafeExamBrowser.Client private LockScreenResult ShowLockScreen(string message, string title, IEnumerable options) { var hasQuitPassword = !string.IsNullOrEmpty(Settings.Security.QuitPasswordHash); - lockScreen = uiFactory.CreateLockScreen(message, title, options); var result = default(LockScreenResult); logger.Info("Showing lock screen..."); PauseActivators(); + lockScreen = uiFactory.CreateLockScreen(message, title, options); lockScreen.Show(); if (Settings.SessionMode == SessionMode.Server) @@ -808,11 +808,11 @@ namespace SafeExamBrowser.Client { result = lockScreen.WaitForResult(); - if (result.Canceled) + if (result.Canceled) { logger.Info("The lock screen has been automaticaly canceled."); unlocked = true; - } + } else if (hasQuitPassword) { var passwordHash = hashAlgorithm.GenerateHashFor(result.Password); diff --git a/SafeExamBrowser.Server.Contracts/Events/LockScreenRequestedEventHandler.cs b/SafeExamBrowser.Server.Contracts/Events/LockScreenRequestedEventHandler.cs index f8c4f3fd..87855076 100644 --- a/SafeExamBrowser.Server.Contracts/Events/LockScreenRequestedEventHandler.cs +++ b/SafeExamBrowser.Server.Contracts/Events/LockScreenRequestedEventHandler.cs @@ -1,14 +1,16 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +/* + * Copyright (c) 2022 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/. + */ namespace SafeExamBrowser.Server.Contracts.Events { /// - /// Event handler used to handle a requested lock screen from SEB Server + /// Event handler used to indicate that a lock screen instruction has been received. /// - public delegate void LockScreenRequestedEventHandler(String message); - + public delegate void LockScreenRequestedEventHandler(string message); + } diff --git a/SafeExamBrowser.Server.Contracts/IServerProxy.cs b/SafeExamBrowser.Server.Contracts/IServerProxy.cs index a74807f7..4f320610 100644 --- a/SafeExamBrowser.Server.Contracts/IServerProxy.cs +++ b/SafeExamBrowser.Server.Contracts/IServerProxy.cs @@ -30,7 +30,7 @@ namespace SafeExamBrowser.Server.Contracts event ServerEventHandler LockScreenConfirmed; /// - /// Event fired when proxy receives a lock screen instruction. + /// Event fired when the proxy receives a lock screen instruction. /// event LockScreenRequestedEventHandler LockScreenRequested; @@ -47,13 +47,18 @@ namespace SafeExamBrowser.Server.Contracts /// /// Event fired when the proxy detects an instruction to terminate SEB. /// - event TerminationRequestedEventHandler TerminationRequested; + event TerminationRequestedEventHandler TerminationRequested; /// /// Attempts to initialize a connection with the server. /// ServerResponse Connect(); + /// + /// Sends a lock screen confirm notification to the server. + /// + ServerResponse ConfirmLockScreen(); + /// /// Terminates a connection with the server. /// @@ -62,7 +67,7 @@ namespace SafeExamBrowser.Server.Contracts /// /// Retrieves a list of all currently available exams, or a list containing the specified exam. /// - ServerResponse> GetAvailableExams(string examId = default(string)); + ServerResponse> GetAvailableExams(string examId = default); /// /// Retrieves the URI of the configuration file for the given exam. @@ -84,16 +89,16 @@ namespace SafeExamBrowser.Server.Contracts /// void Initialize(string api, string connectionToken, string examId, string oauth2Token, ServerSettings settings); + /// + /// Sends a lock screen notification to the server. + /// + ServerResponse LockScreen(string message = default); + /// /// Sends a lower hand notification to the server. /// ServerResponse LowerHand(); - /// - /// Sends a lock screen confirm notification to the server. - /// - ServerResponse ConfirmLockScreen(); - /// /// Sends the given user session identifier of a LMS and thus establishes a connection with the server. /// @@ -112,11 +117,6 @@ namespace SafeExamBrowser.Server.Contracts /// /// Sends a raise hand notification to the server. /// - ServerResponse RaiseHand(string message = default(string)); - - /// - /// Sends a lock screen notification to the server. - /// - ServerResponse LockScreen(string message = default(string)); + ServerResponse RaiseHand(string message = default); } } diff --git a/SafeExamBrowser.Server/Data/Attributes.cs b/SafeExamBrowser.Server/Data/Attributes.cs index 92f3d325..009a25f6 100644 --- a/SafeExamBrowser.Server/Data/Attributes.cs +++ b/SafeExamBrowser.Server/Data/Attributes.cs @@ -15,12 +15,11 @@ namespace SafeExamBrowser.Server.Data internal bool AllowChat { get; set; } internal int Id { get; set; } internal ProctoringInstructionEventArgs Instruction { get; set; } + internal string Message { get; set; } internal bool ReceiveAudio { get; set; } internal bool ReceiveVideo { get; set; } internal string Type { get; set; } - internal string Message { get; set; } - internal Attributes() { Instruction = new ProctoringInstructionEventArgs(); diff --git a/SafeExamBrowser.Server/Data/Instructions.cs b/SafeExamBrowser.Server/Data/Instructions.cs index 06d47804..3a8daffa 100644 --- a/SafeExamBrowser.Server/Data/Instructions.cs +++ b/SafeExamBrowser.Server/Data/Instructions.cs @@ -10,10 +10,10 @@ namespace SafeExamBrowser.Server.Data { internal sealed class Instructions { + internal const string LOCK_SCREEN = "SEB_FORCE_LOCK_SCREEN"; internal const string NOTIFICATION_CONFIRM = "NOTIFICATION_CONFIRM"; internal const string PROCTORING = "SEB_PROCTORING"; internal const string PROCTORING_RECONFIGURATION = "SEB_RECONFIGURE_SETTINGS"; internal const string QUIT = "SEB_QUIT"; - internal const string LOCK_SCREEN = "SEB_FORCE_LOCK_SCREEN"; } } diff --git a/SafeExamBrowser.Server/Parser.cs b/SafeExamBrowser.Server/Parser.cs index 0db21942..51b430fa 100644 --- a/SafeExamBrowser.Server/Parser.cs +++ b/SafeExamBrowser.Server/Parser.cs @@ -216,6 +216,9 @@ namespace SafeExamBrowser.Server switch (instruction) { + case Instructions.LOCK_SCREEN: + ParseLockScreenInstruction(attributes, attributesJson); + break; case Instructions.NOTIFICATION_CONFIRM: ParseNotificationConfirmation(attributes, attributesJson); break; @@ -225,9 +228,6 @@ namespace SafeExamBrowser.Server case Instructions.PROCTORING_RECONFIGURATION: ParseReconfigurationInstruction(attributes, attributesJson); break; - case Instructions.LOCK_SCREEN: - ParseLockScreenInstruction(attributes, attributesJson); - break; } return attributes; diff --git a/SafeExamBrowser.Server/ServerProxy.cs b/SafeExamBrowser.Server/ServerProxy.cs index b02116f5..f4f3ceb1 100644 --- a/SafeExamBrowser.Server/ServerProxy.cs +++ b/SafeExamBrowser.Server/ServerProxy.cs @@ -50,15 +50,14 @@ namespace SafeExamBrowser.Server private ApiVersion1 api; private string connectionToken; - private int currentPowerSupplyValue; private bool connectedToPowergrid; + private int currentLockScreenId; + private int currentPowerSupplyValue; + private int currentRaisHandId; private int currentWlanValue; private string examId; - private int notificationId; - private int currentRaisHandId; - private int currentLockScreenId; - private HttpClient httpClient; + private int notificationId; private string oauth2Token; private int pingNumber; private ServerSettings settings; @@ -472,12 +471,15 @@ namespace SafeExamBrowser.Server { switch (instruction) { - case Instructions.NOTIFICATION_CONFIRM when attributes.Type == "raisehand": - Task.Run(() => HandConfirmed?.Invoke()); + case Instructions.LOCK_SCREEN: + Task.Run(() => LockScreenRequested?.Invoke(attributes.Message)); break; case Instructions.NOTIFICATION_CONFIRM when attributes.Type == "lockscreen": Task.Run(() => LockScreenConfirmed?.Invoke()); break; + case Instructions.NOTIFICATION_CONFIRM when attributes.Type == "raisehand": + Task.Run(() => HandConfirmed?.Invoke()); + break; case Instructions.PROCTORING: Task.Run(() => ProctoringInstructionReceived?.Invoke(attributes.Instruction)); break; @@ -487,9 +489,6 @@ namespace SafeExamBrowser.Server case Instructions.QUIT: Task.Run(() => TerminationRequested?.Invoke()); break; - case Instructions.LOCK_SCREEN: - Task.Run(() => LockScreenRequested?.Invoke(attributes.Message)); - break; } if (instructionConfirmation != default) diff --git a/SafeExamBrowser.UserInterface.Contracts/Windows/Data/LockScreenResult.cs b/SafeExamBrowser.UserInterface.Contracts/Windows/Data/LockScreenResult.cs index 867f282d..97f9efb8 100644 --- a/SafeExamBrowser.UserInterface.Contracts/Windows/Data/LockScreenResult.cs +++ b/SafeExamBrowser.UserInterface.Contracts/Windows/Data/LockScreenResult.cs @@ -15,9 +15,8 @@ namespace SafeExamBrowser.UserInterface.Contracts.Windows.Data /// public class LockScreenResult { - /// - /// This is been set if the lock screen was canceled from another process (E.g.: from SEB Server instruction) + /// Indicates that the lock screen has been canceled (e.g. via a server instruction). /// public bool Canceled { get; set; } diff --git a/SafeExamBrowser.UserInterface.Contracts/Windows/ILockScreen.cs b/SafeExamBrowser.UserInterface.Contracts/Windows/ILockScreen.cs index 9d34fe55..ab8656ed 100644 --- a/SafeExamBrowser.UserInterface.Contracts/Windows/ILockScreen.cs +++ b/SafeExamBrowser.UserInterface.Contracts/Windows/ILockScreen.cs @@ -15,13 +15,14 @@ namespace SafeExamBrowser.UserInterface.Contracts.Windows /// public interface ILockScreen : IWindow { + /// + /// Cancels the operation and closes the lock screen. + /// + void Cancel(); + /// /// Waits for the user to provide the required input to unlock the application. /// LockScreenResult WaitForResult(); - /// - /// This cancel a waiting thread for LockScreenResult and force the lock screen to close - /// - void Cancel(); } } diff --git a/SafeExamBrowser.UserInterface.Desktop/Windows/LockScreen.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Windows/LockScreen.xaml.cs index a7d2a8fd..0d8ecf5d 100644 --- a/SafeExamBrowser.UserInterface.Desktop/Windows/LockScreen.xaml.cs +++ b/SafeExamBrowser.UserInterface.Desktop/Windows/LockScreen.xaml.cs @@ -27,8 +27,8 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows { private readonly AutoResetEvent autoResetEvent; private readonly IText text; - private bool canceled = false; + private bool canceled; private IList windows; event WindowClosedEventHandler IWindow.Closed @@ -57,6 +57,12 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows Dispatcher.Invoke(Activate); } + public void Cancel() + { + canceled = true; + autoResetEvent.Set(); + } + public new void Close() { Dispatcher.Invoke(CloseAll); @@ -87,6 +93,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows }); result.Canceled = canceled; + return result; } @@ -174,11 +181,5 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows autoResetEvent.Set(); } } - - public void Cancel() - { - canceled = true; - autoResetEvent.Set(); - } } } diff --git a/SafeExamBrowser.UserInterface.Mobile/Windows/LockScreen.xaml.cs b/SafeExamBrowser.UserInterface.Mobile/Windows/LockScreen.xaml.cs index 50c29de0..12fdb849 100644 --- a/SafeExamBrowser.UserInterface.Mobile/Windows/LockScreen.xaml.cs +++ b/SafeExamBrowser.UserInterface.Mobile/Windows/LockScreen.xaml.cs @@ -27,8 +27,8 @@ namespace SafeExamBrowser.UserInterface.Mobile.Windows { private readonly AutoResetEvent autoResetEvent; private readonly IText text; - private bool canceled = false; + private bool canceled; private IList windows; event WindowClosedEventHandler IWindow.Closed @@ -57,6 +57,12 @@ namespace SafeExamBrowser.UserInterface.Mobile.Windows Dispatcher.Invoke(Activate); } + public void Cancel() + { + canceled = true; + autoResetEvent.Set(); + } + public new void Close() { Dispatcher.Invoke(CloseAll); @@ -87,6 +93,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Windows }); result.Canceled = canceled; + return result; } @@ -174,11 +181,5 @@ namespace SafeExamBrowser.UserInterface.Mobile.Windows autoResetEvent.Set(); } } - - public void Cancel() - { - canceled = true; - autoResetEvent.Set(); - } } }