SEBWIN-495: Improved error message for prohibited display configuration.
This commit is contained in:
parent
ee2133c0c2
commit
213f45ad3a
14 changed files with 140 additions and 60 deletions
|
@ -414,7 +414,7 @@ namespace SafeExamBrowser.Client.UnitTests
|
|||
|
||||
actionCenter.Setup(t => t.InitializeBounds()).Callback(() => boundsActionCenter = ++order);
|
||||
displayMonitor.Setup(m => m.InitializePrimaryDisplay(It.Is<int>(h => h == height))).Callback(() => workingArea = ++order);
|
||||
displayMonitor.Setup(m => m.IsAllowedConfiguration(It.IsAny<DisplaySettings>())).Returns(true);
|
||||
displayMonitor.Setup(m => m.ValidateConfiguration(It.IsAny<DisplaySettings>())).Returns(new ValidationResult { IsAllowed = true });
|
||||
taskbar.Setup(t => t.GetAbsoluteHeight()).Returns(height);
|
||||
taskbar.Setup(t => t.InitializeBounds()).Callback(() => boundsTaskbar = ++order);
|
||||
|
||||
|
@ -445,7 +445,7 @@ namespace SafeExamBrowser.Client.UnitTests
|
|||
|
||||
actionCenter.Setup(t => t.InitializeBounds()).Callback(() => boundsActionCenter = ++order);
|
||||
displayMonitor.Setup(w => w.InitializePrimaryDisplay(It.Is<int>(h => h == 0))).Callback(() => workingArea = ++order);
|
||||
displayMonitor.Setup(m => m.IsAllowedConfiguration(It.IsAny<DisplaySettings>())).Returns(true);
|
||||
displayMonitor.Setup(m => m.ValidateConfiguration(It.IsAny<DisplaySettings>())).Returns(new ValidationResult { IsAllowed = true });
|
||||
taskbar.Setup(t => t.GetAbsoluteHeight()).Returns(height);
|
||||
taskbar.Setup(t => t.InitializeBounds()).Callback(() => boundsTaskbar = ++order);
|
||||
|
||||
|
|
|
@ -513,7 +513,7 @@ namespace SafeExamBrowser.Client
|
|||
taskbar.InitializeBounds();
|
||||
logger.Info("Desktop successfully restored.");
|
||||
|
||||
if (!displayMonitor.IsAllowedConfiguration(Settings.Display))
|
||||
if (!displayMonitor.ValidateConfiguration(Settings.Display).IsAllowed)
|
||||
{
|
||||
var continueOption = new LockScreenOption { Text = text.Get(TextKey.LockScreen_DisplayConfigurationContinueOption) };
|
||||
var terminateOption = new LockScreenOption { Text = text.Get(TextKey.LockScreen_DisplayConfigurationTerminateOption) };
|
||||
|
|
|
@ -100,6 +100,8 @@ namespace SafeExamBrowser.I18n.Contracts
|
|||
MessageBox_NoButton,
|
||||
MessageBox_DisplayConfigurationError,
|
||||
MessageBox_DisplayConfigurationErrorTitle,
|
||||
MessageBox_DisplayConfigurationInternal,
|
||||
MessageBox_DisplayConfigurationInternalOrExternal,
|
||||
MessageBox_NotSupportedConfigurationResource,
|
||||
MessageBox_NotSupportedConfigurationResourceTitle,
|
||||
MessageBox_OkButton,
|
||||
|
|
|
@ -220,11 +220,17 @@
|
|||
Fehler beim Herunterladen
|
||||
</Entry>
|
||||
<Entry key="MessageBox_DisplayConfigurationError">
|
||||
Die aktive Bildschirm-Konfiguration ist nicht erlaubt! Bitte konsultieren Sie das Applikations-Protokoll für mehr Informationen. SEB wird sich nun beenden...
|
||||
Die aktive Bildschirm-Konfiguration ist nicht erlaubt! Erlaubt sind %%_ALLOWED_COUNT_%% %%_TYPE_%% Bildschirm(e), erkannt wurden %%_INTERNAL_COUNT_%% interne(r) und %%_EXTERNAL_COUNT_%% externe(r) Bildschirm(e). Bitte konsultieren Sie das Applikations-Protokoll für mehr Informationen. SEB wird sich nun beenden...
|
||||
</Entry>
|
||||
<Entry key="MessageBox_DisplayConfigurationErrorTitle">
|
||||
Verbotene Bildschirm-Konfiguration
|
||||
</Entry>
|
||||
<Entry key="MessageBox_DisplayConfigurationInternal">
|
||||
interne(r)
|
||||
</Entry>
|
||||
<Entry key="MessageBox_DisplayConfigurationInternalOrExternal">
|
||||
interne(r) oder externe(r)
|
||||
</Entry>
|
||||
<Entry key="MessageBox_InvalidConfigurationData">
|
||||
Die Konfigurations-Ressource "%%URI%%" enthält ungültige Daten!
|
||||
</Entry>
|
||||
|
|
|
@ -220,11 +220,17 @@
|
|||
Download Error
|
||||
</Entry>
|
||||
<Entry key="MessageBox_DisplayConfigurationError">
|
||||
The active display configuration is not permitted. Please consult the log files for more information. SEB will now shut down...
|
||||
The active display configuration is not permitted. %%_ALLOWED_COUNT_%% %%_TYPE_%% display(s) are allowed, but %%_INTERNAL_COUNT_%% internal and %%_EXTERNAL_COUNT_%% external display(s) were detected. Please consult the log files for more information. SEB will now shut down...
|
||||
</Entry>
|
||||
<Entry key="MessageBox_DisplayConfigurationErrorTitle">
|
||||
Prohibited Display Configuration
|
||||
</Entry>
|
||||
<Entry key="MessageBox_DisplayConfigurationInternal">
|
||||
internal
|
||||
</Entry>
|
||||
<Entry key="MessageBox_DisplayConfigurationInternalOrExternal">
|
||||
internal or external
|
||||
</Entry>
|
||||
<Entry key="MessageBox_InvalidConfigurationData">
|
||||
The configuration resource "%%URI%%" contains invalid data!
|
||||
</Entry>
|
||||
|
|
|
@ -220,11 +220,17 @@
|
|||
Erreur de téléchargement
|
||||
</Entry>
|
||||
<Entry key="MessageBox_DisplayConfigurationError">
|
||||
La configuration d'affichage active n'est pas autorisée. Veuillez consulter les fichiers journaux pour plus d'informations. SEB va maintenant s'arrêter...
|
||||
La configuration d'affichage active n'est pas autorisée. %%_ALLOWED_COUNT_%% affichages %%_TYPE_%% sont autorisés, mais %%_INTERNAL_COUNT_%% affichages interne(s) et %%_EXTERNAL_COUNT_%% externe(s) ont été détecté(s). Veuillez consulter les fichiers journaux pour plus d'informations. SEB va maintenant s'arrêter...
|
||||
</Entry>
|
||||
<Entry key="MessageBox_DisplayConfigurationErrorTitle">
|
||||
Configuration d'affichage interdite
|
||||
</Entry>
|
||||
<Entry key="MessageBox_DisplayConfigurationInternal">
|
||||
interne(s)
|
||||
</Entry>
|
||||
<Entry key="MessageBox_DisplayConfigurationInternalOrExternal">
|
||||
interne(s) ou externe(s)
|
||||
</Entry>
|
||||
<Entry key="MessageBox_InvalidConfigurationData">
|
||||
La ressource de configuration "%%URI%%" contient des données non valides!
|
||||
</Entry>
|
||||
|
|
|
@ -220,11 +220,17 @@
|
|||
Errore di download
|
||||
</Entry>
|
||||
<Entry key="MessageBox_DisplayConfigurationError">
|
||||
La configurazione del display attiva non è consentita. Si prega di consultare i file di registro per ulteriori informazioni. SEB ora si spegnerà...
|
||||
La configurazione del display attiva non è consentita. Sono consentiti %%_ALLOWED_COUNT_%% display %%_TYPE_%%, ma sono stati rilevati %%_INTERNAL_COUNT_%% display interno/i e %%_EXTERNAL_COUNT_%% esterno/i. Si prega di consultare i file di registro per ulteriori informazioni. SEB ora si spegnerà...
|
||||
</Entry>
|
||||
<Entry key="MessageBox_DisplayConfigurationErrorTitle">
|
||||
Configurazione del display vietata
|
||||
</Entry>
|
||||
<Entry key="MessageBox_DisplayConfigurationInternal">
|
||||
interno/i
|
||||
</Entry>
|
||||
<Entry key="MessageBox_DisplayConfigurationInternalOrExternal">
|
||||
interno/i o esterno/i
|
||||
</Entry>
|
||||
<Entry key="MessageBox_InvalidConfigurationData">
|
||||
La risorsa di configurazione "%%URI%%" contiene dati non validi!
|
||||
</Entry>
|
||||
|
|
|
@ -190,11 +190,17 @@
|
|||
下载错误
|
||||
</Entry>
|
||||
<Entry key="MessageBox_DisplayConfigurationError">
|
||||
不允许使用活动的显示配置。 请查阅日志文件以获取更多信息。 SEB现在将关闭...
|
||||
不允许使用活动的显示配置。 允许使用 %%_ALLOWED_COUNT_%% 个%%_TYPE_%%显示器,但检测到 %%_INTERNAL_COUNT_%% 个内部和 %%_EXTERNAL_COUNT_%% 个外部显示器。 请查阅日志文件以获取更多信息。 SEB现在将关闭...
|
||||
</Entry>
|
||||
<Entry key="MessageBox_DisplayConfigurationErrorTitle">
|
||||
禁止的显示配置
|
||||
</Entry>
|
||||
<Entry key="MessageBox_DisplayConfigurationInternal">
|
||||
内部的
|
||||
</Entry>
|
||||
<Entry key="MessageBox_DisplayConfigurationInternalOrExternal">
|
||||
内部或外部
|
||||
</Entry>
|
||||
<Entry key="MessageBox_InvalidConfigurationData">
|
||||
配置"%%URI%%" 中包含无效数据。
|
||||
</Entry>
|
||||
|
@ -360,6 +366,9 @@
|
|||
<Entry key="OperationStatus_InitializeRuntimeConnection">
|
||||
初始化运行时连接
|
||||
</Entry>
|
||||
<Entry key="OperationStatus_InitializeServer">
|
||||
初始化 SEB 服务器
|
||||
</Entry>
|
||||
<Entry key="OperationStatus_InitializeServiceSession">
|
||||
初始化服务会话
|
||||
</Entry>
|
||||
|
|
|
@ -26,11 +26,6 @@ namespace SafeExamBrowser.Monitoring.Contracts.Display
|
|||
/// </summary>
|
||||
void InitializePrimaryDisplay(int taskbarHeight);
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the currently active display configuration is allowed according to the given settings.
|
||||
/// </summary>
|
||||
bool IsAllowedConfiguration(DisplaySettings settings);
|
||||
|
||||
/// <summary>
|
||||
/// Prevents the computer from entering sleep mode and turning its display(s) off.
|
||||
/// </summary>
|
||||
|
@ -50,5 +45,10 @@ namespace SafeExamBrowser.Monitoring.Contracts.Display
|
|||
/// Stops monitoring for display changes.
|
||||
/// </summary>
|
||||
void StopMonitoringDisplayChanges();
|
||||
|
||||
/// <summary>
|
||||
/// Validates the currently active display configuration according to the given settings.
|
||||
/// </summary>
|
||||
ValidationResult ValidateConfiguration(DisplaySettings settings);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
namespace SafeExamBrowser.Monitoring.Contracts.Display
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides the result of a display configuration validation.
|
||||
/// </summary>
|
||||
public class ValidationResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the count of external displays detected.
|
||||
/// </summary>
|
||||
public int ExternalDisplays { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the count of internal displays detected.
|
||||
/// </summary>
|
||||
public int InternalDisplays { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the active display configuration is allowed.
|
||||
/// </summary>
|
||||
public bool IsAllowed { get; set; }
|
||||
}
|
||||
}
|
|
@ -60,6 +60,7 @@
|
|||
<Compile Include="Display\Events\DisplayChangedEventHandler.cs" />
|
||||
<Compile Include="Applications\Events\ExplorerStartedEventHandler.cs" />
|
||||
<Compile Include="Display\IDisplayMonitor.cs" />
|
||||
<Compile Include="Display\ValidationResult.cs" />
|
||||
<Compile Include="Keyboard\IKeyboardInterceptor.cs" />
|
||||
<Compile Include="Mouse\IMouseInterceptor.cs" />
|
||||
<Compile Include="Applications\InitializationResult.cs" />
|
||||
|
|
|
@ -46,41 +46,6 @@ namespace SafeExamBrowser.Monitoring.Display
|
|||
InitializeWallpaper();
|
||||
}
|
||||
|
||||
public bool IsAllowedConfiguration(DisplaySettings settings)
|
||||
{
|
||||
var allowed = false;
|
||||
|
||||
if (TryLoadDisplays(out var displays))
|
||||
{
|
||||
var active = displays.Where(d => d.IsActive);
|
||||
var count = active.Count();
|
||||
|
||||
allowed = count <= settings.AllowedDisplays;
|
||||
|
||||
if (allowed)
|
||||
{
|
||||
logger.Info($"Detected {count} active displays, {settings.AllowedDisplays} are allowed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Warn($"Detected {count} active displays but only {settings.AllowedDisplays} are allowed!");
|
||||
}
|
||||
|
||||
if (settings.InternalDisplayOnly && active.Any(d => !d.IsInternal))
|
||||
{
|
||||
allowed = false;
|
||||
logger.Warn("Detected external display but only internal displays are allowed!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
allowed = settings.IgnoreError;
|
||||
logger.Warn($"Failed to validate display configuration, {(allowed ? "ignoring error" : "active configuration is not allowed")}.");
|
||||
}
|
||||
|
||||
return allowed;
|
||||
}
|
||||
|
||||
public void PreventSleepMode()
|
||||
{
|
||||
nativeMethods.PreventSleepMode();
|
||||
|
@ -105,6 +70,43 @@ namespace SafeExamBrowser.Monitoring.Display
|
|||
logger.Info("Stopped monitoring display changes.");
|
||||
}
|
||||
|
||||
public ValidationResult ValidateConfiguration(DisplaySettings settings)
|
||||
{
|
||||
var result = new ValidationResult();
|
||||
|
||||
if (TryLoadDisplays(out var displays))
|
||||
{
|
||||
var active = displays.Where(d => d.IsActive);
|
||||
var count = active.Count();
|
||||
|
||||
result.ExternalDisplays = active.Count(d => !d.IsInternal);
|
||||
result.InternalDisplays = active.Count(d => d.IsInternal);
|
||||
result.IsAllowed = count <= settings.AllowedDisplays;
|
||||
|
||||
if (result.IsAllowed)
|
||||
{
|
||||
logger.Info($"Detected {count} active displays, {settings.AllowedDisplays} are allowed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Warn($"Detected {count} active displays but only {settings.AllowedDisplays} are allowed!");
|
||||
}
|
||||
|
||||
if (settings.InternalDisplayOnly && active.Any(d => !d.IsInternal))
|
||||
{
|
||||
result.IsAllowed = false;
|
||||
logger.Warn("Detected external display but only internal displays are allowed!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.IsAllowed = settings.IgnoreError;
|
||||
logger.Warn($"Failed to validate display configuration, {(result.IsAllowed ? "ignoring error" : "active configuration is not allowed")}.");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e)
|
||||
{
|
||||
logger.Info("Display change detected!");
|
||||
|
|
|
@ -91,7 +91,7 @@ namespace SafeExamBrowser.Runtime
|
|||
sessionOperations.Enqueue(new DisclaimerOperation(logger, sessionContext));
|
||||
sessionOperations.Enqueue(new RemoteSessionOperation(remoteSessionDetector, logger, sessionContext));
|
||||
sessionOperations.Enqueue(new VirtualMachineOperation(vmDetector, logger, sessionContext));
|
||||
sessionOperations.Enqueue(new DisplayMonitorOperation(displayMonitor, logger, sessionContext));
|
||||
sessionOperations.Enqueue(new DisplayMonitorOperation(displayMonitor, logger, sessionContext, text));
|
||||
sessionOperations.Enqueue(new ServiceOperation(logger, runtimeHost, serviceProxy, sessionContext, THIRTY_SECONDS, userInfo));
|
||||
sessionOperations.Enqueue(new ClientTerminationOperation(logger, processFactory, proxyFactory, runtimeHost, sessionContext, THIRTY_SECONDS));
|
||||
sessionOperations.Enqueue(new ProctoringWorkaroundOperation(logger, sessionContext));
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using SafeExamBrowser.Core.Contracts.OperationModel;
|
||||
using SafeExamBrowser.Core.Contracts.OperationModel.Events;
|
||||
using SafeExamBrowser.I18n.Contracts;
|
||||
|
@ -20,14 +21,16 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
{
|
||||
private readonly IDisplayMonitor displayMonitor;
|
||||
private readonly ILogger logger;
|
||||
private readonly IText text;
|
||||
|
||||
public override event ActionRequiredEventHandler ActionRequired;
|
||||
public override event StatusChangedEventHandler StatusChanged;
|
||||
|
||||
public DisplayMonitorOperation(IDisplayMonitor displayMonitor, ILogger logger, SessionContext context) : base(context)
|
||||
public DisplayMonitorOperation(IDisplayMonitor displayMonitor, ILogger logger, SessionContext context, IText text) : base(context)
|
||||
{
|
||||
this.displayMonitor = displayMonitor;
|
||||
this.logger = logger;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public override OperationResult Perform()
|
||||
|
@ -47,26 +50,34 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
|
||||
private OperationResult CheckDisplayConfiguration()
|
||||
{
|
||||
var args = new MessageEventArgs
|
||||
{
|
||||
Action = MessageBoxAction.Ok,
|
||||
Icon = MessageBoxIcon.Error,
|
||||
Message = TextKey.MessageBox_DisplayConfigurationError,
|
||||
Title = TextKey.MessageBox_DisplayConfigurationErrorTitle
|
||||
};
|
||||
var result = OperationResult.Aborted;
|
||||
|
||||
logger.Info("Validating display configuration...");
|
||||
StatusChanged?.Invoke(TextKey.OperationStatus_ValidateDisplayConfiguration);
|
||||
|
||||
if (displayMonitor.IsAllowedConfiguration(Context.Next.Settings.Display))
|
||||
var result = OperationResult.Failed;
|
||||
var validation = displayMonitor.ValidateConfiguration(Context.Next.Settings.Display);
|
||||
|
||||
if (validation.IsAllowed)
|
||||
{
|
||||
logger.Info("Display configuration is allowed.");
|
||||
result = OperationResult.Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
var args = new MessageEventArgs
|
||||
{
|
||||
Action = MessageBoxAction.Ok,
|
||||
Icon = MessageBoxIcon.Error,
|
||||
Message = TextKey.MessageBox_DisplayConfigurationError,
|
||||
Title = TextKey.MessageBox_DisplayConfigurationErrorTitle
|
||||
};
|
||||
|
||||
logger.Error("Display configuration is not allowed!");
|
||||
|
||||
args.MessagePlaceholders.Add("%%_ALLOWED_COUNT_%%", Convert.ToString(Context.Next.Settings.Display.AllowedDisplays));
|
||||
args.MessagePlaceholders.Add("%%_TYPE_%%", Context.Next.Settings.Display.InternalDisplayOnly ? text.Get(TextKey.MessageBox_DisplayConfigurationInternal) : text.Get(TextKey.MessageBox_DisplayConfigurationInternalOrExternal));
|
||||
args.MessagePlaceholders.Add("%%_EXTERNAL_COUNT_%%", Convert.ToString(validation.ExternalDisplays));
|
||||
args.MessagePlaceholders.Add("%%_INTERNAL_COUNT_%%", Convert.ToString(validation.InternalDisplays));
|
||||
|
||||
ActionRequired?.Invoke(args);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue