SEBWIN-219: Implemented draft of communication operation and runtime communication host.
This commit is contained in:
parent
c10e141e7f
commit
8cd0659a22
32 changed files with 626 additions and 170 deletions
|
@ -58,7 +58,7 @@ namespace SafeExamBrowser.Client
|
||||||
browserInfo = new BrowserApplicationInfo();
|
browserInfo = new BrowserApplicationInfo();
|
||||||
logger = new Logger();
|
logger = new Logger();
|
||||||
nativeMethods = new NativeMethods();
|
nativeMethods = new NativeMethods();
|
||||||
settings = new SettingsRepository().LoadDefaults();
|
settings = new ConfigurationRepository().LoadDefaultSettings();
|
||||||
systemInfo = new SystemInfo();
|
systemInfo = new SystemInfo();
|
||||||
uiFactory = new UserInterfaceFactory();
|
uiFactory = new UserInterfaceFactory();
|
||||||
|
|
||||||
|
|
87
SafeExamBrowser.Configuration/ConfigurationRepository.cs
Normal file
87
SafeExamBrowser.Configuration/ConfigurationRepository.cs
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using SafeExamBrowser.Contracts.Configuration;
|
||||||
|
using SafeExamBrowser.Contracts.Configuration.Settings;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Configuration
|
||||||
|
{
|
||||||
|
public class ConfigurationRepository : IConfigurationRepository
|
||||||
|
{
|
||||||
|
private RuntimeInfo runtimeInfo;
|
||||||
|
|
||||||
|
public ISettings CurrentSettings { get; private set; }
|
||||||
|
|
||||||
|
public IRuntimeInfo RuntimeInfo
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (runtimeInfo == null)
|
||||||
|
{
|
||||||
|
InitializeRuntimeInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
return runtimeInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ISettings LoadSettings(Uri path)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
return LoadDefaultSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ISettings LoadDefaultSettings()
|
||||||
|
{
|
||||||
|
var settings = new Settings.Settings();
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
settings.ServicePolicy = ServicePolicy.Optional;
|
||||||
|
|
||||||
|
CurrentSettings = settings;
|
||||||
|
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeRuntimeInfo()
|
||||||
|
{
|
||||||
|
var appDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), nameof(SafeExamBrowser));
|
||||||
|
var baseAddress = "net.pipe://localhost/safeexambrowser";
|
||||||
|
var clientId = Guid.NewGuid();
|
||||||
|
var executable = Assembly.GetEntryAssembly();
|
||||||
|
var runtimeId = Guid.NewGuid();
|
||||||
|
var startTime = DateTime.Now;
|
||||||
|
var logFolder = Path.Combine(appDataFolder, "Logs");
|
||||||
|
var logFilePrefix = startTime.ToString("yyyy-MM-dd\\_HH\\hmm\\mss\\s");
|
||||||
|
|
||||||
|
runtimeInfo = new RuntimeInfo
|
||||||
|
{
|
||||||
|
ApplicationStartTime = startTime,
|
||||||
|
AppDataFolder = appDataFolder,
|
||||||
|
BrowserCachePath = Path.Combine(appDataFolder, "Cache"),
|
||||||
|
BrowserLogFile = Path.Combine(logFolder, $"{logFilePrefix}_Browser.txt"),
|
||||||
|
ClientId = Guid.NewGuid(),
|
||||||
|
ClientAddress = $"{baseAddress}/client/{clientId}",
|
||||||
|
ClientLogFile = Path.Combine(logFolder, $"{logFilePrefix}_Client.txt"),
|
||||||
|
DefaultSettingsFileName = "SebClientSettings.seb",
|
||||||
|
ProgramCopyright = executable.GetCustomAttribute<AssemblyCopyrightAttribute>().Copyright,
|
||||||
|
ProgramDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), nameof(SafeExamBrowser)),
|
||||||
|
ProgramTitle = executable.GetCustomAttribute<AssemblyTitleAttribute>().Title,
|
||||||
|
ProgramVersion = executable.GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion,
|
||||||
|
RuntimeId = Guid.NewGuid(),
|
||||||
|
RuntimeAddress = $"{baseAddress}/runtime/{runtimeId}",
|
||||||
|
RuntimeLogFile = Path.Combine(logFolder, $"{logFilePrefix}_Runtime.txt"),
|
||||||
|
ServiceAddress = $"{baseAddress}/service"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,12 +18,17 @@ namespace SafeExamBrowser.Configuration
|
||||||
public DateTime ApplicationStartTime { get; set; }
|
public DateTime ApplicationStartTime { get; set; }
|
||||||
public string BrowserCachePath { get; set; }
|
public string BrowserCachePath { get; set; }
|
||||||
public string BrowserLogFile { get; set; }
|
public string BrowserLogFile { get; set; }
|
||||||
|
public string ClientAddress { get; set; }
|
||||||
|
public Guid ClientId { get; set; }
|
||||||
public string ClientLogFile { get; set; }
|
public string ClientLogFile { get; set; }
|
||||||
public string DefaultSettingsFileName { get; set; }
|
public string DefaultSettingsFileName { get; set; }
|
||||||
public string ProgramCopyright { get; set; }
|
public string ProgramCopyright { get; set; }
|
||||||
public string ProgramDataFolder { get; set; }
|
public string ProgramDataFolder { get; set; }
|
||||||
public string ProgramTitle { get; set; }
|
public string ProgramTitle { get; set; }
|
||||||
public string ProgramVersion { get; set; }
|
public string ProgramVersion { get; set; }
|
||||||
|
public string RuntimeAddress { get; set; }
|
||||||
|
public Guid RuntimeId { get; set; }
|
||||||
public string RuntimeLogFile { get; set; }
|
public string RuntimeLogFile { get; set; }
|
||||||
|
public string ServiceAddress { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
<Compile Include="Settings\MouseSettings.cs" />
|
<Compile Include="Settings\MouseSettings.cs" />
|
||||||
<Compile Include="Settings\Settings.cs" />
|
<Compile Include="Settings\Settings.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Settings\SettingsRepository.cs" />
|
<Compile Include="ConfigurationRepository.cs" />
|
||||||
<Compile Include="SystemInfo.cs" />
|
<Compile Include="SystemInfo.cs" />
|
||||||
<Compile Include="Settings\TaskbarSettings.cs" />
|
<Compile Include="Settings\TaskbarSettings.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
|
||||||
*
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using SafeExamBrowser.Contracts.Configuration.Settings;
|
|
||||||
|
|
||||||
namespace SafeExamBrowser.Configuration.Settings
|
|
||||||
{
|
|
||||||
public class SettingsRepository : ISettingsRepository
|
|
||||||
{
|
|
||||||
public ISettings Current { get; private set; }
|
|
||||||
|
|
||||||
public ISettings Load(Uri path)
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
return LoadDefaults();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ISettings LoadDefaults()
|
|
||||||
{
|
|
||||||
var settings = new Settings();
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
settings.ServicePolicy = ServicePolicy.Optional;
|
|
||||||
|
|
||||||
Current = settings;
|
|
||||||
|
|
||||||
return settings;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,6 +6,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
namespace SafeExamBrowser.Contracts.Behaviour
|
namespace SafeExamBrowser.Contracts.Behaviour
|
||||||
{
|
{
|
||||||
public interface IRuntimeController
|
public interface IRuntimeController
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Contracts.Communication
|
||||||
|
{
|
||||||
|
public interface ICommunicationHost
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the host is running and ready for communication.
|
||||||
|
/// </summary>
|
||||||
|
bool IsRunning { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Starts the host and opens it for communication.
|
||||||
|
/// </summary>
|
||||||
|
void Start();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Closes and terminates the host.
|
||||||
|
/// </summary>
|
||||||
|
void Stop();
|
||||||
|
}
|
||||||
|
}
|
15
SafeExamBrowser.Contracts/Communication/IRuntimeHost.cs
Normal file
15
SafeExamBrowser.Contracts/Communication/IRuntimeHost.cs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Contracts.Communication
|
||||||
|
{
|
||||||
|
public interface IRuntimeHost : ICommunicationHost
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,26 +7,32 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using SafeExamBrowser.Contracts.Configuration.Settings;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Contracts.Configuration.Settings
|
namespace SafeExamBrowser.Contracts.Configuration
|
||||||
{
|
{
|
||||||
public interface ISettingsRepository
|
public interface IConfigurationRepository
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the current settings, i.e. the last ones which were loaded. If no settings have been loaded yet, this property will
|
/// Retrieves the current settings, i.e. the last ones which were loaded. If no settings have been loaded yet, this property will
|
||||||
/// be <c>null</c>.
|
/// be <c>null</c>!
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ISettings Current { get; }
|
ISettings CurrentSettings { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The runtime information for the currently running application instance.
|
||||||
|
/// </summary>
|
||||||
|
IRuntimeInfo RuntimeInfo { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attempts to load settings from the specified path.
|
/// Attempts to load settings from the specified path.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <exception cref="System.ArgumentException">Thrown if the given path cannot be resolved to a settings file.</exception>
|
/// <exception cref="ArgumentException">Thrown if the given path cannot be resolved to a settings file.</exception>
|
||||||
ISettings Load(Uri path);
|
ISettings LoadSettings(Uri path);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Loads the default settings.
|
/// Loads the default settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ISettings LoadDefaults();
|
ISettings LoadDefaultSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -32,6 +32,22 @@ namespace SafeExamBrowser.Contracts.Configuration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string BrowserLogFile { get; }
|
string BrowserLogFile { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The communication address of the client component.
|
||||||
|
///
|
||||||
|
/// TODO: Will need to be updated for each new client instance!
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
string ClientAddress { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The unique identifier for the currently running client instance.
|
||||||
|
///
|
||||||
|
/// TODO: Will need to be updated for each new client instance!
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
Guid ClientId { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The file path under which the log of the client component is to be stored.
|
/// The file path under which the log of the client component is to be stored.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -62,9 +78,24 @@ namespace SafeExamBrowser.Contracts.Configuration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string ProgramVersion { get; }
|
string ProgramVersion { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The communication address of the runtime component.
|
||||||
|
/// </summary>
|
||||||
|
string RuntimeAddress { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The unique identifier for the currently running runtime instance.
|
||||||
|
/// </summary>
|
||||||
|
Guid RuntimeId { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The file path under which the log of the runtime component is to be stored.
|
/// The file path under which the log of the runtime component is to be stored.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string RuntimeLogFile { get; }
|
string RuntimeLogFile { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The communication address of the service component.
|
||||||
|
/// </summary>
|
||||||
|
string ServiceAddress { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,12 +35,15 @@ namespace SafeExamBrowser.Contracts.I18n
|
||||||
ProgressIndicator_InitializeTaskbar,
|
ProgressIndicator_InitializeTaskbar,
|
||||||
ProgressIndicator_InitializeWindowMonitoring,
|
ProgressIndicator_InitializeWindowMonitoring,
|
||||||
ProgressIndicator_InitializeWorkingArea,
|
ProgressIndicator_InitializeWorkingArea,
|
||||||
|
ProgressIndicator_RestartCommunicationHost,
|
||||||
ProgressIndicator_RestoreWorkingArea,
|
ProgressIndicator_RestoreWorkingArea,
|
||||||
ProgressIndicator_RevertKioskMode,
|
ProgressIndicator_RevertKioskMode,
|
||||||
ProgressIndicator_ShutdownProcedure,
|
ProgressIndicator_ShutdownProcedure,
|
||||||
|
ProgressIndicator_StartCommunicationHost,
|
||||||
ProgressIndicator_StartEventHandling,
|
ProgressIndicator_StartEventHandling,
|
||||||
ProgressIndicator_StartKeyboardInterception,
|
ProgressIndicator_StartKeyboardInterception,
|
||||||
ProgressIndicator_StartMouseInterception,
|
ProgressIndicator_StartMouseInterception,
|
||||||
|
ProgressIndicator_StopCommunicationHost,
|
||||||
ProgressIndicator_StopEventHandling,
|
ProgressIndicator_StopEventHandling,
|
||||||
ProgressIndicator_StopKeyboardInterception,
|
ProgressIndicator_StopKeyboardInterception,
|
||||||
ProgressIndicator_StopMouseInterception,
|
ProgressIndicator_StopMouseInterception,
|
||||||
|
|
|
@ -58,6 +58,8 @@
|
||||||
<Compile Include="Behaviour\Operations\IOperationSequence.cs" />
|
<Compile Include="Behaviour\Operations\IOperationSequence.cs" />
|
||||||
<Compile Include="Communication\ICommunication.cs" />
|
<Compile Include="Communication\ICommunication.cs" />
|
||||||
<Compile Include="Communication\IClientProxy.cs" />
|
<Compile Include="Communication\IClientProxy.cs" />
|
||||||
|
<Compile Include="Communication\ICommunicationHost.cs" />
|
||||||
|
<Compile Include="Communication\IRuntimeHost.cs" />
|
||||||
<Compile Include="Communication\IRuntimeProxy.cs" />
|
<Compile Include="Communication\IRuntimeProxy.cs" />
|
||||||
<Compile Include="Communication\IServiceProxy.cs" />
|
<Compile Include="Communication\IServiceProxy.cs" />
|
||||||
<Compile Include="Communication\Messages\IMessage.cs" />
|
<Compile Include="Communication\Messages\IMessage.cs" />
|
||||||
|
@ -78,7 +80,7 @@
|
||||||
<Compile Include="Configuration\Settings\IKeyboardSettings.cs" />
|
<Compile Include="Configuration\Settings\IKeyboardSettings.cs" />
|
||||||
<Compile Include="Configuration\Settings\IMouseSettings.cs" />
|
<Compile Include="Configuration\Settings\IMouseSettings.cs" />
|
||||||
<Compile Include="Configuration\Settings\ISettings.cs" />
|
<Compile Include="Configuration\Settings\ISettings.cs" />
|
||||||
<Compile Include="Configuration\Settings\ISettingsRepository.cs" />
|
<Compile Include="Configuration\IConfigurationRepository.cs" />
|
||||||
<Compile Include="Configuration\Settings\ITaskbarSettings.cs" />
|
<Compile Include="Configuration\Settings\ITaskbarSettings.cs" />
|
||||||
<Compile Include="Configuration\Settings\KioskMode.cs" />
|
<Compile Include="Configuration\Settings\KioskMode.cs" />
|
||||||
<Compile Include="Configuration\Settings\ServicePolicy.cs" />
|
<Compile Include="Configuration\Settings\ServicePolicy.cs" />
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using Moq;
|
||||||
|
using SafeExamBrowser.Contracts.Communication;
|
||||||
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
|
using SafeExamBrowser.Core.Behaviour.Operations;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
public class CommunicationOperationTests
|
||||||
|
{
|
||||||
|
private Mock<ICommunicationHost> hostMock;
|
||||||
|
private Mock<ILogger> loggerMock;
|
||||||
|
private CommunicationOperation sut;
|
||||||
|
|
||||||
|
[TestInitialize]
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
hostMock = new Mock<ICommunicationHost>();
|
||||||
|
loggerMock = new Mock<ILogger>();
|
||||||
|
|
||||||
|
sut = new CommunicationOperation(hostMock.Object, loggerMock.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void MustRestartHostOnRepeat()
|
||||||
|
{
|
||||||
|
var order = 0;
|
||||||
|
var stop = 0;
|
||||||
|
var start = 0;
|
||||||
|
|
||||||
|
hostMock.Setup(h => h.Stop()).Callback(() => stop = ++order);
|
||||||
|
hostMock.Setup(h => h.Start()).Callback(() => start = ++order);
|
||||||
|
|
||||||
|
sut.Repeat();
|
||||||
|
|
||||||
|
hostMock.Verify(h => h.Stop(), Times.Once);
|
||||||
|
hostMock.Verify(h => h.Start(), Times.Once);
|
||||||
|
|
||||||
|
Assert.AreEqual(stop, 1);
|
||||||
|
Assert.AreEqual(start, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void MustStartHostOnPerform()
|
||||||
|
{
|
||||||
|
sut.Perform();
|
||||||
|
|
||||||
|
hostMock.Verify(h => h.Start(), Times.Once);
|
||||||
|
hostMock.Verify(h => h.Stop(), Times.Never);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void MustStopHostOnRevert()
|
||||||
|
{
|
||||||
|
sut.Revert();
|
||||||
|
|
||||||
|
hostMock.Verify(h => h.Stop(), Times.Once);
|
||||||
|
hostMock.Verify(h => h.Start(), Times.Never);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,6 +28,29 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
|
||||||
loggerMock = new Mock<ILogger>();
|
loggerMock = new Mock<ILogger>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void MustCreateCopyOfOperationQueue()
|
||||||
|
{
|
||||||
|
var operationA = new Mock<IOperation>();
|
||||||
|
var operationB = new Mock<IOperation>();
|
||||||
|
var operationC = new Mock<IOperation>();
|
||||||
|
var operations = new Queue<IOperation>();
|
||||||
|
|
||||||
|
operations.Enqueue(operationA.Object);
|
||||||
|
operations.Enqueue(operationB.Object);
|
||||||
|
operations.Enqueue(operationC.Object);
|
||||||
|
|
||||||
|
var sut = new OperationSequence(loggerMock.Object, operations);
|
||||||
|
|
||||||
|
operations.Clear();
|
||||||
|
|
||||||
|
sut.TryPerform();
|
||||||
|
|
||||||
|
operationA.Verify(o => o.Perform(), Times.Once);
|
||||||
|
operationB.Verify(o => o.Perform(), Times.Once);
|
||||||
|
operationC.Verify(o => o.Perform(), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
#region Perform Tests
|
#region Perform Tests
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
|
|
|
@ -78,6 +78,7 @@
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Behaviour\Operations\CommunicationOperationTests.cs" />
|
||||||
<Compile Include="Behaviour\Operations\I18nOperationTests.cs" />
|
<Compile Include="Behaviour\Operations\I18nOperationTests.cs" />
|
||||||
<Compile Include="Behaviour\Operations\OperationSequenceTests.cs" />
|
<Compile Include="Behaviour\Operations\OperationSequenceTests.cs" />
|
||||||
<Compile Include="I18n\TextTests.cs" />
|
<Compile Include="I18n\TextTests.cs" />
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using SafeExamBrowser.Contracts.Behaviour.Operations;
|
||||||
|
using SafeExamBrowser.Contracts.Communication;
|
||||||
|
using SafeExamBrowser.Contracts.I18n;
|
||||||
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
|
using SafeExamBrowser.Contracts.UserInterface;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Core.Behaviour.Operations
|
||||||
|
{
|
||||||
|
public class CommunicationOperation : IOperation
|
||||||
|
{
|
||||||
|
private ICommunicationHost host;
|
||||||
|
private ILogger logger;
|
||||||
|
|
||||||
|
public bool Abort { get; private set; }
|
||||||
|
public IProgressIndicator ProgressIndicator { private get; set; }
|
||||||
|
|
||||||
|
public CommunicationOperation(ICommunicationHost host, ILogger logger)
|
||||||
|
{
|
||||||
|
this.host = host;
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Perform()
|
||||||
|
{
|
||||||
|
logger.Info("Starting communication host...");
|
||||||
|
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StartCommunicationHost);
|
||||||
|
|
||||||
|
host.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Repeat()
|
||||||
|
{
|
||||||
|
if (!host.IsRunning)
|
||||||
|
{
|
||||||
|
logger.Info("Restarting communication host...");
|
||||||
|
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_RestartCommunicationHost);
|
||||||
|
|
||||||
|
host.Stop();
|
||||||
|
host.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Revert()
|
||||||
|
{
|
||||||
|
logger.Info("Stopping communication host...");
|
||||||
|
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StopCommunicationHost);
|
||||||
|
|
||||||
|
host.Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -40,7 +40,7 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
|
||||||
|
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
Revert();
|
Revert(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -74,8 +74,8 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Initialize();
|
Initialize(true);
|
||||||
success = Revert(false);
|
success = Revert();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -154,7 +154,7 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool Revert(bool regress = true)
|
private bool Revert(bool regress = false)
|
||||||
{
|
{
|
||||||
var success = true;
|
var success = true;
|
||||||
|
|
||||||
|
|
91
SafeExamBrowser.Core/Communication/BaseHost.cs
Normal file
91
SafeExamBrowser.Core/Communication/BaseHost.cs
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.ServiceModel;
|
||||||
|
using SafeExamBrowser.Contracts.Communication;
|
||||||
|
using SafeExamBrowser.Contracts.Communication.Messages;
|
||||||
|
using SafeExamBrowser.Contracts.Communication.Responses;
|
||||||
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Core.Communication
|
||||||
|
{
|
||||||
|
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
|
||||||
|
public abstract class BaseHost : ICommunication, ICommunicationHost
|
||||||
|
{
|
||||||
|
private string address;
|
||||||
|
private ILogger logger;
|
||||||
|
private ServiceHost host;
|
||||||
|
|
||||||
|
public bool IsRunning
|
||||||
|
{
|
||||||
|
get { return host?.State == CommunicationState.Opened; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseHost(string address, ILogger logger)
|
||||||
|
{
|
||||||
|
this.address = address;
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract IConnectResponse Connect(Guid? token = null);
|
||||||
|
public abstract void Disconnect(IMessage message);
|
||||||
|
public abstract IResponse Send(IMessage message);
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
host = new ServiceHost(this);
|
||||||
|
host.AddServiceEndpoint(typeof(ICommunication), new NetNamedPipeBinding(NetNamedPipeSecurityMode.Transport), address);
|
||||||
|
host.Closed += Host_Closed;
|
||||||
|
host.Closing += Host_Closing;
|
||||||
|
host.Faulted += Host_Faulted;
|
||||||
|
host.Opened += Host_Opened;
|
||||||
|
host.Opening += Host_Opening;
|
||||||
|
host.UnknownMessageReceived += Host_UnknownMessageReceived;
|
||||||
|
host.Open();
|
||||||
|
|
||||||
|
logger.Debug($"Successfully started communication host for endpoint '{address}'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
host?.Close();
|
||||||
|
logger.Debug($"Terminated communication host for endpoint '{address}'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Host_Closed(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
logger.Debug("Communication host has been closed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Host_Closing(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
logger.Debug("Communication host is closing...");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Host_Faulted(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
logger.Debug("Communication host has faulted!");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Host_Opened(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
logger.Debug("Communication host has been opened.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Host_Opening(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
logger.Debug("Communication host is opening...");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Host_UnknownMessageReceived(object sender, UnknownMessageReceivedEventArgs e)
|
||||||
|
{
|
||||||
|
logger.Debug($"Communication host has received an unknown message: {e?.Message}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,7 +23,7 @@ namespace SafeExamBrowser.Core.Communication
|
||||||
protected Guid? CommunicationToken { get; private set; }
|
protected Guid? CommunicationToken { get; private set; }
|
||||||
protected ILogger Logger { get; private set; }
|
protected ILogger Logger { get; private set; }
|
||||||
|
|
||||||
public BaseProxy(ILogger logger, string address)
|
public BaseProxy(string address, ILogger logger)
|
||||||
{
|
{
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.Logger = logger;
|
this.Logger = logger;
|
||||||
|
@ -34,9 +34,11 @@ namespace SafeExamBrowser.Core.Communication
|
||||||
var endpoint = new EndpointAddress(address);
|
var endpoint = new EndpointAddress(address);
|
||||||
|
|
||||||
channel = ChannelFactory<ICommunication>.CreateChannel(new NetNamedPipeBinding(NetNamedPipeSecurityMode.Transport), endpoint);
|
channel = ChannelFactory<ICommunication>.CreateChannel(new NetNamedPipeBinding(NetNamedPipeSecurityMode.Transport), endpoint);
|
||||||
(channel as ICommunicationObject).Closed += CommunicationHostProxy_Closed;
|
(channel as ICommunicationObject).Closed += BaseProxy_Closed;
|
||||||
(channel as ICommunicationObject).Closing += CommunicationHostProxy_Closing;
|
(channel as ICommunicationObject).Closing += BaseProxy_Closing;
|
||||||
(channel as ICommunicationObject).Faulted += CommunicationHostProxy_Faulted;
|
(channel as ICommunicationObject).Faulted += BaseProxy_Faulted;
|
||||||
|
(channel as ICommunicationObject).Opened += BaseProxy_Opened;
|
||||||
|
(channel as ICommunicationObject).Opening += BaseProxy_Opening;
|
||||||
|
|
||||||
var response = channel.Connect(token);
|
var response = channel.Connect(token);
|
||||||
|
|
||||||
|
@ -84,21 +86,31 @@ namespace SafeExamBrowser.Core.Communication
|
||||||
return channel != null && (channel as ICommunicationObject).State == CommunicationState.Opened;
|
return channel != null && (channel as ICommunicationObject).State == CommunicationState.Opened;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CommunicationHostProxy_Closed(object sender, EventArgs e)
|
private void BaseProxy_Closed(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Logger.Debug("Communication channel has been closed.");
|
Logger.Debug("Communication channel has been closed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CommunicationHostProxy_Closing(object sender, EventArgs e)
|
private void BaseProxy_Closing(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Logger.Debug("Communication channel is closing.");
|
Logger.Debug("Communication channel is closing...");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CommunicationHostProxy_Faulted(object sender, EventArgs e)
|
private void BaseProxy_Faulted(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Logger.Debug("Communication channel has faulted!");
|
Logger.Debug("Communication channel has faulted!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void BaseProxy_Opened(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Logger.Debug("Communication channel has been opened.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BaseProxy_Opening(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Logger.Debug("Communication channel is opening...");
|
||||||
|
}
|
||||||
|
|
||||||
private string GetChannelState()
|
private string GetChannelState()
|
||||||
{
|
{
|
||||||
return channel == null ? "null" : $"in state '{(channel as ICommunicationObject).State}'";
|
return channel == null ? "null" : $"in state '{(channel as ICommunicationObject).State}'";
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace SafeExamBrowser.Core.Communication
|
||||||
{
|
{
|
||||||
public bool Ignore { private get; set; }
|
public bool Ignore { private get; set; }
|
||||||
|
|
||||||
public ServiceProxy(ILogger logger, string address) : base(logger, address)
|
public ServiceProxy(string address, ILogger logger) : base(address, logger)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,9 @@
|
||||||
<Entry key="ProgressIndicator_InitializeWorkingArea">
|
<Entry key="ProgressIndicator_InitializeWorkingArea">
|
||||||
Initializing working area
|
Initializing working area
|
||||||
</Entry>
|
</Entry>
|
||||||
|
<Entry key="ProgressIndicator_RestartCommunicationHost">
|
||||||
|
Restarting communication host
|
||||||
|
</Entry>
|
||||||
<Entry key="ProgressIndicator_RestoreWorkingArea">
|
<Entry key="ProgressIndicator_RestoreWorkingArea">
|
||||||
Restoring working area
|
Restoring working area
|
||||||
</Entry>
|
</Entry>
|
||||||
|
@ -69,6 +72,9 @@
|
||||||
<Entry key="ProgressIndicator_ShutdownProcedure">
|
<Entry key="ProgressIndicator_ShutdownProcedure">
|
||||||
Initiating shutdown procedure
|
Initiating shutdown procedure
|
||||||
</Entry>
|
</Entry>
|
||||||
|
<Entry key="ProgressIndicator_StartCommunicationHost">
|
||||||
|
Starting communication host
|
||||||
|
</Entry>
|
||||||
<Entry key="ProgressIndicator_StartEventHandling">
|
<Entry key="ProgressIndicator_StartEventHandling">
|
||||||
Starting event handling
|
Starting event handling
|
||||||
</Entry>
|
</Entry>
|
||||||
|
@ -78,6 +84,9 @@
|
||||||
<Entry key="ProgressIndicator_StartMouseInterception">
|
<Entry key="ProgressIndicator_StartMouseInterception">
|
||||||
Starting mouse interception
|
Starting mouse interception
|
||||||
</Entry>
|
</Entry>
|
||||||
|
<Entry key="ProgressIndicator_StopCommunicationHost">
|
||||||
|
Stopping communication host
|
||||||
|
</Entry>
|
||||||
<Entry key="ProgressIndicator_StopEventHandling">
|
<Entry key="ProgressIndicator_StopEventHandling">
|
||||||
Stopping event handling
|
Stopping event handling
|
||||||
</Entry>
|
</Entry>
|
||||||
|
|
|
@ -55,9 +55,11 @@
|
||||||
<Reference Include="System.Xml.Linq" />
|
<Reference Include="System.Xml.Linq" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Behaviour\Operations\CommunicationOperation.cs" />
|
||||||
<Compile Include="Behaviour\Operations\I18nOperation.cs" />
|
<Compile Include="Behaviour\Operations\I18nOperation.cs" />
|
||||||
<Compile Include="Behaviour\Operations\OperationSequence.cs" />
|
<Compile Include="Behaviour\Operations\OperationSequence.cs" />
|
||||||
<Compile Include="Communication\BaseProxy.cs" />
|
<Compile Include="Communication\BaseProxy.cs" />
|
||||||
|
<Compile Include="Communication\BaseHost.cs" />
|
||||||
<Compile Include="Communication\Messages\Message.cs" />
|
<Compile Include="Communication\Messages\Message.cs" />
|
||||||
<Compile Include="Communication\ServiceProxy.cs" />
|
<Compile Include="Communication\ServiceProxy.cs" />
|
||||||
<Compile Include="Logging\DefaultLogFormatter.cs" />
|
<Compile Include="Logging\DefaultLogFormatter.cs" />
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
||||||
{
|
{
|
||||||
private Mock<ILogger> logger;
|
private Mock<ILogger> logger;
|
||||||
private Mock<IRuntimeInfo> info;
|
private Mock<IRuntimeInfo> info;
|
||||||
private Mock<ISettingsRepository> repository;
|
private Mock<IConfigurationRepository> repository;
|
||||||
private Mock<ISettings> settings;
|
private Mock<ISettings> settings;
|
||||||
private Mock<IText> text;
|
private Mock<IText> text;
|
||||||
private Mock<IUserInterfaceFactory> uiFactory;
|
private Mock<IUserInterfaceFactory> uiFactory;
|
||||||
|
@ -35,7 +35,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
||||||
{
|
{
|
||||||
logger = new Mock<ILogger>();
|
logger = new Mock<ILogger>();
|
||||||
info = new Mock<IRuntimeInfo>();
|
info = new Mock<IRuntimeInfo>();
|
||||||
repository = new Mock<ISettingsRepository>();
|
repository = new Mock<IConfigurationRepository>();
|
||||||
settings = new Mock<ISettings>();
|
settings = new Mock<ISettings>();
|
||||||
text = new Mock<IText>();
|
text = new Mock<IText>();
|
||||||
uiFactory = new Mock<IUserInterfaceFactory>();
|
uiFactory = new Mock<IUserInterfaceFactory>();
|
||||||
|
@ -43,24 +43,24 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
||||||
info.SetupGet(i => i.AppDataFolder).Returns(@"C:\Not\Really\AppData");
|
info.SetupGet(i => i.AppDataFolder).Returns(@"C:\Not\Really\AppData");
|
||||||
info.SetupGet(i => i.DefaultSettingsFileName).Returns("SettingsDummy.txt");
|
info.SetupGet(i => i.DefaultSettingsFileName).Returns("SettingsDummy.txt");
|
||||||
info.SetupGet(i => i.ProgramDataFolder).Returns(@"C:\Not\Really\ProgramData");
|
info.SetupGet(i => i.ProgramDataFolder).Returns(@"C:\Not\Really\ProgramData");
|
||||||
repository.Setup(r => r.Load(It.IsAny<Uri>())).Returns(settings.Object);
|
repository.Setup(r => r.LoadSettings(It.IsAny<Uri>())).Returns(settings.Object);
|
||||||
repository.Setup(r => r.LoadDefaults()).Returns(settings.Object);
|
repository.Setup(r => r.LoadDefaultSettings()).Returns(settings.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void MustNotFailWithoutCommandLineArgs()
|
public void MustNotFailWithoutCommandLineArgs()
|
||||||
{
|
{
|
||||||
repository.Setup(r => r.LoadDefaults());
|
repository.Setup(r => r.LoadDefaultSettings());
|
||||||
|
|
||||||
sut = new ConfigurationOperation(logger.Object, info.Object, repository.Object, text.Object, uiFactory.Object, null);
|
sut = new ConfigurationOperation(repository.Object, logger.Object, info.Object, text.Object, uiFactory.Object, null);
|
||||||
|
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
|
|
||||||
sut = new ConfigurationOperation(logger.Object, info.Object, repository.Object, text.Object, uiFactory.Object, new string[] { });
|
sut = new ConfigurationOperation(repository.Object, logger.Object, info.Object, text.Object, uiFactory.Object, new string[] { });
|
||||||
|
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
|
|
||||||
repository.Verify(r => r.LoadDefaults(), Times.Exactly(2));
|
repository.Verify(r => r.LoadDefaultSettings(), Times.Exactly(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
|
@ -68,7 +68,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
||||||
{
|
{
|
||||||
var path = @"an/invalid\path.'*%yolo/()";
|
var path = @"an/invalid\path.'*%yolo/()";
|
||||||
|
|
||||||
sut = new ConfigurationOperation(logger.Object, info.Object, repository.Object, text.Object, uiFactory.Object, new [] { "blubb.exe", path });
|
sut = new ConfigurationOperation(repository.Object, logger.Object, info.Object, text.Object, uiFactory.Object, new [] { "blubb.exe", path });
|
||||||
|
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
}
|
}
|
||||||
|
@ -82,11 +82,11 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
||||||
info.SetupGet(r => r.ProgramDataFolder).Returns(location);
|
info.SetupGet(r => r.ProgramDataFolder).Returns(location);
|
||||||
info.SetupGet(r => r.AppDataFolder).Returns(location);
|
info.SetupGet(r => r.AppDataFolder).Returns(location);
|
||||||
|
|
||||||
sut = new ConfigurationOperation(logger.Object, info.Object, repository.Object, text.Object, uiFactory.Object, new[] { "blubb.exe", path });
|
sut = new ConfigurationOperation(repository.Object, logger.Object, info.Object, text.Object, uiFactory.Object, new[] { "blubb.exe", path });
|
||||||
|
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
|
|
||||||
repository.Verify(r => r.Load(It.Is<Uri>(u => u.Equals(new Uri(path)))), Times.Once);
|
repository.Verify(r => r.LoadSettings(It.Is<Uri>(u => u.Equals(new Uri(path)))), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
|
@ -97,11 +97,11 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
||||||
info.SetupGet(r => r.ProgramDataFolder).Returns(location);
|
info.SetupGet(r => r.ProgramDataFolder).Returns(location);
|
||||||
info.SetupGet(r => r.AppDataFolder).Returns($@"{location}\WRONG");
|
info.SetupGet(r => r.AppDataFolder).Returns($@"{location}\WRONG");
|
||||||
|
|
||||||
sut = new ConfigurationOperation(logger.Object, info.Object, repository.Object, text.Object, uiFactory.Object, null);
|
sut = new ConfigurationOperation(repository.Object, logger.Object, info.Object, text.Object, uiFactory.Object, null);
|
||||||
|
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
|
|
||||||
repository.Verify(r => r.Load(It.Is<Uri>(u => u.Equals(new Uri(Path.Combine(location, "SettingsDummy.txt"))))), Times.Once);
|
repository.Verify(r => r.LoadSettings(It.Is<Uri>(u => u.Equals(new Uri(Path.Combine(location, "SettingsDummy.txt"))))), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
|
@ -111,21 +111,21 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
||||||
|
|
||||||
info.SetupGet(r => r.AppDataFolder).Returns(location);
|
info.SetupGet(r => r.AppDataFolder).Returns(location);
|
||||||
|
|
||||||
sut = new ConfigurationOperation(logger.Object, info.Object, repository.Object, text.Object, uiFactory.Object, null);
|
sut = new ConfigurationOperation(repository.Object, logger.Object, info.Object, text.Object, uiFactory.Object, null);
|
||||||
|
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
|
|
||||||
repository.Verify(r => r.Load(It.Is<Uri>(u => u.Equals(new Uri(Path.Combine(location, "SettingsDummy.txt"))))), Times.Once);
|
repository.Verify(r => r.LoadSettings(It.Is<Uri>(u => u.Equals(new Uri(Path.Combine(location, "SettingsDummy.txt"))))), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void MustFallbackToDefaultsAsLastPrio()
|
public void MustFallbackToDefaultsAsLastPrio()
|
||||||
{
|
{
|
||||||
sut = new ConfigurationOperation(logger.Object, info.Object, repository.Object, text.Object, uiFactory.Object, null);
|
sut = new ConfigurationOperation(repository.Object, logger.Object, info.Object, text.Object, uiFactory.Object, null);
|
||||||
|
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
|
|
||||||
repository.Verify(r => r.LoadDefaults(), Times.Once);
|
repository.Verify(r => r.LoadDefaultSettings(), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
|
@ -136,7 +136,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
||||||
info.SetupGet(r => r.ProgramDataFolder).Returns(location);
|
info.SetupGet(r => r.ProgramDataFolder).Returns(location);
|
||||||
uiFactory.Setup(u => u.Show(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MessageBoxAction>(), It.IsAny<MessageBoxIcon>())).Returns(MessageBoxResult.Yes);
|
uiFactory.Setup(u => u.Show(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MessageBoxAction>(), It.IsAny<MessageBoxIcon>())).Returns(MessageBoxResult.Yes);
|
||||||
|
|
||||||
sut = new ConfigurationOperation(logger.Object, info.Object, repository.Object, text.Object, uiFactory.Object, null);
|
sut = new ConfigurationOperation(repository.Object, logger.Object, info.Object, text.Object, uiFactory.Object, null);
|
||||||
|
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
||||||
{
|
{
|
||||||
uiFactory.Setup(u => u.Show(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MessageBoxAction>(), It.IsAny<MessageBoxIcon>())).Returns(MessageBoxResult.No);
|
uiFactory.Setup(u => u.Show(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MessageBoxAction>(), It.IsAny<MessageBoxIcon>())).Returns(MessageBoxResult.No);
|
||||||
|
|
||||||
sut = new ConfigurationOperation(logger.Object, info.Object, repository.Object, text.Object, uiFactory.Object, null);
|
sut = new ConfigurationOperation(repository.Object, logger.Object, info.Object, text.Object, uiFactory.Object, null);
|
||||||
|
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
||||||
public class KioskModeOperationTests
|
public class KioskModeOperationTests
|
||||||
{
|
{
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Todo()
|
public void TODO()
|
||||||
{
|
{
|
||||||
Assert.Fail();
|
Assert.Fail();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ using System;
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
using Moq;
|
using Moq;
|
||||||
using SafeExamBrowser.Contracts.Communication;
|
using SafeExamBrowser.Contracts.Communication;
|
||||||
|
using SafeExamBrowser.Contracts.Configuration;
|
||||||
using SafeExamBrowser.Contracts.Configuration.Settings;
|
using SafeExamBrowser.Contracts.Configuration.Settings;
|
||||||
using SafeExamBrowser.Contracts.I18n;
|
using SafeExamBrowser.Contracts.I18n;
|
||||||
using SafeExamBrowser.Contracts.Logging;
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
|
@ -23,7 +24,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
||||||
{
|
{
|
||||||
private Mock<ILogger> logger;
|
private Mock<ILogger> logger;
|
||||||
private Mock<IServiceProxy> service;
|
private Mock<IServiceProxy> service;
|
||||||
private Mock<ISettingsRepository> settings;
|
private Mock<IConfigurationRepository> configuration;
|
||||||
private Mock<IProgressIndicator> progressIndicator;
|
private Mock<IProgressIndicator> progressIndicator;
|
||||||
private Mock<IText> text;
|
private Mock<IText> text;
|
||||||
private ServiceOperation sut;
|
private ServiceOperation sut;
|
||||||
|
@ -33,23 +34,23 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
||||||
{
|
{
|
||||||
logger = new Mock<ILogger>();
|
logger = new Mock<ILogger>();
|
||||||
service = new Mock<IServiceProxy>();
|
service = new Mock<IServiceProxy>();
|
||||||
settings = new Mock<ISettingsRepository>();
|
configuration = new Mock<IConfigurationRepository>();
|
||||||
progressIndicator = new Mock<IProgressIndicator>();
|
progressIndicator = new Mock<IProgressIndicator>();
|
||||||
text = new Mock<IText>();
|
text = new Mock<IText>();
|
||||||
|
|
||||||
sut = new ServiceOperation(logger.Object, service.Object, settings.Object, text.Object);
|
sut = new ServiceOperation(configuration.Object, logger.Object, service.Object, text.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void MustConnectToService()
|
public void MustConnectToService()
|
||||||
{
|
{
|
||||||
service.Setup(s => s.Connect()).Returns(true);
|
service.Setup(s => s.Connect()).Returns(true);
|
||||||
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Mandatory);
|
configuration.SetupGet(s => s.CurrentSettings.ServicePolicy).Returns(ServicePolicy.Mandatory);
|
||||||
|
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
|
|
||||||
service.Setup(s => s.Connect()).Returns(true);
|
service.Setup(s => s.Connect()).Returns(true);
|
||||||
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Optional);
|
configuration.SetupGet(s => s.CurrentSettings.ServicePolicy).Returns(ServicePolicy.Optional);
|
||||||
|
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
|
|
||||||
|
@ -60,22 +61,22 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
||||||
public void MustNotFailIfServiceNotAvailable()
|
public void MustNotFailIfServiceNotAvailable()
|
||||||
{
|
{
|
||||||
service.Setup(s => s.Connect()).Returns(false);
|
service.Setup(s => s.Connect()).Returns(false);
|
||||||
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Mandatory);
|
configuration.SetupGet(s => s.CurrentSettings.ServicePolicy).Returns(ServicePolicy.Mandatory);
|
||||||
|
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
|
|
||||||
service.Setup(s => s.Connect()).Returns(false);
|
service.Setup(s => s.Connect()).Returns(false);
|
||||||
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Optional);
|
configuration.SetupGet(s => s.CurrentSettings.ServicePolicy).Returns(ServicePolicy.Optional);
|
||||||
|
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
|
|
||||||
service.Setup(s => s.Connect()).Throws<Exception>();
|
service.Setup(s => s.Connect()).Throws<Exception>();
|
||||||
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Mandatory);
|
configuration.SetupGet(s => s.CurrentSettings.ServicePolicy).Returns(ServicePolicy.Mandatory);
|
||||||
|
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
|
|
||||||
service.Setup(s => s.Connect()).Throws<Exception>();
|
service.Setup(s => s.Connect()).Throws<Exception>();
|
||||||
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Optional);
|
configuration.SetupGet(s => s.CurrentSettings.ServicePolicy).Returns(ServicePolicy.Optional);
|
||||||
|
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
}
|
}
|
||||||
|
@ -84,7 +85,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
||||||
public void MustAbortIfServiceMandatoryAndNotAvailable()
|
public void MustAbortIfServiceMandatoryAndNotAvailable()
|
||||||
{
|
{
|
||||||
service.Setup(s => s.Connect()).Returns(false);
|
service.Setup(s => s.Connect()).Returns(false);
|
||||||
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Mandatory);
|
configuration.SetupGet(s => s.CurrentSettings.ServicePolicy).Returns(ServicePolicy.Mandatory);
|
||||||
|
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
|
|
||||||
|
@ -95,7 +96,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
||||||
public void MustNotAbortIfServiceOptionalAndNotAvailable()
|
public void MustNotAbortIfServiceOptionalAndNotAvailable()
|
||||||
{
|
{
|
||||||
service.Setup(s => s.Connect()).Returns(false);
|
service.Setup(s => s.Connect()).Returns(false);
|
||||||
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Optional);
|
configuration.SetupGet(s => s.CurrentSettings.ServicePolicy).Returns(ServicePolicy.Optional);
|
||||||
|
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
|
|
||||||
|
@ -107,13 +108,13 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
||||||
public void MustDisconnectWhenReverting()
|
public void MustDisconnectWhenReverting()
|
||||||
{
|
{
|
||||||
service.Setup(s => s.Connect()).Returns(true);
|
service.Setup(s => s.Connect()).Returns(true);
|
||||||
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Mandatory);
|
configuration.SetupGet(s => s.CurrentSettings.ServicePolicy).Returns(ServicePolicy.Mandatory);
|
||||||
|
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
sut.Revert();
|
sut.Revert();
|
||||||
|
|
||||||
service.Setup(s => s.Connect()).Returns(true);
|
service.Setup(s => s.Connect()).Returns(true);
|
||||||
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Optional);
|
configuration.SetupGet(s => s.CurrentSettings.ServicePolicy).Returns(ServicePolicy.Optional);
|
||||||
|
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
sut.Revert();
|
sut.Revert();
|
||||||
|
@ -126,7 +127,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
||||||
{
|
{
|
||||||
service.Setup(s => s.Connect()).Returns(true);
|
service.Setup(s => s.Connect()).Returns(true);
|
||||||
service.Setup(s => s.Disconnect()).Throws<Exception>();
|
service.Setup(s => s.Disconnect()).Throws<Exception>();
|
||||||
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Optional);
|
configuration.SetupGet(s => s.CurrentSettings.ServicePolicy).Returns(ServicePolicy.Optional);
|
||||||
|
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
sut.Revert();
|
sut.Revert();
|
||||||
|
@ -138,25 +139,25 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
||||||
public void MustNotDisconnnectIfNotAvailable()
|
public void MustNotDisconnnectIfNotAvailable()
|
||||||
{
|
{
|
||||||
service.Setup(s => s.Connect()).Returns(false);
|
service.Setup(s => s.Connect()).Returns(false);
|
||||||
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Mandatory);
|
configuration.SetupGet(s => s.CurrentSettings.ServicePolicy).Returns(ServicePolicy.Mandatory);
|
||||||
|
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
sut.Revert();
|
sut.Revert();
|
||||||
|
|
||||||
service.Setup(s => s.Connect()).Returns(false);
|
service.Setup(s => s.Connect()).Returns(false);
|
||||||
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Optional);
|
configuration.SetupGet(s => s.CurrentSettings.ServicePolicy).Returns(ServicePolicy.Optional);
|
||||||
|
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
sut.Revert();
|
sut.Revert();
|
||||||
|
|
||||||
service.Setup(s => s.Connect()).Throws<Exception>();
|
service.Setup(s => s.Connect()).Throws<Exception>();
|
||||||
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Mandatory);
|
configuration.SetupGet(s => s.CurrentSettings.ServicePolicy).Returns(ServicePolicy.Mandatory);
|
||||||
|
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
sut.Revert();
|
sut.Revert();
|
||||||
|
|
||||||
service.Setup(s => s.Connect()).Throws<Exception>();
|
service.Setup(s => s.Connect()).Throws<Exception>();
|
||||||
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Optional);
|
configuration.SetupGet(s => s.CurrentSettings.ServicePolicy).Returns(ServicePolicy.Optional);
|
||||||
|
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
sut.Revert();
|
sut.Revert();
|
||||||
|
|
|
@ -19,9 +19,9 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
||||||
{
|
{
|
||||||
internal class ConfigurationOperation : IOperation
|
internal class ConfigurationOperation : IOperation
|
||||||
{
|
{
|
||||||
|
private IConfigurationRepository repository;
|
||||||
private ILogger logger;
|
private ILogger logger;
|
||||||
private IRuntimeInfo runtimeInfo;
|
private IRuntimeInfo runtimeInfo;
|
||||||
private ISettingsRepository repository;
|
|
||||||
private IText text;
|
private IText text;
|
||||||
private IUserInterfaceFactory uiFactory;
|
private IUserInterfaceFactory uiFactory;
|
||||||
private string[] commandLineArgs;
|
private string[] commandLineArgs;
|
||||||
|
@ -30,16 +30,16 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
||||||
public IProgressIndicator ProgressIndicator { private get; set; }
|
public IProgressIndicator ProgressIndicator { private get; set; }
|
||||||
|
|
||||||
public ConfigurationOperation(
|
public ConfigurationOperation(
|
||||||
|
IConfigurationRepository repository,
|
||||||
ILogger logger,
|
ILogger logger,
|
||||||
IRuntimeInfo runtimeInfo,
|
IRuntimeInfo runtimeInfo,
|
||||||
ISettingsRepository repository,
|
|
||||||
IText text,
|
IText text,
|
||||||
IUserInterfaceFactory uiFactory,
|
IUserInterfaceFactory uiFactory,
|
||||||
string[] commandLineArgs)
|
string[] commandLineArgs)
|
||||||
{
|
{
|
||||||
|
this.repository = repository;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.commandLineArgs = commandLineArgs;
|
this.commandLineArgs = commandLineArgs;
|
||||||
this.repository = repository;
|
|
||||||
this.runtimeInfo = runtimeInfo;
|
this.runtimeInfo = runtimeInfo;
|
||||||
this.text = text;
|
this.text = text;
|
||||||
this.uiFactory = uiFactory;
|
this.uiFactory = uiFactory;
|
||||||
|
@ -56,7 +56,7 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
||||||
if (isValidUri)
|
if (isValidUri)
|
||||||
{
|
{
|
||||||
logger.Info($"Loading configuration from '{uri.AbsolutePath}'...");
|
logger.Info($"Loading configuration from '{uri.AbsolutePath}'...");
|
||||||
settings = repository.Load(uri);
|
settings = repository.LoadSettings(uri);
|
||||||
|
|
||||||
if (settings.ConfigurationMode == ConfigurationMode.ConfigureClient && UserWantsToAbortStartup())
|
if (settings.ConfigurationMode == ConfigurationMode.ConfigureClient && UserWantsToAbortStartup())
|
||||||
{
|
{
|
||||||
|
@ -67,7 +67,7 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger.Info("No valid settings file specified nor found in PROGRAMDATA or APPDATA - loading default settings...");
|
logger.Info("No valid settings file specified nor found in PROGRAMDATA or APPDATA - loading default settings...");
|
||||||
settings = repository.LoadDefaults();
|
settings = repository.LoadDefaultSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using SafeExamBrowser.Contracts.Behaviour.Operations;
|
using SafeExamBrowser.Contracts.Behaviour.Operations;
|
||||||
|
using SafeExamBrowser.Contracts.Configuration;
|
||||||
using SafeExamBrowser.Contracts.Configuration.Settings;
|
using SafeExamBrowser.Contracts.Configuration.Settings;
|
||||||
using SafeExamBrowser.Contracts.I18n;
|
using SafeExamBrowser.Contracts.I18n;
|
||||||
using SafeExamBrowser.Contracts.Logging;
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
|
@ -17,21 +18,21 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
||||||
internal class KioskModeOperation : IOperation
|
internal class KioskModeOperation : IOperation
|
||||||
{
|
{
|
||||||
private ILogger logger;
|
private ILogger logger;
|
||||||
private ISettingsRepository settingsRepository;
|
private IConfigurationRepository configuration;
|
||||||
private KioskMode kioskMode;
|
private KioskMode kioskMode;
|
||||||
|
|
||||||
public bool Abort { get; private set; }
|
public bool Abort { get; private set; }
|
||||||
public IProgressIndicator ProgressIndicator { private get; set; }
|
public IProgressIndicator ProgressIndicator { private get; set; }
|
||||||
|
|
||||||
public KioskModeOperation(ILogger logger, ISettingsRepository settingsRepository)
|
public KioskModeOperation(ILogger logger, IConfigurationRepository configuration)
|
||||||
{
|
{
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.settingsRepository = settingsRepository;
|
this.configuration = configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Perform()
|
public void Perform()
|
||||||
{
|
{
|
||||||
kioskMode = settingsRepository.Current.KioskMode;
|
kioskMode = configuration.CurrentSettings.KioskMode;
|
||||||
|
|
||||||
logger.Info($"Initializing kiosk mode '{kioskMode}'...");
|
logger.Info($"Initializing kiosk mode '{kioskMode}'...");
|
||||||
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeKioskMode);
|
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeKioskMode);
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
using System;
|
using System;
|
||||||
using SafeExamBrowser.Contracts.Behaviour.Operations;
|
using SafeExamBrowser.Contracts.Behaviour.Operations;
|
||||||
using SafeExamBrowser.Contracts.Communication;
|
using SafeExamBrowser.Contracts.Communication;
|
||||||
|
using SafeExamBrowser.Contracts.Configuration;
|
||||||
using SafeExamBrowser.Contracts.Configuration.Settings;
|
using SafeExamBrowser.Contracts.Configuration.Settings;
|
||||||
using SafeExamBrowser.Contracts.I18n;
|
using SafeExamBrowser.Contracts.I18n;
|
||||||
using SafeExamBrowser.Contracts.Logging;
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
|
@ -20,19 +21,19 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
||||||
{
|
{
|
||||||
private bool serviceAvailable;
|
private bool serviceAvailable;
|
||||||
private bool serviceMandatory;
|
private bool serviceMandatory;
|
||||||
|
private IConfigurationRepository configuration;
|
||||||
private ILogger logger;
|
private ILogger logger;
|
||||||
private IServiceProxy service;
|
private IServiceProxy service;
|
||||||
private ISettingsRepository settingsRepository;
|
|
||||||
private IText text;
|
private IText text;
|
||||||
|
|
||||||
public bool Abort { get; private set; }
|
public bool Abort { get; private set; }
|
||||||
public IProgressIndicator ProgressIndicator { private get; set; }
|
public IProgressIndicator ProgressIndicator { private get; set; }
|
||||||
|
|
||||||
public ServiceOperation(ILogger logger, IServiceProxy service, ISettingsRepository settingsRepository, IText text)
|
public ServiceOperation(IConfigurationRepository configuration, ILogger logger, IServiceProxy service, IText text)
|
||||||
{
|
{
|
||||||
|
this.configuration = configuration;
|
||||||
this.service = service;
|
this.service = service;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.settingsRepository = settingsRepository;
|
|
||||||
this.text = text;
|
this.text = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +44,7 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
serviceMandatory = settingsRepository.Current.ServicePolicy == ServicePolicy.Mandatory;
|
serviceMandatory = configuration.CurrentSettings.ServicePolicy == ServicePolicy.Mandatory;
|
||||||
serviceAvailable = service.Connect();
|
serviceAvailable = service.Connect();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|
|
@ -20,36 +20,41 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
{
|
{
|
||||||
internal class RuntimeController : IRuntimeController
|
internal class RuntimeController : IRuntimeController
|
||||||
{
|
{
|
||||||
|
private bool initialized;
|
||||||
|
|
||||||
|
private IConfigurationRepository configuration;
|
||||||
private ILogger logger;
|
private ILogger logger;
|
||||||
private IOperationSequence bootstrapSequence;
|
private IOperationSequence bootstrapSequence;
|
||||||
private IOperationSequence sessionSequence;
|
private IOperationSequence sessionSequence;
|
||||||
|
private IRuntimeHost runtimeHost;
|
||||||
private IRuntimeInfo runtimeInfo;
|
private IRuntimeInfo runtimeInfo;
|
||||||
private IRuntimeWindow runtimeWindow;
|
private IRuntimeWindow runtimeWindow;
|
||||||
private IServiceProxy serviceProxy;
|
private IServiceProxy serviceProxy;
|
||||||
private ISettingsRepository settingsRepository;
|
|
||||||
private ISplashScreen splashScreen;
|
private ISplashScreen splashScreen;
|
||||||
private Action terminationCallback;
|
private Action shutdown;
|
||||||
private IText text;
|
private IText text;
|
||||||
private IUserInterfaceFactory uiFactory;
|
private IUserInterfaceFactory uiFactory;
|
||||||
|
|
||||||
public RuntimeController(
|
public RuntimeController(
|
||||||
|
IConfigurationRepository configuration,
|
||||||
ILogger logger,
|
ILogger logger,
|
||||||
IOperationSequence bootstrapSequence,
|
IOperationSequence bootstrapSequence,
|
||||||
IOperationSequence sessionSequence,
|
IOperationSequence sessionSequence,
|
||||||
|
IRuntimeHost runtimeHost,
|
||||||
IRuntimeInfo runtimeInfo,
|
IRuntimeInfo runtimeInfo,
|
||||||
IServiceProxy serviceProxy,
|
IServiceProxy serviceProxy,
|
||||||
ISettingsRepository settingsRepository,
|
Action shutdown,
|
||||||
Action terminationCallback,
|
|
||||||
IText text,
|
IText text,
|
||||||
IUserInterfaceFactory uiFactory)
|
IUserInterfaceFactory uiFactory)
|
||||||
{
|
{
|
||||||
|
this.configuration = configuration;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.bootstrapSequence = bootstrapSequence;
|
this.bootstrapSequence = bootstrapSequence;
|
||||||
this.sessionSequence = sessionSequence;
|
this.sessionSequence = sessionSequence;
|
||||||
|
this.runtimeHost = runtimeHost;
|
||||||
this.runtimeInfo = runtimeInfo;
|
this.runtimeInfo = runtimeInfo;
|
||||||
this.serviceProxy = serviceProxy;
|
this.serviceProxy = serviceProxy;
|
||||||
this.settingsRepository = settingsRepository;
|
this.shutdown = shutdown;
|
||||||
this.terminationCallback = terminationCallback;
|
|
||||||
this.text = text;
|
this.text = text;
|
||||||
this.uiFactory = uiFactory;
|
this.uiFactory = uiFactory;
|
||||||
}
|
}
|
||||||
|
@ -58,19 +63,16 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
{
|
{
|
||||||
logger.Info("--- Initiating startup procedure ---");
|
logger.Info("--- Initiating startup procedure ---");
|
||||||
|
|
||||||
|
runtimeWindow = uiFactory.CreateRuntimeWindow(runtimeInfo, text);
|
||||||
splashScreen = uiFactory.CreateSplashScreen(runtimeInfo, text);
|
splashScreen = uiFactory.CreateSplashScreen(runtimeInfo, text);
|
||||||
splashScreen.Show();
|
splashScreen.Show();
|
||||||
|
|
||||||
bootstrapSequence.ProgressIndicator = splashScreen;
|
bootstrapSequence.ProgressIndicator = splashScreen;
|
||||||
|
|
||||||
var success = bootstrapSequence.TryPerform();
|
initialized = bootstrapSequence.TryPerform();
|
||||||
|
|
||||||
System.Threading.Thread.Sleep(5000);
|
if (initialized)
|
||||||
|
|
||||||
if (success)
|
|
||||||
{
|
{
|
||||||
runtimeWindow = uiFactory.CreateRuntimeWindow(runtimeInfo, text);
|
|
||||||
|
|
||||||
logger.Info("--- Application successfully initialized! ---");
|
logger.Info("--- Application successfully initialized! ---");
|
||||||
logger.Log(string.Empty);
|
logger.Log(string.Empty);
|
||||||
logger.Subscribe(runtimeWindow);
|
logger.Subscribe(runtimeWindow);
|
||||||
|
@ -85,17 +87,19 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
logger.Log(string.Empty);
|
logger.Log(string.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return initialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Terminate()
|
public void Terminate()
|
||||||
{
|
{
|
||||||
StopSession();
|
// TODO: Necessary here? Move to App.cs as private "started" flag if not...
|
||||||
|
if (!initialized)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO:
|
// TODO: Only if session is running!
|
||||||
// - Disconnect from service
|
StopSession();
|
||||||
// - Terminate runtime communication host
|
|
||||||
// - Revert kiosk mode (or do that when stopping session?)
|
|
||||||
|
|
||||||
logger.Unsubscribe(runtimeWindow);
|
logger.Unsubscribe(runtimeWindow);
|
||||||
runtimeWindow?.Close();
|
runtimeWindow?.Close();
|
||||||
|
@ -104,6 +108,10 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
logger.Log(string.Empty);
|
logger.Log(string.Empty);
|
||||||
logger.Info("--- Initiating shutdown procedure ---");
|
logger.Info("--- Initiating shutdown procedure ---");
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// - Disconnect from service
|
||||||
|
// - Terminate runtime communication host
|
||||||
|
// - Revert kiosk mode (or do that when stopping session?)
|
||||||
var success = bootstrapSequence.TryRevert();
|
var success = bootstrapSequence.TryRevert();
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
|
@ -137,25 +145,28 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
|
// TODO
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Remove!
|
||||||
System.Threading.Thread.Sleep(5000);
|
System.Threading.Thread.Sleep(5000);
|
||||||
|
|
||||||
|
runtimeWindow.HideProgressBar();
|
||||||
runtimeWindow.UpdateText(TextKey.RuntimeWindow_ApplicationRunning);
|
runtimeWindow.UpdateText(TextKey.RuntimeWindow_ApplicationRunning);
|
||||||
|
|
||||||
if (settingsRepository.Current.KioskMode == KioskMode.DisableExplorerShell)
|
if (configuration.CurrentSettings.KioskMode == KioskMode.DisableExplorerShell)
|
||||||
{
|
{
|
||||||
runtimeWindow.Hide();
|
runtimeWindow.Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Remove!
|
||||||
System.Threading.Thread.Sleep(5000);
|
System.Threading.Thread.Sleep(5000);
|
||||||
|
|
||||||
terminationCallback.Invoke();
|
shutdown.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StopSession()
|
private void StopSession()
|
||||||
|
@ -163,12 +174,26 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
logger.Info("Stopping current session...");
|
logger.Info("Stopping current session...");
|
||||||
runtimeWindow.Show();
|
runtimeWindow.Show();
|
||||||
runtimeWindow.BringToForeground();
|
runtimeWindow.BringToForeground();
|
||||||
|
runtimeWindow.ShowProgressBar();
|
||||||
runtimeWindow.UpdateText(TextKey.RuntimeWindow_StopSession, true);
|
runtimeWindow.UpdateText(TextKey.RuntimeWindow_StopSession, true);
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// - Terminate client (or does it terminate itself?)
|
// - Terminate client (or does it terminate itself?)
|
||||||
// - Finalize session with service
|
// - Finalize session with service
|
||||||
// - Stop event handling and close session
|
// - Stop event handling and close session
|
||||||
|
var success = sessionSequence.TryRevert();
|
||||||
|
|
||||||
|
// TODO: Remove!
|
||||||
|
System.Threading.Thread.Sleep(5000);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
42
SafeExamBrowser.Runtime/Communication/RuntimeHost.cs
Normal file
42
SafeExamBrowser.Runtime/Communication/RuntimeHost.cs
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using SafeExamBrowser.Contracts.Communication;
|
||||||
|
using SafeExamBrowser.Contracts.Communication.Messages;
|
||||||
|
using SafeExamBrowser.Contracts.Communication.Responses;
|
||||||
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
|
using SafeExamBrowser.Core.Communication;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Runtime.Communication
|
||||||
|
{
|
||||||
|
internal class RuntimeHost : BaseHost, IRuntimeHost
|
||||||
|
{
|
||||||
|
public RuntimeHost(string address, ILogger logger) : base(address, logger)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IConnectResponse Connect(Guid? token = null)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Disconnect(IMessage message)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IResponse Send(IMessage message)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,11 +8,8 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using SafeExamBrowser.Configuration;
|
using SafeExamBrowser.Configuration;
|
||||||
using SafeExamBrowser.Configuration.Settings;
|
|
||||||
using SafeExamBrowser.Contracts.Behaviour;
|
using SafeExamBrowser.Contracts.Behaviour;
|
||||||
using SafeExamBrowser.Contracts.Behaviour.Operations;
|
using SafeExamBrowser.Contracts.Behaviour.Operations;
|
||||||
using SafeExamBrowser.Contracts.Configuration;
|
using SafeExamBrowser.Contracts.Configuration;
|
||||||
|
@ -23,6 +20,7 @@ using SafeExamBrowser.Core.I18n;
|
||||||
using SafeExamBrowser.Core.Logging;
|
using SafeExamBrowser.Core.Logging;
|
||||||
using SafeExamBrowser.Runtime.Behaviour;
|
using SafeExamBrowser.Runtime.Behaviour;
|
||||||
using SafeExamBrowser.Runtime.Behaviour.Operations;
|
using SafeExamBrowser.Runtime.Behaviour.Operations;
|
||||||
|
using SafeExamBrowser.Runtime.Communication;
|
||||||
using SafeExamBrowser.UserInterface.Classic;
|
using SafeExamBrowser.UserInterface.Classic;
|
||||||
using SafeExamBrowser.WindowsApi;
|
using SafeExamBrowser.WindowsApi;
|
||||||
|
|
||||||
|
@ -31,7 +29,7 @@ namespace SafeExamBrowser.Runtime
|
||||||
internal class CompositionRoot
|
internal class CompositionRoot
|
||||||
{
|
{
|
||||||
private ILogger logger;
|
private ILogger logger;
|
||||||
private RuntimeInfo runtimeInfo;
|
private IRuntimeInfo runtimeInfo;
|
||||||
private ISystemInfo systemInfo;
|
private ISystemInfo systemInfo;
|
||||||
|
|
||||||
internal IRuntimeController RuntimeController { get; private set; }
|
internal IRuntimeController RuntimeController { get; private set; }
|
||||||
|
@ -42,30 +40,30 @@ namespace SafeExamBrowser.Runtime
|
||||||
var bootstrapOperations = new Queue<IOperation>();
|
var bootstrapOperations = new Queue<IOperation>();
|
||||||
var sessionOperations = new Queue<IOperation>();
|
var sessionOperations = new Queue<IOperation>();
|
||||||
var nativeMethods = new NativeMethods();
|
var nativeMethods = new NativeMethods();
|
||||||
var settingsRepository = new SettingsRepository();
|
var configuration = new ConfigurationRepository();
|
||||||
var uiFactory = new UserInterfaceFactory();
|
var uiFactory = new UserInterfaceFactory();
|
||||||
|
|
||||||
logger = new Logger();
|
logger = new Logger();
|
||||||
runtimeInfo = new RuntimeInfo();
|
runtimeInfo = configuration.RuntimeInfo;
|
||||||
systemInfo = new SystemInfo();
|
systemInfo = new SystemInfo();
|
||||||
|
|
||||||
InitializeRuntimeInfo();
|
|
||||||
InitializeLogging();
|
InitializeLogging();
|
||||||
|
|
||||||
var text = new Text(logger);
|
var text = new Text(logger);
|
||||||
var serviceProxy = new ServiceProxy(new ModuleLogger(logger, typeof(ServiceProxy)), "net.pipe://localhost/safeexambrowser/service");
|
var runtimeHost = new RuntimeHost(runtimeInfo.RuntimeAddress, new ModuleLogger(logger, typeof(RuntimeHost)));
|
||||||
|
var serviceProxy = new ServiceProxy(runtimeInfo.ServiceAddress, new ModuleLogger(logger, typeof(ServiceProxy)));
|
||||||
|
|
||||||
bootstrapOperations.Enqueue(new I18nOperation(logger, text));
|
bootstrapOperations.Enqueue(new I18nOperation(logger, text));
|
||||||
// TODO: RuntimeHostOperation here (is IBootstrapOperation -> only performed once per runtime!)
|
bootstrapOperations.Enqueue(new CommunicationOperation(runtimeHost, logger));
|
||||||
|
|
||||||
sessionOperations.Enqueue(new ConfigurationOperation(logger, runtimeInfo, settingsRepository, text, uiFactory, args));
|
sessionOperations.Enqueue(new ConfigurationOperation(configuration, logger, runtimeInfo, text, uiFactory, args));
|
||||||
sessionOperations.Enqueue(new ServiceOperation(logger, serviceProxy, settingsRepository, text));
|
sessionOperations.Enqueue(new ServiceOperation(configuration, logger, serviceProxy, text));
|
||||||
sessionOperations.Enqueue(new KioskModeOperation(logger, settingsRepository));
|
sessionOperations.Enqueue(new KioskModeOperation(logger, configuration));
|
||||||
|
|
||||||
var bootstrapSequence = new OperationSequence(logger, bootstrapOperations);
|
var boostrapSequence = new OperationSequence(logger, bootstrapOperations);
|
||||||
var sessionSequence = new OperationSequence(logger, sessionOperations);
|
var sessionSequence = new OperationSequence(logger, sessionOperations);
|
||||||
|
|
||||||
RuntimeController = new RuntimeController(logger, bootstrapSequence, sessionSequence, runtimeInfo, serviceProxy, settingsRepository, Application.Current.Shutdown, text, uiFactory);
|
RuntimeController = new RuntimeController(configuration, logger, boostrapSequence, sessionSequence, runtimeHost, runtimeInfo, serviceProxy, Application.Current.Shutdown, text, uiFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void LogStartupInformation()
|
internal void LogStartupInformation()
|
||||||
|
@ -84,28 +82,7 @@ namespace SafeExamBrowser.Runtime
|
||||||
|
|
||||||
internal void LogShutdownInformation()
|
internal void LogShutdownInformation()
|
||||||
{
|
{
|
||||||
logger?.Log($"{Environment.NewLine}# Application terminated at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
|
logger?.Log($"# Application terminated at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
|
||||||
}
|
|
||||||
|
|
||||||
private void InitializeRuntimeInfo()
|
|
||||||
{
|
|
||||||
var appDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), nameof(SafeExamBrowser));
|
|
||||||
var executable = Assembly.GetEntryAssembly();
|
|
||||||
var startTime = DateTime.Now;
|
|
||||||
var logFolder = Path.Combine(appDataFolder, "Logs");
|
|
||||||
var logFilePrefix = startTime.ToString("yyyy-MM-dd\\_HH\\hmm\\mss\\s");
|
|
||||||
|
|
||||||
runtimeInfo.ApplicationStartTime = startTime;
|
|
||||||
runtimeInfo.AppDataFolder = appDataFolder;
|
|
||||||
runtimeInfo.BrowserCachePath = Path.Combine(appDataFolder, "Cache");
|
|
||||||
runtimeInfo.BrowserLogFile = Path.Combine(logFolder, $"{logFilePrefix}_Browser.txt");
|
|
||||||
runtimeInfo.ClientLogFile = Path.Combine(logFolder, $"{logFilePrefix}_Client.txt");
|
|
||||||
runtimeInfo.DefaultSettingsFileName = "SebClientSettings.seb";
|
|
||||||
runtimeInfo.ProgramCopyright = executable.GetCustomAttribute<AssemblyCopyrightAttribute>().Copyright;
|
|
||||||
runtimeInfo.ProgramDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), nameof(SafeExamBrowser));
|
|
||||||
runtimeInfo.ProgramTitle = executable.GetCustomAttribute<AssemblyTitleAttribute>().Title;
|
|
||||||
runtimeInfo.ProgramVersion = executable.GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion;
|
|
||||||
runtimeInfo.RuntimeLogFile = Path.Combine(logFolder, $"{logFilePrefix}_Runtime.txt");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitializeLogging()
|
private void InitializeLogging()
|
||||||
|
|
|
@ -90,6 +90,7 @@
|
||||||
<Compile Include="Behaviour\Operations\ConfigurationOperation.cs" />
|
<Compile Include="Behaviour\Operations\ConfigurationOperation.cs" />
|
||||||
<Compile Include="Behaviour\Operations\KioskModeOperation.cs" />
|
<Compile Include="Behaviour\Operations\KioskModeOperation.cs" />
|
||||||
<Compile Include="Behaviour\Operations\ServiceOperation.cs" />
|
<Compile Include="Behaviour\Operations\ServiceOperation.cs" />
|
||||||
|
<Compile Include="Communication\RuntimeHost.cs" />
|
||||||
<Compile Include="CompositionRoot.cs" />
|
<Compile Include="CompositionRoot.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs">
|
<Compile Include="Properties\AssemblyInfo.cs">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
|
|
Loading…
Reference in a new issue