SEBWIN-311: Started implementing scaffolding for third-party applications & monitoring. Renamed ApplicationSettings to AppSettings, resolved dependency from WindowsApi on Monitoring namespace and introduced ClientContext for runtime data of the client.
This commit is contained in:
parent
b2013412dd
commit
8fd22032b6
85 changed files with 1145 additions and 1003 deletions
|
@ -10,6 +10,7 @@ using System;
|
|||
using SafeExamBrowser.Browser.Contracts;
|
||||
using SafeExamBrowser.Communication.Contracts.Hosts;
|
||||
using SafeExamBrowser.Configuration.Contracts;
|
||||
using SafeExamBrowser.Settings;
|
||||
|
||||
namespace SafeExamBrowser.Client.Contracts
|
||||
{
|
||||
|
@ -41,7 +42,7 @@ namespace SafeExamBrowser.Client.Contracts
|
|||
/// <summary>
|
||||
/// The settings to be used during application execution.
|
||||
/// </summary>
|
||||
Settings.ApplicationSettings Settings { set; }
|
||||
AppSettings Settings { set; }
|
||||
|
||||
/// <summary>
|
||||
/// Reverts any changes, releases all used resources and terminates the client.
|
||||
|
|
|
@ -17,14 +17,13 @@ using SafeExamBrowser.Communication.Contracts.Hosts;
|
|||
using SafeExamBrowser.Communication.Contracts.Proxies;
|
||||
using SafeExamBrowser.Configuration.Contracts;
|
||||
using SafeExamBrowser.Configuration.Contracts.Cryptography;
|
||||
using SafeExamBrowser.Settings;
|
||||
using SafeExamBrowser.Core.Contracts.OperationModel;
|
||||
using SafeExamBrowser.Core.Contracts.OperationModel.Events;
|
||||
using SafeExamBrowser.I18n.Contracts;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Applications;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Display;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Processes;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Windows;
|
||||
using SafeExamBrowser.Settings;
|
||||
using SafeExamBrowser.UserInterface.Contracts;
|
||||
using SafeExamBrowser.UserInterface.Contracts.MessageBox;
|
||||
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
||||
|
@ -38,6 +37,7 @@ namespace SafeExamBrowser.Client.UnitTests
|
|||
{
|
||||
private AppConfig appConfig;
|
||||
private Mock<IActionCenter> actionCenter;
|
||||
private Mock<IApplicationMonitor> applicationMonitor;
|
||||
private Mock<IBrowserApplication> browserController;
|
||||
private Mock<IClientHost> clientHost;
|
||||
private Mock<IDisplayMonitor> displayMonitor;
|
||||
|
@ -45,17 +45,15 @@ namespace SafeExamBrowser.Client.UnitTests
|
|||
private Mock<IHashAlgorithm> hashAlgorithm;
|
||||
private Mock<ILogger> logger;
|
||||
private Mock<IMessageBox> messageBox;
|
||||
private Mock<IProcessMonitor> processMonitor;
|
||||
private Mock<IOperationSequence> operationSequence;
|
||||
private Mock<IRuntimeProxy> runtimeProxy;
|
||||
private Guid sessionId;
|
||||
private ApplicationSettings settings;
|
||||
private AppSettings settings;
|
||||
private Mock<Action> shutdown;
|
||||
private Mock<ITaskbar> taskbar;
|
||||
private Mock<ITerminationActivator> terminationActivator;
|
||||
private Mock<IText> text;
|
||||
private Mock<IUserInterfaceFactory> uiFactory;
|
||||
private Mock<IWindowMonitor> windowMonitor;
|
||||
|
||||
private ClientController sut;
|
||||
|
||||
|
@ -64,6 +62,7 @@ namespace SafeExamBrowser.Client.UnitTests
|
|||
{
|
||||
appConfig = new AppConfig();
|
||||
actionCenter = new Mock<IActionCenter>();
|
||||
applicationMonitor = new Mock<IApplicationMonitor>();
|
||||
browserController = new Mock<IBrowserApplication>();
|
||||
clientHost = new Mock<IClientHost>();
|
||||
displayMonitor = new Mock<IDisplayMonitor>();
|
||||
|
@ -71,17 +70,15 @@ namespace SafeExamBrowser.Client.UnitTests
|
|||
hashAlgorithm = new Mock<IHashAlgorithm>();
|
||||
logger = new Mock<ILogger>();
|
||||
messageBox = new Mock<IMessageBox>();
|
||||
processMonitor = new Mock<IProcessMonitor>();
|
||||
operationSequence = new Mock<IOperationSequence>();
|
||||
runtimeProxy = new Mock<IRuntimeProxy>();
|
||||
sessionId = Guid.NewGuid();
|
||||
settings = new ApplicationSettings();
|
||||
settings = new AppSettings();
|
||||
shutdown = new Mock<Action>();
|
||||
taskbar = new Mock<ITaskbar>();
|
||||
terminationActivator = new Mock<ITerminationActivator>();
|
||||
text = new Mock<IText>();
|
||||
uiFactory = new Mock<IUserInterfaceFactory>();
|
||||
windowMonitor = new Mock<IWindowMonitor>();
|
||||
|
||||
operationSequence.Setup(o => o.TryPerform()).Returns(OperationResult.Success);
|
||||
runtimeProxy.Setup(r => r.InformClientReady()).Returns(new CommunicationResult(true));
|
||||
|
@ -89,20 +86,19 @@ namespace SafeExamBrowser.Client.UnitTests
|
|||
|
||||
sut = new ClientController(
|
||||
actionCenter.Object,
|
||||
applicationMonitor.Object,
|
||||
displayMonitor.Object,
|
||||
explorerShell.Object,
|
||||
hashAlgorithm.Object,
|
||||
logger.Object,
|
||||
messageBox.Object,
|
||||
operationSequence.Object,
|
||||
processMonitor.Object,
|
||||
runtimeProxy.Object,
|
||||
shutdown.Object,
|
||||
taskbar.Object,
|
||||
terminationActivator.Object,
|
||||
text.Object,
|
||||
uiFactory.Object,
|
||||
windowMonitor.Object);
|
||||
uiFactory.Object);
|
||||
|
||||
sut.AppConfig = appConfig;
|
||||
sut.Browser = browserController.Object;
|
||||
|
@ -111,6 +107,30 @@ namespace SafeExamBrowser.Client.UnitTests
|
|||
sut.Settings = settings;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ApplicationMonitor_MustHandleExplorerStartCorrectly()
|
||||
{
|
||||
var order = 0;
|
||||
var shell = 0;
|
||||
var workingArea = 0;
|
||||
var bounds = 0;
|
||||
|
||||
explorerShell.Setup(e => e.Terminate()).Callback(() => shell = ++order);
|
||||
displayMonitor.Setup(w => w.InitializePrimaryDisplay(taskbar.Object.GetAbsoluteHeight())).Callback(() => workingArea = ++order);
|
||||
taskbar.Setup(t => t.InitializeBounds()).Callback(() => bounds = ++order);
|
||||
|
||||
sut.TryStart();
|
||||
applicationMonitor.Raise(p => p.ExplorerStarted += null);
|
||||
|
||||
explorerShell.Verify(p => p.Terminate(), Times.Once);
|
||||
displayMonitor.Verify(w => w.InitializePrimaryDisplay(taskbar.Object.GetAbsoluteHeight()), Times.Once);
|
||||
taskbar.Verify(t => t.InitializeBounds(), Times.Once);
|
||||
|
||||
Assert.IsTrue(shell == 1);
|
||||
Assert.IsTrue(workingArea == 2);
|
||||
Assert.IsTrue(bounds == 3);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Communication_MustCorrectlyHandleMessageBoxRequest()
|
||||
{
|
||||
|
@ -265,30 +285,6 @@ namespace SafeExamBrowser.Client.UnitTests
|
|||
splashScreen.Verify(s => s.UpdateStatus(It.Is<TextKey>(k => k == key), It.IsAny<bool>()), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProcessMonitor_MustHandleExplorerStartCorrectly()
|
||||
{
|
||||
var order = 0;
|
||||
var shell = 0;
|
||||
var workingArea = 0;
|
||||
var bounds = 0;
|
||||
|
||||
explorerShell.Setup(e => e.Terminate()).Callback(() => shell = ++order);
|
||||
displayMonitor.Setup(w => w.InitializePrimaryDisplay(taskbar.Object.GetAbsoluteHeight())).Callback(() => workingArea = ++order);
|
||||
taskbar.Setup(t => t.InitializeBounds()).Callback(() => bounds = ++order);
|
||||
|
||||
sut.TryStart();
|
||||
processMonitor.Raise(p => p.ExplorerStarted += null);
|
||||
|
||||
explorerShell.Verify(p => p.Terminate(), Times.Once);
|
||||
displayMonitor.Verify(w => w.InitializePrimaryDisplay(taskbar.Object.GetAbsoluteHeight()), Times.Once);
|
||||
taskbar.Verify(t => t.InitializeBounds(), Times.Once);
|
||||
|
||||
Assert.IsTrue(shell == 1);
|
||||
Assert.IsTrue(workingArea == 2);
|
||||
Assert.IsTrue(bounds == 3);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Reconfiguration_MustDenyIfInExamMode()
|
||||
{
|
||||
|
@ -642,67 +638,5 @@ namespace SafeExamBrowser.Client.UnitTests
|
|||
terminationActivator.Verify(t => t.Resume(), Times.Once);
|
||||
runtimeProxy.Verify(p => p.RequestShutdown(), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void WindowMonitor_MustHandleAllowedWindowChangeCorrectly()
|
||||
{
|
||||
var window = new IntPtr(12345);
|
||||
|
||||
processMonitor.Setup(p => p.BelongsToAllowedProcess(window)).Returns(true);
|
||||
|
||||
sut.TryStart();
|
||||
windowMonitor.Raise(w => w.WindowChanged += null, window);
|
||||
|
||||
processMonitor.Verify(p => p.BelongsToAllowedProcess(window), Times.Once);
|
||||
windowMonitor.Verify(w => w.Hide(window), Times.Never);
|
||||
windowMonitor.Verify(w => w.Close(window), Times.Never);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void WindowMonitor_MustHandleUnallowedWindowHideCorrectly()
|
||||
{
|
||||
var order = 0;
|
||||
var belongs = 0;
|
||||
var hide = 0;
|
||||
var window = new IntPtr(12345);
|
||||
|
||||
processMonitor.Setup(p => p.BelongsToAllowedProcess(window)).Returns(false).Callback(() => belongs = ++order);
|
||||
windowMonitor.Setup(w => w.Hide(window)).Returns(true).Callback(() => hide = ++order);
|
||||
|
||||
sut.TryStart();
|
||||
windowMonitor.Raise(w => w.WindowChanged += null, window);
|
||||
|
||||
processMonitor.Verify(p => p.BelongsToAllowedProcess(window), Times.Once);
|
||||
windowMonitor.Verify(w => w.Hide(window), Times.Once);
|
||||
windowMonitor.Verify(w => w.Close(window), Times.Never);
|
||||
|
||||
Assert.IsTrue(belongs == 1);
|
||||
Assert.IsTrue(hide == 2);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void WindowMonitor_MustHandleUnallowedWindowCloseCorrectly()
|
||||
{
|
||||
var order = 0;
|
||||
var belongs = 0;
|
||||
var hide = 0;
|
||||
var close = 0;
|
||||
var window = new IntPtr(12345);
|
||||
|
||||
processMonitor.Setup(p => p.BelongsToAllowedProcess(window)).Returns(false).Callback(() => belongs = ++order);
|
||||
windowMonitor.Setup(w => w.Hide(window)).Returns(false).Callback(() => hide = ++order);
|
||||
windowMonitor.Setup(w => w.Close(window)).Callback(() => close = ++order);
|
||||
|
||||
sut.TryStart();
|
||||
windowMonitor.Raise(w => w.WindowChanged += null, window);
|
||||
|
||||
processMonitor.Verify(p => p.BelongsToAllowedProcess(window), Times.Once);
|
||||
windowMonitor.Verify(w => w.Hide(window), Times.Once);
|
||||
windowMonitor.Verify(w => w.Close(window), Times.Once);
|
||||
|
||||
Assert.IsTrue(belongs == 1);
|
||||
Assert.IsTrue(hide == 2);
|
||||
Assert.IsTrue(close == 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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 Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace SafeExamBrowser.Client.UnitTests.Operations
|
||||
{
|
||||
[TestClass]
|
||||
public class ApplicationOperationTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void TODO()
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,9 +13,9 @@ using SafeExamBrowser.Client.Operations;
|
|||
using SafeExamBrowser.Communication.Contracts.Data;
|
||||
using SafeExamBrowser.Communication.Contracts.Proxies;
|
||||
using SafeExamBrowser.Configuration.Contracts;
|
||||
using SafeExamBrowser.Settings;
|
||||
using SafeExamBrowser.Core.Contracts.OperationModel;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.Settings;
|
||||
|
||||
namespace SafeExamBrowser.Client.UnitTests.Operations
|
||||
{
|
||||
|
@ -23,6 +23,7 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
|||
public class ConfigurationOperationTests
|
||||
{
|
||||
private ClientConfiguration configuration;
|
||||
private ClientContext context;
|
||||
private Mock<ILogger> logger;
|
||||
private Mock<IRuntimeProxy> runtime;
|
||||
private ConfigurationOperation sut;
|
||||
|
@ -31,10 +32,11 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
|||
public void Initialize()
|
||||
{
|
||||
configuration = new ClientConfiguration();
|
||||
context = new ClientContext();
|
||||
logger = new Mock<ILogger>();
|
||||
runtime = new Mock<IRuntimeProxy>();
|
||||
|
||||
sut = new ConfigurationOperation(configuration, logger.Object, runtime.Object);
|
||||
sut = new ConfigurationOperation(configuration, context, logger.Object, runtime.Object);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
@ -46,7 +48,7 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
|||
{
|
||||
AppConfig = new AppConfig(),
|
||||
SessionId = Guid.NewGuid(),
|
||||
Settings = new ApplicationSettings()
|
||||
Settings = new AppSettings()
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ using Moq;
|
|||
using SafeExamBrowser.Client.Operations;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Keyboard;
|
||||
using SafeExamBrowser.WindowsApi.Contracts;
|
||||
|
||||
namespace SafeExamBrowser.Client.UnitTests.Operations
|
||||
{
|
||||
|
@ -20,7 +19,6 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
|||
{
|
||||
private Mock<IKeyboardInterceptor> keyboardInterceptorMock;
|
||||
private Mock<ILogger> loggerMock;
|
||||
private Mock<INativeMethods> nativeMethodsMock;
|
||||
|
||||
private KeyboardInterceptorOperation sut;
|
||||
|
||||
|
@ -29,9 +27,8 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
|||
{
|
||||
keyboardInterceptorMock = new Mock<IKeyboardInterceptor>();
|
||||
loggerMock = new Mock<ILogger>();
|
||||
nativeMethodsMock = new Mock<INativeMethods>();
|
||||
|
||||
sut = new KeyboardInterceptorOperation(keyboardInterceptorMock.Object, loggerMock.Object, nativeMethodsMock.Object);
|
||||
sut = new KeyboardInterceptorOperation(keyboardInterceptorMock.Object, loggerMock.Object);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
@ -39,7 +36,8 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
|||
{
|
||||
sut.Perform();
|
||||
|
||||
nativeMethodsMock.Verify(n => n.RegisterKeyboardHook(It.IsAny<IKeyboardInterceptor>()), Times.Once);
|
||||
keyboardInterceptorMock.Verify(i => i.Start(), Times.Once);
|
||||
keyboardInterceptorMock.Verify(i => i.Stop(), Times.Never);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
@ -47,7 +45,8 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
|||
{
|
||||
sut.Revert();
|
||||
|
||||
nativeMethodsMock.Verify(n => n.DeregisterKeyboardHook(It.IsAny<IKeyboardInterceptor>()), Times.Once);
|
||||
keyboardInterceptorMock.Verify(i => i.Start(), Times.Never);
|
||||
keyboardInterceptorMock.Verify(i => i.Stop(), Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ using Moq;
|
|||
using SafeExamBrowser.Client.Operations;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Mouse;
|
||||
using SafeExamBrowser.WindowsApi.Contracts;
|
||||
|
||||
namespace SafeExamBrowser.Client.UnitTests.Operations
|
||||
{
|
||||
|
@ -20,7 +19,6 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
|||
{
|
||||
private Mock<IMouseInterceptor> mouseInterceptorMock;
|
||||
private Mock<ILogger> loggerMock;
|
||||
private Mock<INativeMethods> nativeMethodsMock;
|
||||
|
||||
private MouseInterceptorOperation sut;
|
||||
|
||||
|
@ -29,9 +27,8 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
|||
{
|
||||
mouseInterceptorMock = new Mock<IMouseInterceptor>();
|
||||
loggerMock = new Mock<ILogger>();
|
||||
nativeMethodsMock = new Mock<INativeMethods>();
|
||||
|
||||
sut = new MouseInterceptorOperation(loggerMock.Object, mouseInterceptorMock.Object, nativeMethodsMock.Object);
|
||||
sut = new MouseInterceptorOperation(loggerMock.Object, mouseInterceptorMock.Object);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
@ -39,7 +36,8 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
|||
{
|
||||
sut.Perform();
|
||||
|
||||
nativeMethodsMock.Verify(n => n.RegisterMouseHook(It.IsAny<IMouseInterceptor>()), Times.Once);
|
||||
mouseInterceptorMock.Verify(i => i.Start(), Times.Once);
|
||||
mouseInterceptorMock.Verify(i => i.Stop(), Times.Never);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
@ -47,7 +45,8 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
|||
{
|
||||
sut.Revert();
|
||||
|
||||
nativeMethodsMock.Verify(n => n.DeregisterMouseHook(It.IsAny<IMouseInterceptor>()), Times.Once);
|
||||
mouseInterceptorMock.Verify(i => i.Start(), Times.Never);
|
||||
mouseInterceptorMock.Verify(i => i.Stop(), Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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 Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using SafeExamBrowser.Client.Operations;
|
||||
using SafeExamBrowser.Settings;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Processes;
|
||||
|
||||
namespace SafeExamBrowser.Client.UnitTests.Operations
|
||||
{
|
||||
[TestClass]
|
||||
public class ProcessMonitorOperationTests
|
||||
{
|
||||
private Mock<ILogger> logger;
|
||||
private Mock<IProcessMonitor> processMonitor;
|
||||
private ApplicationSettings settings;
|
||||
private ProcessMonitorOperation sut;
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
logger = new Mock<ILogger>();
|
||||
processMonitor = new Mock<IProcessMonitor>();
|
||||
settings = new ApplicationSettings();
|
||||
|
||||
sut = new ProcessMonitorOperation(logger.Object, processMonitor.Object,settings);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MustObserveExplorerWithDisableExplorerShell()
|
||||
{
|
||||
var counter = 0;
|
||||
var start = 0;
|
||||
var stop = 0;
|
||||
|
||||
settings.KioskMode = KioskMode.DisableExplorerShell;
|
||||
processMonitor.Setup(p => p.StartMonitoringExplorer()).Callback(() => start = ++counter);
|
||||
processMonitor.Setup(p => p.StopMonitoringExplorer()).Callback(() => stop = ++counter);
|
||||
|
||||
sut.Perform();
|
||||
sut.Revert();
|
||||
|
||||
processMonitor.Verify(p => p.StartMonitoringExplorer(), Times.Once);
|
||||
processMonitor.Verify(p => p.StopMonitoringExplorer(), Times.Once);
|
||||
|
||||
Assert.AreEqual(1, start);
|
||||
Assert.AreEqual(2, stop);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MustNotObserveExplorerWithOtherKioskModes()
|
||||
{
|
||||
settings.KioskMode = KioskMode.CreateNewDesktop;
|
||||
|
||||
sut.Perform();
|
||||
sut.Revert();
|
||||
|
||||
settings.KioskMode = KioskMode.None;
|
||||
|
||||
sut.Perform();
|
||||
sut.Revert();
|
||||
|
||||
processMonitor.Verify(p => p.StartMonitoringExplorer(), Times.Never);
|
||||
processMonitor.Verify(p => p.StopMonitoringExplorer(), Times.Never);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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 Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using SafeExamBrowser.Client.Operations;
|
||||
using SafeExamBrowser.Settings;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Windows;
|
||||
|
||||
namespace SafeExamBrowser.Client.UnitTests.Operations
|
||||
{
|
||||
[TestClass]
|
||||
public class WindowMonitorOperationTests
|
||||
{
|
||||
private Mock<ILogger> loggerMock;
|
||||
private Mock<IWindowMonitor> windowMonitorMock;
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
loggerMock = new Mock<ILogger>();
|
||||
windowMonitorMock = new Mock<IWindowMonitor>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MustPerformCorrectlyForCreateNewDesktop()
|
||||
{
|
||||
var sut = new WindowMonitorOperation(KioskMode.CreateNewDesktop, loggerMock.Object, windowMonitorMock.Object);
|
||||
|
||||
sut.Perform();
|
||||
|
||||
windowMonitorMock.Verify(w => w.StartMonitoringWindows(), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MustRevertCorrectlyForCreateNewDesktop()
|
||||
{
|
||||
var sut = new WindowMonitorOperation(KioskMode.CreateNewDesktop, loggerMock.Object, windowMonitorMock.Object);
|
||||
|
||||
sut.Revert();
|
||||
|
||||
windowMonitorMock.Verify(w => w.StopMonitoringWindows(), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MustPerformCorrectlyForDisableExplorerShell()
|
||||
{
|
||||
var sut = new WindowMonitorOperation(KioskMode.DisableExplorerShell, loggerMock.Object, windowMonitorMock.Object);
|
||||
|
||||
sut.Perform();
|
||||
|
||||
windowMonitorMock.Verify(w => w.StartMonitoringWindows(), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MustRevertCorrectlyForDisableExplorerShell()
|
||||
{
|
||||
var sut = new WindowMonitorOperation(KioskMode.DisableExplorerShell, loggerMock.Object, windowMonitorMock.Object);
|
||||
|
||||
sut.Revert();
|
||||
|
||||
windowMonitorMock.Verify(w => w.StopMonitoringWindows(), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MustDoNothingWithoutKioskMode()
|
||||
{
|
||||
var sut = new WindowMonitorOperation(KioskMode.None, loggerMock.Object, windowMonitorMock.Object);
|
||||
|
||||
sut.Perform();
|
||||
sut.Revert();
|
||||
|
||||
windowMonitorMock.VerifyNoOtherCalls();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -81,6 +81,7 @@
|
|||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Operations\ApplicationOperationTests.cs" />
|
||||
<Compile Include="Operations\BrowserOperationTests.cs" />
|
||||
<Compile Include="Operations\ClientHostDisconnectionOperationTests.cs" />
|
||||
<Compile Include="Operations\ClipboardOperationTests.cs" />
|
||||
|
@ -88,10 +89,8 @@
|
|||
<Compile Include="Operations\DisplayMonitorOperationTests.cs" />
|
||||
<Compile Include="Operations\KeyboardInterceptorOperationTests.cs" />
|
||||
<Compile Include="Operations\MouseInterceptorOperationTests.cs" />
|
||||
<Compile Include="Operations\ProcessMonitorOperationTests.cs" />
|
||||
<Compile Include="Operations\RuntimeConnectionOperationTests.cs" />
|
||||
<Compile Include="Operations\ShellOperationTests.cs" />
|
||||
<Compile Include="Operations\WindowMonitorOperationTests.cs" />
|
||||
<Compile Include="Communication\ClientHostTests.cs" />
|
||||
<Compile Include="Notifications\AboutNotificationControllerTests.cs" />
|
||||
<Compile Include="Notifications\LogNotificationControllerTests.cs" />
|
||||
|
|
29
SafeExamBrowser.Client/ClientContext.cs
Normal file
29
SafeExamBrowser.Client/ClientContext.cs
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.Configuration.Contracts;
|
||||
using SafeExamBrowser.Settings;
|
||||
|
||||
namespace SafeExamBrowser.Client
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds all configuration and runtime data for the client.
|
||||
/// </summary>
|
||||
internal class ClientContext
|
||||
{
|
||||
/// <summary>
|
||||
/// The global application configuration.
|
||||
/// </summary>
|
||||
internal AppConfig AppConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The settings for the current session.
|
||||
/// </summary>
|
||||
internal AppSettings Settings { get; set; }
|
||||
}
|
||||
}
|
|
@ -17,14 +17,13 @@ using SafeExamBrowser.Communication.Contracts.Hosts;
|
|||
using SafeExamBrowser.Communication.Contracts.Proxies;
|
||||
using SafeExamBrowser.Configuration.Contracts;
|
||||
using SafeExamBrowser.Configuration.Contracts.Cryptography;
|
||||
using SafeExamBrowser.Settings;
|
||||
using SafeExamBrowser.Core.Contracts.OperationModel;
|
||||
using SafeExamBrowser.Core.Contracts.OperationModel.Events;
|
||||
using SafeExamBrowser.I18n.Contracts;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Applications;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Display;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Processes;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Windows;
|
||||
using SafeExamBrowser.Settings;
|
||||
using SafeExamBrowser.UserInterface.Contracts;
|
||||
using SafeExamBrowser.UserInterface.Contracts.MessageBox;
|
||||
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
||||
|
@ -36,13 +35,13 @@ namespace SafeExamBrowser.Client
|
|||
internal class ClientController : IClientController
|
||||
{
|
||||
private IActionCenter actionCenter;
|
||||
private IApplicationMonitor applicationMonitor;
|
||||
private IDisplayMonitor displayMonitor;
|
||||
private IExplorerShell explorerShell;
|
||||
private IHashAlgorithm hashAlgorithm;
|
||||
private ILogger logger;
|
||||
private IMessageBox messageBox;
|
||||
private IOperationSequence operations;
|
||||
private IProcessMonitor processMonitor;
|
||||
private IRuntimeProxy runtime;
|
||||
private Action shutdown;
|
||||
private ISplashScreen splashScreen;
|
||||
|
@ -50,13 +49,12 @@ namespace SafeExamBrowser.Client
|
|||
private ITerminationActivator terminationActivator;
|
||||
private IText text;
|
||||
private IUserInterfaceFactory uiFactory;
|
||||
private IWindowMonitor windowMonitor;
|
||||
private AppConfig appConfig;
|
||||
|
||||
public IBrowserApplication Browser { private get; set; }
|
||||
public IClientHost ClientHost { private get; set; }
|
||||
public Guid SessionId { private get; set; }
|
||||
public ApplicationSettings Settings { private get; set; }
|
||||
public AppSettings Settings { private get; set; }
|
||||
|
||||
public AppConfig AppConfig
|
||||
{
|
||||
|
@ -73,36 +71,34 @@ namespace SafeExamBrowser.Client
|
|||
|
||||
public ClientController(
|
||||
IActionCenter actionCenter,
|
||||
IApplicationMonitor applicationMonitor,
|
||||
IDisplayMonitor displayMonitor,
|
||||
IExplorerShell explorerShell,
|
||||
IHashAlgorithm hashAlgorithm,
|
||||
ILogger logger,
|
||||
IMessageBox messageBox,
|
||||
IOperationSequence operations,
|
||||
IProcessMonitor processMonitor,
|
||||
IRuntimeProxy runtime,
|
||||
Action shutdown,
|
||||
ITaskbar taskbar,
|
||||
ITerminationActivator terminationActivator,
|
||||
IText text,
|
||||
IUserInterfaceFactory uiFactory,
|
||||
IWindowMonitor windowMonitor)
|
||||
IUserInterfaceFactory uiFactory)
|
||||
{
|
||||
this.actionCenter = actionCenter;
|
||||
this.applicationMonitor = applicationMonitor;
|
||||
this.displayMonitor = displayMonitor;
|
||||
this.explorerShell = explorerShell;
|
||||
this.hashAlgorithm = hashAlgorithm;
|
||||
this.logger = logger;
|
||||
this.messageBox = messageBox;
|
||||
this.operations = operations;
|
||||
this.processMonitor = processMonitor;
|
||||
this.runtime = runtime;
|
||||
this.shutdown = shutdown;
|
||||
this.taskbar = taskbar;
|
||||
this.terminationActivator = terminationActivator;
|
||||
this.text = text;
|
||||
this.uiFactory = uiFactory;
|
||||
this.windowMonitor = windowMonitor;
|
||||
}
|
||||
|
||||
public bool TryStart()
|
||||
|
@ -110,6 +106,7 @@ namespace SafeExamBrowser.Client
|
|||
logger.Info("Initiating startup procedure...");
|
||||
|
||||
splashScreen = uiFactory.CreateSplashScreen();
|
||||
operations.ActionRequired += Operations_ActionRequired;
|
||||
operations.ProgressChanged += Operations_ProgressChanged;
|
||||
operations.StatusChanged += Operations_StatusChanged;
|
||||
|
||||
|
@ -175,28 +172,26 @@ namespace SafeExamBrowser.Client
|
|||
private void RegisterEvents()
|
||||
{
|
||||
actionCenter.QuitButtonClicked += Shell_QuitButtonClicked;
|
||||
applicationMonitor.ExplorerStarted += ApplicationMonitor_ExplorerStarted;
|
||||
Browser.ConfigurationDownloadRequested += Browser_ConfigurationDownloadRequested;
|
||||
ClientHost.MessageBoxRequested += ClientHost_MessageBoxRequested;
|
||||
ClientHost.PasswordRequested += ClientHost_PasswordRequested;
|
||||
ClientHost.ReconfigurationDenied += ClientHost_ReconfigurationDenied;
|
||||
ClientHost.Shutdown += ClientHost_Shutdown;
|
||||
displayMonitor.DisplayChanged += DisplayMonitor_DisplaySettingsChanged;
|
||||
processMonitor.ExplorerStarted += ProcessMonitor_ExplorerStarted;
|
||||
runtime.ConnectionLost += Runtime_ConnectionLost;
|
||||
taskbar.QuitButtonClicked += Shell_QuitButtonClicked;
|
||||
terminationActivator.Activated += TerminationActivator_Activated;
|
||||
windowMonitor.WindowChanged += WindowMonitor_WindowChanged;
|
||||
}
|
||||
|
||||
private void DeregisterEvents()
|
||||
{
|
||||
actionCenter.QuitButtonClicked -= Shell_QuitButtonClicked;
|
||||
applicationMonitor.ExplorerStarted -= ApplicationMonitor_ExplorerStarted;
|
||||
displayMonitor.DisplayChanged -= DisplayMonitor_DisplaySettingsChanged;
|
||||
processMonitor.ExplorerStarted -= ProcessMonitor_ExplorerStarted;
|
||||
runtime.ConnectionLost -= Runtime_ConnectionLost;
|
||||
taskbar.QuitButtonClicked -= Shell_QuitButtonClicked;
|
||||
terminationActivator.Activated -= TerminationActivator_Activated;
|
||||
windowMonitor.WindowChanged -= WindowMonitor_WindowChanged;
|
||||
|
||||
if (Browser != null)
|
||||
{
|
||||
|
@ -226,6 +221,18 @@ namespace SafeExamBrowser.Client
|
|||
Browser.Start();
|
||||
}
|
||||
|
||||
private void ApplicationMonitor_ExplorerStarted()
|
||||
{
|
||||
logger.Info("Trying to terminate Windows explorer...");
|
||||
explorerShell.Terminate();
|
||||
logger.Info("Reinitializing working area...");
|
||||
displayMonitor.InitializePrimaryDisplay(taskbar.GetAbsoluteHeight());
|
||||
logger.Info("Reinitializing shell...");
|
||||
actionCenter.InitializeBounds();
|
||||
taskbar.InitializeBounds();
|
||||
logger.Info("Desktop successfully restored.");
|
||||
}
|
||||
|
||||
private void Browser_ConfigurationDownloadRequested(string fileName, DownloadEventArgs args)
|
||||
{
|
||||
if (Settings.ConfigurationMode == ConfigurationMode.ConfigureClient)
|
||||
|
@ -339,6 +346,11 @@ namespace SafeExamBrowser.Client
|
|||
logger.Info("Desktop successfully restored.");
|
||||
}
|
||||
|
||||
private void Operations_ActionRequired(ActionRequiredEventArgs args)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
private void Operations_ProgressChanged(ProgressChangedEventArgs args)
|
||||
{
|
||||
if (args.CurrentValue.HasValue)
|
||||
|
@ -372,18 +384,6 @@ namespace SafeExamBrowser.Client
|
|||
splashScreen?.UpdateStatus(status, true);
|
||||
}
|
||||
|
||||
private void ProcessMonitor_ExplorerStarted()
|
||||
{
|
||||
logger.Info("Trying to terminate Windows explorer...");
|
||||
explorerShell.Terminate();
|
||||
logger.Info("Reinitializing working area...");
|
||||
displayMonitor.InitializePrimaryDisplay(taskbar.GetAbsoluteHeight());
|
||||
logger.Info("Reinitializing shell...");
|
||||
actionCenter.InitializeBounds();
|
||||
taskbar.InitializeBounds();
|
||||
logger.Info("Desktop successfully restored.");
|
||||
}
|
||||
|
||||
private void Runtime_ConnectionLost()
|
||||
{
|
||||
logger.Error("Lost connection to the runtime!");
|
||||
|
@ -406,21 +406,6 @@ namespace SafeExamBrowser.Client
|
|||
terminationActivator.Resume();
|
||||
}
|
||||
|
||||
private void WindowMonitor_WindowChanged(IntPtr window)
|
||||
{
|
||||
var allowed = processMonitor.BelongsToAllowedProcess(window);
|
||||
|
||||
if (!allowed)
|
||||
{
|
||||
var success = windowMonitor.Hide(window);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
windowMonitor.Close(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryInitiateShutdown()
|
||||
{
|
||||
var hasQuitPassword = !String.IsNullOrEmpty(Settings.QuitPasswordHash);
|
||||
|
|
|
@ -23,7 +23,6 @@ using SafeExamBrowser.Communication.Contracts.Proxies;
|
|||
using SafeExamBrowser.Communication.Hosts;
|
||||
using SafeExamBrowser.Communication.Proxies;
|
||||
using SafeExamBrowser.Configuration.Contracts;
|
||||
using SafeExamBrowser.Settings.UserInterface;
|
||||
using SafeExamBrowser.Configuration.Cryptography;
|
||||
using SafeExamBrowser.Core.Contracts.OperationModel;
|
||||
using SafeExamBrowser.Core.OperationModel;
|
||||
|
@ -32,13 +31,13 @@ using SafeExamBrowser.I18n;
|
|||
using SafeExamBrowser.I18n.Contracts;
|
||||
using SafeExamBrowser.Logging;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Processes;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Windows;
|
||||
using SafeExamBrowser.Monitoring.Applications;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Applications;
|
||||
using SafeExamBrowser.Monitoring.Display;
|
||||
using SafeExamBrowser.Monitoring.Keyboard;
|
||||
using SafeExamBrowser.Monitoring.Mouse;
|
||||
using SafeExamBrowser.Monitoring.Processes;
|
||||
using SafeExamBrowser.Monitoring.Windows;
|
||||
using SafeExamBrowser.Settings.Logging;
|
||||
using SafeExamBrowser.Settings.UserInterface;
|
||||
using SafeExamBrowser.SystemComponents;
|
||||
using SafeExamBrowser.SystemComponents.Audio;
|
||||
using SafeExamBrowser.SystemComponents.Contracts;
|
||||
|
@ -52,7 +51,6 @@ using SafeExamBrowser.WindowsApi;
|
|||
using SafeExamBrowser.WindowsApi.Contracts;
|
||||
using Desktop = SafeExamBrowser.UserInterface.Desktop;
|
||||
using Mobile = SafeExamBrowser.UserInterface.Mobile;
|
||||
using SafeExamBrowser.Settings.Logging;
|
||||
|
||||
namespace SafeExamBrowser.Client
|
||||
{
|
||||
|
@ -60,17 +58,18 @@ namespace SafeExamBrowser.Client
|
|||
{
|
||||
private Guid authenticationToken;
|
||||
private ClientConfiguration configuration;
|
||||
private ClientContext context;
|
||||
private string logFilePath;
|
||||
private LogLevel logLevel;
|
||||
private string runtimeHostUri;
|
||||
private UserInterfaceMode uiMode;
|
||||
|
||||
private IActionCenter actionCenter;
|
||||
private IApplicationMonitor applicationMonitor;
|
||||
private IBrowserApplication browser;
|
||||
private IClientHost clientHost;
|
||||
private ILogger logger;
|
||||
private IMessageBox messageBox;
|
||||
private IProcessMonitor processMonitor;
|
||||
private INativeMethods nativeMethods;
|
||||
private IRuntimeProxy runtimeProxy;
|
||||
private ISystemInfo systemInfo;
|
||||
|
@ -79,7 +78,6 @@ namespace SafeExamBrowser.Client
|
|||
private IText text;
|
||||
private ITextResource textResource;
|
||||
private IUserInterfaceFactory uiFactory;
|
||||
private IWindowMonitor windowMonitor;
|
||||
|
||||
internal IClientController ClientController { get; private set; }
|
||||
|
||||
|
@ -96,13 +94,13 @@ namespace SafeExamBrowser.Client
|
|||
InitializeText();
|
||||
|
||||
actionCenter = BuildActionCenter();
|
||||
applicationMonitor = new ApplicationMonitor(new ModuleLogger(logger, nameof(ApplicationMonitor)), nativeMethods);
|
||||
context = new ClientContext();
|
||||
messageBox = BuildMessageBox();
|
||||
processMonitor = new ProcessMonitor(new ModuleLogger(logger, nameof(ProcessMonitor)), nativeMethods);
|
||||
uiFactory = BuildUserInterfaceFactory();
|
||||
runtimeProxy = new RuntimeProxy(runtimeHostUri, new ProxyObjectFactory(), new ModuleLogger(logger, nameof(RuntimeProxy)), Interlocutor.Client);
|
||||
taskbar = BuildTaskbar();
|
||||
terminationActivator = new TerminationActivator(new ModuleLogger(logger, nameof(TerminationActivator)));
|
||||
windowMonitor = new WindowMonitor(new ModuleLogger(logger, nameof(WindowMonitor)), nativeMethods);
|
||||
|
||||
var displayMonitor = new DisplayMonitor(new ModuleLogger(logger, nameof(DisplayMonitor)), nativeMethods, systemInfo);
|
||||
var explorerShell = new ExplorerShell(new ModuleLogger(logger, nameof(ExplorerShell)), nativeMethods);
|
||||
|
@ -112,14 +110,13 @@ namespace SafeExamBrowser.Client
|
|||
|
||||
operations.Enqueue(new I18nOperation(logger, text, textResource));
|
||||
operations.Enqueue(new RuntimeConnectionOperation(logger, runtimeProxy, authenticationToken));
|
||||
operations.Enqueue(new ConfigurationOperation(configuration, logger, runtimeProxy));
|
||||
operations.Enqueue(new ConfigurationOperation(configuration, context, logger, runtimeProxy));
|
||||
operations.Enqueue(new DelegateOperation(UpdateAppConfig));
|
||||
operations.Enqueue(new LazyInitializationOperation(BuildClientHostOperation));
|
||||
operations.Enqueue(new LazyInitializationOperation(BuildClientHostDisconnectionOperation));
|
||||
operations.Enqueue(new LazyInitializationOperation(BuildKeyboardInterceptorOperation));
|
||||
operations.Enqueue(new LazyInitializationOperation(BuildMouseInterceptorOperation));
|
||||
operations.Enqueue(new LazyInitializationOperation(BuildWindowMonitorOperation));
|
||||
operations.Enqueue(new LazyInitializationOperation(BuildProcessMonitorOperation));
|
||||
operations.Enqueue(new LazyInitializationOperation(BuildApplicationOperation));
|
||||
operations.Enqueue(new DisplayMonitorOperation(displayMonitor, logger, taskbar));
|
||||
operations.Enqueue(new LazyInitializationOperation(BuildShellOperation));
|
||||
operations.Enqueue(new LazyInitializationOperation(BuildBrowserOperation));
|
||||
|
@ -130,20 +127,19 @@ namespace SafeExamBrowser.Client
|
|||
|
||||
ClientController = new ClientController(
|
||||
actionCenter,
|
||||
applicationMonitor,
|
||||
displayMonitor,
|
||||
explorerShell,
|
||||
hashAlgorithm,
|
||||
logger,
|
||||
messageBox,
|
||||
sequence,
|
||||
processMonitor,
|
||||
runtimeProxy,
|
||||
shutdown,
|
||||
taskbar,
|
||||
terminationActivator,
|
||||
text,
|
||||
uiFactory,
|
||||
windowMonitor);
|
||||
uiFactory);
|
||||
}
|
||||
|
||||
internal void LogStartupInformation()
|
||||
|
@ -202,6 +198,11 @@ namespace SafeExamBrowser.Client
|
|||
textResource = new XmlTextResource(path);
|
||||
}
|
||||
|
||||
private IOperation BuildApplicationOperation()
|
||||
{
|
||||
return new ApplicationOperation(applicationMonitor, context, logger);
|
||||
}
|
||||
|
||||
private IOperation BuildBrowserOperation()
|
||||
{
|
||||
var moduleLogger = new ModuleLogger(logger, nameof(BrowserApplication));
|
||||
|
@ -238,25 +239,20 @@ namespace SafeExamBrowser.Client
|
|||
|
||||
private IOperation BuildKeyboardInterceptorOperation()
|
||||
{
|
||||
var keyboardInterceptor = new KeyboardInterceptor(configuration.Settings.Keyboard, new ModuleLogger(logger, nameof(KeyboardInterceptor)));
|
||||
var operation = new KeyboardInterceptorOperation(keyboardInterceptor, logger, nativeMethods);
|
||||
var keyboardInterceptor = new KeyboardInterceptor(configuration.Settings.Keyboard, new ModuleLogger(logger, nameof(KeyboardInterceptor)), nativeMethods);
|
||||
var operation = new KeyboardInterceptorOperation(keyboardInterceptor, logger);
|
||||
|
||||
return operation;
|
||||
}
|
||||
|
||||
private IOperation BuildMouseInterceptorOperation()
|
||||
{
|
||||
var mouseInterceptor = new MouseInterceptor(new ModuleLogger(logger, nameof(MouseInterceptor)), configuration.Settings.Mouse);
|
||||
var operation = new MouseInterceptorOperation(logger, mouseInterceptor, nativeMethods);
|
||||
var mouseInterceptor = new MouseInterceptor(new ModuleLogger(logger, nameof(MouseInterceptor)), configuration.Settings.Mouse, nativeMethods);
|
||||
var operation = new MouseInterceptorOperation(logger, mouseInterceptor);
|
||||
|
||||
return operation;
|
||||
}
|
||||
|
||||
private IOperation BuildProcessMonitorOperation()
|
||||
{
|
||||
return new ProcessMonitorOperation(logger, processMonitor, configuration.Settings);
|
||||
}
|
||||
|
||||
private IOperation BuildShellOperation()
|
||||
{
|
||||
var aboutInfo = new AboutNotificationInfo(text);
|
||||
|
@ -295,11 +291,6 @@ namespace SafeExamBrowser.Client
|
|||
return operation;
|
||||
}
|
||||
|
||||
private IOperation BuildWindowMonitorOperation()
|
||||
{
|
||||
return new WindowMonitorOperation(configuration.Settings.KioskMode, logger, windowMonitor);
|
||||
}
|
||||
|
||||
private IActionCenter BuildActionCenter()
|
||||
{
|
||||
switch (uiMode)
|
||||
|
|
136
SafeExamBrowser.Client/Operations/ApplicationOperation.cs
Normal file
136
SafeExamBrowser.Client/Operations/ApplicationOperation.cs
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SafeExamBrowser.Client.Operations.Events;
|
||||
using SafeExamBrowser.Core.Contracts.OperationModel;
|
||||
using SafeExamBrowser.Core.Contracts.OperationModel.Events;
|
||||
using SafeExamBrowser.I18n.Contracts;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Applications;
|
||||
using SafeExamBrowser.Settings;
|
||||
using SafeExamBrowser.Settings.Applications;
|
||||
|
||||
namespace SafeExamBrowser.Client.Operations
|
||||
{
|
||||
internal class ApplicationOperation : ClientOperation
|
||||
{
|
||||
private ILogger logger;
|
||||
private IApplicationMonitor applicationMonitor;
|
||||
|
||||
public override event ActionRequiredEventHandler ActionRequired;
|
||||
public override event StatusChangedEventHandler StatusChanged;
|
||||
|
||||
public ApplicationOperation(IApplicationMonitor applicationMonitor, ClientContext context, ILogger logger) : base(context)
|
||||
{
|
||||
this.applicationMonitor = applicationMonitor;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public override OperationResult Perform()
|
||||
{
|
||||
logger.Info("Initializing applications...");
|
||||
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeProcessMonitoring);
|
||||
|
||||
var result = InitializeApplications();
|
||||
|
||||
if (result == OperationResult.Success)
|
||||
{
|
||||
StartMonitor();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override OperationResult Revert()
|
||||
{
|
||||
logger.Info("Finalizing applications...");
|
||||
StatusChanged?.Invoke(TextKey.OperationStatus_StopProcessMonitoring);
|
||||
|
||||
TerminateApplications();
|
||||
StopMonitor();
|
||||
|
||||
return OperationResult.Success;
|
||||
}
|
||||
|
||||
private OperationResult InitializeApplications()
|
||||
{
|
||||
var initialization = applicationMonitor.Initialize(Context.Settings.Applications);
|
||||
var result = OperationResult.Success;
|
||||
|
||||
if (initialization.RunningApplications.Any())
|
||||
{
|
||||
result = TryTerminate(initialization.RunningApplications);
|
||||
}
|
||||
|
||||
if (result == OperationResult.Success)
|
||||
{
|
||||
foreach (var application in Context.Settings.Applications.Whitelist)
|
||||
{
|
||||
Create(application);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void Create(WhitelistApplication application)
|
||||
{
|
||||
// TODO: Use IApplicationFactory to create new application according to configuration, load into Context.Applications
|
||||
}
|
||||
|
||||
private void StartMonitor()
|
||||
{
|
||||
if (Context.Settings.KioskMode != KioskMode.None)
|
||||
{
|
||||
applicationMonitor.Start();
|
||||
}
|
||||
}
|
||||
|
||||
private void StopMonitor()
|
||||
{
|
||||
if (Context.Settings.KioskMode != KioskMode.None)
|
||||
{
|
||||
applicationMonitor.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
private void TerminateApplications()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private OperationResult TryTerminate(IEnumerable<RunningApplicationInfo> runningApplications)
|
||||
{
|
||||
var args = new ProcessTerminationEventArgs();
|
||||
var result = OperationResult.Success;
|
||||
|
||||
ActionRequired?.Invoke(args);
|
||||
|
||||
if (args.TerminateProcesses)
|
||||
{
|
||||
// TODO: Terminate all processes of all running applications
|
||||
|
||||
//foreach (var application in runningApplications)
|
||||
//{
|
||||
// foreach (var process in application.Processes)
|
||||
// {
|
||||
// process.Kill();
|
||||
// }
|
||||
//}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = OperationResult.Aborted;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
32
SafeExamBrowser.Client/Operations/ClientOperation.cs
Normal file
32
SafeExamBrowser.Client/Operations/ClientOperation.cs
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using SafeExamBrowser.Core.Contracts.OperationModel;
|
||||
using SafeExamBrowser.Core.Contracts.OperationModel.Events;
|
||||
|
||||
namespace SafeExamBrowser.Client.Operations
|
||||
{
|
||||
/// <summary>
|
||||
/// The base implementation to be used for all operations in the client operation sequence.
|
||||
/// </summary>
|
||||
internal abstract class ClientOperation : IOperation
|
||||
{
|
||||
protected ClientContext Context { get; private set; }
|
||||
|
||||
public abstract event ActionRequiredEventHandler ActionRequired;
|
||||
public abstract event StatusChangedEventHandler StatusChanged;
|
||||
|
||||
public ClientOperation(ClientContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
public abstract OperationResult Perform();
|
||||
public abstract OperationResult Revert();
|
||||
}
|
||||
}
|
|
@ -15,23 +15,24 @@ using SafeExamBrowser.Logging.Contracts;
|
|||
|
||||
namespace SafeExamBrowser.Client.Operations
|
||||
{
|
||||
internal class ConfigurationOperation : IOperation
|
||||
internal class ConfigurationOperation : ClientOperation
|
||||
{
|
||||
private ClientConfiguration configuration;
|
||||
private ILogger logger;
|
||||
private IRuntimeProxy runtime;
|
||||
|
||||
public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
|
||||
public event StatusChangedEventHandler StatusChanged;
|
||||
public override event ActionRequiredEventHandler ActionRequired { add { } remove { } }
|
||||
public override event StatusChangedEventHandler StatusChanged;
|
||||
|
||||
public ConfigurationOperation(ClientConfiguration configuration, ILogger logger, IRuntimeProxy runtime)
|
||||
// TODO: Remove and delete ClientConfiguration!
|
||||
public ConfigurationOperation(ClientConfiguration configuration, ClientContext context, ILogger logger, IRuntimeProxy runtime) : base(context)
|
||||
{
|
||||
this.configuration = configuration;
|
||||
this.logger = logger;
|
||||
this.runtime = runtime;
|
||||
}
|
||||
|
||||
public OperationResult Perform()
|
||||
public override OperationResult Perform()
|
||||
{
|
||||
logger.Info("Initializing application configuration...");
|
||||
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeConfiguration);
|
||||
|
@ -43,6 +44,9 @@ namespace SafeExamBrowser.Client.Operations
|
|||
configuration.SessionId = config.SessionId;
|
||||
configuration.Settings = config.Settings;
|
||||
|
||||
Context.AppConfig = config.AppConfig;
|
||||
Context.Settings = config.Settings;
|
||||
|
||||
logger.Info("Successfully retrieved the application configuration from the runtime.");
|
||||
logger.Info($" -> Client-ID: {configuration.AppConfig.ClientId}");
|
||||
logger.Info($" -> Runtime-ID: {configuration.AppConfig.RuntimeId}");
|
||||
|
@ -51,7 +55,7 @@ namespace SafeExamBrowser.Client.Operations
|
|||
return OperationResult.Success;
|
||||
}
|
||||
|
||||
public OperationResult Revert()
|
||||
public override OperationResult Revert()
|
||||
{
|
||||
return OperationResult.Success;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using SafeExamBrowser.Core.Contracts.OperationModel.Events;
|
||||
|
||||
namespace SafeExamBrowser.Client.Operations.Events
|
||||
{
|
||||
internal class ProcessTerminationEventArgs : ActionRequiredEventArgs
|
||||
{
|
||||
public bool TerminateProcesses { get; set; }
|
||||
}
|
||||
}
|
|
@ -11,7 +11,6 @@ using SafeExamBrowser.Core.Contracts.OperationModel.Events;
|
|||
using SafeExamBrowser.I18n.Contracts;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Keyboard;
|
||||
using SafeExamBrowser.WindowsApi.Contracts;
|
||||
|
||||
namespace SafeExamBrowser.Client.Operations
|
||||
{
|
||||
|
@ -19,19 +18,14 @@ namespace SafeExamBrowser.Client.Operations
|
|||
{
|
||||
private IKeyboardInterceptor keyboardInterceptor;
|
||||
private ILogger logger;
|
||||
private INativeMethods nativeMethods;
|
||||
|
||||
public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
|
||||
public event StatusChangedEventHandler StatusChanged;
|
||||
|
||||
public KeyboardInterceptorOperation(
|
||||
IKeyboardInterceptor keyboardInterceptor,
|
||||
ILogger logger,
|
||||
INativeMethods nativeMethods)
|
||||
public KeyboardInterceptorOperation(IKeyboardInterceptor keyboardInterceptor, ILogger logger)
|
||||
{
|
||||
this.keyboardInterceptor = keyboardInterceptor;
|
||||
this.logger = logger;
|
||||
this.nativeMethods = nativeMethods;
|
||||
}
|
||||
|
||||
public OperationResult Perform()
|
||||
|
@ -39,7 +33,7 @@ namespace SafeExamBrowser.Client.Operations
|
|||
logger.Info("Starting keyboard interception...");
|
||||
StatusChanged?.Invoke(TextKey.OperationStatus_StartKeyboardInterception);
|
||||
|
||||
nativeMethods.RegisterKeyboardHook(keyboardInterceptor);
|
||||
keyboardInterceptor.Start();
|
||||
|
||||
return OperationResult.Success;
|
||||
}
|
||||
|
@ -49,7 +43,7 @@ namespace SafeExamBrowser.Client.Operations
|
|||
logger.Info("Stopping keyboard interception...");
|
||||
StatusChanged?.Invoke(TextKey.OperationStatus_StopKeyboardInterception);
|
||||
|
||||
nativeMethods.DeregisterKeyboardHook(keyboardInterceptor);
|
||||
keyboardInterceptor.Stop();
|
||||
|
||||
return OperationResult.Success;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ using SafeExamBrowser.Core.Contracts.OperationModel.Events;
|
|||
using SafeExamBrowser.I18n.Contracts;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Mouse;
|
||||
using SafeExamBrowser.WindowsApi.Contracts;
|
||||
|
||||
namespace SafeExamBrowser.Client.Operations
|
||||
{
|
||||
|
@ -19,19 +18,14 @@ namespace SafeExamBrowser.Client.Operations
|
|||
{
|
||||
private ILogger logger;
|
||||
private IMouseInterceptor mouseInterceptor;
|
||||
private INativeMethods nativeMethods;
|
||||
|
||||
public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
|
||||
public event StatusChangedEventHandler StatusChanged;
|
||||
|
||||
public MouseInterceptorOperation(
|
||||
ILogger logger,
|
||||
IMouseInterceptor mouseInterceptor,
|
||||
INativeMethods nativeMethods)
|
||||
public MouseInterceptorOperation(ILogger logger, IMouseInterceptor mouseInterceptor)
|
||||
{
|
||||
this.logger = logger;
|
||||
this.mouseInterceptor = mouseInterceptor;
|
||||
this.nativeMethods = nativeMethods;
|
||||
}
|
||||
|
||||
public OperationResult Perform()
|
||||
|
@ -39,7 +33,7 @@ namespace SafeExamBrowser.Client.Operations
|
|||
logger.Info("Starting mouse interception...");
|
||||
StatusChanged?.Invoke(TextKey.OperationStatus_StartMouseInterception);
|
||||
|
||||
nativeMethods.RegisterMouseHook(mouseInterceptor);
|
||||
mouseInterceptor.Start();
|
||||
|
||||
return OperationResult.Success;
|
||||
}
|
||||
|
@ -49,7 +43,7 @@ namespace SafeExamBrowser.Client.Operations
|
|||
logger.Info("Stopping mouse interception...");
|
||||
StatusChanged?.Invoke(TextKey.OperationStatus_StopMouseInterception);
|
||||
|
||||
nativeMethods.DeregisterMouseHook(mouseInterceptor);
|
||||
mouseInterceptor.Stop();
|
||||
|
||||
return OperationResult.Success;
|
||||
}
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.Settings;
|
||||
using SafeExamBrowser.Core.Contracts.OperationModel;
|
||||
using SafeExamBrowser.Core.Contracts.OperationModel.Events;
|
||||
using SafeExamBrowser.I18n.Contracts;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Processes;
|
||||
|
||||
namespace SafeExamBrowser.Client.Operations
|
||||
{
|
||||
internal class ProcessMonitorOperation : IOperation
|
||||
{
|
||||
private ILogger logger;
|
||||
private IProcessMonitor processMonitor;
|
||||
private ApplicationSettings settings;
|
||||
|
||||
public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
|
||||
public event StatusChangedEventHandler StatusChanged;
|
||||
|
||||
public ProcessMonitorOperation(ILogger logger, IProcessMonitor processMonitor, ApplicationSettings settings)
|
||||
{
|
||||
this.logger = logger;
|
||||
this.processMonitor = processMonitor;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
public OperationResult Perform()
|
||||
{
|
||||
logger.Info("Initializing process monitoring...");
|
||||
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeProcessMonitoring);
|
||||
|
||||
if (settings.KioskMode == KioskMode.DisableExplorerShell)
|
||||
{
|
||||
processMonitor.StartMonitoringExplorer();
|
||||
}
|
||||
|
||||
return OperationResult.Success;
|
||||
}
|
||||
|
||||
public OperationResult Revert()
|
||||
{
|
||||
logger.Info("Stopping process monitoring...");
|
||||
StatusChanged?.Invoke(TextKey.OperationStatus_StopProcessMonitoring);
|
||||
|
||||
if (settings.KioskMode == KioskMode.DisableExplorerShell)
|
||||
{
|
||||
processMonitor.StopMonitoringExplorer();
|
||||
}
|
||||
|
||||
return OperationResult.Success;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.Settings;
|
||||
using SafeExamBrowser.Core.Contracts.OperationModel;
|
||||
using SafeExamBrowser.Core.Contracts.OperationModel.Events;
|
||||
using SafeExamBrowser.I18n.Contracts;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Windows;
|
||||
|
||||
namespace SafeExamBrowser.Client.Operations
|
||||
{
|
||||
internal class WindowMonitorOperation : IOperation
|
||||
{
|
||||
private KioskMode kioskMode;
|
||||
private ILogger logger;
|
||||
private IWindowMonitor windowMonitor;
|
||||
|
||||
public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
|
||||
public event StatusChangedEventHandler StatusChanged;
|
||||
|
||||
public WindowMonitorOperation(KioskMode kioskMode, ILogger logger, IWindowMonitor windowMonitor)
|
||||
{
|
||||
this.kioskMode = kioskMode;
|
||||
this.logger = logger;
|
||||
this.windowMonitor = windowMonitor;
|
||||
}
|
||||
|
||||
public OperationResult Perform()
|
||||
{
|
||||
logger.Info("Initializing window monitoring...");
|
||||
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeWindowMonitoring);
|
||||
|
||||
if (kioskMode != KioskMode.None)
|
||||
{
|
||||
windowMonitor.StartMonitoringWindows();
|
||||
}
|
||||
|
||||
return OperationResult.Success;
|
||||
}
|
||||
|
||||
public OperationResult Revert()
|
||||
{
|
||||
logger.Info("Stopping window monitoring...");
|
||||
StatusChanged?.Invoke(TextKey.OperationStatus_StopWindowMonitoring);
|
||||
|
||||
if (kioskMode != KioskMode.None)
|
||||
{
|
||||
windowMonitor.StopMonitoringWindows();
|
||||
}
|
||||
|
||||
return OperationResult.Success;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -71,9 +71,12 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="App.cs" />
|
||||
<Compile Include="ClientContext.cs" />
|
||||
<Compile Include="ClientController.cs" />
|
||||
<Compile Include="Operations\ClientHostDisconnectionOperation.cs" />
|
||||
<Compile Include="Operations\ClientOperation.cs" />
|
||||
<Compile Include="Operations\ConfigurationOperation.cs" />
|
||||
<Compile Include="Operations\Events\ProcessTerminationEventArgs.cs" />
|
||||
<Compile Include="Operations\RuntimeConnectionOperation.cs" />
|
||||
<Compile Include="Communication\ClientHost.cs" />
|
||||
<Compile Include="CompositionRoot.cs" />
|
||||
|
@ -88,9 +91,8 @@
|
|||
<Compile Include="Operations\DisplayMonitorOperation.cs" />
|
||||
<Compile Include="Operations\KeyboardInterceptorOperation.cs" />
|
||||
<Compile Include="Operations\MouseInterceptorOperation.cs" />
|
||||
<Compile Include="Operations\ProcessMonitorOperation.cs" />
|
||||
<Compile Include="Operations\ApplicationOperation.cs" />
|
||||
<Compile Include="Operations\ShellOperation.cs" />
|
||||
<Compile Include="Operations\WindowMonitorOperation.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
@ -220,6 +222,7 @@
|
|||
<ItemGroup>
|
||||
<Resource Include="SafeExamBrowser.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>robocopy "$(SolutionDir)SafeExamBrowser.Browser\bin\$(PlatformName)\$(ConfigurationName)" "$(ProjectDir)bin\$(PlatformName)\$(ConfigurationName)" /e /np
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using SafeExamBrowser.Settings;
|
||||
|
||||
namespace SafeExamBrowser.Configuration.Contracts
|
||||
{
|
||||
|
@ -29,6 +30,6 @@ namespace SafeExamBrowser.Configuration.Contracts
|
|||
/// <summary>
|
||||
/// The application settings to be used by the client.
|
||||
/// </summary>
|
||||
public Settings.ApplicationSettings Settings { get; set; }
|
||||
public AppSettings Settings { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ using System;
|
|||
using SafeExamBrowser.Configuration.Contracts.Cryptography;
|
||||
using SafeExamBrowser.Configuration.Contracts.DataFormats;
|
||||
using SafeExamBrowser.Configuration.Contracts.DataResources;
|
||||
using SafeExamBrowser.Settings;
|
||||
|
||||
namespace SafeExamBrowser.Configuration.Contracts
|
||||
{
|
||||
|
@ -36,7 +37,7 @@ namespace SafeExamBrowser.Configuration.Contracts
|
|||
/// <summary>
|
||||
/// Loads the default settings.
|
||||
/// </summary>
|
||||
Settings.ApplicationSettings LoadDefaultSettings();
|
||||
AppSettings LoadDefaultSettings();
|
||||
|
||||
/// <summary>
|
||||
/// Registers the specified <see cref="IDataParser"/> to be used to parse configuration data.
|
||||
|
@ -61,6 +62,6 @@ namespace SafeExamBrowser.Configuration.Contracts
|
|||
/// <summary>
|
||||
/// Attempts to load settings from the specified resource.
|
||||
/// </summary>
|
||||
LoadStatus TryLoadSettings(Uri resource, out Settings.ApplicationSettings settings, PasswordParameters password = null);
|
||||
LoadStatus TryLoadSettings(Uri resource, out AppSettings settings, PasswordParameters password = null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using SafeExamBrowser.Settings;
|
||||
|
||||
namespace SafeExamBrowser.Configuration.Contracts
|
||||
{
|
||||
|
@ -29,7 +30,7 @@ namespace SafeExamBrowser.Configuration.Contracts
|
|||
/// <summary>
|
||||
/// The application settings to be used by the service.
|
||||
/// </summary>
|
||||
public Settings.ApplicationSettings Settings { get; set; }
|
||||
public AppSettings Settings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The user name of the currently logged in user.
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using SafeExamBrowser.Settings;
|
||||
|
||||
namespace SafeExamBrowser.Configuration.Contracts
|
||||
{
|
||||
|
@ -16,7 +17,7 @@ namespace SafeExamBrowser.Configuration.Contracts
|
|||
public class SessionConfiguration
|
||||
{
|
||||
/// <summary>
|
||||
/// The active application configuration for this session.
|
||||
/// The application configuration for this session.
|
||||
/// </summary>
|
||||
public AppConfig AppConfig { get; set; }
|
||||
|
||||
|
@ -33,6 +34,6 @@ namespace SafeExamBrowser.Configuration.Contracts
|
|||
/// <summary>
|
||||
/// The settings used for this session.
|
||||
/// </summary>
|
||||
public Settings.ApplicationSettings Settings { get; set; }
|
||||
public AppSettings Settings { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.Collections.Generic;
|
||||
using SafeExamBrowser.Settings;
|
||||
using SafeExamBrowser.Settings.Applications;
|
||||
|
||||
namespace SafeExamBrowser.Configuration.ConfigurationData
|
||||
{
|
||||
internal partial class DataMapper
|
||||
{
|
||||
private void MapApplicationBlacklist(AppSettings settings, object value)
|
||||
{
|
||||
if (value is IList<object> applications)
|
||||
{
|
||||
foreach (var item in applications)
|
||||
{
|
||||
if (item is IDictionary<string, object> applicationData)
|
||||
{
|
||||
var isActive = applicationData.TryGetValue(Keys.Applications.ApplicationActive, out var v) && v is bool active && active;
|
||||
var isWindowsProcess = applicationData.TryGetValue(Keys.Applications.ApplicationOs, out v) && v is int os && os == Keys.WINDOWS;
|
||||
|
||||
if (isActive && isWindowsProcess)
|
||||
{
|
||||
var application = new BlacklistApplication();
|
||||
|
||||
if (applicationData.TryGetValue(Keys.Applications.ApplicationAutoTerminate, out v) && v is bool autoTerminate)
|
||||
{
|
||||
application.AutoTerminate = autoTerminate;
|
||||
}
|
||||
|
||||
if (applicationData.TryGetValue(Keys.Applications.ApplicationExecutable, out v) && v is string executableName)
|
||||
{
|
||||
application.ExecutableName = executableName;
|
||||
}
|
||||
|
||||
if (applicationData.TryGetValue(Keys.Applications.ApplicationOriginalName, out v) && v is string originalName)
|
||||
{
|
||||
application.ExecutableOriginalName = originalName;
|
||||
}
|
||||
|
||||
settings.Applications.Blacklist.Add(application);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void MapApplicationWhitelist(AppSettings settings, object value)
|
||||
{
|
||||
if (value is IList<object> applications)
|
||||
{
|
||||
foreach (var item in applications)
|
||||
{
|
||||
if (item is IDictionary<string, object> application)
|
||||
{
|
||||
var isActive = application.TryGetValue(Keys.Applications.ApplicationActive, out var v) && v is bool active && active;
|
||||
var isWindowsProcess = application.TryGetValue(Keys.Applications.ApplicationOs, out v) && v is int os && os == Keys.WINDOWS;
|
||||
|
||||
if (isActive && isWindowsProcess)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
{
|
||||
internal partial class DataMapper
|
||||
{
|
||||
private void MapInitialVolumeLevel(ApplicationSettings settings, object value)
|
||||
private void MapInitialVolumeLevel(AppSettings settings, object value)
|
||||
{
|
||||
if (value is int volume)
|
||||
{
|
||||
|
@ -20,7 +20,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapMuteAudio(ApplicationSettings settings, object value)
|
||||
private void MapMuteAudio(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool mute)
|
||||
{
|
||||
|
@ -28,7 +28,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapSetInitialVolumeLevel(ApplicationSettings settings, object value)
|
||||
private void MapSetInitialVolumeLevel(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool initialize)
|
||||
{
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
{
|
||||
internal partial class DataMapper
|
||||
{
|
||||
private void MapAllowAddressBar(ApplicationSettings settings, object value)
|
||||
private void MapAllowAddressBar(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool allow)
|
||||
{
|
||||
|
@ -23,7 +23,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapAllowAddressBarAdditionalWindow(ApplicationSettings settings, object value)
|
||||
private void MapAllowAddressBarAdditionalWindow(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool allow)
|
||||
{
|
||||
|
@ -31,7 +31,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapAllowConfigurationDownloads(ApplicationSettings settings, object value)
|
||||
private void MapAllowConfigurationDownloads(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool allow)
|
||||
{
|
||||
|
@ -39,7 +39,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapAllowDeveloperConsole(ApplicationSettings settings, object value)
|
||||
private void MapAllowDeveloperConsole(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool allow)
|
||||
{
|
||||
|
@ -48,7 +48,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapAllowDownloads(ApplicationSettings settings, object value)
|
||||
private void MapAllowDownloads(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool allow)
|
||||
{
|
||||
|
@ -56,7 +56,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapAllowNavigation(ApplicationSettings settings, object value)
|
||||
private void MapAllowNavigation(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool allow)
|
||||
{
|
||||
|
@ -65,7 +65,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapAllowNavigationAdditionalWindow(ApplicationSettings settings, object value)
|
||||
private void MapAllowNavigationAdditionalWindow(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool allow)
|
||||
{
|
||||
|
@ -74,7 +74,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapAllowPageZoom(ApplicationSettings settings, object value)
|
||||
private void MapAllowPageZoom(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool allow)
|
||||
{
|
||||
|
@ -82,7 +82,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapAllowPopups(ApplicationSettings settings, object value)
|
||||
private void MapAllowPopups(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool block)
|
||||
{
|
||||
|
@ -90,7 +90,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapAllowReload(ApplicationSettings settings, object value)
|
||||
private void MapAllowReload(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool allow)
|
||||
{
|
||||
|
@ -98,7 +98,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapAllowReloadAdditionalWindow(ApplicationSettings settings, object value)
|
||||
private void MapAllowReloadAdditionalWindow(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool allow)
|
||||
{
|
||||
|
@ -106,7 +106,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapEnableContentRequestFilter(ApplicationSettings settings, object value)
|
||||
private void MapEnableContentRequestFilter(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool process)
|
||||
{
|
||||
|
@ -114,7 +114,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapEnableMainRequestFilter(ApplicationSettings settings, object value)
|
||||
private void MapEnableMainRequestFilter(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool process)
|
||||
{
|
||||
|
@ -122,7 +122,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapUrlFilterRules(ApplicationSettings settings, object value)
|
||||
private void MapUrlFilterRules(AppSettings settings, object value)
|
||||
{
|
||||
const int ALLOW = 1;
|
||||
|
||||
|
@ -132,7 +132,9 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
{
|
||||
if (item is IDictionary<string, object> ruleData)
|
||||
{
|
||||
if (ruleData.TryGetValue(Keys.Browser.Filter.RuleIsActive, out var v) && v is bool active && active)
|
||||
var isActive = ruleData.TryGetValue(Keys.Browser.Filter.RuleIsActive, out var v) && v is bool active && active;
|
||||
|
||||
if (isActive)
|
||||
{
|
||||
var rule = new FilterRuleSettings();
|
||||
|
||||
|
@ -158,7 +160,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapMainWindowMode(ApplicationSettings settings, object value)
|
||||
private void MapMainWindowMode(AppSettings settings, object value)
|
||||
{
|
||||
const int FULLSCREEN = 1;
|
||||
|
||||
|
@ -168,7 +170,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapShowReloadWarning(ApplicationSettings settings, object value)
|
||||
private void MapShowReloadWarning(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool show)
|
||||
{
|
||||
|
@ -176,7 +178,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapShowReloadWarningAdditionalWindow(ApplicationSettings settings, object value)
|
||||
private void MapShowReloadWarningAdditionalWindow(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool show)
|
||||
{
|
||||
|
@ -184,7 +186,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapUserAgentMode(IDictionary<string, object> rawData, ApplicationSettings settings)
|
||||
private void MapUserAgentMode(IDictionary<string, object> rawData, AppSettings settings)
|
||||
{
|
||||
const int DEFAULT = 0;
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
{
|
||||
internal partial class DataMapper
|
||||
{
|
||||
private void MapConfigurationMode(ApplicationSettings settings, object value)
|
||||
private void MapConfigurationMode(AppSettings settings, object value)
|
||||
{
|
||||
const int CONFIGURE_CLIENT = 1;
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
{
|
||||
internal partial class DataMapper
|
||||
{
|
||||
private void MapAdminPasswordHash(ApplicationSettings settings, object value)
|
||||
private void MapAdminPasswordHash(AppSettings settings, object value)
|
||||
{
|
||||
if (value is string hash)
|
||||
{
|
||||
|
@ -22,7 +22,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapApplicationLogAccess(IDictionary<string, object> rawData, ApplicationSettings settings)
|
||||
private void MapApplicationLogAccess(IDictionary<string, object> rawData, AppSettings settings)
|
||||
{
|
||||
var hasValue = rawData.TryGetValue(Keys.General.AllowApplicationLog, out var value);
|
||||
|
||||
|
@ -42,7 +42,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapLogLevel(ApplicationSettings settings, object value)
|
||||
private void MapLogLevel(AppSettings settings, object value)
|
||||
{
|
||||
const int ERROR = 0, WARNING = 1, INFO = 2;
|
||||
|
||||
|
@ -52,7 +52,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapQuitPasswordHash(ApplicationSettings settings, object value)
|
||||
private void MapQuitPasswordHash(AppSettings settings, object value)
|
||||
{
|
||||
if (value is string hash)
|
||||
{
|
||||
|
@ -60,7 +60,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapStartUrl(ApplicationSettings settings, object value)
|
||||
private void MapStartUrl(AppSettings settings, object value)
|
||||
{
|
||||
if (value is string url)
|
||||
{
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
{
|
||||
internal partial class DataMapper
|
||||
{
|
||||
private void MapEnableAltEsc(ApplicationSettings settings, object value)
|
||||
private void MapEnableAltEsc(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool enabled)
|
||||
{
|
||||
|
@ -20,7 +20,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapEnableAltF4(ApplicationSettings settings, object value)
|
||||
private void MapEnableAltF4(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool enabled)
|
||||
{
|
||||
|
@ -28,7 +28,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapEnableAltTab(ApplicationSettings settings, object value)
|
||||
private void MapEnableAltTab(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool enabled)
|
||||
{
|
||||
|
@ -36,7 +36,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapEnableCtrlEsc(ApplicationSettings settings, object value)
|
||||
private void MapEnableCtrlEsc(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool enabled)
|
||||
{
|
||||
|
@ -44,7 +44,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapEnableEsc(ApplicationSettings settings, object value)
|
||||
private void MapEnableEsc(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool enabled)
|
||||
{
|
||||
|
@ -52,7 +52,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapEnableF1(ApplicationSettings settings, object value)
|
||||
private void MapEnableF1(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool enabled)
|
||||
{
|
||||
|
@ -60,7 +60,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapEnableF2(ApplicationSettings settings, object value)
|
||||
private void MapEnableF2(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool enabled)
|
||||
{
|
||||
|
@ -68,7 +68,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapEnableF3(ApplicationSettings settings, object value)
|
||||
private void MapEnableF3(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool enabled)
|
||||
{
|
||||
|
@ -76,7 +76,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapEnableF4(ApplicationSettings settings, object value)
|
||||
private void MapEnableF4(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool enabled)
|
||||
{
|
||||
|
@ -84,7 +84,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapEnableF5(ApplicationSettings settings, object value)
|
||||
private void MapEnableF5(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool enabled)
|
||||
{
|
||||
|
@ -92,7 +92,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapEnableF6(ApplicationSettings settings, object value)
|
||||
private void MapEnableF6(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool enabled)
|
||||
{
|
||||
|
@ -100,7 +100,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapEnableF7(ApplicationSettings settings, object value)
|
||||
private void MapEnableF7(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool enabled)
|
||||
{
|
||||
|
@ -108,7 +108,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapEnableF8(ApplicationSettings settings, object value)
|
||||
private void MapEnableF8(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool enabled)
|
||||
{
|
||||
|
@ -116,7 +116,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapEnableF9(ApplicationSettings settings, object value)
|
||||
private void MapEnableF9(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool enabled)
|
||||
{
|
||||
|
@ -124,7 +124,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapEnableF10(ApplicationSettings settings, object value)
|
||||
private void MapEnableF10(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool enabled)
|
||||
{
|
||||
|
@ -132,7 +132,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapEnableF11(ApplicationSettings settings, object value)
|
||||
private void MapEnableF11(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool enabled)
|
||||
{
|
||||
|
@ -140,7 +140,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapEnableF12(ApplicationSettings settings, object value)
|
||||
private void MapEnableF12(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool enabled)
|
||||
{
|
||||
|
@ -148,7 +148,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapEnablePrintScreen(ApplicationSettings settings, object value)
|
||||
private void MapEnablePrintScreen(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool enabled)
|
||||
{
|
||||
|
@ -156,7 +156,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapEnableSystemKey(ApplicationSettings settings, object value)
|
||||
private void MapEnableSystemKey(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool enabled)
|
||||
{
|
||||
|
@ -164,7 +164,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapEnableRightMouse(ApplicationSettings settings, object value)
|
||||
private void MapEnableRightMouse(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool enabled)
|
||||
{
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
{
|
||||
internal partial class DataMapper
|
||||
{
|
||||
private void MapKioskMode(IDictionary<string, object> rawData, ApplicationSettings settings)
|
||||
private void MapKioskMode(IDictionary<string, object> rawData, AppSettings settings)
|
||||
{
|
||||
var hasCreateNewDesktop = rawData.TryGetValue(Keys.Security.KioskModeCreateNewDesktop, out var createNewDesktop);
|
||||
var hasDisableExplorerShell = rawData.TryGetValue(Keys.Security.KioskModeDisableExplorerShell, out var disableExplorerShell);
|
||||
|
@ -35,7 +35,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapServicePolicy(ApplicationSettings settings, object value)
|
||||
private void MapServicePolicy(AppSettings settings, object value)
|
||||
{
|
||||
const int WARN = 1;
|
||||
const int FORCE = 2;
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
{
|
||||
internal partial class DataMapper
|
||||
{
|
||||
private void MapApplicationLogButton(ApplicationSettings settings, object value)
|
||||
private void MapApplicationLogButton(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool show)
|
||||
{
|
||||
|
@ -21,7 +21,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapAudio(ApplicationSettings settings, object value)
|
||||
private void MapAudio(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool show)
|
||||
{
|
||||
|
@ -30,7 +30,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapClock(ApplicationSettings settings, object value)
|
||||
private void MapClock(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool show)
|
||||
{
|
||||
|
@ -39,7 +39,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapKeyboardLayout(ApplicationSettings settings, object value)
|
||||
private void MapKeyboardLayout(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool show)
|
||||
{
|
||||
|
@ -48,7 +48,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapWirelessNetwork(ApplicationSettings settings, object value)
|
||||
private void MapWirelessNetwork(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool show)
|
||||
{
|
||||
|
@ -57,7 +57,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapUserInterfaceMode(ApplicationSettings settings, object value)
|
||||
private void MapUserInterfaceMode(AppSettings settings, object value)
|
||||
{
|
||||
if (value is bool mobile)
|
||||
{
|
||||
|
|
|
@ -13,10 +13,11 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
{
|
||||
internal partial class DataMapper
|
||||
{
|
||||
internal void MapRawDataToSettings(IDictionary<string, object> rawData, ApplicationSettings settings)
|
||||
internal void MapRawDataToSettings(IDictionary<string, object> rawData, AppSettings settings)
|
||||
{
|
||||
foreach (var item in rawData)
|
||||
{
|
||||
MapApplicationSettings(item.Key, item.Value, settings);
|
||||
MapAudioSettings(item.Key, item.Value, settings);
|
||||
MapBrowserSettings(item.Key, item.Value, settings);
|
||||
MapConfigurationFileSettings(item.Key, item.Value, settings);
|
||||
|
@ -31,7 +32,20 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
MapUserAgentMode(rawData, settings);
|
||||
}
|
||||
|
||||
private void MapAudioSettings(string key, object value, ApplicationSettings settings)
|
||||
private void MapApplicationSettings(string key, object value, AppSettings settings)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case Keys.Applications.Blacklist:
|
||||
MapApplicationBlacklist(settings, value);
|
||||
break;
|
||||
case Keys.Applications.Whitelist:
|
||||
MapApplicationWhitelist(settings, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void MapAudioSettings(string key, object value, AppSettings settings)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
|
@ -47,7 +61,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapBrowserSettings(string key, object value, ApplicationSettings settings)
|
||||
private void MapBrowserSettings(string key, object value, AppSettings settings)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
|
@ -105,7 +119,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapConfigurationFileSettings(string key, object value, ApplicationSettings settings)
|
||||
private void MapConfigurationFileSettings(string key, object value, AppSettings settings)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
|
@ -115,7 +129,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapGeneralSettings(string key, object value, ApplicationSettings settings)
|
||||
private void MapGeneralSettings(string key, object value, AppSettings settings)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
|
@ -134,7 +148,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapInputSettings(string key, object value, ApplicationSettings settings)
|
||||
private void MapInputSettings(string key, object value, AppSettings settings)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
|
@ -201,7 +215,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapSecuritySettings(string key, object value, ApplicationSettings settings)
|
||||
private void MapSecuritySettings(string key, object value, AppSettings settings)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
|
@ -211,7 +225,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
}
|
||||
}
|
||||
|
||||
private void MapUserInterfaceSettings(string key, object value, ApplicationSettings settings)
|
||||
private void MapUserInterfaceSettings(string key, object value, AppSettings settings)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
|
|
|
@ -99,9 +99,9 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
return configuration;
|
||||
}
|
||||
|
||||
internal ApplicationSettings LoadDefaultSettings()
|
||||
internal AppSettings LoadDefaultSettings()
|
||||
{
|
||||
var settings = new ApplicationSettings();
|
||||
var settings = new AppSettings();
|
||||
|
||||
settings.ActionCenter.EnableActionCenter = true;
|
||||
settings.ActionCenter.ShowApplicationInfo = true;
|
||||
|
|
|
@ -10,12 +10,21 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
{
|
||||
internal static class Keys
|
||||
{
|
||||
internal const int WINDOWS = 1;
|
||||
|
||||
internal static class AdditionalResources
|
||||
{
|
||||
}
|
||||
|
||||
internal static class Applications
|
||||
{
|
||||
internal const string ApplicationActive = "active";
|
||||
internal const string ApplicationAutoTerminate = "strongKill";
|
||||
internal const string ApplicationExecutable = "executable";
|
||||
internal const string ApplicationOriginalName = "originalName";
|
||||
internal const string ApplicationOs = "os";
|
||||
internal const string Blacklist = "prohibitedProcesses";
|
||||
internal const string Whitelist = "permittedProcesses";
|
||||
}
|
||||
|
||||
internal static class Audio
|
||||
|
|
|
@ -100,7 +100,7 @@ namespace SafeExamBrowser.Configuration
|
|||
return dataValues.InitializeSessionConfiguration();
|
||||
}
|
||||
|
||||
public ApplicationSettings LoadDefaultSettings()
|
||||
public AppSettings LoadDefaultSettings()
|
||||
{
|
||||
return dataValues.LoadDefaultSettings();
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ namespace SafeExamBrowser.Configuration
|
|||
resourceSavers.Add(saver);
|
||||
}
|
||||
|
||||
public LoadStatus TryLoadSettings(Uri resource, out ApplicationSettings settings, PasswordParameters password = null)
|
||||
public LoadStatus TryLoadSettings(Uri resource, out AppSettings settings, PasswordParameters password = null)
|
||||
{
|
||||
logger.Info($"Attempting to load '{resource}'...");
|
||||
|
||||
|
|
|
@ -66,6 +66,9 @@
|
|||
<Compile Include="DataFormats\BinarySerializer.cs" />
|
||||
<Compile Include="DataFormats\BinaryBlock.cs" />
|
||||
<Compile Include="ConfigurationData\DataMapper.cs" />
|
||||
<Compile Include="ConfigurationData\DataMapper.Applications.cs">
|
||||
<DependentUpon>DataMapper.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ConfigurationData\DataMapper.Audio.cs">
|
||||
<DependentUpon>DataMapper.cs</DependentUpon>
|
||||
</Compile>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
namespace SafeExamBrowser.Monitoring.Contracts.Processes.Events
|
||||
namespace SafeExamBrowser.Monitoring.Contracts.Applications.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that the Windows explorer process has started.
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.Monitoring.Contracts.Applications.Events;
|
||||
using SafeExamBrowser.Settings.Applications;
|
||||
|
||||
namespace SafeExamBrowser.Monitoring.Contracts.Applications
|
||||
{
|
||||
/// <summary>
|
||||
/// Monitors applications running on the computer.
|
||||
/// </summary>
|
||||
public interface IApplicationMonitor
|
||||
{
|
||||
/// <summary>
|
||||
/// Event fired when a new instance of the Windows Explorer has been started.
|
||||
/// </summary>
|
||||
event ExplorerStartedEventHandler ExplorerStarted;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the application monitor.
|
||||
/// </summary>
|
||||
InitializationResult Initialize(ApplicationSettings settings);
|
||||
|
||||
/// <summary>
|
||||
/// Starts monitoring all initialized applications. Windows Explorer will always be monitored.
|
||||
/// </summary>
|
||||
void Start();
|
||||
|
||||
/// <summary>
|
||||
/// Stops the application monitoring.
|
||||
/// </summary>
|
||||
void Stop();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.Collections.Generic;
|
||||
|
||||
namespace SafeExamBrowser.Monitoring.Contracts.Applications
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides information about the initialization of the <see cref="IApplicationMonitor"/>.
|
||||
/// </summary>
|
||||
public class InitializationResult
|
||||
{
|
||||
/// <summary>
|
||||
/// A list of currently running applications which need to be terminated.
|
||||
/// </summary>
|
||||
public IEnumerable<RunningApplicationInfo> RunningApplications { get; }
|
||||
|
||||
public InitializationResult()
|
||||
{
|
||||
RunningApplications = new List<RunningApplicationInfo>();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.Collections.Generic;
|
||||
using SafeExamBrowser.WindowsApi.Contracts;
|
||||
|
||||
namespace SafeExamBrowser.Monitoring.Contracts.Applications
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides information about a running application.
|
||||
/// </summary>
|
||||
public class RunningApplicationInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the application.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of processes which belong to the application.
|
||||
/// </summary>
|
||||
public IEnumerable<IProcess> Processes { get; set; }
|
||||
}
|
||||
}
|
|
@ -14,8 +14,13 @@ namespace SafeExamBrowser.Monitoring.Contracts.Keyboard
|
|||
public interface IKeyboardInterceptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns <c>true</c> if the given key should be blocked, otherwise <c>false</c>. The key code corresponds to a Win32 Virtual-Key.
|
||||
/// Starts intercepting keyboard input.
|
||||
/// </summary>
|
||||
bool Block(int keyCode, KeyModifier modifier, KeyState state);
|
||||
void Start();
|
||||
|
||||
/// <summary>
|
||||
/// Stops intercepting keyboard input.
|
||||
/// </summary>
|
||||
void Stop();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,8 +14,13 @@ namespace SafeExamBrowser.Monitoring.Contracts.Mouse
|
|||
public interface IMouseInterceptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns <c>true</c> if the given button should be blocked, otherwise <c>false</c>.
|
||||
/// Starts intercepting mouse input.
|
||||
/// </summary>
|
||||
bool Block(MouseButton button, MouseButtonState state);
|
||||
void Start();
|
||||
|
||||
/// <summary>
|
||||
/// Stops intercepting mouse input.
|
||||
/// </summary>
|
||||
void Stop();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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 SafeExamBrowser.Monitoring.Contracts.Processes.Events;
|
||||
|
||||
namespace SafeExamBrowser.Monitoring.Contracts.Processes
|
||||
{
|
||||
/// <summary>
|
||||
/// Monitors the processes running on the computer and provides access to process-related functionality.
|
||||
/// </summary>
|
||||
public interface IProcessMonitor
|
||||
{
|
||||
/// <summary>
|
||||
/// Event fired when the process monitor observes that a new instance of the Windows explorer has been started.
|
||||
/// </summary>
|
||||
event ExplorerStartedEventHandler ExplorerStarted;
|
||||
|
||||
/// <summary>
|
||||
/// Performs a check whether the process associated to the given window is allowed.
|
||||
/// </summary>
|
||||
bool BelongsToAllowedProcess(IntPtr window);
|
||||
|
||||
/// <summary>
|
||||
/// Starts monitoring the Windows explorer, i.e. any newly created instances of <c>explorer.exe</c> will trigger the
|
||||
/// <see cref="ExplorerStarted"/> event.
|
||||
/// </summary>
|
||||
void StartMonitoringExplorer();
|
||||
|
||||
/// <summary>
|
||||
/// Stops monitoring the Windows explorer.
|
||||
/// </summary>
|
||||
void StopMonitoringExplorer();
|
||||
}
|
||||
}
|
|
@ -53,19 +53,25 @@
|
|||
<Reference Include="Microsoft.CSharp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Applications\RunningApplicationInfo.cs" />
|
||||
<Compile Include="Display\Events\DisplayChangedEventHandler.cs" />
|
||||
<Compile Include="Processes\Events\ExplorerStartedEventHandler.cs" />
|
||||
<Compile Include="Windows\Events\WindowChangedEventHandler.cs" />
|
||||
<Compile Include="Applications\Events\ExplorerStartedEventHandler.cs" />
|
||||
<Compile Include="Display\IDisplayMonitor.cs" />
|
||||
<Compile Include="Keyboard\IKeyboardInterceptor.cs" />
|
||||
<Compile Include="Mouse\MouseButtonState.cs" />
|
||||
<Compile Include="Mouse\IMouseInterceptor.cs" />
|
||||
<Compile Include="Processes\IProcessMonitor.cs" />
|
||||
<Compile Include="Windows\IWindowMonitor.cs" />
|
||||
<Compile Include="Keyboard\KeyModifier.cs" />
|
||||
<Compile Include="Keyboard\KeyState.cs" />
|
||||
<Compile Include="Mouse\MouseButton.cs" />
|
||||
<Compile Include="Applications\InitializationResult.cs" />
|
||||
<Compile Include="Applications\IApplicationMonitor.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Settings\SafeExamBrowser.Settings.csproj">
|
||||
<Project>{30b2d907-5861-4f39-abad-c4abf1b3470e}</Project>
|
||||
<Name>SafeExamBrowser.Settings</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SafeExamBrowser.WindowsApi.Contracts\SafeExamBrowser.WindowsApi.Contracts.csproj">
|
||||
<Project>{7016f080-9aa5-41b2-a225-385ad877c171}</Project>
|
||||
<Name>SafeExamBrowser.WindowsApi.Contracts</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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 SafeExamBrowser.Monitoring.Contracts.Windows.Events;
|
||||
|
||||
namespace SafeExamBrowser.Monitoring.Contracts.Windows
|
||||
{
|
||||
/// <summary>
|
||||
/// Monitors the windows associated with the current desktop and provides window-related functionality.
|
||||
/// </summary>
|
||||
public interface IWindowMonitor
|
||||
{
|
||||
/// <summary>
|
||||
/// Event fired when the window monitor observes that the foreground window has changed.
|
||||
/// </summary>
|
||||
event WindowChangedEventHandler WindowChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Forcefully closes the specified window.
|
||||
/// </summary>
|
||||
void Close(IntPtr window);
|
||||
|
||||
/// <summary>
|
||||
/// Hides the specified window. Returns <c>true</c> if the window was successfully hidden, otherwise <c>false</c>.
|
||||
/// </summary>
|
||||
bool Hide(IntPtr window);
|
||||
|
||||
/// <summary>
|
||||
/// Starts monitoring application windows by subscribing to specific system events.
|
||||
/// If a window is shown which is not supposed to do so, it will be automatically hidden.
|
||||
/// </summary>
|
||||
void StartMonitoringWindows();
|
||||
|
||||
/// <summary>
|
||||
/// Stops monitoring windows and deregisters from any subscribed system events.
|
||||
/// </summary>
|
||||
void StopMonitoringWindows();
|
||||
}
|
||||
}
|
177
SafeExamBrowser.Monitoring/Applications/ApplicationMonitor.cs
Normal file
177
SafeExamBrowser.Monitoring/Applications/ApplicationMonitor.cs
Normal file
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.Diagnostics;
|
||||
using System.Management;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Applications;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Applications.Events;
|
||||
using SafeExamBrowser.Settings.Applications;
|
||||
using SafeExamBrowser.WindowsApi.Contracts;
|
||||
|
||||
namespace SafeExamBrowser.Monitoring.Applications
|
||||
{
|
||||
public class ApplicationMonitor : IApplicationMonitor
|
||||
{
|
||||
private IntPtr activeWindow;
|
||||
private Guid? captureHookId;
|
||||
private Guid? foregroundHookId;
|
||||
private ILogger logger;
|
||||
private INativeMethods nativeMethods;
|
||||
private ManagementEventWatcher explorerWatcher;
|
||||
|
||||
public event ExplorerStartedEventHandler ExplorerStarted;
|
||||
|
||||
public ApplicationMonitor(ILogger logger, INativeMethods nativeMethods)
|
||||
{
|
||||
this.logger = logger;
|
||||
this.nativeMethods = nativeMethods;
|
||||
}
|
||||
|
||||
public InitializationResult Initialize(ApplicationSettings settings)
|
||||
{
|
||||
// TODO
|
||||
// Initialize blacklist
|
||||
// Initialize whitelist
|
||||
// Check for running processes
|
||||
|
||||
return new InitializationResult();
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
// TODO: Start monitoring blacklist...
|
||||
|
||||
explorerWatcher = new ManagementEventWatcher(@"\\.\root\CIMV2", GetQueryFor("explorer.exe"));
|
||||
explorerWatcher.EventArrived += new EventArrivedEventHandler(ExplorerWatcher_EventArrived);
|
||||
explorerWatcher.Start();
|
||||
logger.Info("Started monitoring process 'explorer.exe'.");
|
||||
|
||||
captureHookId = nativeMethods.RegisterSystemCaptureStartEvent(SystemEvent_WindowChanged);
|
||||
logger.Info($"Registered system capture start event with ID = {captureHookId}.");
|
||||
|
||||
foregroundHookId = nativeMethods.RegisterSystemForegroundEvent(SystemEvent_WindowChanged);
|
||||
logger.Info($"Registered system foreground event with ID = {foregroundHookId}.");
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
explorerWatcher?.Stop();
|
||||
logger.Info("Stopped monitoring 'explorer.exe'.");
|
||||
|
||||
if (captureHookId.HasValue)
|
||||
{
|
||||
nativeMethods.DeregisterSystemEventHook(captureHookId.Value);
|
||||
logger.Info($"Unregistered system capture start event with ID = {captureHookId}.");
|
||||
}
|
||||
|
||||
if (foregroundHookId.HasValue)
|
||||
{
|
||||
nativeMethods.DeregisterSystemEventHook(foregroundHookId.Value);
|
||||
logger.Info($"Unregistered system foreground event with ID = {foregroundHookId}.");
|
||||
}
|
||||
}
|
||||
|
||||
public bool Terminate(int processId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private void Check(IntPtr window)
|
||||
{
|
||||
var allowed = IsAllowed(window);
|
||||
|
||||
if (!allowed)
|
||||
{
|
||||
var success = TryHide(window);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
Close(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Close(IntPtr window)
|
||||
{
|
||||
var title = nativeMethods.GetWindowTitle(window);
|
||||
|
||||
nativeMethods.SendCloseMessageTo(window);
|
||||
logger.Info($"Sent close message to window '{title}' with handle = {window}.");
|
||||
}
|
||||
|
||||
private bool IsAllowed(IntPtr window)
|
||||
{
|
||||
var processId = nativeMethods.GetProcessIdFor(window);
|
||||
var process = Process.GetProcessById(Convert.ToInt32(processId));
|
||||
|
||||
if (process != null)
|
||||
{
|
||||
var allowed = process.ProcessName == "SafeExamBrowser" || process.ProcessName == "SafeExamBrowser.Client";
|
||||
|
||||
if (!allowed)
|
||||
{
|
||||
logger.Warn($"Window with handle = {window} belongs to not allowed process '{process.ProcessName}'!");
|
||||
}
|
||||
|
||||
return allowed;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryHide(IntPtr window)
|
||||
{
|
||||
var title = nativeMethods.GetWindowTitle(window);
|
||||
var success = nativeMethods.HideWindow(window);
|
||||
|
||||
if (success)
|
||||
{
|
||||
logger.Info($"Hid window '{title}' with handle = {window}.");
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Warn($"Failed to hide window '{title}' with handle = {window}!");
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
private void ExplorerWatcher_EventArrived(object sender, EventArrivedEventArgs e)
|
||||
{
|
||||
var eventName = e.NewEvent.ClassPath.ClassName;
|
||||
|
||||
if (eventName == "__InstanceCreationEvent")
|
||||
{
|
||||
logger.Warn("A new instance of Windows explorer has been started!");
|
||||
ExplorerStarted?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
private void SystemEvent_WindowChanged(IntPtr window)
|
||||
{
|
||||
if (window != IntPtr.Zero && activeWindow != window)
|
||||
{
|
||||
logger.Debug($"Window has changed from {activeWindow} to {window}.");
|
||||
activeWindow = window;
|
||||
Check(window);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetQueryFor(string processName)
|
||||
{
|
||||
return $@"
|
||||
SELECT *
|
||||
FROM __InstanceOperationEvent
|
||||
WITHIN 2
|
||||
WHERE TargetInstance ISA 'Win32_Process'
|
||||
AND TargetInstance.Name = '{processName}'";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,24 +9,42 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Windows.Input;
|
||||
using SafeExamBrowser.Settings.Monitoring;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Keyboard;
|
||||
using SafeExamBrowser.Settings.Monitoring;
|
||||
using SafeExamBrowser.WindowsApi.Contracts;
|
||||
using SafeExamBrowser.WindowsApi.Contracts.Events;
|
||||
|
||||
namespace SafeExamBrowser.Monitoring.Keyboard
|
||||
{
|
||||
public class KeyboardInterceptor : IKeyboardInterceptor
|
||||
{
|
||||
private KeyboardSettings settings;
|
||||
private Guid? hookId;
|
||||
private ILogger logger;
|
||||
private INativeMethods nativeMethods;
|
||||
private KeyboardSettings settings;
|
||||
|
||||
public KeyboardInterceptor(KeyboardSettings settings, ILogger logger)
|
||||
public KeyboardInterceptor(KeyboardSettings settings, ILogger logger, INativeMethods nativeMethods)
|
||||
{
|
||||
this.logger = logger;
|
||||
this.nativeMethods = nativeMethods;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
public bool Block(int keyCode, KeyModifier modifier, KeyState state)
|
||||
public void Start()
|
||||
{
|
||||
hookId = nativeMethods.RegisterKeyboardHook(KeyboardHookCallback);
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
if (hookId.HasValue)
|
||||
{
|
||||
nativeMethods.DeregisterKeyboardHook(hookId.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private bool KeyboardHookCallback(int keyCode, KeyModifier modifier, KeyState state)
|
||||
{
|
||||
var block = false;
|
||||
var key = KeyInterop.KeyFromVirtualKey(keyCode);
|
||||
|
|
|
@ -6,24 +6,43 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using SafeExamBrowser.Settings.Monitoring;
|
||||
using System;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Mouse;
|
||||
using SafeExamBrowser.Settings.Monitoring;
|
||||
using SafeExamBrowser.WindowsApi.Contracts;
|
||||
using SafeExamBrowser.WindowsApi.Contracts.Events;
|
||||
|
||||
namespace SafeExamBrowser.Monitoring.Mouse
|
||||
{
|
||||
public class MouseInterceptor : IMouseInterceptor
|
||||
{
|
||||
private Guid? hookId;
|
||||
private ILogger logger;
|
||||
private INativeMethods nativeMethods;
|
||||
private MouseSettings settings;
|
||||
|
||||
public MouseInterceptor(ILogger logger, MouseSettings settings)
|
||||
public MouseInterceptor(ILogger logger, MouseSettings settings, INativeMethods nativeMethods)
|
||||
{
|
||||
this.logger = logger;
|
||||
this.nativeMethods = nativeMethods;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
public bool Block(MouseButton button, MouseButtonState state)
|
||||
public void Start()
|
||||
{
|
||||
hookId = nativeMethods.RegisterMouseHook(MouseHookCallback);
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
if (hookId.HasValue)
|
||||
{
|
||||
nativeMethods.DeregisterMouseHook(hookId.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private bool MouseHookCallback(MouseButton button, MouseButtonState state)
|
||||
{
|
||||
var block = false;
|
||||
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.Diagnostics;
|
||||
using System.Management;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Processes;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Processes.Events;
|
||||
using SafeExamBrowser.WindowsApi.Contracts;
|
||||
|
||||
namespace SafeExamBrowser.Monitoring.Processes
|
||||
{
|
||||
public class ProcessMonitor : IProcessMonitor
|
||||
{
|
||||
private ILogger logger;
|
||||
private INativeMethods nativeMethods;
|
||||
private ManagementEventWatcher explorerWatcher;
|
||||
|
||||
public event ExplorerStartedEventHandler ExplorerStarted;
|
||||
|
||||
public ProcessMonitor(ILogger logger, INativeMethods nativeMethods)
|
||||
{
|
||||
this.logger = logger;
|
||||
this.nativeMethods = nativeMethods;
|
||||
}
|
||||
|
||||
public bool BelongsToAllowedProcess(IntPtr window)
|
||||
{
|
||||
var processId = nativeMethods.GetProcessIdFor(window);
|
||||
var process = Process.GetProcessById(Convert.ToInt32(processId));
|
||||
|
||||
if (process != null)
|
||||
{
|
||||
var allowed = process.ProcessName == "SafeExamBrowser" || process.ProcessName == "SafeExamBrowser.Client";
|
||||
|
||||
if (!allowed)
|
||||
{
|
||||
logger.Warn($"Window with handle = {window} belongs to not allowed process '{process.ProcessName}'!");
|
||||
}
|
||||
|
||||
return allowed;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void StartMonitoringExplorer()
|
||||
{
|
||||
explorerWatcher = new ManagementEventWatcher(@"\\.\root\CIMV2", GetQueryFor("explorer.exe"));
|
||||
explorerWatcher.EventArrived += new EventArrivedEventHandler(ExplorerWatcher_EventArrived);
|
||||
explorerWatcher.Start();
|
||||
|
||||
logger.Info("Started monitoring process 'explorer.exe'.");
|
||||
}
|
||||
|
||||
public void StopMonitoringExplorer()
|
||||
{
|
||||
explorerWatcher?.Stop();
|
||||
logger.Info("Stopped monitoring 'explorer.exe'.");
|
||||
}
|
||||
|
||||
private void ExplorerWatcher_EventArrived(object sender, EventArrivedEventArgs e)
|
||||
{
|
||||
var eventName = e.NewEvent.ClassPath.ClassName;
|
||||
|
||||
if (eventName == "__InstanceCreationEvent")
|
||||
{
|
||||
logger.Warn("A new instance of Windows explorer has been started!");
|
||||
ExplorerStarted?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
private string GetQueryFor(string processName)
|
||||
{
|
||||
return $@"
|
||||
SELECT *
|
||||
FROM __InstanceOperationEvent
|
||||
WITHIN 2
|
||||
WHERE TargetInstance ISA 'Win32_Process'
|
||||
AND TargetInstance.Name = '{processName}'";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -60,9 +60,8 @@
|
|||
<Compile Include="Display\DisplayMonitor.cs" />
|
||||
<Compile Include="Keyboard\KeyboardInterceptor.cs" />
|
||||
<Compile Include="Mouse\MouseInterceptor.cs" />
|
||||
<Compile Include="Processes\ProcessMonitor.cs" />
|
||||
<Compile Include="Applications\ApplicationMonitor.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Windows\WindowMonitor.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Logging.Contracts\SafeExamBrowser.Logging.Contracts.csproj">
|
||||
|
|
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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 SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Windows;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Windows.Events;
|
||||
using SafeExamBrowser.WindowsApi.Contracts;
|
||||
|
||||
namespace SafeExamBrowser.Monitoring.Windows
|
||||
{
|
||||
public class WindowMonitor : IWindowMonitor
|
||||
{
|
||||
private IntPtr activeWindow;
|
||||
private Guid? captureHookId;
|
||||
private Guid? foregroundHookId;
|
||||
private ILogger logger;
|
||||
private INativeMethods nativeMethods;
|
||||
|
||||
public event WindowChangedEventHandler WindowChanged;
|
||||
|
||||
public WindowMonitor(ILogger logger, INativeMethods nativeMethods)
|
||||
{
|
||||
this.logger = logger;
|
||||
this.nativeMethods = nativeMethods;
|
||||
}
|
||||
|
||||
public void Close(IntPtr window)
|
||||
{
|
||||
var title = nativeMethods.GetWindowTitle(window);
|
||||
|
||||
nativeMethods.SendCloseMessageTo(window);
|
||||
logger.Info($"Sent close message to window '{title}' with handle = {window}.");
|
||||
}
|
||||
|
||||
public bool Hide(IntPtr window)
|
||||
{
|
||||
var title = nativeMethods.GetWindowTitle(window);
|
||||
var success = nativeMethods.HideWindow(window);
|
||||
|
||||
if (success)
|
||||
{
|
||||
logger.Info($"Hid window '{title}' with handle = {window}.");
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Warn($"Failed to hide window '{title}' with handle = {window}!");
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
public void StartMonitoringWindows()
|
||||
{
|
||||
captureHookId = nativeMethods.RegisterSystemCaptureStartEvent(OnWindowChanged);
|
||||
logger.Info($"Registered system capture start event with ID = {captureHookId}.");
|
||||
|
||||
foregroundHookId = nativeMethods.RegisterSystemForegroundEvent(OnWindowChanged);
|
||||
logger.Info($"Registered system foreground event with ID = {foregroundHookId}.");
|
||||
}
|
||||
|
||||
public void StopMonitoringWindows()
|
||||
{
|
||||
if (captureHookId.HasValue)
|
||||
{
|
||||
nativeMethods.DeregisterSystemEventHook(captureHookId.Value);
|
||||
logger.Info($"Unregistered system capture start event with ID = {captureHookId}.");
|
||||
}
|
||||
|
||||
if (foregroundHookId.HasValue)
|
||||
{
|
||||
nativeMethods.DeregisterSystemEventHook(foregroundHookId.Value);
|
||||
logger.Info($"Unregistered system foreground event with ID = {foregroundHookId}.");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnWindowChanged(IntPtr window)
|
||||
{
|
||||
if (window != IntPtr.Zero && activeWindow != window)
|
||||
{
|
||||
logger.Debug($"Window has changed from {activeWindow} to {window}.");
|
||||
activeWindow = window;
|
||||
WindowChanged?.Invoke(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -171,7 +171,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication
|
|||
public void MustHandleConfigurationRequestCorrectly()
|
||||
{
|
||||
var args = default(ClientConfigurationEventArgs);
|
||||
var configuration = new ClientConfiguration { Settings = new ApplicationSettings { AdminPasswordHash = "12345" } };
|
||||
var configuration = new ClientConfiguration { Settings = new AppSettings { AdminPasswordHash = "12345" } };
|
||||
|
||||
sut.AllowConnection = true;
|
||||
sut.ClientConfigurationNeeded += (a) => { args = a; args.ClientConfiguration = configuration; };
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
private Mock<IRuntimeHost> runtimeHost;
|
||||
private SessionConfiguration session;
|
||||
private SessionContext sessionContext;
|
||||
private ApplicationSettings settings;
|
||||
private AppSettings settings;
|
||||
private ClientOperation sut;
|
||||
|
||||
[TestInitialize]
|
||||
|
@ -53,7 +53,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
runtimeHost = new Mock<IRuntimeHost>();
|
||||
session = new SessionConfiguration();
|
||||
sessionContext = new SessionContext();
|
||||
settings = new ApplicationSettings();
|
||||
settings = new AppSettings();
|
||||
terminated = new Action(() =>
|
||||
{
|
||||
runtimeHost.Raise(h => h.ClientDisconnected += null);
|
||||
|
|
|
@ -56,7 +56,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
[TestMethod]
|
||||
public void Perform_MustUseCommandLineArgumentAs1stPrio()
|
||||
{
|
||||
var settings = new ApplicationSettings { ConfigurationMode = ConfigurationMode.Exam };
|
||||
var settings = new AppSettings { ConfigurationMode = ConfigurationMode.Exam };
|
||||
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
||||
var location = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations), "Testdata", FILE_NAME);
|
||||
|
||||
|
@ -77,7 +77,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
public void Perform_MustUseProgramDataAs2ndPrio()
|
||||
{
|
||||
var location = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations), "Testdata", FILE_NAME);
|
||||
var settings = default(ApplicationSettings);
|
||||
var settings = default(AppSettings);
|
||||
|
||||
appConfig.ProgramDataFilePath = location;
|
||||
|
||||
|
@ -94,7 +94,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
public void Perform_MustUseAppDataAs3rdPrio()
|
||||
{
|
||||
var location = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations), "Testdata", FILE_NAME);
|
||||
var settings = default(ApplicationSettings);
|
||||
var settings = default(AppSettings);
|
||||
|
||||
appConfig.AppDataFilePath = location;
|
||||
repository.Setup(r => r.TryLoadSettings(It.IsAny<Uri>(), out settings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
|
||||
|
@ -109,7 +109,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
[TestMethod]
|
||||
public void Perform_MustTestdatalyHandleBrowserResource()
|
||||
{
|
||||
var settings = new ApplicationSettings { ConfigurationMode = ConfigurationMode.Exam };
|
||||
var settings = new AppSettings { ConfigurationMode = ConfigurationMode.Exam };
|
||||
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
||||
|
||||
nextSession.Settings = settings;
|
||||
|
@ -125,7 +125,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
[TestMethod]
|
||||
public void Perform_MustFallbackToDefaultsAsLastPrio()
|
||||
{
|
||||
var defaultSettings = new ApplicationSettings();
|
||||
var defaultSettings = new AppSettings();
|
||||
|
||||
repository.Setup(r => r.LoadDefaultSettings()).Returns(defaultSettings);
|
||||
|
||||
|
@ -141,7 +141,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
[TestMethod]
|
||||
public void Perform_MustAbortIfWishedByUser()
|
||||
{
|
||||
var settings = new ApplicationSettings();
|
||||
var settings = new AppSettings();
|
||||
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
||||
|
||||
sessionContext.Current = null;
|
||||
|
@ -166,7 +166,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
[TestMethod]
|
||||
public void Perform_MustNotAbortIfNotWishedByUser()
|
||||
{
|
||||
var settings = new ApplicationSettings();
|
||||
var settings = new AppSettings();
|
||||
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
||||
|
||||
settings.ConfigurationMode = ConfigurationMode.ConfigureClient;
|
||||
|
@ -191,7 +191,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
public void Perform_MustInformAboutClientConfigurationError()
|
||||
{
|
||||
var informed = false;
|
||||
var settings = new ApplicationSettings();
|
||||
var settings = new AppSettings();
|
||||
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
||||
|
||||
settings.ConfigurationMode = ConfigurationMode.ConfigureClient;
|
||||
|
@ -216,7 +216,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
[TestMethod]
|
||||
public void Perform_MustNotAllowToAbortIfNotInConfigureClientMode()
|
||||
{
|
||||
var settings = new ApplicationSettings();
|
||||
var settings = new AppSettings();
|
||||
|
||||
settings.ConfigurationMode = ConfigurationMode.Exam;
|
||||
repository.Setup(r => r.TryLoadSettings(It.IsAny<Uri>(), out settings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
|
||||
|
@ -238,7 +238,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
[TestMethod]
|
||||
public void Perform_MustNotFailWithoutCommandLineArgs()
|
||||
{
|
||||
var defaultSettings = new ApplicationSettings();
|
||||
var defaultSettings = new AppSettings();
|
||||
var result = OperationResult.Failed;
|
||||
|
||||
repository.Setup(r => r.LoadDefaultSettings()).Returns(defaultSettings);
|
||||
|
@ -272,8 +272,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
public void Perform_MustOnlyAllowToEnterAdminPasswordFiveTimes()
|
||||
{
|
||||
var count = 0;
|
||||
var localSettings = new ApplicationSettings { AdminPasswordHash = "1234" };
|
||||
var settings = new ApplicationSettings { AdminPasswordHash = "9876", ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||
var localSettings = new AppSettings { AdminPasswordHash = "1234" };
|
||||
var settings = new AppSettings { AdminPasswordHash = "9876", ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
||||
|
||||
appConfig.AppDataFilePath = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations), "Testdata", FILE_NAME);
|
||||
|
@ -302,7 +302,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
public void Perform_MustOnlyAllowToEnterSettingsPasswordFiveTimes()
|
||||
{
|
||||
var count = 0;
|
||||
var settings = default(ApplicationSettings);
|
||||
var settings = default(AppSettings);
|
||||
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
||||
|
||||
repository.Setup(r => r.TryLoadSettings(It.IsAny<Uri>(), out settings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.PasswordNeeded);
|
||||
|
@ -329,8 +329,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
public void Perform_MustSucceedIfAdminPasswordTestdata()
|
||||
{
|
||||
var password = "test";
|
||||
var currentSettings = new ApplicationSettings { AdminPasswordHash = "1234", ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||
var nextSettings = new ApplicationSettings { AdminPasswordHash = "9876", ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||
var currentSettings = new AppSettings { AdminPasswordHash = "1234", ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||
var nextSettings = new AppSettings { AdminPasswordHash = "9876", ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
||||
|
||||
nextSession.Settings = nextSettings;
|
||||
|
@ -359,8 +359,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
[TestMethod]
|
||||
public void Perform_MustNotAuthenticateIfSameAdminPassword()
|
||||
{
|
||||
var currentSettings = new ApplicationSettings { AdminPasswordHash = "1234", ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||
var nextSettings = new ApplicationSettings { AdminPasswordHash = "1234", ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||
var currentSettings = new AppSettings { AdminPasswordHash = "1234", ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||
var nextSettings = new AppSettings { AdminPasswordHash = "1234", ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
||||
|
||||
nextSession.Settings = nextSettings;
|
||||
|
@ -388,7 +388,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
public void Perform_MustSucceedIfSettingsPasswordTestdata()
|
||||
{
|
||||
var password = "test";
|
||||
var settings = new ApplicationSettings { ConfigurationMode = ConfigurationMode.Exam };
|
||||
var settings = new AppSettings { ConfigurationMode = ConfigurationMode.Exam };
|
||||
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
||||
|
||||
repository.Setup(r => r.TryLoadSettings(It.IsAny<Uri>(), out settings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.PasswordNeeded);
|
||||
|
@ -416,7 +416,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
{
|
||||
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
||||
var location = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations), "Testdata", FILE_NAME);
|
||||
var settings = new ApplicationSettings { AdminPasswordHash = "1234", ConfigurationMode = ConfigurationMode.Exam };
|
||||
var settings = new AppSettings { AdminPasswordHash = "1234", ConfigurationMode = ConfigurationMode.Exam };
|
||||
|
||||
appConfig.AppDataFilePath = location;
|
||||
|
||||
|
@ -442,8 +442,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
public void Perform_MustAbortAskingForAdminPasswordIfDecidedByUser()
|
||||
{
|
||||
var password = "test";
|
||||
var currentSettings = new ApplicationSettings { AdminPasswordHash = "1234", ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||
var nextSettings = new ApplicationSettings { AdminPasswordHash = "9876", ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||
var currentSettings = new AppSettings { AdminPasswordHash = "1234", ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||
var nextSettings = new AppSettings { AdminPasswordHash = "9876", ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
||||
|
||||
appConfig.AppDataFilePath = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations), "Testdata", FILE_NAME);
|
||||
|
@ -472,7 +472,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
[TestMethod]
|
||||
public void Perform_MustAbortAskingForSettingsPasswordIfDecidedByUser()
|
||||
{
|
||||
var settings = default(ApplicationSettings);
|
||||
var settings = default(AppSettings);
|
||||
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
||||
|
||||
repository.Setup(r => r.TryLoadSettings(It.IsAny<Uri>(), out settings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.PasswordNeeded);
|
||||
|
@ -494,10 +494,10 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
[TestMethod]
|
||||
public void Repeat_MustPerformForExamWithTestdataUri()
|
||||
{
|
||||
var currentSettings = new ApplicationSettings();
|
||||
var currentSettings = new AppSettings();
|
||||
var location = Path.GetDirectoryName(GetType().Assembly.Location);
|
||||
var resource = new Uri(Path.Combine(location, nameof(Operations), "Testdata", FILE_NAME));
|
||||
var settings = new ApplicationSettings { ConfigurationMode = ConfigurationMode.Exam };
|
||||
var settings = new AppSettings { ConfigurationMode = ConfigurationMode.Exam };
|
||||
|
||||
currentSession.Settings = currentSettings;
|
||||
sessionContext.ReconfigurationFilePath = resource.LocalPath;
|
||||
|
@ -515,10 +515,10 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
[TestMethod]
|
||||
public void Repeat_MustPerformForClientConfigurationWithTestdataUri()
|
||||
{
|
||||
var currentSettings = new ApplicationSettings();
|
||||
var currentSettings = new AppSettings();
|
||||
var location = Path.GetDirectoryName(GetType().Assembly.Location);
|
||||
var resource = new Uri(Path.Combine(location, nameof(Operations), "Testdata", FILE_NAME));
|
||||
var settings = new ApplicationSettings { ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||
var settings = new AppSettings { ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||
|
||||
currentSession.Settings = currentSettings;
|
||||
sessionContext.ReconfigurationFilePath = resource.LocalPath;
|
||||
|
@ -538,7 +538,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
public void Repeat_MustFailWithInvalidUri()
|
||||
{
|
||||
var resource = new Uri("file:///C:/does/not/exist.txt");
|
||||
var settings = default(ApplicationSettings);
|
||||
var settings = default(AppSettings);
|
||||
|
||||
sessionContext.ReconfigurationFilePath = null;
|
||||
repository.Setup(r => r.TryLoadSettings(It.IsAny<Uri>(), out settings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
|
||||
|
@ -559,10 +559,10 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
[TestMethod]
|
||||
public void Repeat_MustAbortForSettingsPasswordIfWishedByUser()
|
||||
{
|
||||
var currentSettings = new ApplicationSettings();
|
||||
var currentSettings = new AppSettings();
|
||||
var location = Path.GetDirectoryName(GetType().Assembly.Location);
|
||||
var resource = new Uri(Path.Combine(location, nameof(Operations), "Testdata", FILE_NAME));
|
||||
var settings = new ApplicationSettings { ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||
var settings = new AppSettings { ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||
|
||||
currentSession.Settings = currentSettings;
|
||||
sessionContext.ReconfigurationFilePath = resource.LocalPath;
|
||||
|
|
|
@ -21,12 +21,12 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
public class KioskModeOperationTests
|
||||
{
|
||||
private SessionConfiguration currentSession;
|
||||
private ApplicationSettings currentSettings;
|
||||
private AppSettings currentSettings;
|
||||
private Mock<IDesktopFactory> desktopFactory;
|
||||
private Mock<IExplorerShell> explorerShell;
|
||||
private Mock<ILogger> logger;
|
||||
private SessionConfiguration nextSession;
|
||||
private ApplicationSettings nextSettings;
|
||||
private AppSettings nextSettings;
|
||||
private Mock<IProcessFactory> processFactory;
|
||||
private SessionContext sessionContext;
|
||||
|
||||
|
@ -36,12 +36,12 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
public void Initialize()
|
||||
{
|
||||
currentSession = new SessionConfiguration();
|
||||
currentSettings = new ApplicationSettings();
|
||||
currentSettings = new AppSettings();
|
||||
desktopFactory = new Mock<IDesktopFactory>();
|
||||
explorerShell = new Mock<IExplorerShell>();
|
||||
logger = new Mock<ILogger>();
|
||||
nextSession = new SessionConfiguration();
|
||||
nextSettings = new ApplicationSettings();
|
||||
nextSettings = new AppSettings();
|
||||
processFactory = new Mock<IProcessFactory>();
|
||||
sessionContext = new SessionContext();
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
private EventWaitHandle serviceEvent;
|
||||
private SessionConfiguration session;
|
||||
private SessionContext sessionContext;
|
||||
private ApplicationSettings settings;
|
||||
private AppSettings settings;
|
||||
private Mock<IUserInfo> userInfo;
|
||||
private ServiceOperation sut;
|
||||
|
||||
|
@ -50,7 +50,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
serviceEvent = new EventWaitHandle(false, EventResetMode.AutoReset, serviceEventName);
|
||||
session = new SessionConfiguration();
|
||||
sessionContext = new SessionContext();
|
||||
settings = new ApplicationSettings();
|
||||
settings = new AppSettings();
|
||||
userInfo = new Mock<IUserInfo>();
|
||||
|
||||
appConfig.ServiceEventName = serviceEventName;
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using SafeExamBrowser.Configuration.Contracts;
|
||||
using SafeExamBrowser.Settings;
|
||||
using SafeExamBrowser.Core.Contracts.OperationModel;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.Runtime.Operations;
|
||||
using SafeExamBrowser.Settings;
|
||||
using SafeExamBrowser.Settings.Logging;
|
||||
|
||||
namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||
|
@ -23,7 +23,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
private SessionConfiguration currentSession;
|
||||
private Mock<ILogger> logger;
|
||||
private SessionConfiguration nextSession;
|
||||
private ApplicationSettings nextSettings;
|
||||
private AppSettings nextSettings;
|
||||
private SessionContext sessionContext;
|
||||
|
||||
private SessionActivationOperation sut;
|
||||
|
@ -34,7 +34,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
currentSession = new SessionConfiguration();
|
||||
logger = new Mock<ILogger>();
|
||||
nextSession = new SessionConfiguration();
|
||||
nextSettings = new ApplicationSettings();
|
||||
nextSettings = new AppSettings();
|
||||
sessionContext = new SessionContext();
|
||||
|
||||
nextSession.Settings = nextSettings;
|
||||
|
|
|
@ -36,11 +36,11 @@ namespace SafeExamBrowser.Runtime.UnitTests
|
|||
private Mock<IProcess> clientProcess;
|
||||
private Mock<IClientProxy> clientProxy;
|
||||
private SessionConfiguration currentSession;
|
||||
private ApplicationSettings currentSettings;
|
||||
private AppSettings currentSettings;
|
||||
private Mock<ILogger> logger;
|
||||
private Mock<IMessageBox> messageBox;
|
||||
private SessionConfiguration nextSession;
|
||||
private ApplicationSettings nextSettings;
|
||||
private AppSettings nextSettings;
|
||||
private Mock<Action> shutdown;
|
||||
private Mock<IText> text;
|
||||
private Mock<IUserInterfaceFactory> uiFactory;
|
||||
|
@ -58,11 +58,11 @@ namespace SafeExamBrowser.Runtime.UnitTests
|
|||
clientProcess = new Mock<IProcess>();
|
||||
clientProxy = new Mock<IClientProxy>();
|
||||
currentSession = new SessionConfiguration();
|
||||
currentSettings = new ApplicationSettings();
|
||||
currentSettings = new AppSettings();
|
||||
logger = new Mock<ILogger>();
|
||||
messageBox = new Mock<IMessageBox>();
|
||||
nextSession = new SessionConfiguration();
|
||||
nextSettings = new ApplicationSettings();
|
||||
nextSettings = new AppSettings();
|
||||
runtimeHost = new Mock<IRuntimeHost>();
|
||||
service = new Mock<IServiceProxy>();
|
||||
sessionContext = new SessionContext();
|
||||
|
@ -134,7 +134,7 @@ namespace SafeExamBrowser.Runtime.UnitTests
|
|||
var args = new ClientConfigurationEventArgs();
|
||||
var nextAppConfig = new AppConfig();
|
||||
var nextSessionId = Guid.NewGuid();
|
||||
var nextSettings = new ApplicationSettings();
|
||||
var nextSettings = new AppSettings();
|
||||
|
||||
nextSession.AppConfig = nextAppConfig;
|
||||
nextSession.SessionId = nextSessionId;
|
||||
|
|
|
@ -107,7 +107,7 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
{
|
||||
var currentPassword = default(string);
|
||||
var passwordParams = default(PasswordParameters);
|
||||
var settings = default(ApplicationSettings);
|
||||
var settings = default(AppSettings);
|
||||
var status = default(LoadStatus?);
|
||||
|
||||
if (source == UriSource.CommandLine)
|
||||
|
@ -161,7 +161,7 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
}
|
||||
}
|
||||
|
||||
private OperationResult DetermineLoadResult(Uri uri, UriSource source, ApplicationSettings settings, LoadStatus status, PasswordParameters passwordParams, string currentPassword = default(string))
|
||||
private OperationResult DetermineLoadResult(Uri uri, UriSource source, AppSettings settings, LoadStatus status, PasswordParameters passwordParams, string currentPassword = default(string))
|
||||
{
|
||||
if (status == LoadStatus.LoadWithBrowser || status == LoadStatus.Success)
|
||||
{
|
||||
|
@ -218,7 +218,7 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
return OperationResult.Failed;
|
||||
}
|
||||
|
||||
private LoadStatus? TryLoadSettings(Uri uri, UriSource source, out PasswordParameters passwordParams, out ApplicationSettings settings, string currentPassword = default(string))
|
||||
private LoadStatus? TryLoadSettings(Uri uri, UriSource source, out PasswordParameters passwordParams, out AppSettings settings, string currentPassword = default(string))
|
||||
{
|
||||
passwordParams = new PasswordParameters { Password = string.Empty, IsHash = true };
|
||||
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using SafeExamBrowser.Settings;
|
||||
using SafeExamBrowser.Core.Contracts.OperationModel;
|
||||
using SafeExamBrowser.Core.Contracts.OperationModel.Events;
|
||||
using SafeExamBrowser.I18n.Contracts;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.Settings;
|
||||
using SafeExamBrowser.WindowsApi.Contracts;
|
||||
|
||||
namespace SafeExamBrowser.Runtime.Operations
|
||||
|
|
|
@ -21,9 +21,9 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
public abstract event ActionRequiredEventHandler ActionRequired;
|
||||
public abstract event StatusChangedEventHandler StatusChanged;
|
||||
|
||||
public SessionOperation(SessionContext sessionContext)
|
||||
public SessionOperation(SessionContext context)
|
||||
{
|
||||
Context = sessionContext;
|
||||
Context = context;
|
||||
}
|
||||
|
||||
public abstract OperationResult Perform();
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace SafeExamBrowser.Service.UnitTests.Operations
|
|||
private Mock<IFeatureConfigurationFactory> factory;
|
||||
private Mock<IFeatureConfigurationMonitor> monitor;
|
||||
private Mock<ILogger> logger;
|
||||
private ApplicationSettings settings;
|
||||
private AppSettings settings;
|
||||
private SessionContext sessionContext;
|
||||
private LockdownOperation sut;
|
||||
|
||||
|
@ -38,7 +38,7 @@ namespace SafeExamBrowser.Service.UnitTests.Operations
|
|||
factory = new Mock<IFeatureConfigurationFactory>();
|
||||
monitor = new Mock<IFeatureConfigurationMonitor>();
|
||||
logger = new Mock<ILogger>();
|
||||
settings = new ApplicationSettings();
|
||||
settings = new AppSettings();
|
||||
sessionContext = new SessionContext
|
||||
{
|
||||
Configuration = new ServiceConfiguration { Settings = settings, UserName = "TestName", UserSid = "S-1-234-TEST" }
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace SafeExamBrowser.Service.UnitTests.Operations
|
|||
sessionContext.Configuration = new ServiceConfiguration
|
||||
{
|
||||
AppConfig = new AppConfig { ServiceEventName = $"{nameof(SafeExamBrowser)}-{nameof(SessionInitializationOperationTests)}" },
|
||||
Settings = new ApplicationSettings()
|
||||
Settings = new AppSettings()
|
||||
};
|
||||
|
||||
sut = new SessionInitializationOperation(logger.Object, serviceEventFactory.Object, sessionContext);
|
||||
|
|
|
@ -82,7 +82,7 @@ namespace SafeExamBrowser.Service.UnitTests
|
|||
{
|
||||
AppConfig = new AppConfig { ServiceLogFilePath = "Test.log" },
|
||||
SessionId = Guid.NewGuid(),
|
||||
Settings = new ApplicationSettings { LogLevel = LogLevel.Warning }
|
||||
Settings = new AppSettings { LogLevel = LogLevel.Warning }
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using SafeExamBrowser.Settings.Applications;
|
||||
using SafeExamBrowser.Settings.Browser;
|
||||
using SafeExamBrowser.Settings.Logging;
|
||||
using SafeExamBrowser.Settings.Monitoring;
|
||||
|
@ -20,7 +21,7 @@ namespace SafeExamBrowser.Settings
|
|||
/// Defines all settings for the application.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class ApplicationSettings
|
||||
public class AppSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// All action center-related settings.
|
||||
|
@ -37,6 +38,11 @@ namespace SafeExamBrowser.Settings
|
|||
/// </summary>
|
||||
public bool AllowApplicationLogAccess { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// All settings related to third-party applications.
|
||||
/// </summary>
|
||||
public ApplicationSettings Applications { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// All audio-related settings.
|
||||
/// </summary>
|
||||
|
@ -92,9 +98,10 @@ namespace SafeExamBrowser.Settings
|
|||
/// </summary>
|
||||
public UserInterfaceMode UserInterfaceMode { get; set; }
|
||||
|
||||
public ApplicationSettings()
|
||||
public AppSettings()
|
||||
{
|
||||
ActionCenter = new ActionCenterSettings();
|
||||
Applications = new ApplicationSettings();
|
||||
Audio = new AudioSettings();
|
||||
Browser = new BrowserSettings();
|
||||
Keyboard = new KeyboardSettings();
|
36
SafeExamBrowser.Settings/Applications/ApplicationSettings.cs
Normal file
36
SafeExamBrowser.Settings/Applications/ApplicationSettings.cs
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.Settings.Applications
|
||||
{
|
||||
/// <summary>
|
||||
/// TODO
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class ApplicationSettings
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IList<BlacklistApplication> Blacklist { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IList<WhitelistApplication> Whitelist { get; set; }
|
||||
|
||||
public ApplicationSettings()
|
||||
{
|
||||
Blacklist = new List<BlacklistApplication>();
|
||||
Whitelist = new List<WhitelistApplication>();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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;
|
||||
|
||||
namespace SafeExamBrowser.Settings.Applications
|
||||
{
|
||||
/// <summary>
|
||||
/// TODO
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class BlacklistApplication
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool AutoTerminate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string ExecutableName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string ExecutableOriginalName { get; set; }
|
||||
}
|
||||
}
|
|
@ -8,10 +8,13 @@
|
|||
|
||||
using System;
|
||||
|
||||
namespace SafeExamBrowser.Monitoring.Contracts.Windows.Events
|
||||
namespace SafeExamBrowser.Settings.Applications
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that the input focus has changed to the window with the specified handle.
|
||||
/// TODO
|
||||
/// </summary>
|
||||
public delegate void WindowChangedEventHandler(IntPtr window);
|
||||
[Serializable]
|
||||
public class WhitelistApplication
|
||||
{
|
||||
}
|
||||
}
|
|
@ -53,6 +53,9 @@
|
|||
<Reference Include="Microsoft.CSharp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Applications\ApplicationSettings.cs" />
|
||||
<Compile Include="Applications\BlacklistApplication.cs" />
|
||||
<Compile Include="Applications\WhitelistApplication.cs" />
|
||||
<Compile Include="Browser\BrowserFilterSettings.cs" />
|
||||
<Compile Include="Browser\BrowserSettings.cs" />
|
||||
<Compile Include="Browser\BrowserWindowSettings.cs" />
|
||||
|
@ -67,11 +70,12 @@
|
|||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Service\ServicePolicy.cs" />
|
||||
<Compile Include="Service\ServiceSettings.cs" />
|
||||
<Compile Include="ApplicationSettings.cs" />
|
||||
<Compile Include="AppSettings.cs" />
|
||||
<Compile Include="SystemComponents\AudioSettings.cs" />
|
||||
<Compile Include="UserInterface\ActionCenterSettings.cs" />
|
||||
<Compile Include="UserInterface\TaskbarSettings.cs" />
|
||||
<Compile Include="UserInterface\UserInterfaceMode.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
|
@ -8,10 +8,10 @@
|
|||
|
||||
using System;
|
||||
|
||||
namespace SafeExamBrowser.Monitoring.Contracts.Keyboard
|
||||
namespace SafeExamBrowser.WindowsApi.Contracts.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// The key modifiers which can be detected by the <see cref="IKeyboardInterceptor"/>.
|
||||
/// The key modifiers which can be detected by a keyboard hook.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum KeyModifier
|
|
@ -6,10 +6,10 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
namespace SafeExamBrowser.Monitoring.Contracts.Keyboard
|
||||
namespace SafeExamBrowser.WindowsApi.Contracts.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// The key states which can be detected by the <see cref="IKeyboardInterceptor"/>.
|
||||
/// The key states which can be detected by a keyboard hook.
|
||||
/// </summary>
|
||||
public enum KeyState
|
||||
{
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.WindowsApi.Contracts.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// The callback for a keyboard hook. Return <c>true</c> to consume (i.e. block) the user input, otherwise <c>false</c>.
|
||||
/// </summary>
|
||||
public delegate bool KeyboardHookCallback(int keyCode, KeyModifier modifier, KeyState state);
|
||||
}
|
|
@ -6,10 +6,10 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
namespace SafeExamBrowser.Monitoring.Contracts.Mouse
|
||||
namespace SafeExamBrowser.WindowsApi.Contracts.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// The mouse buttons which can be detected by the <see cref="IMouseInterceptor"/>.
|
||||
/// The mouse buttons which can be detected by a mouse hook.
|
||||
/// </summary>
|
||||
public enum MouseButton
|
||||
{
|
|
@ -6,10 +6,10 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
namespace SafeExamBrowser.Monitoring.Contracts.Mouse
|
||||
namespace SafeExamBrowser.WindowsApi.Contracts.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// The mouse button states which can be detected by the <see cref="IMouseInterceptor"/>.
|
||||
/// The mouse button states which can be detected a mouse hook.
|
||||
/// </summary>
|
||||
public enum MouseButtonState
|
||||
{
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.WindowsApi.Contracts.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// The callback for a mouse hook. Return <c>true</c> to consume (i.e. block) the user input, otherwise <c>false</c>.
|
||||
/// </summary>
|
||||
public delegate bool MouseHookCallback(MouseButton button, MouseButtonState state);
|
||||
}
|
|
@ -6,7 +6,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
|
||||
namespace SafeExamBrowser.WindowsApi.Contracts
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Keyboard;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Mouse;
|
||||
using SafeExamBrowser.WindowsApi.Contracts.Events;
|
||||
|
||||
namespace SafeExamBrowser.WindowsApi.Contracts
|
||||
|
@ -20,20 +18,20 @@ namespace SafeExamBrowser.WindowsApi.Contracts
|
|||
public interface INativeMethods
|
||||
{
|
||||
/// <summary>
|
||||
/// Deregisters the system hook for the given keyboard interceptor.
|
||||
/// Deregisters a previously registered keyboard hook.
|
||||
/// </summary>
|
||||
/// <exception cref="System.ComponentModel.Win32Exception">
|
||||
/// If the hook for the given interceptor could not be successfully removed.
|
||||
/// If the hook could not be successfully removed.
|
||||
/// </exception>
|
||||
void DeregisterKeyboardHook(IKeyboardInterceptor interceptor);
|
||||
void DeregisterKeyboardHook(Guid hookId);
|
||||
|
||||
/// <summary>
|
||||
/// Deregisters the system hook for the given mouse interceptor.
|
||||
/// Deregisters a previously registered mouse hook.
|
||||
/// </summary>
|
||||
/// <exception cref="System.ComponentModel.Win32Exception">
|
||||
/// If the hook for the given interceptor could not be successfully removed.
|
||||
/// If the hook could not be successfully removed.
|
||||
/// </exception>
|
||||
void DeregisterMouseHook(IMouseInterceptor interceptor);
|
||||
void DeregisterMouseHook(Guid hookId);
|
||||
|
||||
/// <summary>
|
||||
/// Deregisters a previously registered system event hook.
|
||||
|
@ -65,14 +63,12 @@ namespace SafeExamBrowser.WindowsApi.Contracts
|
|||
uint GetProcessIdFor(IntPtr window);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a window handle to the Windows taskbar. Returns <c>IntPtr.Zero</c>
|
||||
/// if the taskbar could not be found (i.e. if it isn't running).
|
||||
/// Retrieves a window handle to the Windows taskbar. Returns <c>IntPtr.Zero</c> if the taskbar could not be found (i.e. if it isn't running).
|
||||
/// </summary>
|
||||
IntPtr GetShellWindowHandle();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the process ID of the main Windows explorer instance controlling
|
||||
/// desktop and taskbar or <c>0</c>, if the process isn't running.
|
||||
/// Retrieves the process identifier of the main Windows explorer instance controlling desktop and taskbar or <c>0</c>, if the process isn't running.
|
||||
/// </summary>
|
||||
uint GetShellProcessId();
|
||||
|
||||
|
@ -121,24 +117,24 @@ namespace SafeExamBrowser.WindowsApi.Contracts
|
|||
void PreventSleepMode();
|
||||
|
||||
/// <summary>
|
||||
/// Registers a system hook for the given keyboard interceptor.
|
||||
/// Registers a keyboard hook for the given callback. Returns the identifier of the newly registered hook.
|
||||
/// </summary>
|
||||
void RegisterKeyboardHook(IKeyboardInterceptor interceptor);
|
||||
Guid RegisterKeyboardHook(KeyboardHookCallback callback);
|
||||
|
||||
/// <summary>
|
||||
/// Registers a system hook for the given mouse interceptor.
|
||||
/// Registers a mouse hook for the given callback. Returns the identifier of the newly registered hook.
|
||||
/// </summary>
|
||||
void RegisterMouseHook(IMouseInterceptor interceptor);
|
||||
Guid RegisterMouseHook(MouseHookCallback callback);
|
||||
|
||||
/// <summary>
|
||||
/// Registers a system event which will invoke the specified callback when a window has received mouse capture.
|
||||
/// Returns the ID of the newly registered Windows event hook.
|
||||
/// Registers a system event which will invoke the specified callback when a window has received mouse capture. Returns the identifier of
|
||||
/// the newly registered Windows event hook.
|
||||
/// </summary>
|
||||
Guid RegisterSystemCaptureStartEvent(SystemEventCallback callback);
|
||||
|
||||
/// <summary>
|
||||
/// Registers a system event which will invoke the specified callback when the foreground window has changed.
|
||||
/// Returns a handle to the newly registered Windows event hook.
|
||||
/// Registers a system event which will invoke the specified callback when the foreground window has changed. Returns the identifier of the
|
||||
/// newly registered Windows event hook.
|
||||
/// </summary>
|
||||
Guid RegisterSystemForegroundEvent(SystemEventCallback callback);
|
||||
|
||||
|
@ -156,7 +152,7 @@ namespace SafeExamBrowser.WindowsApi.Contracts
|
|||
void RestoreWindow(IntPtr window);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to resume the thread referenced by the given thread ID. Returns <c>true</c> if the thread was successfully resumed,
|
||||
/// Attempts to resume the thread referenced by the given thread identifier. Returns <c>true</c> if the thread was successfully resumed,
|
||||
/// otherwise <c>false</c>.
|
||||
/// </summary>
|
||||
bool ResumeThread(int threadId);
|
||||
|
@ -183,7 +179,7 @@ namespace SafeExamBrowser.WindowsApi.Contracts
|
|||
void SetWorkingArea(IBounds bounds);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to suspend the thread referenced by the given thread ID. Returns <c>true</c> if the thread was successfully suspended,
|
||||
/// Attempts to suspend the thread referenced by the given thread identifier. Returns <c>true</c> if the thread was successfully suspended,
|
||||
/// otherwise <c>false</c>.
|
||||
/// </summary>
|
||||
bool SuspendThread(int threadId);
|
||||
|
|
|
@ -53,6 +53,12 @@
|
|||
<Reference Include="Microsoft.CSharp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Events\KeyboardHookCallback.cs" />
|
||||
<Compile Include="Events\KeyModifier.cs" />
|
||||
<Compile Include="Events\KeyState.cs" />
|
||||
<Compile Include="Events\MouseButton.cs" />
|
||||
<Compile Include="Events\MouseButtonState.cs" />
|
||||
<Compile Include="Events\MouseHookCallback.cs" />
|
||||
<Compile Include="Events\ProcessTerminatedEventHandler.cs" />
|
||||
<Compile Include="Events\SystemEventCallback.cs" />
|
||||
<Compile Include="Events\TerminationActivatorEventHandler.cs" />
|
||||
|
@ -66,11 +72,5 @@
|
|||
<Compile Include="ITerminationActivator.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Monitoring.Contracts\SafeExamBrowser.Monitoring.Contracts.csproj">
|
||||
<Project>{6d563a30-366d-4c35-815b-2c9e6872278b}</Project>
|
||||
<Name>SafeExamBrowser.Monitoring.Contracts</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
|
@ -8,8 +8,8 @@
|
|||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Keyboard;
|
||||
using SafeExamBrowser.WindowsApi.Constants;
|
||||
using SafeExamBrowser.WindowsApi.Contracts.Events;
|
||||
using SafeExamBrowser.WindowsApi.Delegates;
|
||||
using SafeExamBrowser.WindowsApi.Types;
|
||||
|
||||
|
@ -18,14 +18,16 @@ namespace SafeExamBrowser.WindowsApi.Hooks
|
|||
internal class KeyboardHook
|
||||
{
|
||||
private bool altPressed, ctrlPressed;
|
||||
private KeyboardHookCallback callback;
|
||||
private IntPtr handle;
|
||||
private HookDelegate hookDelegate;
|
||||
|
||||
internal IntPtr Handle { get; private set; }
|
||||
internal IKeyboardInterceptor Interceptor { get; private set; }
|
||||
internal Guid Id { get; private set; }
|
||||
|
||||
internal KeyboardHook(IKeyboardInterceptor interceptor)
|
||||
internal KeyboardHook(KeyboardHookCallback callback)
|
||||
{
|
||||
Interceptor = interceptor;
|
||||
this.callback = callback;
|
||||
this.Id = Guid.NewGuid();
|
||||
}
|
||||
|
||||
internal void Attach()
|
||||
|
@ -38,13 +40,12 @@ namespace SafeExamBrowser.WindowsApi.Hooks
|
|||
// Ensures that the hook delegate does not get garbage collected prematurely, as it will be passed to unmanaged code.
|
||||
// Not doing so will result in a <c>CallbackOnCollectedDelegate</c> error and subsequent application crash!
|
||||
hookDelegate = new HookDelegate(LowLevelKeyboardProc);
|
||||
|
||||
Handle = User32.SetWindowsHookEx(HookType.WH_KEYBOARD_LL, hookDelegate, moduleHandle, 0);
|
||||
handle = User32.SetWindowsHookEx(HookType.WH_KEYBOARD_LL, hookDelegate, moduleHandle, 0);
|
||||
}
|
||||
|
||||
internal bool Detach()
|
||||
{
|
||||
return User32.UnhookWindowsHookEx(Handle);
|
||||
return User32.UnhookWindowsHookEx(handle);
|
||||
}
|
||||
|
||||
private IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam)
|
||||
|
@ -55,13 +56,13 @@ namespace SafeExamBrowser.WindowsApi.Hooks
|
|||
var modifier = GetModifiers(keyData, wParam.ToInt32());
|
||||
var state = GetState(wParam.ToInt32());
|
||||
|
||||
if (Interceptor.Block((int) keyData.KeyCode, modifier, state))
|
||||
if (callback((int) keyData.KeyCode, modifier, state))
|
||||
{
|
||||
return (IntPtr) 1;
|
||||
}
|
||||
}
|
||||
|
||||
return User32.CallNextHookEx(Handle, nCode, wParam, lParam);
|
||||
return User32.CallNextHookEx(handle, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
private KeyState GetState(int wParam)
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Mouse;
|
||||
using SafeExamBrowser.WindowsApi.Constants;
|
||||
using SafeExamBrowser.WindowsApi.Contracts.Events;
|
||||
using SafeExamBrowser.WindowsApi.Delegates;
|
||||
using SafeExamBrowser.WindowsApi.Types;
|
||||
|
||||
|
@ -17,14 +17,16 @@ namespace SafeExamBrowser.WindowsApi.Hooks
|
|||
{
|
||||
internal class MouseHook
|
||||
{
|
||||
private MouseHookCallback callback;
|
||||
private IntPtr handle;
|
||||
private HookDelegate hookDelegate;
|
||||
|
||||
internal IntPtr Handle { get; private set; }
|
||||
internal IMouseInterceptor Interceptor { get; private set; }
|
||||
internal Guid Id { get; private set; }
|
||||
|
||||
internal MouseHook(IMouseInterceptor interceptor)
|
||||
internal MouseHook(MouseHookCallback callback)
|
||||
{
|
||||
Interceptor = interceptor;
|
||||
this.callback = callback;
|
||||
this.Id = Guid.NewGuid();
|
||||
}
|
||||
|
||||
internal void Attach()
|
||||
|
@ -37,13 +39,12 @@ namespace SafeExamBrowser.WindowsApi.Hooks
|
|||
// Ensures that the hook delegate does not get garbage collected prematurely, as it will be passed to unmanaged code.
|
||||
// Not doing so will result in a <c>CallbackOnCollectedDelegate</c> error and subsequent application crash!
|
||||
hookDelegate = new HookDelegate(LowLevelMouseProc);
|
||||
|
||||
Handle = User32.SetWindowsHookEx(HookType.WH_MOUSE_LL, hookDelegate, moduleHandle, 0);
|
||||
handle = User32.SetWindowsHookEx(HookType.WH_MOUSE_LL, hookDelegate, moduleHandle, 0);
|
||||
}
|
||||
|
||||
internal bool Detach()
|
||||
{
|
||||
return User32.UnhookWindowsHookEx(Handle);
|
||||
return User32.UnhookWindowsHookEx(handle);
|
||||
}
|
||||
|
||||
private IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam)
|
||||
|
@ -54,13 +55,13 @@ namespace SafeExamBrowser.WindowsApi.Hooks
|
|||
var button = GetButton(wParam.ToInt32());
|
||||
var state = GetState(wParam.ToInt32());
|
||||
|
||||
if (Interceptor.Block(button, state))
|
||||
if (callback(button, state))
|
||||
{
|
||||
return (IntPtr) 1;
|
||||
}
|
||||
}
|
||||
|
||||
return User32.CallNextHookEx(Handle, nCode, wParam, lParam);
|
||||
return User32.CallNextHookEx(handle, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
private bool Ignore(int wParam)
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using SafeExamBrowser.WindowsApi.Contracts.Events;
|
||||
using SafeExamBrowser.WindowsApi.Constants;
|
||||
using SafeExamBrowser.WindowsApi.Contracts.Events;
|
||||
using SafeExamBrowser.WindowsApi.Delegates;
|
||||
|
||||
namespace SafeExamBrowser.WindowsApi.Hooks
|
||||
|
@ -21,8 +21,8 @@ namespace SafeExamBrowser.WindowsApi.Hooks
|
|||
private bool detachSuccess;
|
||||
private EventDelegate eventDelegate;
|
||||
private uint eventId;
|
||||
private IntPtr handle;
|
||||
|
||||
internal IntPtr Handle { get; private set; }
|
||||
internal Guid Id { get; private set; }
|
||||
|
||||
public SystemHook(SystemEventCallback callback, uint eventId)
|
||||
|
@ -40,14 +40,13 @@ namespace SafeExamBrowser.WindowsApi.Hooks
|
|||
// Ensures that the hook delegate does not get garbage collected prematurely, as it will be passed to unmanaged code.
|
||||
// Not doing so will result in a <c>CallbackOnCollectedDelegate</c> error and subsequent application crash!
|
||||
eventDelegate = new EventDelegate(LowLevelSystemProc);
|
||||
|
||||
Handle = User32.SetWinEventHook(eventId, eventId, IntPtr.Zero, eventDelegate, 0, 0, Constant.WINEVENT_OUTOFCONTEXT);
|
||||
handle = User32.SetWinEventHook(eventId, eventId, IntPtr.Zero, eventDelegate, 0, 0, Constant.WINEVENT_OUTOFCONTEXT);
|
||||
}
|
||||
|
||||
internal void AwaitDetach()
|
||||
{
|
||||
detachEvent.WaitOne();
|
||||
detachSuccess = User32.UnhookWinEvent(Handle);
|
||||
detachSuccess = User32.UnhookWinEvent(handle);
|
||||
detachResultAvailableEvent.Set();
|
||||
}
|
||||
|
||||
|
|
|
@ -14,8 +14,6 @@ using System.Linq;
|
|||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Keyboard;
|
||||
using SafeExamBrowser.Monitoring.Contracts.Mouse;
|
||||
using SafeExamBrowser.WindowsApi.Constants;
|
||||
using SafeExamBrowser.WindowsApi.Contracts;
|
||||
using SafeExamBrowser.WindowsApi.Contracts.Events;
|
||||
|
@ -26,34 +24,34 @@ namespace SafeExamBrowser.WindowsApi
|
|||
{
|
||||
public class NativeMethods : INativeMethods
|
||||
{
|
||||
private ConcurrentDictionary<IntPtr, KeyboardHook> KeyboardHooks = new ConcurrentDictionary<IntPtr, KeyboardHook>();
|
||||
private ConcurrentDictionary<IntPtr, MouseHook> MouseHooks = new ConcurrentDictionary<IntPtr, MouseHook>();
|
||||
private ConcurrentDictionary<IntPtr, SystemHook> SystemHooks = new ConcurrentDictionary<IntPtr, SystemHook>();
|
||||
private ConcurrentBag<KeyboardHook> KeyboardHooks = new ConcurrentBag<KeyboardHook>();
|
||||
private ConcurrentBag<MouseHook> MouseHooks = new ConcurrentBag<MouseHook>();
|
||||
private ConcurrentBag<SystemHook> SystemHooks = new ConcurrentBag<SystemHook>();
|
||||
|
||||
/// <summary>
|
||||
/// Upon finalization, unregister all active system events and hooks...
|
||||
/// </summary>
|
||||
~NativeMethods()
|
||||
{
|
||||
foreach (var hook in SystemHooks.Values)
|
||||
foreach (var hook in SystemHooks)
|
||||
{
|
||||
hook.Detach();
|
||||
}
|
||||
|
||||
foreach (var hook in KeyboardHooks.Values)
|
||||
foreach (var hook in KeyboardHooks)
|
||||
{
|
||||
hook.Detach();
|
||||
}
|
||||
|
||||
foreach (var hook in MouseHooks.Values)
|
||||
foreach (var hook in MouseHooks)
|
||||
{
|
||||
hook.Detach();
|
||||
}
|
||||
}
|
||||
|
||||
public void DeregisterKeyboardHook(IKeyboardInterceptor interceptor)
|
||||
public void DeregisterKeyboardHook(Guid hookId)
|
||||
{
|
||||
var hook = KeyboardHooks.Values.FirstOrDefault(h => h.Interceptor == interceptor);
|
||||
var hook = KeyboardHooks.FirstOrDefault(h => h.Id == hookId);
|
||||
|
||||
if (hook != null)
|
||||
{
|
||||
|
@ -64,13 +62,13 @@ namespace SafeExamBrowser.WindowsApi
|
|||
throw new Win32Exception(Marshal.GetLastWin32Error());
|
||||
}
|
||||
|
||||
KeyboardHooks.TryRemove(hook.Handle, out _);
|
||||
KeyboardHooks.TryTake(out _);
|
||||
}
|
||||
}
|
||||
|
||||
public void DeregisterMouseHook(IMouseInterceptor interceptor)
|
||||
public void DeregisterMouseHook(Guid hookId)
|
||||
{
|
||||
var hook = MouseHooks.Values.FirstOrDefault(h => h.Interceptor == interceptor);
|
||||
var hook = MouseHooks.FirstOrDefault(h => h.Id == hookId);
|
||||
|
||||
if (hook != null)
|
||||
{
|
||||
|
@ -81,13 +79,13 @@ namespace SafeExamBrowser.WindowsApi
|
|||
throw new Win32Exception(Marshal.GetLastWin32Error());
|
||||
}
|
||||
|
||||
MouseHooks.TryRemove(hook.Handle, out _);
|
||||
MouseHooks.TryTake(out _);
|
||||
}
|
||||
}
|
||||
|
||||
public void DeregisterSystemEventHook(Guid hookId)
|
||||
{
|
||||
var hook = SystemHooks.Values.FirstOrDefault(h => h.Id == hookId);
|
||||
var hook = SystemHooks.FirstOrDefault(h => h.Id == hookId);
|
||||
|
||||
if (hook != null)
|
||||
{
|
||||
|
@ -98,7 +96,7 @@ namespace SafeExamBrowser.WindowsApi
|
|||
throw new Win32Exception(Marshal.GetLastWin32Error());
|
||||
}
|
||||
|
||||
SystemHooks.TryRemove(hook.Handle, out _);
|
||||
SystemHooks.TryTake(out _);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,16 +234,18 @@ namespace SafeExamBrowser.WindowsApi
|
|||
Kernel32.SetThreadExecutionState(EXECUTION_STATE.CONTINUOUS | EXECUTION_STATE.DISPLAY_REQUIRED | EXECUTION_STATE.SYSTEM_REQUIRED);
|
||||
}
|
||||
|
||||
public void RegisterKeyboardHook(IKeyboardInterceptor interceptor)
|
||||
public Guid RegisterKeyboardHook(KeyboardHookCallback callback)
|
||||
{
|
||||
var hookId = default(Guid);
|
||||
var hookReadyEvent = new AutoResetEvent(false);
|
||||
var hookThread = new Thread(() =>
|
||||
{
|
||||
var hook = new KeyboardHook(interceptor);
|
||||
var hook = new KeyboardHook(callback);
|
||||
var sleepEvent = new AutoResetEvent(false);
|
||||
|
||||
hook.Attach();
|
||||
KeyboardHooks[hook.Handle] = hook;
|
||||
hookId = hook.Id;
|
||||
KeyboardHooks.Add(hook);
|
||||
hookReadyEvent.Set();
|
||||
|
||||
while (true)
|
||||
|
@ -259,18 +259,22 @@ namespace SafeExamBrowser.WindowsApi
|
|||
hookThread.Start();
|
||||
|
||||
hookReadyEvent.WaitOne();
|
||||
|
||||
return hookId;
|
||||
}
|
||||
|
||||
public void RegisterMouseHook(IMouseInterceptor interceptor)
|
||||
public Guid RegisterMouseHook(MouseHookCallback callback)
|
||||
{
|
||||
var hookId = default(Guid);
|
||||
var hookReadyEvent = new AutoResetEvent(false);
|
||||
var hookThread = new Thread(() =>
|
||||
{
|
||||
var hook = new MouseHook(interceptor);
|
||||
var hook = new MouseHook(callback);
|
||||
var sleepEvent = new AutoResetEvent(false);
|
||||
|
||||
hook.Attach();
|
||||
MouseHooks[hook.Handle] = hook;
|
||||
hookId = hook.Id;
|
||||
MouseHooks.Add(hook);
|
||||
hookReadyEvent.Set();
|
||||
|
||||
while (true)
|
||||
|
@ -284,6 +288,8 @@ namespace SafeExamBrowser.WindowsApi
|
|||
hookThread.Start();
|
||||
|
||||
hookReadyEvent.WaitOne();
|
||||
|
||||
return hookId;
|
||||
}
|
||||
|
||||
public Guid RegisterSystemCaptureStartEvent(SystemEventCallback callback)
|
||||
|
@ -306,7 +312,7 @@ namespace SafeExamBrowser.WindowsApi
|
|||
|
||||
hook.Attach();
|
||||
hookId = hook.Id;
|
||||
SystemHooks[hook.Handle] = hook;
|
||||
SystemHooks.Add(hook);
|
||||
hookReadyEvent.Set();
|
||||
hook.AwaitDetach();
|
||||
});
|
||||
|
|
|
@ -96,10 +96,6 @@
|
|||
<Project>{64ea30fb-11d4-436a-9c2b-88566285363e}</Project>
|
||||
<Name>SafeExamBrowser.Logging.Contracts</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Monitoring.Contracts\SafeExamBrowser.Monitoring.Contracts.csproj">
|
||||
<Project>{6d563a30-366d-4c35-815b-2c9e6872278b}</Project>
|
||||
<Name>SafeExamBrowser.Monitoring.Contracts</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SafeExamBrowser.UserInterface.Contracts\SafeExamBrowser.UserInterface.Contracts.csproj">
|
||||
<Project>{c7889e97-6ff6-4a58-b7cb-521ed276b316}</Project>
|
||||
<Name>SafeExamBrowser.UserInterface.Contracts</Name>
|
||||
|
|
Loading…
Add table
Reference in a new issue