diff --git a/SafeExamBrowser.Client/ClientController.cs b/SafeExamBrowser.Client/ClientController.cs
index 07f47a62..8cffa761 100644
--- a/SafeExamBrowser.Client/ClientController.cs
+++ b/SafeExamBrowser.Client/ClientController.cs
@@ -7,7 +7,6 @@
*/
using System;
-using System.ComponentModel;
using System.IO;
using SafeExamBrowser.Contracts.Browser;
using SafeExamBrowser.Contracts.Communication.Data;
@@ -18,6 +17,7 @@ using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Configuration.Settings;
using SafeExamBrowser.Contracts.Core;
using SafeExamBrowser.Contracts.Core.OperationModel;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Contracts.Monitoring;
@@ -97,7 +97,8 @@ namespace SafeExamBrowser.Client
logger.Info("Initiating startup procedure...");
splashScreen = uiFactory.CreateSplashScreen();
- operations.ProgressIndicator = splashScreen;
+ operations.ProgressChanged += Operations_ProgressChanged;
+ operations.StatusChanged += Operations_StatusChanged;
var success = operations.TryPerform() == OperationResult.Success;
@@ -276,6 +277,39 @@ namespace SafeExamBrowser.Client
shutdown.Invoke();
}
+ private void Operations_ProgressChanged(ProgressChangedEventArgs args)
+ {
+ if (args.CurrentValue.HasValue)
+ {
+ splashScreen?.SetValue(args.CurrentValue.Value);
+ }
+
+ if (args.IsIndeterminate == true)
+ {
+ splashScreen?.SetIndeterminate();
+ }
+
+ if (args.MaxValue.HasValue)
+ {
+ splashScreen?.SetMaxValue(args.MaxValue.Value);
+ }
+
+ if (args.Progress == true)
+ {
+ splashScreen?.Progress();
+ }
+
+ if (args.Regress == true)
+ {
+ splashScreen?.Regress();
+ }
+ }
+
+ private void Operations_StatusChanged(TextKey status)
+ {
+ splashScreen?.UpdateText(status);
+ }
+
private void Runtime_ConnectionLost()
{
logger.Error("Lost connection to the runtime!");
@@ -285,7 +319,7 @@ namespace SafeExamBrowser.Client
shutdown.Invoke();
}
- private void Taskbar_QuitButtonClicked(CancelEventArgs args)
+ private void Taskbar_QuitButtonClicked(System.ComponentModel.CancelEventArgs args)
{
var result = messageBox.Show(TextKey.MessageBox_Quit, TextKey.MessageBox_QuitTitle, MessageBoxAction.YesNo, MessageBoxIcon.Question);
diff --git a/SafeExamBrowser.Client/Operations/BrowserOperation.cs b/SafeExamBrowser.Client/Operations/BrowserOperation.cs
index de7b0c62..c0bb2cc6 100644
--- a/SafeExamBrowser.Client/Operations/BrowserOperation.cs
+++ b/SafeExamBrowser.Client/Operations/BrowserOperation.cs
@@ -9,6 +9,7 @@
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Core;
using SafeExamBrowser.Contracts.Core.OperationModel;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Contracts.UserInterface;
@@ -24,7 +25,8 @@ namespace SafeExamBrowser.Client.Operations
private ITaskbar taskbar;
private IUserInterfaceFactory uiFactory;
- public IProgressIndicator ProgressIndicator { private get; set; }
+ public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
+ public event StatusChangedEventHandler StatusChanged;
public BrowserOperation(
IApplicationController browserController,
@@ -43,7 +45,7 @@ namespace SafeExamBrowser.Client.Operations
public OperationResult Perform()
{
logger.Info("Initializing browser...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeBrowser, true);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_InitializeBrowser);
var browserButton = uiFactory.CreateApplicationButton(browserInfo);
@@ -63,7 +65,7 @@ namespace SafeExamBrowser.Client.Operations
public void Revert()
{
logger.Info("Terminating browser...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_TerminateBrowser, true);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_TerminateBrowser);
browserController.Terminate();
}
diff --git a/SafeExamBrowser.Client/Operations/ClientHostDisconnectionOperation.cs b/SafeExamBrowser.Client/Operations/ClientHostDisconnectionOperation.cs
index 64cca6d6..06589f0a 100644
--- a/SafeExamBrowser.Client/Operations/ClientHostDisconnectionOperation.cs
+++ b/SafeExamBrowser.Client/Operations/ClientHostDisconnectionOperation.cs
@@ -10,8 +10,8 @@ using System.Threading;
using SafeExamBrowser.Contracts.Communication.Events;
using SafeExamBrowser.Contracts.Communication.Hosts;
using SafeExamBrowser.Contracts.Core.OperationModel;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
using SafeExamBrowser.Contracts.Logging;
-using SafeExamBrowser.Contracts.UserInterface;
namespace SafeExamBrowser.Client.Operations
{
@@ -25,7 +25,8 @@ namespace SafeExamBrowser.Client.Operations
private ILogger logger;
private int timeout_ms;
- public IProgressIndicator ProgressIndicator { private get; set; }
+ public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
+ public event StatusChangedEventHandler StatusChanged { add { } remove { } }
public ClientHostDisconnectionOperation(IClientHost clientHost, ILogger logger, int timeout_ms)
{
@@ -50,6 +51,8 @@ namespace SafeExamBrowser.Client.Operations
var disconnectedEvent = new AutoResetEvent(false);
var disconnectedEventHandler = new CommunicationEventHandler(() => disconnectedEvent.Set());
+ // TODO: Update status!
+
clientHost.RuntimeDisconnected += disconnectedEventHandler;
if (clientHost.IsConnected)
diff --git a/SafeExamBrowser.Client/Operations/ClipboardOperation.cs b/SafeExamBrowser.Client/Operations/ClipboardOperation.cs
index 681caf96..a2b4cebe 100644
--- a/SafeExamBrowser.Client/Operations/ClipboardOperation.cs
+++ b/SafeExamBrowser.Client/Operations/ClipboardOperation.cs
@@ -7,9 +7,9 @@
*/
using SafeExamBrowser.Contracts.Core.OperationModel;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
-using SafeExamBrowser.Contracts.UserInterface;
using SafeExamBrowser.Contracts.WindowsApi;
namespace SafeExamBrowser.Client.Operations
@@ -19,7 +19,8 @@ namespace SafeExamBrowser.Client.Operations
private ILogger logger;
private INativeMethods nativeMethods;
- public IProgressIndicator ProgressIndicator { private get; set; }
+ public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
+ public event StatusChangedEventHandler StatusChanged;
public ClipboardOperation(ILogger logger, INativeMethods nativeMethods)
{
@@ -47,7 +48,7 @@ namespace SafeExamBrowser.Client.Operations
private void EmptyClipboard()
{
logger.Info("Emptying clipboard...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_EmptyClipboard);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_EmptyClipboard);
nativeMethods.EmptyClipboard();
}
diff --git a/SafeExamBrowser.Client/Operations/ConfigurationOperation.cs b/SafeExamBrowser.Client/Operations/ConfigurationOperation.cs
index c78fce78..ee1e6539 100644
--- a/SafeExamBrowser.Client/Operations/ConfigurationOperation.cs
+++ b/SafeExamBrowser.Client/Operations/ConfigurationOperation.cs
@@ -7,12 +7,12 @@
*/
using System;
-using SafeExamBrowser.Contracts.Core.OperationModel;
using SafeExamBrowser.Contracts.Communication.Proxies;
using SafeExamBrowser.Contracts.Configuration;
+using SafeExamBrowser.Contracts.Core.OperationModel;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
-using SafeExamBrowser.Contracts.UserInterface;
namespace SafeExamBrowser.Client.Operations
{
@@ -22,7 +22,8 @@ namespace SafeExamBrowser.Client.Operations
private ILogger logger;
private IRuntimeProxy runtime;
- public IProgressIndicator ProgressIndicator { private get; set; }
+ public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
+ public event StatusChangedEventHandler StatusChanged;
public ConfigurationOperation(ClientConfiguration configuration, ILogger logger, IRuntimeProxy runtime)
{
@@ -34,7 +35,7 @@ namespace SafeExamBrowser.Client.Operations
public OperationResult Perform()
{
logger.Info("Initializing application configuration...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeConfiguration);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_InitializeConfiguration);
try
{
diff --git a/SafeExamBrowser.Client/Operations/DisplayMonitorOperation.cs b/SafeExamBrowser.Client/Operations/DisplayMonitorOperation.cs
index 8bd8896a..972bd2f9 100644
--- a/SafeExamBrowser.Client/Operations/DisplayMonitorOperation.cs
+++ b/SafeExamBrowser.Client/Operations/DisplayMonitorOperation.cs
@@ -7,10 +7,10 @@
*/
using SafeExamBrowser.Contracts.Core.OperationModel;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Contracts.Monitoring;
-using SafeExamBrowser.Contracts.UserInterface;
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
namespace SafeExamBrowser.Client.Operations
@@ -21,7 +21,8 @@ namespace SafeExamBrowser.Client.Operations
private ILogger logger;
private ITaskbar taskbar;
- public IProgressIndicator ProgressIndicator { private get; set; }
+ public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
+ public event StatusChangedEventHandler StatusChanged;
public DisplayMonitorOperation(IDisplayMonitor displayMonitor, ILogger logger, ITaskbar taskbar)
{
@@ -33,7 +34,7 @@ namespace SafeExamBrowser.Client.Operations
public OperationResult Perform()
{
logger.Info("Initializing working area...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeWorkingArea);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_InitializeWorkingArea);
displayMonitor.PreventSleepMode();
displayMonitor.InitializePrimaryDisplay(taskbar.GetAbsoluteHeight());
@@ -50,7 +51,7 @@ namespace SafeExamBrowser.Client.Operations
public void Revert()
{
logger.Info("Restoring working area...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_RestoreWorkingArea);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_RestoreWorkingArea);
displayMonitor.StopMonitoringDisplayChanges();
displayMonitor.ResetPrimaryDisplay();
diff --git a/SafeExamBrowser.Client/Operations/KeyboardInterceptorOperation.cs b/SafeExamBrowser.Client/Operations/KeyboardInterceptorOperation.cs
index 444ea1cd..ffd5caa7 100644
--- a/SafeExamBrowser.Client/Operations/KeyboardInterceptorOperation.cs
+++ b/SafeExamBrowser.Client/Operations/KeyboardInterceptorOperation.cs
@@ -7,10 +7,10 @@
*/
using SafeExamBrowser.Contracts.Core.OperationModel;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Contracts.Monitoring;
-using SafeExamBrowser.Contracts.UserInterface;
using SafeExamBrowser.Contracts.WindowsApi;
namespace SafeExamBrowser.Client.Operations
@@ -21,8 +21,9 @@ namespace SafeExamBrowser.Client.Operations
private ILogger logger;
private INativeMethods nativeMethods;
- public IProgressIndicator ProgressIndicator { private get; set; }
-
+ public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
+ public event StatusChangedEventHandler StatusChanged;
+
public KeyboardInterceptorOperation(
IKeyboardInterceptor keyboardInterceptor,
ILogger logger,
@@ -36,7 +37,7 @@ namespace SafeExamBrowser.Client.Operations
public OperationResult Perform()
{
logger.Info("Starting keyboard interception...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StartKeyboardInterception);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_StartKeyboardInterception);
nativeMethods.RegisterKeyboardHook(keyboardInterceptor);
@@ -51,7 +52,7 @@ namespace SafeExamBrowser.Client.Operations
public void Revert()
{
logger.Info("Stopping keyboard interception...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StopKeyboardInterception);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_StopKeyboardInterception);
nativeMethods.DeregisterKeyboardHook(keyboardInterceptor);
}
diff --git a/SafeExamBrowser.Client/Operations/MouseInterceptorOperation.cs b/SafeExamBrowser.Client/Operations/MouseInterceptorOperation.cs
index d47c173a..1692e304 100644
--- a/SafeExamBrowser.Client/Operations/MouseInterceptorOperation.cs
+++ b/SafeExamBrowser.Client/Operations/MouseInterceptorOperation.cs
@@ -7,10 +7,10 @@
*/
using SafeExamBrowser.Contracts.Core.OperationModel;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Contracts.Monitoring;
-using SafeExamBrowser.Contracts.UserInterface;
using SafeExamBrowser.Contracts.WindowsApi;
namespace SafeExamBrowser.Client.Operations
@@ -21,7 +21,8 @@ namespace SafeExamBrowser.Client.Operations
private IMouseInterceptor mouseInterceptor;
private INativeMethods nativeMethods;
- public IProgressIndicator ProgressIndicator { private get; set; }
+ public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
+ public event StatusChangedEventHandler StatusChanged;
public MouseInterceptorOperation(
ILogger logger,
@@ -36,7 +37,7 @@ namespace SafeExamBrowser.Client.Operations
public OperationResult Perform()
{
logger.Info("Starting mouse interception...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StartMouseInterception);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_StartMouseInterception);
nativeMethods.RegisterMouseHook(mouseInterceptor);
@@ -51,7 +52,7 @@ namespace SafeExamBrowser.Client.Operations
public void Revert()
{
logger.Info("Stopping mouse interception...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StopMouseInterception);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_StopMouseInterception);
nativeMethods.DeregisterMouseHook(mouseInterceptor);
}
diff --git a/SafeExamBrowser.Client/Operations/ProcessMonitorOperation.cs b/SafeExamBrowser.Client/Operations/ProcessMonitorOperation.cs
index 92f0f9d1..9d534f83 100644
--- a/SafeExamBrowser.Client/Operations/ProcessMonitorOperation.cs
+++ b/SafeExamBrowser.Client/Operations/ProcessMonitorOperation.cs
@@ -6,12 +6,12 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-using SafeExamBrowser.Contracts.Core.OperationModel;
using SafeExamBrowser.Contracts.Configuration.Settings;
+using SafeExamBrowser.Contracts.Core.OperationModel;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Contracts.Monitoring;
-using SafeExamBrowser.Contracts.UserInterface;
namespace SafeExamBrowser.Client.Operations
{
@@ -21,7 +21,8 @@ namespace SafeExamBrowser.Client.Operations
private IProcessMonitor processMonitor;
private Settings settings;
- public IProgressIndicator ProgressIndicator { private get; set; }
+ public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
+ public event StatusChangedEventHandler StatusChanged;
public ProcessMonitorOperation(ILogger logger, IProcessMonitor processMonitor, Settings settings)
{
@@ -33,7 +34,7 @@ namespace SafeExamBrowser.Client.Operations
public OperationResult Perform()
{
logger.Info("Initializing process monitoring...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeProcessMonitoring);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_InitializeProcessMonitoring);
if (settings.KioskMode == KioskMode.DisableExplorerShell)
{
@@ -51,7 +52,7 @@ namespace SafeExamBrowser.Client.Operations
public void Revert()
{
logger.Info("Stopping process monitoring...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StopProcessMonitoring);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_StopProcessMonitoring);
if (settings.KioskMode == KioskMode.DisableExplorerShell)
{
diff --git a/SafeExamBrowser.Client/Operations/RuntimeConnectionOperation.cs b/SafeExamBrowser.Client/Operations/RuntimeConnectionOperation.cs
index 5d20ac3a..99adb8a6 100644
--- a/SafeExamBrowser.Client/Operations/RuntimeConnectionOperation.cs
+++ b/SafeExamBrowser.Client/Operations/RuntimeConnectionOperation.cs
@@ -7,11 +7,11 @@
*/
using System;
-using SafeExamBrowser.Contracts.Core.OperationModel;
using SafeExamBrowser.Contracts.Communication.Proxies;
+using SafeExamBrowser.Contracts.Core.OperationModel;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
-using SafeExamBrowser.Contracts.UserInterface;
namespace SafeExamBrowser.Client.Operations
{
@@ -22,7 +22,8 @@ namespace SafeExamBrowser.Client.Operations
private IRuntimeProxy runtime;
private Guid token;
- public IProgressIndicator ProgressIndicator { private get; set; }
+ public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
+ public event StatusChangedEventHandler StatusChanged;
public RuntimeConnectionOperation(ILogger logger, IRuntimeProxy runtime, Guid token)
{
@@ -34,7 +35,7 @@ namespace SafeExamBrowser.Client.Operations
public OperationResult Perform()
{
logger.Info("Initializing runtime connection...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeRuntimeConnection);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_InitializeRuntimeConnection);
connected = runtime.Connect(token);
@@ -58,7 +59,7 @@ namespace SafeExamBrowser.Client.Operations
public void Revert()
{
logger.Info("Closing runtime connection...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_CloseRuntimeConnection);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_CloseRuntimeConnection);
if (connected)
{
diff --git a/SafeExamBrowser.Client/Operations/TaskbarOperation.cs b/SafeExamBrowser.Client/Operations/TaskbarOperation.cs
index e5174df4..a3375ada 100644
--- a/SafeExamBrowser.Client/Operations/TaskbarOperation.cs
+++ b/SafeExamBrowser.Client/Operations/TaskbarOperation.cs
@@ -6,10 +6,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-using SafeExamBrowser.Contracts.Core;
-using SafeExamBrowser.Contracts.Core.OperationModel;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Configuration.Settings;
+using SafeExamBrowser.Contracts.Core;
+using SafeExamBrowser.Contracts.Core.OperationModel;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Contracts.SystemComponents;
@@ -32,7 +33,8 @@ namespace SafeExamBrowser.Client.Operations
private IUserInterfaceFactory uiFactory;
private IText text;
- public IProgressIndicator ProgressIndicator { private get; set; }
+ public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
+ public event StatusChangedEventHandler StatusChanged;
public TaskbarOperation(
ILogger logger,
@@ -63,7 +65,7 @@ namespace SafeExamBrowser.Client.Operations
public OperationResult Perform()
{
logger.Info("Initializing taskbar...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeTaskbar);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_InitializeTaskbar);
if (settings.AllowApplicationLog)
{
@@ -96,7 +98,7 @@ namespace SafeExamBrowser.Client.Operations
public void Revert()
{
logger.Info("Terminating taskbar...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_TerminateTaskbar);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_TerminateTaskbar);
if (settings.AllowApplicationLog)
{
diff --git a/SafeExamBrowser.Client/Operations/WindowMonitorOperation.cs b/SafeExamBrowser.Client/Operations/WindowMonitorOperation.cs
index 0cdcc4fa..3308a9d0 100644
--- a/SafeExamBrowser.Client/Operations/WindowMonitorOperation.cs
+++ b/SafeExamBrowser.Client/Operations/WindowMonitorOperation.cs
@@ -8,10 +8,10 @@
using SafeExamBrowser.Contracts.Configuration.Settings;
using SafeExamBrowser.Contracts.Core.OperationModel;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Contracts.Monitoring;
-using SafeExamBrowser.Contracts.UserInterface;
namespace SafeExamBrowser.Client.Operations
{
@@ -21,7 +21,8 @@ namespace SafeExamBrowser.Client.Operations
private ILogger logger;
private IWindowMonitor windowMonitor;
- public IProgressIndicator ProgressIndicator { private get; set; }
+ public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
+ public event StatusChangedEventHandler StatusChanged;
public WindowMonitorOperation(KioskMode kioskMode, ILogger logger, IWindowMonitor windowMonitor)
{
@@ -33,7 +34,7 @@ namespace SafeExamBrowser.Client.Operations
public OperationResult Perform()
{
logger.Info("Initializing window monitoring...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeWindowMonitoring);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_InitializeWindowMonitoring);
if (kioskMode == KioskMode.DisableExplorerShell)
{
@@ -56,7 +57,7 @@ namespace SafeExamBrowser.Client.Operations
public void Revert()
{
logger.Info("Stopping window monitoring...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StopWindowMonitoring);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_StopWindowMonitoring);
if (kioskMode != KioskMode.None)
{
diff --git a/SafeExamBrowser.Configuration/ConfigurationRepository.cs b/SafeExamBrowser.Configuration/ConfigurationRepository.cs
index 280068db..af18ef18 100644
--- a/SafeExamBrowser.Configuration/ConfigurationRepository.cs
+++ b/SafeExamBrowser.Configuration/ConfigurationRepository.cs
@@ -88,7 +88,7 @@ namespace SafeExamBrowser.Configuration
CurrentSettings = new Settings();
- CurrentSettings.KioskMode = KioskMode.CreateNewDesktop;
+ CurrentSettings.KioskMode = KioskMode.None;
CurrentSettings.ServicePolicy = ServicePolicy.Optional;
CurrentSettings.Browser.StartUrl = "https://www.safeexambrowser.org/testing";
diff --git a/SafeExamBrowser.Contracts/Core/OperationModel/Events/ActionRequiredEventArgs.cs b/SafeExamBrowser.Contracts/Core/OperationModel/Events/ActionRequiredEventArgs.cs
new file mode 100644
index 00000000..729d1c41
--- /dev/null
+++ b/SafeExamBrowser.Contracts/Core/OperationModel/Events/ActionRequiredEventArgs.cs
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2018 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.Contracts.Core.OperationModel.Events
+{
+ ///
+ /// Base class for all event arguments used for .
+ ///
+ public class ActionRequiredEventArgs
+ {
+ }
+}
diff --git a/SafeExamBrowser.Contracts/Core/OperationModel/Events/ActionRequiredEventHandler.cs b/SafeExamBrowser.Contracts/Core/OperationModel/Events/ActionRequiredEventHandler.cs
new file mode 100644
index 00000000..e25ab622
--- /dev/null
+++ b/SafeExamBrowser.Contracts/Core/OperationModel/Events/ActionRequiredEventHandler.cs
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2018 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.Contracts.Core.OperationModel.Events
+{
+ ///
+ /// Event handler used to indicate that an requires user interaction.
+ ///
+ public delegate void ActionRequiredEventHandler(ActionRequiredEventArgs args);
+}
diff --git a/SafeExamBrowser.Contracts/Core/OperationModel/Events/ProgressChangedEventArgs.cs b/SafeExamBrowser.Contracts/Core/OperationModel/Events/ProgressChangedEventArgs.cs
new file mode 100644
index 00000000..a0f661fa
--- /dev/null
+++ b/SafeExamBrowser.Contracts/Core/OperationModel/Events/ProgressChangedEventArgs.cs
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2018 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.Contracts.Core.OperationModel.Events
+{
+ ///
+ /// The event arguments used for .
+ ///
+ public class ProgressChangedEventArgs
+ {
+ ///
+ /// Specifies the current progress value, if set.
+ ///
+ public int? CurrentValue { get; set; }
+
+ ///
+ /// Indicates that the progress value is indeterminate, if set.
+ ///
+ public bool? IsIndeterminate { get; set; }
+
+ ///
+ /// Sets the maximum progress value, if set.
+ ///
+ public int? MaxValue { get; set; }
+
+ ///
+ /// Indicates that the current progress value has increased by 1, if set.
+ ///
+ public bool? Progress { get; set; }
+
+ ///
+ /// Indicates that the current progress value has decreased by 1, if set.
+ ///
+ public bool? Regress { get; set; }
+ }
+}
diff --git a/SafeExamBrowser.Contracts/Core/OperationModel/Events/ProgressChangedEventHandler.cs b/SafeExamBrowser.Contracts/Core/OperationModel/Events/ProgressChangedEventHandler.cs
new file mode 100644
index 00000000..0832c0c4
--- /dev/null
+++ b/SafeExamBrowser.Contracts/Core/OperationModel/Events/ProgressChangedEventHandler.cs
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2018 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.Contracts.Core.OperationModel.Events
+{
+ ///
+ /// Event handler used to indicate that the progress of an has changed.
+ ///
+ public delegate void ProgressChangedEventHandler(ProgressChangedEventArgs args);
+}
diff --git a/SafeExamBrowser.Contracts/Core/OperationModel/Events/StatusChangedEventHandler.cs b/SafeExamBrowser.Contracts/Core/OperationModel/Events/StatusChangedEventHandler.cs
new file mode 100644
index 00000000..7075d994
--- /dev/null
+++ b/SafeExamBrowser.Contracts/Core/OperationModel/Events/StatusChangedEventHandler.cs
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2018 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.Contracts.I18n;
+
+namespace SafeExamBrowser.Contracts.Core.OperationModel.Events
+{
+ ///
+ /// Event handler used to indicate that the status of an has changed.
+ ///
+ public delegate void StatusChangedEventHandler(TextKey status);
+}
diff --git a/SafeExamBrowser.Contracts/Core/OperationModel/IOperation.cs b/SafeExamBrowser.Contracts/Core/OperationModel/IOperation.cs
index f6070470..dad3186c 100644
--- a/SafeExamBrowser.Contracts/Core/OperationModel/IOperation.cs
+++ b/SafeExamBrowser.Contracts/Core/OperationModel/IOperation.cs
@@ -6,7 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-using SafeExamBrowser.Contracts.UserInterface;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
namespace SafeExamBrowser.Contracts.Core.OperationModel
{
@@ -16,9 +16,14 @@ namespace SafeExamBrowser.Contracts.Core.OperationModel
public interface IOperation
{
///
- /// The progress indicator to be used to show status information to the user. Will be ignored if null.
+ /// Event fired when the operation requires user interaction.
///
- IProgressIndicator ProgressIndicator { set; }
+ event ActionRequiredEventHandler ActionRequired;
+
+ ///
+ /// Event fired when the status of the operation has changed.
+ ///
+ event StatusChangedEventHandler StatusChanged;
///
/// Performs the operation.
diff --git a/SafeExamBrowser.Contracts/Core/OperationModel/IOperationSequence.cs b/SafeExamBrowser.Contracts/Core/OperationModel/IOperationSequence.cs
index 8a450f74..a1202c47 100644
--- a/SafeExamBrowser.Contracts/Core/OperationModel/IOperationSequence.cs
+++ b/SafeExamBrowser.Contracts/Core/OperationModel/IOperationSequence.cs
@@ -6,7 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-using SafeExamBrowser.Contracts.UserInterface;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
namespace SafeExamBrowser.Contracts.Core.OperationModel
{
@@ -24,9 +24,19 @@ namespace SafeExamBrowser.Contracts.Core.OperationModel
public interface IOperationSequence
{
///
- /// The progress indicator to be used when executing an operation. Will be ignored if null.
+ /// Event fired when an operation requires user interaction.
///
- IProgressIndicator ProgressIndicator { set; }
+ event ActionRequiredEventHandler ActionRequired;
+
+ ///
+ /// Event fired when the progress of the sequence has changed.
+ ///
+ event ProgressChangedEventHandler ProgressChanged;
+
+ ///
+ /// Event fired when the status of an operation has changed.
+ ///
+ event StatusChangedEventHandler StatusChanged;
///
/// Tries to perform the operations of this sequence according to their initialized order. If any operation fails, the already
diff --git a/SafeExamBrowser.Contracts/I18n/TextKey.cs b/SafeExamBrowser.Contracts/I18n/TextKey.cs
index dd9dce29..4ea88db8 100644
--- a/SafeExamBrowser.Contracts/I18n/TextKey.cs
+++ b/SafeExamBrowser.Contracts/I18n/TextKey.cs
@@ -50,6 +50,7 @@ namespace SafeExamBrowser.Contracts.I18n
PasswordDialog_Confirm,
PasswordDialog_SettingsPasswordRequired,
PasswordDialog_SettingsPasswordRequiredTitle,
+ // TODO: Rename these...
ProgressIndicator_CloseRuntimeConnection,
ProgressIndicator_EmptyClipboard,
ProgressIndicator_FinalizeServiceSession,
diff --git a/SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj b/SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj
index d776f3c4..2103c185 100644
--- a/SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj
+++ b/SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj
@@ -57,6 +57,11 @@
+
+
+
+
+
diff --git a/SafeExamBrowser.Contracts/UserInterface/IProgressIndicator.cs b/SafeExamBrowser.Contracts/UserInterface/IProgressIndicator.cs
index 4408e32d..fb2a0705 100644
--- a/SafeExamBrowser.Contracts/UserInterface/IProgressIndicator.cs
+++ b/SafeExamBrowser.Contracts/UserInterface/IProgressIndicator.cs
@@ -16,14 +16,14 @@ namespace SafeExamBrowser.Contracts.UserInterface
public interface IProgressIndicator
{
///
- /// Updates the progress value according to the specified amount.
+ /// Increases the current progress value by 1.
///
- void Progress(int amount = 1);
+ void Progress();
///
- /// Regresses the progress value according to the specified amount.
+ /// Decreases the current progress value by 1.
///
- void Regress(int amount = 1);
+ void Regress();
///
/// Sets the style of the progress indicator to indeterminate (Progress and Regress won't have any effect when called).
@@ -42,6 +42,7 @@ namespace SafeExamBrowser.Contracts.UserInterface
///
/// Updates the status text. If the busy flag is set, an animation will be shown to indicate a long-running operation.
+ /// TODO: Automatically show busy indication in implementations after e.g. 2 seconds!
///
void UpdateText(TextKey key, bool showBusyIndication = false);
}
diff --git a/SafeExamBrowser.Contracts/UserInterface/MessageBox/IMessageBox.cs b/SafeExamBrowser.Contracts/UserInterface/MessageBox/IMessageBox.cs
index 6103b19a..bb3d7f9a 100644
--- a/SafeExamBrowser.Contracts/UserInterface/MessageBox/IMessageBox.cs
+++ b/SafeExamBrowser.Contracts/UserInterface/MessageBox/IMessageBox.cs
@@ -7,6 +7,7 @@
*/
using SafeExamBrowser.Contracts.I18n;
+using SafeExamBrowser.Contracts.UserInterface.Windows;
namespace SafeExamBrowser.Contracts.UserInterface.MessageBox
{
@@ -18,11 +19,11 @@ namespace SafeExamBrowser.Contracts.UserInterface.MessageBox
///
/// Shows a message box according to the specified parameters and returns the result chosen by the user.
///
- MessageBoxResult Show(string message, string title, MessageBoxAction action = MessageBoxAction.Confirm, MessageBoxIcon icon = MessageBoxIcon.Information);
+ MessageBoxResult Show(string message, string title, MessageBoxAction action = MessageBoxAction.Confirm, MessageBoxIcon icon = MessageBoxIcon.Information, IWindow parent = null);
///
/// Shows a message box according to the specified parameters and returns the result chosen by the user.
///
- MessageBoxResult Show(TextKey message, TextKey title, MessageBoxAction action = MessageBoxAction.Confirm, MessageBoxIcon icon = MessageBoxIcon.Information);
+ MessageBoxResult Show(TextKey message, TextKey title, MessageBoxAction action = MessageBoxAction.Confirm, MessageBoxIcon icon = MessageBoxIcon.Information, IWindow parent = null);
}
}
diff --git a/SafeExamBrowser.Core.UnitTests/OperationModel/OperationSequenceTests.cs b/SafeExamBrowser.Core.UnitTests/OperationModel/OperationSequenceTests.cs
index d078e1c1..ab2cee5a 100644
--- a/SafeExamBrowser.Core.UnitTests/OperationModel/OperationSequenceTests.cs
+++ b/SafeExamBrowser.Core.UnitTests/OperationModel/OperationSequenceTests.cs
@@ -12,7 +12,6 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using SafeExamBrowser.Contracts.Core.OperationModel;
using SafeExamBrowser.Contracts.Logging;
-using SafeExamBrowser.Contracts.UserInterface;
using SafeExamBrowser.Core.OperationModel;
namespace SafeExamBrowser.Core.UnitTests.OperationModel
@@ -251,10 +250,8 @@ namespace SafeExamBrowser.Core.UnitTests.OperationModel
public void MustNotFailInCaseOfUnexpectedError()
{
var sut = new OperationSequence(loggerMock.Object, new Queue());
- var indicatorMock = new Mock();
- indicatorMock.Setup(i => i.SetMaxValue(It.IsAny())).Throws();
- sut.ProgressIndicator = indicatorMock.Object;
+ sut.ProgressChanged += (args) => throw new Exception();
var result = sut.TryPerform();
@@ -406,10 +403,8 @@ namespace SafeExamBrowser.Core.UnitTests.OperationModel
public void MustNotFailInCaseOfUnexpectedErrorWhenRepeating()
{
var sut = new OperationSequence(loggerMock.Object, new Queue());
- var indicatorMock = new Mock();
- indicatorMock.Setup(i => i.SetMaxValue(It.IsAny())).Throws();
- sut.ProgressIndicator = indicatorMock.Object;
+ sut.ProgressChanged += (args) => throw new Exception();
var result = sut.TryRepeat();
@@ -570,10 +565,8 @@ namespace SafeExamBrowser.Core.UnitTests.OperationModel
public void MustNotFailInCaseOfUnexpectedErrorWhenReverting()
{
var sut = new OperationSequence(loggerMock.Object, new Queue());
- var indicatorMock = new Mock();
- indicatorMock.Setup(i => i.SetIndeterminate()).Throws();
- sut.ProgressIndicator = indicatorMock.Object;
+ sut.ProgressChanged += (args) => throw new Exception();
var success = sut.TryRevert();
diff --git a/SafeExamBrowser.Core.UnitTests/OperationModel/QueueExtensionTests.cs b/SafeExamBrowser.Core.UnitTests/OperationModel/QueueExtensionTests.cs
new file mode 100644
index 00000000..67ca5548
--- /dev/null
+++ b/SafeExamBrowser.Core.UnitTests/OperationModel/QueueExtensionTests.cs
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018 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 System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using SafeExamBrowser.Core.OperationModel;
+
+namespace SafeExamBrowser.Core.UnitTests.OperationModel
+{
+ [TestClass]
+ public class QueueExtensionTests
+ {
+ [TestMethod]
+ public void MustCorrectlyIterateThroughQueue()
+ {
+ var order = 0;
+ var queue = new Queue(Enumerable.Range(1, 25));
+ var action = new Action(i =>
+ {
+ Assert.AreEqual(i, ++order);
+ Assert.AreEqual(queue.ElementAt(i - 1), i);
+ });
+
+ queue.ForEach(action);
+
+ Assert.AreEqual(queue.Count, order);
+ }
+ }
+}
diff --git a/SafeExamBrowser.Core.UnitTests/Operations/LazyInitializationOperationTests.cs b/SafeExamBrowser.Core.UnitTests/Operations/LazyInitializationOperationTests.cs
index 39419e62..18d643e5 100644
--- a/SafeExamBrowser.Core.UnitTests/Operations/LazyInitializationOperationTests.cs
+++ b/SafeExamBrowser.Core.UnitTests/Operations/LazyInitializationOperationTests.cs
@@ -10,7 +10,8 @@ using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using SafeExamBrowser.Contracts.Core.OperationModel;
-using SafeExamBrowser.Contracts.UserInterface;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
+using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Core.Operations;
namespace SafeExamBrowser.Core.UnitTests.Operations
@@ -94,23 +95,47 @@ namespace SafeExamBrowser.Core.UnitTests.Operations
}
[TestMethod]
- public void MustUpdateProgressIndicator()
+ public void MustCorrectlyHandleEventSubscription()
{
IOperation initialize()
{
return operationMock.Object;
};
- var sut = new LazyInitializationOperation(initialize)
- {
- ProgressIndicator = new Mock().Object
- };
+ var actionRequired = 0;
+ var actionRequiredHandler = new ActionRequiredEventHandler(args => actionRequired++);
+ var statusChanged = 0;
+ var statusChangedHandler = new StatusChangedEventHandler(t => statusChanged++);
+ var sut = new LazyInitializationOperation(initialize);
+
+ sut.ActionRequired += actionRequiredHandler;
+ sut.StatusChanged += statusChangedHandler;
sut.Perform();
- sut.Repeat();
- sut.Revert();
- operationMock.VerifySet(o => o.ProgressIndicator = It.IsAny(), Times.Exactly(3));
+ operationMock.Raise(o => o.ActionRequired += null, new ActionRequiredEventArgs());
+ operationMock.Raise(o => o.StatusChanged += null, default(TextKey));
+
+ Assert.AreEqual(1, actionRequired);
+ Assert.AreEqual(1, statusChanged);
+
+ sut.ActionRequired -= actionRequiredHandler;
+ sut.StatusChanged -= statusChangedHandler;
+
+ operationMock.Raise(o => o.ActionRequired += null, new ActionRequiredEventArgs());
+ operationMock.Raise(o => o.StatusChanged += null, default(TextKey));
+
+ Assert.AreEqual(1, actionRequired);
+ Assert.AreEqual(1, statusChanged);
+
+ sut.ActionRequired += actionRequiredHandler;
+ sut.StatusChanged += statusChangedHandler;
+
+ operationMock.Raise(o => o.ActionRequired += null, new ActionRequiredEventArgs());
+ operationMock.Raise(o => o.StatusChanged += null, default(TextKey));
+
+ Assert.AreEqual(2, actionRequired);
+ Assert.AreEqual(2, statusChanged);
}
[TestMethod]
diff --git a/SafeExamBrowser.Core.UnitTests/SafeExamBrowser.Core.UnitTests.csproj b/SafeExamBrowser.Core.UnitTests/SafeExamBrowser.Core.UnitTests.csproj
index 9df2ddfc..d79a245b 100644
--- a/SafeExamBrowser.Core.UnitTests/SafeExamBrowser.Core.UnitTests.csproj
+++ b/SafeExamBrowser.Core.UnitTests/SafeExamBrowser.Core.UnitTests.csproj
@@ -78,6 +78,7 @@
+
diff --git a/SafeExamBrowser.Core/OperationModel/OperationSequence.cs b/SafeExamBrowser.Core/OperationModel/OperationSequence.cs
index 6530f72f..c7511d08 100644
--- a/SafeExamBrowser.Core/OperationModel/OperationSequence.cs
+++ b/SafeExamBrowser.Core/OperationModel/OperationSequence.cs
@@ -10,8 +10,8 @@ using System;
using System.Collections.Generic;
using System.Linq;
using SafeExamBrowser.Contracts.Core.OperationModel;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
using SafeExamBrowser.Contracts.Logging;
-using SafeExamBrowser.Contracts.UserInterface;
namespace SafeExamBrowser.Core.OperationModel
{
@@ -24,7 +24,19 @@ namespace SafeExamBrowser.Core.OperationModel
private Queue operations = new Queue();
private Stack stack = new Stack();
- public IProgressIndicator ProgressIndicator { private get; set; }
+ public event ActionRequiredEventHandler ActionRequired
+ {
+ add { operations.ForEach(o => o.ActionRequired += value); }
+ remove { operations.ForEach(o => o.ActionRequired -= value); }
+ }
+
+ public event ProgressChangedEventHandler ProgressChanged;
+
+ public event StatusChangedEventHandler StatusChanged
+ {
+ add { operations.ForEach(o => o.StatusChanged += value); }
+ remove { operations.ForEach(o => o.StatusChanged -= value); }
+ }
public OperationSequence(ILogger logger, Queue operations)
{
@@ -92,12 +104,11 @@ namespace SafeExamBrowser.Core.OperationModel
{
if (indeterminate)
{
- ProgressIndicator?.SetIndeterminate();
+ ProgressChanged?.Invoke(new ProgressChangedEventArgs { IsIndeterminate = true });
}
else
{
- ProgressIndicator?.SetValue(0);
- ProgressIndicator?.SetMaxValue(operations.Count);
+ ProgressChanged?.Invoke(new ProgressChangedEventArgs { CurrentValue = 0, MaxValue = operations.Count });
}
}
@@ -111,7 +122,6 @@ namespace SafeExamBrowser.Core.OperationModel
try
{
- operation.ProgressIndicator = ProgressIndicator;
result = operation.Perform();
}
catch (Exception e)
@@ -124,7 +134,7 @@ namespace SafeExamBrowser.Core.OperationModel
return result;
}
- ProgressIndicator?.Progress();
+ ProgressChanged?.Invoke(new ProgressChangedEventArgs { Progress = true });
}
return OperationResult.Success;
@@ -138,7 +148,6 @@ namespace SafeExamBrowser.Core.OperationModel
try
{
- operation.ProgressIndicator = ProgressIndicator;
result = operation.Repeat();
}
catch (Exception e)
@@ -151,7 +160,7 @@ namespace SafeExamBrowser.Core.OperationModel
return result;
}
- ProgressIndicator?.Progress();
+ ProgressChanged?.Invoke(new ProgressChangedEventArgs { Progress = true });
}
return OperationResult.Success;
@@ -167,7 +176,6 @@ namespace SafeExamBrowser.Core.OperationModel
try
{
- operation.ProgressIndicator = ProgressIndicator;
operation.Revert();
}
catch (Exception e)
@@ -178,7 +186,7 @@ namespace SafeExamBrowser.Core.OperationModel
if (regress)
{
- ProgressIndicator?.Regress();
+ ProgressChanged?.Invoke(new ProgressChangedEventArgs { Regress = true });
}
}
diff --git a/SafeExamBrowser.Core/OperationModel/QueueExtensions.cs b/SafeExamBrowser.Core/OperationModel/QueueExtensions.cs
new file mode 100644
index 00000000..f94c2bf4
--- /dev/null
+++ b/SafeExamBrowser.Core/OperationModel/QueueExtensions.cs
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018 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 System;
+using System.Collections.Generic;
+
+namespace SafeExamBrowser.Core.OperationModel
+{
+ internal static class QueueExtensions
+ {
+ internal static void ForEach(this Queue queue, Action action)
+ {
+ foreach (var element in queue)
+ {
+ action(element);
+ }
+ }
+ }
+}
diff --git a/SafeExamBrowser.Core/Operations/CommunicationHostOperation.cs b/SafeExamBrowser.Core/Operations/CommunicationHostOperation.cs
index 1b15466e..81f49400 100644
--- a/SafeExamBrowser.Core/Operations/CommunicationHostOperation.cs
+++ b/SafeExamBrowser.Core/Operations/CommunicationHostOperation.cs
@@ -8,9 +8,9 @@
using SafeExamBrowser.Contracts.Communication;
using SafeExamBrowser.Contracts.Core.OperationModel;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
-using SafeExamBrowser.Contracts.UserInterface;
namespace SafeExamBrowser.Core.Operations
{
@@ -23,7 +23,8 @@ namespace SafeExamBrowser.Core.Operations
private ICommunicationHost host;
private ILogger logger;
- public IProgressIndicator ProgressIndicator { private get; set; }
+ public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
+ public event StatusChangedEventHandler StatusChanged;
public CommunicationHostOperation(ICommunicationHost host, ILogger logger)
{
@@ -34,7 +35,7 @@ namespace SafeExamBrowser.Core.Operations
public OperationResult Perform()
{
logger.Info("Starting communication host...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StartCommunicationHost);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_StartCommunicationHost);
host.Start();
@@ -46,7 +47,7 @@ namespace SafeExamBrowser.Core.Operations
if (!host.IsRunning)
{
logger.Info("Restarting communication host...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_RestartCommunicationHost);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_RestartCommunicationHost);
host.Stop();
host.Start();
@@ -58,7 +59,7 @@ namespace SafeExamBrowser.Core.Operations
public void Revert()
{
logger.Info("Stopping communication host...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StopCommunicationHost);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_StopCommunicationHost);
host.Stop();
}
diff --git a/SafeExamBrowser.Core/Operations/DelegateOperation.cs b/SafeExamBrowser.Core/Operations/DelegateOperation.cs
index d1193dee..b77ff039 100644
--- a/SafeExamBrowser.Core/Operations/DelegateOperation.cs
+++ b/SafeExamBrowser.Core/Operations/DelegateOperation.cs
@@ -8,7 +8,7 @@
using System;
using SafeExamBrowser.Contracts.Core.OperationModel;
-using SafeExamBrowser.Contracts.UserInterface;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
namespace SafeExamBrowser.Core.Operations
{
@@ -22,7 +22,8 @@ namespace SafeExamBrowser.Core.Operations
private Action repeat;
private Action revert;
- public IProgressIndicator ProgressIndicator { private get; set; }
+ public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
+ public event StatusChangedEventHandler StatusChanged { add { } remove { } }
public DelegateOperation(Action perform, Action repeat = null, Action revert = null)
{
diff --git a/SafeExamBrowser.Core/Operations/I18nOperation.cs b/SafeExamBrowser.Core/Operations/I18nOperation.cs
index 25454d10..544f3d1a 100644
--- a/SafeExamBrowser.Core/Operations/I18nOperation.cs
+++ b/SafeExamBrowser.Core/Operations/I18nOperation.cs
@@ -8,9 +8,9 @@
using System.Globalization;
using SafeExamBrowser.Contracts.Core.OperationModel;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
-using SafeExamBrowser.Contracts.UserInterface;
namespace SafeExamBrowser.Core.Operations
{
@@ -23,7 +23,8 @@ namespace SafeExamBrowser.Core.Operations
private IText text;
private ITextResource textResource;
- public IProgressIndicator ProgressIndicator { private get; set; }
+ public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
+ public event StatusChangedEventHandler StatusChanged { add { } remove { } }
public I18nOperation(ILogger logger, IText text, ITextResource textResource)
{
diff --git a/SafeExamBrowser.Core/Operations/LazyInitializationOperation.cs b/SafeExamBrowser.Core/Operations/LazyInitializationOperation.cs
index 1c3a791f..949b11b2 100644
--- a/SafeExamBrowser.Core/Operations/LazyInitializationOperation.cs
+++ b/SafeExamBrowser.Core/Operations/LazyInitializationOperation.cs
@@ -8,7 +8,7 @@
using System;
using SafeExamBrowser.Contracts.Core.OperationModel;
-using SafeExamBrowser.Contracts.UserInterface;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
namespace SafeExamBrowser.Core.Operations
{
@@ -22,7 +22,52 @@ namespace SafeExamBrowser.Core.Operations
private Func initialize;
private IOperation operation;
- public IProgressIndicator ProgressIndicator { get; set; }
+ private event ActionRequiredEventHandler ActionRequiredImpl;
+ private event StatusChangedEventHandler StatusChangedImpl;
+
+ public event ActionRequiredEventHandler ActionRequired
+ {
+ add
+ {
+ ActionRequiredImpl += value;
+
+ if (operation != null)
+ {
+ operation.ActionRequired += value;
+ }
+ }
+ remove
+ {
+ ActionRequiredImpl -= value;
+
+ if (operation != null)
+ {
+ operation.ActionRequired -= value;
+ }
+ }
+ }
+
+ public event StatusChangedEventHandler StatusChanged
+ {
+ add
+ {
+ StatusChangedImpl += value;
+
+ if (operation != null)
+ {
+ operation.StatusChanged += value;
+ }
+ }
+ remove
+ {
+ StatusChangedImpl -= value;
+
+ if (operation != null)
+ {
+ operation.StatusChanged -= value;
+ }
+ }
+ }
public LazyInitializationOperation(Func initialize)
{
@@ -32,21 +77,19 @@ namespace SafeExamBrowser.Core.Operations
public OperationResult Perform()
{
operation = initialize.Invoke();
- operation.ProgressIndicator = ProgressIndicator;
+ operation.ActionRequired += ActionRequiredImpl;
+ operation.StatusChanged += StatusChangedImpl;
return operation.Perform();
}
public OperationResult Repeat()
{
- operation.ProgressIndicator = ProgressIndicator;
-
return operation.Repeat();
}
public void Revert()
{
- operation.ProgressIndicator = ProgressIndicator;
operation.Revert();
}
}
diff --git a/SafeExamBrowser.Core/Properties/AssemblyInfo.cs b/SafeExamBrowser.Core/Properties/AssemblyInfo.cs
index 399a8176..8a2e7eed 100644
--- a/SafeExamBrowser.Core/Properties/AssemblyInfo.cs
+++ b/SafeExamBrowser.Core/Properties/AssemblyInfo.cs
@@ -1,4 +1,5 @@
using System.Reflection;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
@@ -14,6 +15,7 @@ using System.Runtime.InteropServices;
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
+[assembly: InternalsVisibleTo("SafeExamBrowser.Core.UnitTests")]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("3d6fdbb6-a4af-4626-bb2b-bf329d44f9cc")]
diff --git a/SafeExamBrowser.Core/SafeExamBrowser.Core.csproj b/SafeExamBrowser.Core/SafeExamBrowser.Core.csproj
index d5f36572..d5e2dcc1 100644
--- a/SafeExamBrowser.Core/SafeExamBrowser.Core.csproj
+++ b/SafeExamBrowser.Core/SafeExamBrowser.Core.csproj
@@ -54,6 +54,7 @@
+
diff --git a/SafeExamBrowser.Runtime.UnitTests/Operations/ConfigurationOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Operations/ConfigurationOperationTests.cs
index ca599c05..20e45362 100644
--- a/SafeExamBrowser.Runtime.UnitTests/Operations/ConfigurationOperationTests.cs
+++ b/SafeExamBrowser.Runtime.UnitTests/Operations/ConfigurationOperationTests.cs
@@ -11,18 +11,13 @@ using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using SafeExamBrowser.Contracts.Communication.Data;
-using SafeExamBrowser.Contracts.Communication.Events;
-using SafeExamBrowser.Contracts.Communication.Hosts;
using SafeExamBrowser.Contracts.Communication.Proxies;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Configuration.Settings;
using SafeExamBrowser.Contracts.Core.OperationModel;
-using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
-using SafeExamBrowser.Contracts.UserInterface;
-using SafeExamBrowser.Contracts.UserInterface.MessageBox;
-using SafeExamBrowser.Contracts.UserInterface.Windows;
using SafeExamBrowser.Runtime.Operations;
+using SafeExamBrowser.Runtime.Operations.Events;
namespace SafeExamBrowser.Runtime.UnitTests.Operations
{
@@ -31,14 +26,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
{
private AppConfig appConfig;
private Mock logger;
- private Mock messageBox;
- private Mock passwordDialog;
private Mock repository;
private Mock resourceLoader;
- private Mock runtimeHost;
private Settings settings;
- private Mock text;
- private Mock uiFactory;
private ConfigurationOperation sut;
[TestInitialize]
@@ -46,22 +36,15 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
{
appConfig = new AppConfig();
logger = new Mock();
- messageBox = new Mock();
- passwordDialog = new Mock();
repository = new Mock();
resourceLoader = new Mock();
- runtimeHost = new Mock();
settings = new Settings();
- text = new Mock();
- uiFactory = new Mock();
appConfig.AppDataFolder = @"C:\Not\Really\AppData";
appConfig.DefaultSettingsFileName = "SettingsDummy.txt";
appConfig.ProgramDataFolder = @"C:\Not\Really\ProgramData";
repository.SetupGet(r => r.CurrentSettings).Returns(settings);
-
- uiFactory.Setup(f => f.CreatePasswordDialog(It.IsAny(), It.IsAny())).Returns(passwordDialog.Object);
}
[TestMethod]
@@ -75,7 +58,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.Success);
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, new[] { "blubb.exe", url });
+ sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url });
sut.Perform();
var resource = new Uri(url);
@@ -93,7 +76,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.Success);
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, null);
+ sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, null);
sut.Perform();
var resource = new Uri(Path.Combine(location, "SettingsDummy.txt"));
@@ -110,7 +93,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.Success);
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, null);
+ sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, null);
sut.Perform();
var resource = new Uri(Path.Combine(location, "SettingsDummy.txt"));
@@ -121,7 +104,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
[TestMethod]
public void MustFallbackToDefaultsAsLastPrio()
{
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, null);
+ sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, null);
sut.Perform();
repository.Verify(r => r.LoadDefaultSettings(), Times.Once);
@@ -131,10 +114,16 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
public void MustAbortIfWishedByUser()
{
appConfig.ProgramDataFolder = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations));
- messageBox.Setup(m => m.Show(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(MessageBoxResult.Yes);
repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.Success);
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, null);
+ sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, null);
+ sut.ActionRequired += args =>
+ {
+ if (args is ConfigurationCompletedEventArgs c)
+ {
+ c.AbortStartup = true;
+ }
+ };
var result = sut.Perform();
@@ -144,10 +133,16 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
[TestMethod]
public void MustNotAbortIfNotWishedByUser()
{
- messageBox.Setup(m => m.Show(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(MessageBoxResult.No);
repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.Success);
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, null);
+ sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, null);
+ sut.ActionRequired += args =>
+ {
+ if (args is ConfigurationCompletedEventArgs c)
+ {
+ c.AbortStartup = false;
+ }
+ };
var result = sut.Perform();
@@ -160,10 +155,16 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
settings.ConfigurationMode = ConfigurationMode.Exam;
repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.Success);
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, null);
- sut.Perform();
+ sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, null);
+ sut.ActionRequired += args =>
+ {
+ if (args is ConfigurationCompletedEventArgs c)
+ {
+ Assert.Fail();
+ }
+ };
- messageBox.Verify(m => m.Show(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Never);
+ sut.Perform();
}
[TestMethod]
@@ -171,10 +172,10 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
{
repository.Setup(r => r.LoadDefaultSettings());
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, null);
+ sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, null);
sut.Perform();
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, new string[] { });
+ sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new string[] { });
sut.Perform();
repository.Verify(r => r.LoadDefaultSettings(), Times.Exactly(2));
@@ -185,20 +186,26 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
{
var uri = @"an/invalid\uri.'*%yolo/()你好";
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, new[] { "blubb.exe", uri });
+ sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", uri });
sut.Perform();
}
[TestMethod]
public void MustOnlyAllowToEnterAdminPasswordFiveTimes()
{
- var result = new PasswordDialogResultStub { Success = true };
var url = @"http://www.safeexambrowser.org/whatever.seb";
- passwordDialog.Setup(d => d.Show(null)).Returns(result);
repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.AdminPasswordNeeded);
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, new[] { "blubb.exe", url });
+ sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url });
+ sut.ActionRequired += args =>
+ {
+ if (args is PasswordRequiredEventArgs p)
+ {
+ p.Success = true;
+ }
+ };
+
sut.Perform();
repository.Verify(r => r.LoadSettings(It.IsAny(), null, null), Times.Exactly(5));
@@ -207,13 +214,19 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
[TestMethod]
public void MustOnlyAllowToEnterSettingsPasswordFiveTimes()
{
- var result = new PasswordDialogResultStub { Success = true };
var url = @"http://www.safeexambrowser.org/whatever.seb";
- passwordDialog.Setup(d => d.Show(null)).Returns(result);
repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.SettingsPasswordNeeded);
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, new[] { "blubb.exe", url });
+ sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url });
+ sut.ActionRequired += args =>
+ {
+ if (args is PasswordRequiredEventArgs p)
+ {
+ p.Success = true;
+ }
+ };
+
sut.Perform();
repository.Verify(r => r.LoadSettings(It.IsAny(), null, null), Times.Exactly(5));
@@ -223,14 +236,21 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
public void MustSucceedIfAdminPasswordCorrect()
{
var password = "test";
- var result = new PasswordDialogResultStub { Password = password, Success = true };
var url = @"http://www.safeexambrowser.org/whatever.seb";
- passwordDialog.Setup(d => d.Show(null)).Returns(result);
repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.AdminPasswordNeeded);
repository.Setup(r => r.LoadSettings(It.IsAny(), password, null)).Returns(LoadStatus.Success);
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, new[] { "blubb.exe", url });
+ sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url });
+ sut.ActionRequired += args =>
+ {
+ if (args is PasswordRequiredEventArgs p)
+ {
+ p.Password = password;
+ p.Success = true;
+ }
+ };
+
sut.Perform();
repository.Verify(r => r.LoadSettings(It.IsAny(), null, null), Times.Once);
@@ -241,14 +261,21 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
public void MustSucceedIfSettingsPasswordCorrect()
{
var password = "test";
- var result = new PasswordDialogResultStub { Password = password, Success = true };
var url = @"http://www.safeexambrowser.org/whatever.seb";
- passwordDialog.Setup(d => d.Show(null)).Returns(result);
repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.SettingsPasswordNeeded);
repository.Setup(r => r.LoadSettings(It.IsAny(), null, password)).Returns(LoadStatus.Success);
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, new[] { "blubb.exe", url });
+ sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url });
+ sut.ActionRequired += args =>
+ {
+ if (args is PasswordRequiredEventArgs p)
+ {
+ p.Password = password;
+ p.Success = true;
+ }
+ };
+
sut.Perform();
repository.Verify(r => r.LoadSettings(It.IsAny(), null, null), Times.Once);
@@ -258,13 +285,18 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
[TestMethod]
public void MustAbortAskingForAdminPasswordIfDecidedByUser()
{
- var dialogResult = new PasswordDialogResultStub { Success = false };
var url = @"http://www.safeexambrowser.org/whatever.seb";
- passwordDialog.Setup(d => d.Show(null)).Returns(dialogResult);
repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.AdminPasswordNeeded);
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, new[] { "blubb.exe", url });
+ sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url });
+ sut.ActionRequired += args =>
+ {
+ if (args is PasswordRequiredEventArgs p)
+ {
+ p.Success = false;
+ }
+ };
var result = sut.Perform();
@@ -274,13 +306,18 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
[TestMethod]
public void MustAbortAskingForSettingsPasswordIfDecidedByUser()
{
- var dialogResult = new PasswordDialogResultStub { Success = false };
var url = @"http://www.safeexambrowser.org/whatever.seb";
- passwordDialog.Setup(d => d.Show(null)).Returns(dialogResult);
repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.SettingsPasswordNeeded);
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, new[] { "blubb.exe", url });
+ sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url });
+ sut.ActionRequired += args =>
+ {
+ if (args is PasswordRequiredEventArgs p)
+ {
+ p.Success = false;
+ }
+ };
var result = sut.Perform();
@@ -291,18 +328,23 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
public void MustAllowEnteringBothPasswords()
{
var adminPassword = "xyz";
- var adminResult = new PasswordDialogResultStub { Password = adminPassword, Success = true };
- var adminCallback = new Action(() => passwordDialog.Setup(d => d.Show(null)).Returns(adminResult));
var settingsPassword = "abc";
- var settingsResult = new PasswordDialogResultStub { Password = settingsPassword, Success = true };
- var settingsCallback = new Action(() => passwordDialog.Setup(d => d.Show(null)).Returns(settingsResult));
var url = @"http://www.safeexambrowser.org/whatever.seb";
- repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.SettingsPasswordNeeded).Callback(settingsCallback);
- repository.Setup(r => r.LoadSettings(It.IsAny(), null, settingsPassword)).Returns(LoadStatus.AdminPasswordNeeded).Callback(adminCallback);
+ repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.SettingsPasswordNeeded);
+ repository.Setup(r => r.LoadSettings(It.IsAny(), null, settingsPassword)).Returns(LoadStatus.AdminPasswordNeeded);
repository.Setup(r => r.LoadSettings(It.IsAny(), adminPassword, settingsPassword)).Returns(LoadStatus.Success);
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, new[] { "blubb.exe", url });
+ sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url });
+ sut.ActionRequired += args =>
+ {
+ if (args is PasswordRequiredEventArgs p)
+ {
+ p.Password = p.Purpose == PasswordRequestPurpose.Administrator ? adminPassword : settingsPassword;
+ p.Success = true;
+ }
+ };
+
sut.Perform();
repository.Verify(r => r.LoadSettings(It.IsAny(), null, null), Times.Once);
@@ -310,79 +352,6 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
repository.Verify(r => r.LoadSettings(It.IsAny(), adminPassword, settingsPassword), Times.Once);
}
- [TestMethod]
- public void MustRequestPasswordViaDialogOnDefaultDesktop()
- {
- var clientProxy = new Mock();
- var session = new Mock();
- var url = @"http://www.safeexambrowser.org/whatever.seb";
-
- passwordDialog.Setup(d => d.Show(null)).Returns(new PasswordDialogResultStub { Success = true });
- repository.SetupGet(r => r.CurrentSession).Returns(session.Object);
- repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.SettingsPasswordNeeded);
- session.SetupGet(r => r.ClientProxy).Returns(clientProxy.Object);
- settings.KioskMode = KioskMode.DisableExplorerShell;
-
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, new[] { "blubb.exe", url });
- sut.Perform();
-
- clientProxy.Verify(c => c.RequestPassword(It.IsAny(), It.IsAny()), Times.Never);
- passwordDialog.Verify(p => p.Show(null), Times.AtLeastOnce);
- session.VerifyGet(s => s.ClientProxy, Times.Never);
- }
-
- [TestMethod]
- public void MustRequestPasswordViaClientDuringReconfigurationOnNewDesktop()
- {
- var clientProxy = new Mock();
- var communication = new CommunicationResult(true);
- var passwordReceived = new Action((p, id) =>
- {
- runtimeHost.Raise(r => r.PasswordReceived += null, new PasswordReplyEventArgs { RequestId = id, Success = true });
- });
- var session = new Mock();
- var url = @"http://www.safeexambrowser.org/whatever.seb";
-
- clientProxy.Setup(c => c.RequestPassword(It.IsAny(), It.IsAny())).Returns(communication).Callback(passwordReceived);
- passwordDialog.Setup(d => d.Show(null)).Returns(new PasswordDialogResultStub { Success = true });
- repository.SetupGet(r => r.CurrentSession).Returns(session.Object);
- repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.SettingsPasswordNeeded);
- session.SetupGet(r => r.ClientProxy).Returns(clientProxy.Object);
- settings.KioskMode = KioskMode.CreateNewDesktop;
-
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, new[] { "blubb.exe", url });
- sut.Perform();
-
- clientProxy.Verify(c => c.RequestPassword(It.IsAny(), It.IsAny()), Times.AtLeastOnce);
- passwordDialog.Verify(p => p.Show(null), Times.Never);
- session.VerifyGet(s => s.ClientProxy, Times.AtLeastOnce);
- }
-
- [TestMethod]
- public void MustAbortAskingForPasswordViaClientIfDecidedByUser()
- {
- var clientProxy = new Mock();
- var communication = new CommunicationResult(true);
- var passwordReceived = new Action((p, id) =>
- {
- runtimeHost.Raise(r => r.PasswordReceived += null, new PasswordReplyEventArgs { RequestId = id, Success = false });
- });
- var session = new Mock();
- var url = @"http://www.safeexambrowser.org/whatever.seb";
-
- clientProxy.Setup(c => c.RequestPassword(It.IsAny(), It.IsAny())).Returns(communication).Callback(passwordReceived);
- repository.SetupGet(r => r.CurrentSession).Returns(session.Object);
- repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.SettingsPasswordNeeded);
- session.SetupGet(r => r.ClientProxy).Returns(clientProxy.Object);
- settings.KioskMode = KioskMode.CreateNewDesktop;
-
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, new[] { "blubb.exe", url });
-
- var result = sut.Perform();
-
- Assert.AreEqual(OperationResult.Aborted, result);
- }
-
[TestMethod]
public void MustNotWaitForPasswordViaClientIfCommunicationHasFailed()
{
@@ -397,7 +366,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
session.SetupGet(r => r.ClientProxy).Returns(clientProxy.Object);
settings.KioskMode = KioskMode.CreateNewDesktop;
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, new[] { "blubb.exe", url });
+ sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url });
var result = sut.Perform();
@@ -412,7 +381,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
resourceLoader.Setup(r => r.IsHtmlResource(It.IsAny())).Returns(false);
repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.InvalidData);
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, new[] { "blubb.exe", url });
+ sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url });
var result = sut.Perform();
@@ -427,7 +396,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
resourceLoader.Setup(r => r.IsHtmlResource(It.IsAny())).Returns(true);
repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.InvalidData);
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, new[] { "blubb.exe", url });
+ sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url });
var result = sut.Perform();
@@ -444,7 +413,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
repository.SetupGet(r => r.ReconfigurationFilePath).Returns(resource.AbsolutePath);
repository.Setup(r => r.LoadSettings(It.Is(u => u.Equals(resource)), null, null)).Returns(LoadStatus.Success);
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, null);
+ sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, null);
var result = sut.Repeat();
@@ -461,7 +430,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
repository.SetupGet(r => r.ReconfigurationFilePath).Returns(null as string);
repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.Success);
- sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, null);
+ sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, null);
var result = sut.Repeat();
diff --git a/SafeExamBrowser.Runtime.UnitTests/RuntimeControllerTests.cs b/SafeExamBrowser.Runtime.UnitTests/RuntimeControllerTests.cs
index 4e7e7830..447736d0 100644
--- a/SafeExamBrowser.Runtime.UnitTests/RuntimeControllerTests.cs
+++ b/SafeExamBrowser.Runtime.UnitTests/RuntimeControllerTests.cs
@@ -18,5 +18,78 @@ namespace SafeExamBrowser.Runtime.UnitTests
{
Assert.Fail();
}
+
+ //[TestMethod]
+ //public void MustRequestPasswordViaDialogOnDefaultDesktop()
+ //{
+ // var clientProxy = new Mock();
+ // var session = new Mock();
+ // var url = @"http://www.safeexambrowser.org/whatever.seb";
+
+ // passwordDialog.Setup(d => d.Show(null)).Returns(new PasswordDialogResultStub { Success = true });
+ // repository.SetupGet(r => r.CurrentSession).Returns(session.Object);
+ // repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.SettingsPasswordNeeded);
+ // session.SetupGet(r => r.ClientProxy).Returns(clientProxy.Object);
+ // settings.KioskMode = KioskMode.DisableExplorerShell;
+
+ // sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url });
+ // sut.Perform();
+
+ // clientProxy.Verify(c => c.RequestPassword(It.IsAny(), It.IsAny()), Times.Never);
+ // passwordDialog.Verify(p => p.Show(null), Times.AtLeastOnce);
+ // session.VerifyGet(s => s.ClientProxy, Times.Never);
+ //}
+
+ //[TestMethod]
+ //public void MustRequestPasswordViaClientDuringReconfigurationOnNewDesktop()
+ //{
+ // var clientProxy = new Mock();
+ // var communication = new CommunicationResult(true);
+ // var passwordReceived = new Action((p, id) =>
+ // {
+ // runtimeHost.Raise(r => r.PasswordReceived += null, new PasswordReplyEventArgs { RequestId = id, Success = true });
+ // });
+ // var session = new Mock();
+ // var url = @"http://www.safeexambrowser.org/whatever.seb";
+
+ // clientProxy.Setup(c => c.RequestPassword(It.IsAny(), It.IsAny())).Returns(communication).Callback(passwordReceived);
+ // passwordDialog.Setup(d => d.Show(null)).Returns(new PasswordDialogResultStub { Success = true });
+ // repository.SetupGet(r => r.CurrentSession).Returns(session.Object);
+ // repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.SettingsPasswordNeeded);
+ // session.SetupGet(r => r.ClientProxy).Returns(clientProxy.Object);
+ // settings.KioskMode = KioskMode.CreateNewDesktop;
+
+ // sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url });
+ // sut.Perform();
+
+ // clientProxy.Verify(c => c.RequestPassword(It.IsAny(), It.IsAny()), Times.AtLeastOnce);
+ // passwordDialog.Verify(p => p.Show(null), Times.Never);
+ // session.VerifyGet(s => s.ClientProxy, Times.AtLeastOnce);
+ //}
+
+ //[TestMethod]
+ //public void MustAbortAskingForPasswordViaClientIfDecidedByUser()
+ //{
+ // var clientProxy = new Mock();
+ // var communication = new CommunicationResult(true);
+ // var passwordReceived = new Action((p, id) =>
+ // {
+ // runtimeHost.Raise(r => r.PasswordReceived += null, new PasswordReplyEventArgs { RequestId = id, Success = false });
+ // });
+ // var session = new Mock();
+ // var url = @"http://www.safeexambrowser.org/whatever.seb";
+
+ // clientProxy.Setup(c => c.RequestPassword(It.IsAny(), It.IsAny())).Returns(communication).Callback(passwordReceived);
+ // repository.SetupGet(r => r.CurrentSession).Returns(session.Object);
+ // repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.SettingsPasswordNeeded);
+ // session.SetupGet(r => r.ClientProxy).Returns(clientProxy.Object);
+ // settings.KioskMode = KioskMode.CreateNewDesktop;
+
+ // sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url });
+
+ // var result = sut.Perform();
+
+ // Assert.AreEqual(OperationResult.Aborted, result);
+ //}
}
}
diff --git a/SafeExamBrowser.Runtime.UnitTests/SafeExamBrowser.Runtime.UnitTests.csproj b/SafeExamBrowser.Runtime.UnitTests/SafeExamBrowser.Runtime.UnitTests.csproj
index bf1f637b..3115bdf3 100644
--- a/SafeExamBrowser.Runtime.UnitTests/SafeExamBrowser.Runtime.UnitTests.csproj
+++ b/SafeExamBrowser.Runtime.UnitTests/SafeExamBrowser.Runtime.UnitTests.csproj
@@ -81,7 +81,6 @@
-
diff --git a/SafeExamBrowser.Runtime/CompositionRoot.cs b/SafeExamBrowser.Runtime/CompositionRoot.cs
index 46bdb00b..d86b3179 100644
--- a/SafeExamBrowser.Runtime/CompositionRoot.cs
+++ b/SafeExamBrowser.Runtime/CompositionRoot.cs
@@ -71,7 +71,7 @@ namespace SafeExamBrowser.Runtime
bootstrapOperations.Enqueue(new I18nOperation(logger, text, textResource));
bootstrapOperations.Enqueue(new CommunicationHostOperation(runtimeHost, logger));
- sessionOperations.Enqueue(new ConfigurationOperation(appConfig, configuration, logger, messageBox, resourceLoader, runtimeHost, text, uiFactory, args));
+ sessionOperations.Enqueue(new ConfigurationOperation(appConfig, configuration, logger, resourceLoader, args));
sessionOperations.Enqueue(new SessionInitializationOperation(configuration, logger, runtimeHost));
sessionOperations.Enqueue(new ServiceOperation(configuration, logger, serviceProxy));
sessionOperations.Enqueue(new ClientTerminationOperation(configuration, logger, processFactory, proxyFactory, runtimeHost, FIFTEEN_SECONDS));
@@ -81,7 +81,7 @@ namespace SafeExamBrowser.Runtime
var bootstrapSequence = new OperationSequence(logger, bootstrapOperations);
var sessionSequence = new OperationSequence(logger, sessionOperations);
- RuntimeController = new RuntimeController(appConfig, configuration, logger, messageBox, bootstrapSequence, sessionSequence, runtimeHost, serviceProxy, shutdown, uiFactory);
+ RuntimeController = new RuntimeController(appConfig, configuration, logger, messageBox, bootstrapSequence, sessionSequence, runtimeHost, serviceProxy, shutdown, text, uiFactory);
}
internal void LogStartupInformation()
diff --git a/SafeExamBrowser.Runtime/Operations/ClientOperation.cs b/SafeExamBrowser.Runtime/Operations/ClientOperation.cs
index b7ad6154..ad1fa6e6 100644
--- a/SafeExamBrowser.Runtime/Operations/ClientOperation.cs
+++ b/SafeExamBrowser.Runtime/Operations/ClientOperation.cs
@@ -12,9 +12,9 @@ using SafeExamBrowser.Contracts.Communication.Hosts;
using SafeExamBrowser.Contracts.Communication.Proxies;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Core.OperationModel;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
-using SafeExamBrowser.Contracts.UserInterface;
using SafeExamBrowser.Contracts.WindowsApi;
using SafeExamBrowser.Contracts.WindowsApi.Events;
@@ -30,7 +30,8 @@ namespace SafeExamBrowser.Runtime.Operations
protected IProxyFactory proxyFactory;
protected IRuntimeHost runtimeHost;
- public IProgressIndicator ProgressIndicator { protected get; set; }
+ public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
+ public event StatusChangedEventHandler StatusChanged;
protected IProcess ClientProcess
{
@@ -62,7 +63,7 @@ namespace SafeExamBrowser.Runtime.Operations
public virtual OperationResult Perform()
{
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StartClient, true);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_StartClient);
var success = TryStartClient();
@@ -87,7 +88,7 @@ namespace SafeExamBrowser.Runtime.Operations
{
if (ClientProcess != null && !ClientProcess.HasTerminated)
{
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StopClient, true);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_StopClient);
TryStopClient();
}
}
diff --git a/SafeExamBrowser.Runtime/Operations/ClientTerminationOperation.cs b/SafeExamBrowser.Runtime/Operations/ClientTerminationOperation.cs
index 88ac8830..126045e5 100644
--- a/SafeExamBrowser.Runtime/Operations/ClientTerminationOperation.cs
+++ b/SafeExamBrowser.Runtime/Operations/ClientTerminationOperation.cs
@@ -6,10 +6,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-using SafeExamBrowser.Contracts.Core.OperationModel;
using SafeExamBrowser.Contracts.Communication.Hosts;
using SafeExamBrowser.Contracts.Communication.Proxies;
using SafeExamBrowser.Contracts.Configuration;
+using SafeExamBrowser.Contracts.Core.OperationModel;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Contracts.WindowsApi;
@@ -18,6 +19,9 @@ namespace SafeExamBrowser.Runtime.Operations
{
internal class ClientTerminationOperation : ClientOperation
{
+ public new event ActionRequiredEventHandler ActionRequired { add { } remove { } }
+ public new event StatusChangedEventHandler StatusChanged;
+
public ClientTerminationOperation(
IConfigurationRepository configuration,
ILogger logger,
@@ -39,7 +43,7 @@ namespace SafeExamBrowser.Runtime.Operations
if (ClientProcess != null && !ClientProcess.HasTerminated)
{
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StopClient, true);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_StopClient);
success = TryStopClient();
}
diff --git a/SafeExamBrowser.Runtime/Operations/ConfigurationOperation.cs b/SafeExamBrowser.Runtime/Operations/ConfigurationOperation.cs
index a1781a75..52b25fce 100644
--- a/SafeExamBrowser.Runtime/Operations/ConfigurationOperation.cs
+++ b/SafeExamBrowser.Runtime/Operations/ConfigurationOperation.cs
@@ -8,17 +8,14 @@
using System;
using System.IO;
-using System.Threading;
-using SafeExamBrowser.Contracts.Core.OperationModel;
using SafeExamBrowser.Contracts.Communication.Data;
-using SafeExamBrowser.Contracts.Communication.Events;
-using SafeExamBrowser.Contracts.Communication.Hosts;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Configuration.Settings;
+using SafeExamBrowser.Contracts.Core.OperationModel;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
-using SafeExamBrowser.Contracts.UserInterface;
-using SafeExamBrowser.Contracts.UserInterface.MessageBox;
+using SafeExamBrowser.Runtime.Operations.Events;
namespace SafeExamBrowser.Runtime.Operations
{
@@ -26,42 +23,31 @@ namespace SafeExamBrowser.Runtime.Operations
{
private IConfigurationRepository configuration;
private ILogger logger;
- private IMessageBox messageBox;
private IResourceLoader resourceLoader;
- private IRuntimeHost runtimeHost;
private AppConfig appConfig;
- private IText text;
- private IUserInterfaceFactory uiFactory;
private string[] commandLineArgs;
- public IProgressIndicator ProgressIndicator { private get; set; }
+ public event ActionRequiredEventHandler ActionRequired;
+ public event StatusChangedEventHandler StatusChanged;
public ConfigurationOperation(
AppConfig appConfig,
IConfigurationRepository configuration,
ILogger logger,
- IMessageBox messageBox,
IResourceLoader resourceLoader,
- IRuntimeHost runtimeHost,
- IText text,
- IUserInterfaceFactory uiFactory,
string[] commandLineArgs)
{
this.appConfig = appConfig;
this.logger = logger;
- this.messageBox = messageBox;
this.configuration = configuration;
this.resourceLoader = resourceLoader;
- this.runtimeHost = runtimeHost;
- this.text = text;
- this.uiFactory = uiFactory;
this.commandLineArgs = commandLineArgs;
}
public OperationResult Perform()
{
logger.Info("Initializing application configuration...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeConfiguration);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_InitializeConfiguration);
var isValidUri = TryInitializeSettingsUri(out Uri uri);
@@ -86,7 +72,7 @@ namespace SafeExamBrowser.Runtime.Operations
public OperationResult Repeat()
{
logger.Info("Initializing new application configuration...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeConfiguration);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_InitializeConfiguration);
var isValidUri = TryValidateSettingsUri(configuration.ReconfigurationFilePath, out Uri uri);
@@ -123,18 +109,17 @@ namespace SafeExamBrowser.Runtime.Operations
if (status == LoadStatus.AdminPasswordNeeded || status == LoadStatus.SettingsPasswordNeeded)
{
- var purpose = status == LoadStatus.AdminPasswordNeeded ? PasswordRequestPurpose.Administrator : PasswordRequestPurpose.Settings;
- var aborted = !TryGetPassword(purpose, out string password);
+ var result = TryGetPassword(status);
- adminAttempts += purpose == PasswordRequestPurpose.Administrator ? 1 : 0;
- adminPassword = purpose == PasswordRequestPurpose.Administrator ? password : adminPassword;
- settingsAttempts += purpose == PasswordRequestPurpose.Settings ? 1 : 0;
- settingsPassword = purpose == PasswordRequestPurpose.Settings ? password : settingsPassword;
-
- if (aborted)
+ if (!result.Success)
{
return OperationResult.Aborted;
}
+
+ adminAttempts += status == LoadStatus.AdminPasswordNeeded ? 1 : 0;
+ adminPassword = status == LoadStatus.AdminPasswordNeeded ? result.Password : adminPassword;
+ settingsAttempts += status == LoadStatus.SettingsPasswordNeeded ? 1 : 0;
+ settingsPassword = status == LoadStatus.SettingsPasswordNeeded ? result.Password : settingsPassword;
}
else
{
@@ -150,64 +135,14 @@ namespace SafeExamBrowser.Runtime.Operations
return status == LoadStatus.Success ? OperationResult.Success : OperationResult.Failed;
}
- private bool TryGetPassword(PasswordRequestPurpose purpose, out string password)
+ private PasswordRequiredEventArgs TryGetPassword(LoadStatus status)
{
- var isStartup = configuration.CurrentSession == null;
- var isRunningOnDefaultDesktop = configuration.CurrentSettings?.KioskMode == KioskMode.DisableExplorerShell;
+ var purpose = status == LoadStatus.AdminPasswordNeeded ? PasswordRequestPurpose.Administrator : PasswordRequestPurpose.Settings;
+ var args = new PasswordRequiredEventArgs { Purpose = purpose };
- if (isStartup || isRunningOnDefaultDesktop)
- {
- return TryGetPasswordViaDialog(purpose, out password);
- }
- else
- {
- return TryGetPasswordViaClient(purpose, out password);
- }
- }
+ ActionRequired?.Invoke(args);
- private bool TryGetPasswordViaDialog(PasswordRequestPurpose purpose, out string password)
- {
- var isAdmin = purpose == PasswordRequestPurpose.Administrator;
- var message = isAdmin ? TextKey.PasswordDialog_AdminPasswordRequired : TextKey.PasswordDialog_SettingsPasswordRequired;
- var title = isAdmin ? TextKey.PasswordDialog_AdminPasswordRequiredTitle : TextKey.PasswordDialog_SettingsPasswordRequiredTitle;
- var dialog = uiFactory.CreatePasswordDialog(text.Get(message), text.Get(title));
- var result = dialog.Show();
- var success = result.Success;
-
- password = success ? result.Password : default(string);
-
- return success;
- }
-
- private bool TryGetPasswordViaClient(PasswordRequestPurpose purpose, out string password)
- {
- var requestId = Guid.NewGuid();
- var response = default(PasswordReplyEventArgs);
- var responseEvent = new AutoResetEvent(false);
- var responseEventHandler = new CommunicationEventHandler((args) =>
- {
- if (args.RequestId == requestId)
- {
- response = args;
- responseEvent.Set();
- }
- });
-
- runtimeHost.PasswordReceived += responseEventHandler;
-
- var communication = configuration.CurrentSession.ClientProxy.RequestPassword(purpose, requestId);
-
- if (communication.Success)
- {
- responseEvent.WaitOne();
- }
-
- var success = response?.Success == true;
-
- runtimeHost.PasswordReceived -= responseEventHandler;
- password = success ? response.Password : default(string);
-
- return success;
+ return args;
}
private void HandleInvalidData(ref LoadStatus status, Uri uri)
@@ -273,26 +208,19 @@ namespace SafeExamBrowser.Runtime.Operations
{
if (result == OperationResult.Success && configuration.CurrentSettings.ConfigurationMode == ConfigurationMode.ConfigureClient)
{
- var abort = IsConfigurationSufficient();
+ var args = new ConfigurationCompletedEventArgs();
- logger.Info($"The user chose to {(abort ? "abort" : "continue")} after successful client configuration.");
+ ActionRequired?.Invoke(args);
- if (abort)
+ logger.Info($"The user chose to {(args.AbortStartup ? "abort" : "continue")} after successful client configuration.");
+
+ if (args.AbortStartup)
{
result = OperationResult.Aborted;
}
}
}
- private bool IsConfigurationSufficient()
- {
- var message = text.Get(TextKey.MessageBox_ClientConfigurationQuestion);
- var title = text.Get(TextKey.MessageBox_ClientConfigurationQuestionTitle);
- var abort = messageBox.Show(message, title, MessageBoxAction.YesNo, MessageBoxIcon.Question);
-
- return abort == MessageBoxResult.Yes;
- }
-
private void LogOperationResult(OperationResult result)
{
switch (result)
diff --git a/SafeExamBrowser.Runtime/Operations/Events/ConfigurationCompletedEventArgs.cs b/SafeExamBrowser.Runtime/Operations/Events/ConfigurationCompletedEventArgs.cs
new file mode 100644
index 00000000..ab91b08b
--- /dev/null
+++ b/SafeExamBrowser.Runtime/Operations/Events/ConfigurationCompletedEventArgs.cs
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2018 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.Contracts.Core.OperationModel.Events;
+
+namespace SafeExamBrowser.Runtime.Operations.Events
+{
+ internal class ConfigurationCompletedEventArgs : ActionRequiredEventArgs
+ {
+ public bool AbortStartup { get; set; }
+ }
+}
diff --git a/SafeExamBrowser.Runtime.UnitTests/Operations/PasswordDialogResultStub.cs b/SafeExamBrowser.Runtime/Operations/Events/PasswordRequiredEventArgs.cs
similarity index 57%
rename from SafeExamBrowser.Runtime.UnitTests/Operations/PasswordDialogResultStub.cs
rename to SafeExamBrowser.Runtime/Operations/Events/PasswordRequiredEventArgs.cs
index 8fc620a9..bf50c951 100644
--- a/SafeExamBrowser.Runtime.UnitTests/Operations/PasswordDialogResultStub.cs
+++ b/SafeExamBrowser.Runtime/Operations/Events/PasswordRequiredEventArgs.cs
@@ -6,13 +6,15 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-using SafeExamBrowser.Contracts.UserInterface.Windows;
+using SafeExamBrowser.Contracts.Communication.Data;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
-namespace SafeExamBrowser.Runtime.UnitTests.Operations
+namespace SafeExamBrowser.Runtime.Operations.Events
{
- internal class PasswordDialogResultStub : IPasswordDialogResult
+ internal class PasswordRequiredEventArgs : ActionRequiredEventArgs
{
public string Password { get; set; }
+ public PasswordRequestPurpose Purpose { get; set; }
public bool Success { get; set; }
}
}
diff --git a/SafeExamBrowser.Runtime/Operations/KioskModeOperation.cs b/SafeExamBrowser.Runtime/Operations/KioskModeOperation.cs
index a75a36bf..159aaa77 100644
--- a/SafeExamBrowser.Runtime/Operations/KioskModeOperation.cs
+++ b/SafeExamBrowser.Runtime/Operations/KioskModeOperation.cs
@@ -9,9 +9,9 @@
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Configuration.Settings;
using SafeExamBrowser.Contracts.Core.OperationModel;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
-using SafeExamBrowser.Contracts.UserInterface;
using SafeExamBrowser.Contracts.WindowsApi;
namespace SafeExamBrowser.Runtime.Operations
@@ -27,7 +27,8 @@ namespace SafeExamBrowser.Runtime.Operations
private IDesktop newDesktop;
private IDesktop originalDesktop;
- public IProgressIndicator ProgressIndicator { private get; set; }
+ public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
+ public event StatusChangedEventHandler StatusChanged;
public KioskModeOperation(
IConfigurationRepository configuration,
@@ -48,7 +49,7 @@ namespace SafeExamBrowser.Runtime.Operations
kioskMode = configuration.CurrentSettings.KioskMode;
logger.Info($"Initializing kiosk mode '{kioskMode}'...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeKioskMode);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_InitializeKioskMode);
switch (kioskMode)
{
@@ -86,7 +87,7 @@ namespace SafeExamBrowser.Runtime.Operations
public void Revert()
{
logger.Info($"Reverting kiosk mode '{kioskMode}'...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_RevertKioskMode);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_RevertKioskMode);
switch (kioskMode)
{
@@ -142,13 +143,13 @@ namespace SafeExamBrowser.Runtime.Operations
private void TerminateExplorerShell()
{
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_WaitExplorerTermination, true);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_WaitExplorerTermination);
explorerShell.Terminate();
}
private void RestartExplorerShell()
{
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_WaitExplorerStartup, true);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_WaitExplorerStartup);
explorerShell.Start();
}
}
diff --git a/SafeExamBrowser.Runtime/Operations/ServiceOperation.cs b/SafeExamBrowser.Runtime/Operations/ServiceOperation.cs
index 574ed748..70918297 100644
--- a/SafeExamBrowser.Runtime/Operations/ServiceOperation.cs
+++ b/SafeExamBrowser.Runtime/Operations/ServiceOperation.cs
@@ -10,9 +10,9 @@ using SafeExamBrowser.Contracts.Communication.Proxies;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Configuration.Settings;
using SafeExamBrowser.Contracts.Core.OperationModel;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
-using SafeExamBrowser.Contracts.UserInterface;
namespace SafeExamBrowser.Runtime.Operations
{
@@ -23,7 +23,8 @@ namespace SafeExamBrowser.Runtime.Operations
private ILogger logger;
private IServiceProxy service;
- public IProgressIndicator ProgressIndicator { private get; set; }
+ public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
+ public event StatusChangedEventHandler StatusChanged;
public ServiceOperation(IConfigurationRepository configuration, ILogger logger, IServiceProxy service)
{
@@ -35,7 +36,7 @@ namespace SafeExamBrowser.Runtime.Operations
public OperationResult Perform()
{
logger.Info($"Initializing service session...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeServiceSession);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_InitializeServiceSession);
mandatory = configuration.CurrentSettings.ServicePolicy == ServicePolicy.Mandatory;
connected = service.Connect();
@@ -73,7 +74,7 @@ namespace SafeExamBrowser.Runtime.Operations
public void Revert()
{
logger.Info("Finalizing service session...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_FinalizeServiceSession);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_FinalizeServiceSession);
if (connected)
{
diff --git a/SafeExamBrowser.Runtime/Operations/SessionInitializationOperation.cs b/SafeExamBrowser.Runtime/Operations/SessionInitializationOperation.cs
index c7525399..aaecfd9b 100644
--- a/SafeExamBrowser.Runtime/Operations/SessionInitializationOperation.cs
+++ b/SafeExamBrowser.Runtime/Operations/SessionInitializationOperation.cs
@@ -9,9 +9,9 @@
using SafeExamBrowser.Contracts.Communication.Hosts;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Core.OperationModel;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
-using SafeExamBrowser.Contracts.UserInterface;
namespace SafeExamBrowser.Runtime.Operations
{
@@ -21,7 +21,8 @@ namespace SafeExamBrowser.Runtime.Operations
private ILogger logger;
private IRuntimeHost runtimeHost;
- public IProgressIndicator ProgressIndicator { private get; set; }
+ public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
+ public event StatusChangedEventHandler StatusChanged;
public SessionInitializationOperation(IConfigurationRepository configuration, ILogger logger, IRuntimeHost runtimeHost)
{
@@ -52,7 +53,7 @@ namespace SafeExamBrowser.Runtime.Operations
private void InitializeSessionConfiguration()
{
logger.Info("Initializing new session configuration...");
- ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeSession, true);
+ StatusChanged?.Invoke(TextKey.ProgressIndicator_InitializeSession);
configuration.InitializeSessionConfiguration();
runtimeHost.StartupToken = configuration.CurrentSession.StartupToken;
diff --git a/SafeExamBrowser.Runtime/RuntimeController.cs b/SafeExamBrowser.Runtime/RuntimeController.cs
index 6a63cdfb..c1ee5415 100644
--- a/SafeExamBrowser.Runtime/RuntimeController.cs
+++ b/SafeExamBrowser.Runtime/RuntimeController.cs
@@ -7,6 +7,8 @@
*/
using System;
+using System.Threading;
+using SafeExamBrowser.Contracts.Communication.Data;
using SafeExamBrowser.Contracts.Communication.Events;
using SafeExamBrowser.Contracts.Communication.Hosts;
using SafeExamBrowser.Contracts.Communication.Proxies;
@@ -14,11 +16,13 @@ using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Configuration.Settings;
using SafeExamBrowser.Contracts.Core;
using SafeExamBrowser.Contracts.Core.OperationModel;
+using SafeExamBrowser.Contracts.Core.OperationModel.Events;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Contracts.UserInterface;
using SafeExamBrowser.Contracts.UserInterface.MessageBox;
using SafeExamBrowser.Contracts.UserInterface.Windows;
+using SafeExamBrowser.Runtime.Operations.Events;
namespace SafeExamBrowser.Runtime
{
@@ -37,6 +41,7 @@ namespace SafeExamBrowser.Runtime
private IServiceProxy service;
private ISplashScreen splashScreen;
private Action shutdown;
+ private IText text;
private IUserInterfaceFactory uiFactory;
public RuntimeController(
@@ -49,6 +54,7 @@ namespace SafeExamBrowser.Runtime
IRuntimeHost runtimeHost,
IServiceProxy service,
Action shutdown,
+ IText text,
IUserInterfaceFactory uiFactory)
{
this.appConfig = appConfig;
@@ -60,6 +66,7 @@ namespace SafeExamBrowser.Runtime
this.sessionSequence = sessionSequence;
this.service = service;
this.shutdown = shutdown;
+ this.text = text;
this.uiFactory = uiFactory;
}
@@ -70,8 +77,11 @@ namespace SafeExamBrowser.Runtime
runtimeWindow = uiFactory.CreateRuntimeWindow(appConfig);
splashScreen = uiFactory.CreateSplashScreen(appConfig);
- bootstrapSequence.ProgressIndicator = splashScreen;
- sessionSequence.ProgressIndicator = runtimeWindow;
+ bootstrapSequence.ProgressChanged += BootstrapSequence_ProgressChanged;
+ bootstrapSequence.StatusChanged += BootstrapSequence_StatusChanged;
+ sessionSequence.ActionRequired += SessionSequence_ActionRequired;
+ sessionSequence.ProgressChanged += SessionSequence_ProgressChanged;
+ sessionSequence.StatusChanged += SessionSequence_StatusChanged;
splashScreen.Show();
@@ -93,7 +103,7 @@ namespace SafeExamBrowser.Runtime
logger.Info("Application startup aborted!");
logger.Log(string.Empty);
- messageBox.Show(TextKey.MessageBox_StartupError, TextKey.MessageBox_StartupErrorTitle, icon: MessageBoxIcon.Error);
+ messageBox.Show(TextKey.MessageBox_StartupError, TextKey.MessageBox_StartupErrorTitle, icon: MessageBoxIcon.Error, parent: splashScreen);
}
return initialized && sessionRunning;
@@ -128,7 +138,7 @@ namespace SafeExamBrowser.Runtime
logger.Info("Shutdown procedure failed!");
logger.Log(string.Empty);
- messageBox.Show(TextKey.MessageBox_ShutdownError, TextKey.MessageBox_ShutdownErrorTitle, icon: MessageBoxIcon.Error);
+ messageBox.Show(TextKey.MessageBox_ShutdownError, TextKey.MessageBox_ShutdownErrorTitle, icon: MessageBoxIcon.Error, parent: splashScreen);
}
splashScreen?.Close();
@@ -171,7 +181,7 @@ namespace SafeExamBrowser.Runtime
if (result == OperationResult.Failed)
{
// TODO: Check if message box is rendered on new desktop as well! -> E.g. if settings for reconfiguration are invalid
- messageBox.Show(TextKey.MessageBox_SessionStartError, TextKey.MessageBox_SessionStartErrorTitle, icon: MessageBoxIcon.Error);
+ messageBox.Show(TextKey.MessageBox_SessionStartError, TextKey.MessageBox_SessionStartErrorTitle, icon: MessageBoxIcon.Error, parent: runtimeWindow);
if (!initial)
{
@@ -201,7 +211,7 @@ namespace SafeExamBrowser.Runtime
else
{
logger.Info("### --- Session Stop Failed --- ###");
- messageBox.Show(TextKey.MessageBox_SessionStopError, TextKey.MessageBox_SessionStopErrorTitle, icon: MessageBoxIcon.Error);
+ messageBox.Show(TextKey.MessageBox_SessionStopError, TextKey.MessageBox_SessionStopErrorTitle, icon: MessageBoxIcon.Error, parent: runtimeWindow);
}
}
@@ -229,10 +239,44 @@ namespace SafeExamBrowser.Runtime
configuration.CurrentSession.ClientProxy.ConnectionLost -= Client_ConnectionLost;
}
+ private void BootstrapSequence_ProgressChanged(ProgressChangedEventArgs args)
+ {
+ // TODO: Duplicated code (for splashScreen as well as runtimeWindow)!
+ if (args.CurrentValue.HasValue)
+ {
+ splashScreen?.SetValue(args.CurrentValue.Value);
+ }
+
+ if (args.IsIndeterminate == true)
+ {
+ splashScreen?.SetIndeterminate();
+ }
+
+ if (args.MaxValue.HasValue)
+ {
+ splashScreen?.SetMaxValue(args.MaxValue.Value);
+ }
+
+ if (args.Progress == true)
+ {
+ splashScreen?.Progress();
+ }
+
+ if (args.Regress == true)
+ {
+ splashScreen?.Regress();
+ }
+ }
+
+ private void BootstrapSequence_StatusChanged(TextKey status)
+ {
+ splashScreen?.UpdateText(status);
+ }
+
private void ClientProcess_Terminated(int exitCode)
{
logger.Error($"Client application has unexpectedly terminated with exit code {exitCode}!");
- // TODO: Check if message box is rendered on new desktop as well -> otherwise shutdown is blocked!
+ // TODO: Check if message box is rendered on new desktop as well -> otherwise shutdown is blocked! Check if parent needed!
messageBox.Show(TextKey.MessageBox_ApplicationError, TextKey.MessageBox_ApplicationErrorTitle, icon: MessageBoxIcon.Error);
shutdown.Invoke();
@@ -241,7 +285,7 @@ namespace SafeExamBrowser.Runtime
private void Client_ConnectionLost()
{
logger.Error("Lost connection to the client application!");
- // TODO: Check if message box is rendered on new desktop as well -> otherwise shutdown is blocked!
+ // TODO: Check if message box is rendered on new desktop as well -> otherwise shutdown is blocked! Check if parent needed!
messageBox.Show(TextKey.MessageBox_ApplicationError, TextKey.MessageBox_ApplicationErrorTitle, icon: MessageBoxIcon.Error);
shutdown.Invoke();
@@ -270,5 +314,120 @@ namespace SafeExamBrowser.Runtime
logger.Info("Received shutdown request from the client application.");
shutdown.Invoke();
}
+
+ private void SessionSequence_ActionRequired(ActionRequiredEventArgs args)
+ {
+ switch (args)
+ {
+ case ConfigurationCompletedEventArgs a:
+ AskIfConfigurationSufficient(a);
+ break;
+ case PasswordRequiredEventArgs p:
+ AskForPassword(p);
+ break;
+ }
+ }
+
+ private void AskIfConfigurationSufficient(ConfigurationCompletedEventArgs args)
+ {
+ var message = TextKey.MessageBox_ClientConfigurationQuestion;
+ var title = TextKey.MessageBox_ClientConfigurationQuestionTitle;
+ var result = messageBox.Show(message, title, MessageBoxAction.YesNo, MessageBoxIcon.Question, runtimeWindow);
+
+ args.AbortStartup = result == MessageBoxResult.Yes;
+ }
+
+ private void AskForPassword(PasswordRequiredEventArgs args)
+ {
+ var isStartup = configuration.CurrentSession == null;
+ var isRunningOnDefaultDesktop = configuration.CurrentSettings?.KioskMode == KioskMode.DisableExplorerShell;
+
+ if (isStartup || isRunningOnDefaultDesktop)
+ {
+ TryGetPasswordViaDialog(args);
+ }
+ else
+ {
+ TryGetPasswordViaClient(args);
+ }
+ }
+
+ private void TryGetPasswordViaDialog(PasswordRequiredEventArgs args)
+ {
+ var isAdmin = args.Purpose == PasswordRequestPurpose.Administrator;
+ var message = isAdmin ? TextKey.PasswordDialog_AdminPasswordRequired : TextKey.PasswordDialog_SettingsPasswordRequired;
+ var title = isAdmin ? TextKey.PasswordDialog_AdminPasswordRequiredTitle : TextKey.PasswordDialog_SettingsPasswordRequiredTitle;
+ var dialog = uiFactory.CreatePasswordDialog(text.Get(message), text.Get(title));
+ var result = dialog.Show(runtimeWindow);
+
+ args.Password = result.Password;
+ args.Success = result.Success;
+ }
+
+ private void TryGetPasswordViaClient(PasswordRequiredEventArgs args)
+ {
+ var requestId = Guid.NewGuid();
+ var response = default(PasswordReplyEventArgs);
+ var responseEvent = new AutoResetEvent(false);
+ var responseEventHandler = new CommunicationEventHandler((a) =>
+ {
+ if (a.RequestId == requestId)
+ {
+ response = a;
+ responseEvent.Set();
+ }
+ });
+
+ runtimeHost.PasswordReceived += responseEventHandler;
+
+ var communication = configuration.CurrentSession.ClientProxy.RequestPassword(args.Purpose, requestId);
+
+ if (communication.Success)
+ {
+ responseEvent.WaitOne();
+ args.Password = response.Password;
+ args.Success = response.Success;
+ }
+ else
+ {
+ args.Password = default(string);
+ args.Success = false;
+ }
+
+ runtimeHost.PasswordReceived -= responseEventHandler;
+ }
+
+ private void SessionSequence_ProgressChanged(ProgressChangedEventArgs args)
+ {
+ if (args.CurrentValue.HasValue)
+ {
+ runtimeWindow?.SetValue(args.CurrentValue.Value);
+ }
+
+ if (args.IsIndeterminate == true)
+ {
+ runtimeWindow?.SetIndeterminate();
+ }
+
+ if (args.MaxValue.HasValue)
+ {
+ runtimeWindow?.SetMaxValue(args.MaxValue.Value);
+ }
+
+ if (args.Progress == true)
+ {
+ runtimeWindow?.Progress();
+ }
+
+ if (args.Regress == true)
+ {
+ runtimeWindow?.Regress();
+ }
+ }
+
+ private void SessionSequence_StatusChanged(TextKey status)
+ {
+ runtimeWindow?.UpdateText(status);
+ }
}
}
diff --git a/SafeExamBrowser.Runtime/SafeExamBrowser.Runtime.csproj b/SafeExamBrowser.Runtime/SafeExamBrowser.Runtime.csproj
index 18e52cc9..158bf775 100644
--- a/SafeExamBrowser.Runtime/SafeExamBrowser.Runtime.csproj
+++ b/SafeExamBrowser.Runtime/SafeExamBrowser.Runtime.csproj
@@ -89,6 +89,8 @@
+
+
diff --git a/SafeExamBrowser.UserInterface.Classic/MessageBox.cs b/SafeExamBrowser.UserInterface.Classic/MessageBox.cs
index cea59c5c..1993bb81 100644
--- a/SafeExamBrowser.UserInterface.Classic/MessageBox.cs
+++ b/SafeExamBrowser.UserInterface.Classic/MessageBox.cs
@@ -9,6 +9,7 @@
using System.Windows;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.UserInterface.MessageBox;
+using SafeExamBrowser.Contracts.UserInterface.Windows;
using MessageBoxResult = SafeExamBrowser.Contracts.UserInterface.MessageBox.MessageBoxResult;
namespace SafeExamBrowser.UserInterface.Classic
@@ -22,16 +23,25 @@ namespace SafeExamBrowser.UserInterface.Classic
this.text = text;
}
- public MessageBoxResult Show(string message, string title, MessageBoxAction action = MessageBoxAction.Confirm, MessageBoxIcon icon = MessageBoxIcon.Information)
+ public MessageBoxResult Show(string message, string title, MessageBoxAction action = MessageBoxAction.Confirm, MessageBoxIcon icon = MessageBoxIcon.Information, IWindow parent = null)
{
- var result = System.Windows.MessageBox.Show(message, title, ToButton(action), ToImage(icon));
+ var result = default(System.Windows.MessageBoxResult);
+
+ if (parent is Window window)
+ {
+ result = window.Dispatcher.Invoke(() => System.Windows.MessageBox.Show(window, message, title, ToButton(action), ToImage(icon)));
+ }
+ else
+ {
+ result = System.Windows.MessageBox.Show(message, title, ToButton(action), ToImage(icon));
+ }
return ToResult(result);
}
- public MessageBoxResult Show(TextKey message, TextKey title, MessageBoxAction action = MessageBoxAction.Confirm, MessageBoxIcon icon = MessageBoxIcon.Information)
+ public MessageBoxResult Show(TextKey message, TextKey title, MessageBoxAction action = MessageBoxAction.Confirm, MessageBoxIcon icon = MessageBoxIcon.Information, IWindow parent = null)
{
- return Show(text.Get(message), text.Get(title), action, icon);
+ return Show(text.Get(message), text.Get(title), action, icon, parent);
}
private MessageBoxButton ToButton(MessageBoxAction action)
diff --git a/SafeExamBrowser.UserInterface.Classic/RuntimeWindow.xaml.cs b/SafeExamBrowser.UserInterface.Classic/RuntimeWindow.xaml.cs
index decad95d..c46f22a5 100644
--- a/SafeExamBrowser.UserInterface.Classic/RuntimeWindow.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Classic/RuntimeWindow.xaml.cs
@@ -81,14 +81,14 @@ namespace SafeExamBrowser.UserInterface.Classic
});
}
- public void Progress(int amount = 1)
+ public void Progress()
{
- model.CurrentProgress += amount;
+ model.CurrentProgress += 1;
}
- public void Regress(int amount = 1)
+ public void Regress()
{
- model.CurrentProgress -= amount;
+ model.CurrentProgress -= 1;
}
public void SetIndeterminate()
diff --git a/SafeExamBrowser.UserInterface.Classic/SplashScreen.xaml.cs b/SafeExamBrowser.UserInterface.Classic/SplashScreen.xaml.cs
index 7e841f7c..8682ce84 100644
--- a/SafeExamBrowser.UserInterface.Classic/SplashScreen.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Classic/SplashScreen.xaml.cs
@@ -77,14 +77,14 @@ namespace SafeExamBrowser.UserInterface.Classic
Dispatcher.Invoke(base.Show);
}
- public void Progress(int amount = 1)
+ public void Progress()
{
- model.CurrentProgress += amount;
+ model.CurrentProgress += 1;
}
- public void Regress(int amount = 1)
+ public void Regress()
{
- model.CurrentProgress -= amount;
+ model.CurrentProgress -= 1;
}
public void SetIndeterminate()
diff --git a/SafeExamBrowser.UserInterface.Windows10/SplashScreen.xaml.cs b/SafeExamBrowser.UserInterface.Windows10/SplashScreen.xaml.cs
index 5c29e4c5..d3a48787 100644
--- a/SafeExamBrowser.UserInterface.Windows10/SplashScreen.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Windows10/SplashScreen.xaml.cs
@@ -75,14 +75,14 @@ namespace SafeExamBrowser.UserInterface.Windows10
Dispatcher.Invoke(base.Show);
}
- public void Progress(int amount = 1)
+ public void Progress()
{
- model.CurrentProgress += amount;
+ model.CurrentProgress += 1;
}
- public void Regress(int amount = 1)
+ public void Regress()
{
- model.CurrentProgress -= amount;
+ model.CurrentProgress -= 1;
}
public void SetIndeterminate()