diff --git a/SafeExamBrowser.I18n.Contracts/TextKey.cs b/SafeExamBrowser.I18n.Contracts/TextKey.cs index 173de3a4..00f7e45a 100644 --- a/SafeExamBrowser.I18n.Contracts/TextKey.cs +++ b/SafeExamBrowser.I18n.Contracts/TextKey.cs @@ -165,6 +165,11 @@ namespace SafeExamBrowser.I18n.Contracts PasswordDialog_SettingsPasswordRequired, PasswordDialog_SettingsPasswordRequiredTitle, RuntimeWindow_ApplicationRunning, + ServerFailureDialog_Abort, + ServerFailureDialog_Fallback, + ServerFailureDialog_Message, + ServerFailureDialog_Retry, + ServerFailureDialog_Title, Shell_QuitButton, SystemControl_AudioDeviceInfo, SystemControl_AudioDeviceInfoMuted, diff --git a/SafeExamBrowser.I18n/Data/de.xml b/SafeExamBrowser.I18n/Data/de.xml index 4c55906d..eb56b7bb 100644 --- a/SafeExamBrowser.I18n/Data/de.xml +++ b/SafeExamBrowser.I18n/Data/de.xml @@ -453,6 +453,21 @@ SEB wird ausgeführt. + + Abbrechen + + + Fallback + + + Bei der Kommunikation mit dem SEB-Server ist ein Fehler aufgetreten. + + + Wiederholen + + + SEB-Server-Fehler + Sitzung beenden diff --git a/SafeExamBrowser.I18n/Data/en.xml b/SafeExamBrowser.I18n/Data/en.xml index 348b38fc..36cdb0a3 100644 --- a/SafeExamBrowser.I18n/Data/en.xml +++ b/SafeExamBrowser.I18n/Data/en.xml @@ -453,6 +453,21 @@ SEB is running. + + Abort + + + Fallback + + + An error occurred while trying to communicate with the SEB server. + + + Retry + + + SEB-Server Error + Terminate Session diff --git a/SafeExamBrowser.Runtime/Operations/Events/ServerFailureEventArgs.cs b/SafeExamBrowser.Runtime/Operations/Events/ServerFailureEventArgs.cs index 3d0178d3..7febce61 100644 --- a/SafeExamBrowser.Runtime/Operations/Events/ServerFailureEventArgs.cs +++ b/SafeExamBrowser.Runtime/Operations/Events/ServerFailureEventArgs.cs @@ -16,10 +16,12 @@ namespace SafeExamBrowser.Runtime.Operations.Events public bool Fallback { get; set; } public string Message { get; set; } public bool Retry { get; set; } + public bool ShowFallback { get; } - public ServerFailureEventArgs(string message) + public ServerFailureEventArgs(string message, bool showFallback) { Message = message; + ShowFallback = showFallback; } } } diff --git a/SafeExamBrowser.Runtime/Operations/ServerOperation.cs b/SafeExamBrowser.Runtime/Operations/ServerOperation.cs index 21f20382..4e3de3cd 100644 --- a/SafeExamBrowser.Runtime/Operations/ServerOperation.cs +++ b/SafeExamBrowser.Runtime/Operations/ServerOperation.cs @@ -70,6 +70,7 @@ namespace SafeExamBrowser.Runtime.Operations if (status == LoadStatus.Success) { Context.Next.Settings = settings; + Context.Next.Settings.Browser.StartUrl = exam.Url; result = OperationResult.Success; } else @@ -116,7 +117,7 @@ namespace SafeExamBrowser.Runtime.Operations { var result = OperationResult.Failed; - if (Context.Current.Settings.SessionMode == SessionMode.Server) + if (Context.Current?.Settings.SessionMode == SessionMode.Server) { logger.Info("Finalizing server..."); StatusChanged?.Invoke(TextKey.OperationStatus_FinalizeServer); @@ -192,7 +193,7 @@ namespace SafeExamBrowser.Runtime.Operations private bool Retry(string message, out bool abort, out bool fallback) { - var args = new ServerFailureEventArgs(message); + var args = new ServerFailureEventArgs(message, Context.Next.Settings.Server.PerformFallback); ActionRequired?.Invoke(args); diff --git a/SafeExamBrowser.Runtime/RuntimeController.cs b/SafeExamBrowser.Runtime/RuntimeController.cs index 88a2d823..0b1a5592 100644 --- a/SafeExamBrowser.Runtime/RuntimeController.cs +++ b/SafeExamBrowser.Runtime/RuntimeController.cs @@ -417,7 +417,18 @@ namespace SafeExamBrowser.Runtime private void AskForServerFailureAction(ServerFailureEventArgs args) { - // TODO: Also implement mechanism to retrieve selection via client!! + var isStartup = !SessionIsRunning; + var isRunningOnDefaultDesktop = SessionIsRunning && Session.Settings.Security.KioskMode == KioskMode.DisableExplorerShell; + + if (isStartup || isRunningOnDefaultDesktop) + { + TryAskForServerFailureActionViaDialog(args); + } + else + { + // TODO: Also implement mechanism to retrieve selection via client!! + // TryAskForServerFailureActionViaClient(args); + } } private void AskIfConfigurationSufficient(ConfigurationCompletedEventArgs args) @@ -503,15 +514,23 @@ namespace SafeExamBrowser.Runtime private void TryAskForExamSelectionViaDialog(ExamSelectionEventArgs args) { - var message = TextKey.ExamSelectionDialog_Message; - var title = TextKey.ExamSelectionDialog_Title; - var dialog = uiFactory.CreateExamSelectionDialog(text.Get(message), text.Get(title), args.Exams); + var dialog = uiFactory.CreateExamSelectionDialog(args.Exams); var result = dialog.Show(runtimeWindow); args.SelectedExam = result.SelectedExam; args.Success = result.Success; } + private void TryAskForServerFailureActionViaDialog(ServerFailureEventArgs args) + { + var dialog = uiFactory.CreateServerFailureDialog(args.Message, args.ShowFallback); + var result = dialog.Show(runtimeWindow); + + args.Abort = result.Abort; + args.Fallback = result.Fallback; + args.Retry = result.Retry; + } + private void TryGetPasswordViaDialog(PasswordRequiredEventArgs args) { var message = default(TextKey); diff --git a/SafeExamBrowser.Server.Contracts/Exam.cs b/SafeExamBrowser.Server.Contracts/Exam.cs index 96a4d09c..de303948 100644 --- a/SafeExamBrowser.Server.Contracts/Exam.cs +++ b/SafeExamBrowser.Server.Contracts/Exam.cs @@ -18,6 +18,11 @@ namespace SafeExamBrowser.Server.Contracts /// public string Id { get; set; } + /// + /// The name of the learning management system (LMS) on which the exam is running. + /// + public string LmsName { get; set; } + /// /// The name of the exam. /// diff --git a/SafeExamBrowser.Server/ServerProxy.cs b/SafeExamBrowser.Server/ServerProxy.cs index 63340d50..e5909291 100644 --- a/SafeExamBrowser.Server/ServerProxy.cs +++ b/SafeExamBrowser.Server/ServerProxy.cs @@ -223,6 +223,7 @@ namespace SafeExamBrowser.Server exams.Add(new Exam { Id = exam["examId"].Value(), + LmsName = exam["lmsType"].Value(), Name = exam["name"].Value(), Url = exam["url"].Value() }); @@ -314,7 +315,7 @@ namespace SafeExamBrowser.Server private string ToString(HttpResponseMessage response) { - return $"{(int) response.StatusCode} {response.StatusCode} {response.ReasonPhrase}"; + return $"{(int?) response?.StatusCode} {response?.StatusCode} {response?.ReasonPhrase}"; } } } diff --git a/SafeExamBrowser.UserInterface.Contracts/IUserInterfaceFactory.cs b/SafeExamBrowser.UserInterface.Contracts/IUserInterfaceFactory.cs index 16a98687..70418550 100644 --- a/SafeExamBrowser.UserInterface.Contracts/IUserInterfaceFactory.cs +++ b/SafeExamBrowser.UserInterface.Contracts/IUserInterfaceFactory.cs @@ -58,7 +58,7 @@ namespace SafeExamBrowser.UserInterface.Contracts /// /// Creates an exam selection dialog for the given exams. /// - IExamSelectionDialog CreateExamSelectionDialog(string message, string title, IEnumerable exams); + IExamSelectionDialog CreateExamSelectionDialog(IEnumerable exams); /// /// Creates a system control which allows to change the keyboard layout of the computer. @@ -98,9 +98,13 @@ namespace SafeExamBrowser.UserInterface.Contracts /// /// Creates a new runtime window which runs on its own thread. /// - /// IRuntimeWindow CreateRuntimeWindow(AppConfig appConfig); + /// + /// Creates a new server failure dialog with the given parameters. + /// + IServerFailureDialog CreateServerFailureDialog(string info, bool showFallback); + /// /// Creates a new splash screen which runs on its own thread. /// diff --git a/SafeExamBrowser.UserInterface.Contracts/SafeExamBrowser.UserInterface.Contracts.csproj b/SafeExamBrowser.UserInterface.Contracts/SafeExamBrowser.UserInterface.Contracts.csproj index 84b0b350..737c7268 100644 --- a/SafeExamBrowser.UserInterface.Contracts/SafeExamBrowser.UserInterface.Contracts.csproj +++ b/SafeExamBrowser.UserInterface.Contracts/SafeExamBrowser.UserInterface.Contracts.csproj @@ -89,12 +89,14 @@ + + diff --git a/SafeExamBrowser.UserInterface.Contracts/Windows/Data/ServerFailureDialogResult.cs b/SafeExamBrowser.UserInterface.Contracts/Windows/Data/ServerFailureDialogResult.cs new file mode 100644 index 00000000..fff576d0 --- /dev/null +++ b/SafeExamBrowser.UserInterface.Contracts/Windows/Data/ServerFailureDialogResult.cs @@ -0,0 +1,36 @@ +/* + * 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/. + */ + +namespace SafeExamBrowser.UserInterface.Contracts.Windows.Data +{ + /// + /// Defines the user interaction result of an . + /// + public class ServerFailureDialogResult + { + /// + /// Indicates whether the user wants to abort the operation. + /// + public bool Abort { get; set; } + + /// + /// Indicates whether the user wants to performa a fallback. + /// + public bool Fallback { get; set; } + + /// + /// Indicates whether the user wants to retry the operation. + /// + public bool Retry { get; set; } + + /// + /// Indicates whether the user confirmed the dialog or not. + /// + public bool Success { get; set; } + } +} diff --git a/SafeExamBrowser.UserInterface.Contracts/Windows/IExamSelectionDialog.cs b/SafeExamBrowser.UserInterface.Contracts/Windows/IExamSelectionDialog.cs index 9d4d524d..ed414fa0 100644 --- a/SafeExamBrowser.UserInterface.Contracts/Windows/IExamSelectionDialog.cs +++ b/SafeExamBrowser.UserInterface.Contracts/Windows/IExamSelectionDialog.cs @@ -11,7 +11,7 @@ using SafeExamBrowser.UserInterface.Contracts.Windows.Data; namespace SafeExamBrowser.UserInterface.Contracts.Windows { /// - /// Defines the functionality of an exam selection dialog. + /// The dialog shown to let the user select which server exam to start. /// public interface IExamSelectionDialog { diff --git a/SafeExamBrowser.UserInterface.Contracts/Windows/IServerFailureDialog.cs b/SafeExamBrowser.UserInterface.Contracts/Windows/IServerFailureDialog.cs new file mode 100644 index 00000000..880697b8 --- /dev/null +++ b/SafeExamBrowser.UserInterface.Contracts/Windows/IServerFailureDialog.cs @@ -0,0 +1,23 @@ +/* + * 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 SafeExamBrowser.UserInterface.Contracts.Windows.Data; + +namespace SafeExamBrowser.UserInterface.Contracts.Windows +{ + /// + /// The dialog shown in case a communication failure with a server occurs. + /// + public interface IServerFailureDialog + { + /// + /// Shows the dialog as topmost window. If a parent window is specified, the dialog is rendered modally for the given parent. + /// + ServerFailureDialogResult Show(IWindow parent = null); + } +} diff --git a/SafeExamBrowser.UserInterface.Desktop/SafeExamBrowser.UserInterface.Desktop.csproj b/SafeExamBrowser.UserInterface.Desktop/SafeExamBrowser.UserInterface.Desktop.csproj index 4a249a14..668ecd69 100644 --- a/SafeExamBrowser.UserInterface.Desktop/SafeExamBrowser.UserInterface.Desktop.csproj +++ b/SafeExamBrowser.UserInterface.Desktop/SafeExamBrowser.UserInterface.Desktop.csproj @@ -168,6 +168,9 @@ RuntimeWindow.xaml + + ServerFailureDialog.xaml + SplashScreen.xaml @@ -347,6 +350,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/SafeExamBrowser.UserInterface.Desktop/UserInterfaceFactory.cs b/SafeExamBrowser.UserInterface.Desktop/UserInterfaceFactory.cs index 6c834894..41fde627 100644 --- a/SafeExamBrowser.UserInterface.Desktop/UserInterfaceFactory.cs +++ b/SafeExamBrowser.UserInterface.Desktop/UserInterfaceFactory.cs @@ -82,9 +82,9 @@ namespace SafeExamBrowser.UserInterface.Desktop return Application.Current.Dispatcher.Invoke(() => new BrowserWindow(control, settings, isMainWindow, text)); } - public IExamSelectionDialog CreateExamSelectionDialog(string message, string title, IEnumerable exams) + public IExamSelectionDialog CreateExamSelectionDialog(IEnumerable exams) { - return Application.Current.Dispatcher.Invoke(() => new ExamSelectionDialog(message, title, text, exams)); + return Application.Current.Dispatcher.Invoke(() => new ExamSelectionDialog(exams, text)); } public ISystemControl CreateKeyboardLayoutControl(IKeyboard keyboard, Location location) @@ -167,6 +167,11 @@ namespace SafeExamBrowser.UserInterface.Desktop return Application.Current.Dispatcher.Invoke(() => new RuntimeWindow(appConfig, text)); } + public IServerFailureDialog CreateServerFailureDialog(string info, bool showFallback) + { + return Application.Current.Dispatcher.Invoke(() => new ServerFailureDialog(info, showFallback, text)); + } + public ISplashScreen CreateSplashScreen(AppConfig appConfig = null) { var window = default(SplashScreen); diff --git a/SafeExamBrowser.UserInterface.Desktop/Windows/ExamSelectionDialog.xaml b/SafeExamBrowser.UserInterface.Desktop/Windows/ExamSelectionDialog.xaml index 9d869466..f2025823 100644 --- a/SafeExamBrowser.UserInterface.Desktop/Windows/ExamSelectionDialog.xaml +++ b/SafeExamBrowser.UserInterface.Desktop/Windows/ExamSelectionDialog.xaml @@ -39,7 +39,7 @@ - + diff --git a/SafeExamBrowser.UserInterface.Desktop/Windows/ExamSelectionDialog.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Windows/ExamSelectionDialog.xaml.cs index 0fb386f8..5e31bb55 100644 --- a/SafeExamBrowser.UserInterface.Desktop/Windows/ExamSelectionDialog.xaml.cs +++ b/SafeExamBrowser.UserInterface.Desktop/Windows/ExamSelectionDialog.xaml.cs @@ -20,12 +20,12 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows { private readonly IText text; - public ExamSelectionDialog(string message, string title, IText text, IEnumerable exams) + public ExamSelectionDialog(IEnumerable exams, IText text) { this.text = text; InitializeComponent(); - InitializeExamSelectionDialog(message, title, exams); + InitializeExamSelectionDialog(exams); } public ExamSelectionDialogResult Show(IWindow parent = null) @@ -50,10 +50,10 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows }); } - private void InitializeExamSelectionDialog(string message, string title, IEnumerable exams) + private void InitializeExamSelectionDialog(IEnumerable exams) { - Message.Text = message; - Title = title; + Message.Text = text.Get(TextKey.ExamSelectionDialog_Message); + Title = text.Get(TextKey.ExamSelectionDialog_Title); WindowStartupLocation = WindowStartupLocation.CenterScreen; CancelButton.Content = text.Get(TextKey.ExamSelectionDialog_Cancel); diff --git a/SafeExamBrowser.UserInterface.Desktop/Windows/ServerFailureDialog.xaml b/SafeExamBrowser.UserInterface.Desktop/Windows/ServerFailureDialog.xaml new file mode 100644 index 00000000..f5b13700 --- /dev/null +++ b/SafeExamBrowser.UserInterface.Desktop/Windows/ServerFailureDialog.xaml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +