SEBWIN-301: Started working on service architecture.
This commit is contained in:
parent
ccf7727d4c
commit
73c7e28a33
18 changed files with 338 additions and 37 deletions
|
@ -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/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Contracts.Communication.Hosts
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the functionality of the communication host for the service application component.
|
||||||
|
/// </summary>
|
||||||
|
public interface IServiceHost : ICommunicationHost
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -59,6 +59,7 @@
|
||||||
<Compile Include="Communication\Events\ClientConfigurationEventArgs.cs" />
|
<Compile Include="Communication\Events\ClientConfigurationEventArgs.cs" />
|
||||||
<Compile Include="Communication\Events\MessageBoxReplyEventArgs.cs" />
|
<Compile Include="Communication\Events\MessageBoxReplyEventArgs.cs" />
|
||||||
<Compile Include="Communication\Events\MessageBoxRequestEventArgs.cs" />
|
<Compile Include="Communication\Events\MessageBoxRequestEventArgs.cs" />
|
||||||
|
<Compile Include="Communication\Hosts\IServiceHost.cs" />
|
||||||
<Compile Include="Configuration\Cryptography\EncryptionParameters.cs" />
|
<Compile Include="Configuration\Cryptography\EncryptionParameters.cs" />
|
||||||
<Compile Include="Configuration\Cryptography\ICertificateStore.cs" />
|
<Compile Include="Configuration\Cryptography\ICertificateStore.cs" />
|
||||||
<Compile Include="Configuration\Cryptography\IPasswordEncryption.cs" />
|
<Compile Include="Configuration\Cryptography\IPasswordEncryption.cs" />
|
||||||
|
|
|
@ -58,7 +58,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
{
|
{
|
||||||
var settings = new Settings { ConfigurationMode = ConfigurationMode.Exam };
|
var settings = new Settings { ConfigurationMode = ConfigurationMode.Exam };
|
||||||
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
||||||
var location = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations), FILE_NAME);
|
var location = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations), "Testdata", FILE_NAME);
|
||||||
|
|
||||||
appConfig.AppDataFilePath = location;
|
appConfig.AppDataFilePath = location;
|
||||||
appConfig.ProgramDataFilePath = location;
|
appConfig.ProgramDataFilePath = location;
|
||||||
|
@ -76,7 +76,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Perform_MustUseProgramDataAs2ndPrio()
|
public void Perform_MustUseProgramDataAs2ndPrio()
|
||||||
{
|
{
|
||||||
var location = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations), FILE_NAME);
|
var location = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations), "Testdata", FILE_NAME);
|
||||||
var settings = default(Settings);
|
var settings = default(Settings);
|
||||||
|
|
||||||
appConfig.ProgramDataFilePath = location;
|
appConfig.ProgramDataFilePath = location;
|
||||||
|
@ -93,7 +93,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Perform_MustUseAppDataAs3rdPrio()
|
public void Perform_MustUseAppDataAs3rdPrio()
|
||||||
{
|
{
|
||||||
var location = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations), FILE_NAME);
|
var location = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations), "Testdata", FILE_NAME);
|
||||||
var settings = default(Settings);
|
var settings = default(Settings);
|
||||||
|
|
||||||
appConfig.AppDataFilePath = location;
|
appConfig.AppDataFilePath = location;
|
||||||
|
@ -107,7 +107,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Perform_MustCorrectlyHandleBrowserResource()
|
public void Perform_MustTestdatalyHandleBrowserResource()
|
||||||
{
|
{
|
||||||
var settings = new Settings { ConfigurationMode = ConfigurationMode.Exam };
|
var settings = new Settings { ConfigurationMode = ConfigurationMode.Exam };
|
||||||
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
||||||
|
@ -281,7 +281,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
var settings = new Settings { AdminPasswordHash = "9876", ConfigurationMode = ConfigurationMode.ConfigureClient };
|
var settings = new Settings { AdminPasswordHash = "9876", ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||||
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
||||||
|
|
||||||
appConfig.AppDataFilePath = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations), FILE_NAME);
|
appConfig.AppDataFilePath = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations), "Testdata", FILE_NAME);
|
||||||
|
|
||||||
repository.Setup(r => r.TryLoadSettings(It.IsAny<Uri>(), out settings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
|
repository.Setup(r => r.TryLoadSettings(It.IsAny<Uri>(), out settings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
|
||||||
repository.Setup(r => r.TryLoadSettings(It.Is<Uri>(u => u.LocalPath.Contains(FILE_NAME)), out localSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
|
repository.Setup(r => r.TryLoadSettings(It.Is<Uri>(u => u.LocalPath.Contains(FILE_NAME)), out localSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
|
||||||
|
@ -331,16 +331,14 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Perform_MustSucceedIfAdminPasswordCorrect()
|
public void Perform_MustSucceedIfAdminPasswordTestdata()
|
||||||
{
|
{
|
||||||
var password = "test";
|
var password = "test";
|
||||||
var currentSettings = new Settings { AdminPasswordHash = "1234", ConfigurationMode = ConfigurationMode.ConfigureClient };
|
var currentSettings = new Settings { AdminPasswordHash = "1234", ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||||
var nextSettings = new Settings { AdminPasswordHash = "9876", ConfigurationMode = ConfigurationMode.ConfigureClient };
|
var nextSettings = new Settings { AdminPasswordHash = "9876", ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||||
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
||||||
|
|
||||||
appConfig.AppDataFilePath = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations), FILE_NAME);
|
|
||||||
nextSession.SetupGet(s => s.Settings).Returns(nextSettings);
|
nextSession.SetupGet(s => s.Settings).Returns(nextSettings);
|
||||||
|
|
||||||
hashAlgorithm.Setup(h => h.GenerateHashFor(It.Is<string>(p => p == password))).Returns(currentSettings.AdminPasswordHash);
|
hashAlgorithm.Setup(h => h.GenerateHashFor(It.Is<string>(p => p == password))).Returns(currentSettings.AdminPasswordHash);
|
||||||
repository.Setup(r => r.TryLoadSettings(It.IsAny<Uri>(), out currentSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
|
repository.Setup(r => r.TryLoadSettings(It.IsAny<Uri>(), out currentSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
|
||||||
repository.Setup(r => r.TryLoadSettings(It.Is<Uri>(u => u.AbsoluteUri == url), out nextSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
|
repository.Setup(r => r.TryLoadSettings(It.Is<Uri>(u => u.AbsoluteUri == url), out nextSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
|
||||||
|
@ -370,9 +368,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
var nextSettings = new Settings { AdminPasswordHash = "1234", ConfigurationMode = ConfigurationMode.ConfigureClient };
|
var nextSettings = new Settings { AdminPasswordHash = "1234", ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||||
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
||||||
|
|
||||||
appConfig.AppDataFilePath = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations), FILE_NAME);
|
|
||||||
nextSession.SetupGet(s => s.Settings).Returns(nextSettings);
|
nextSession.SetupGet(s => s.Settings).Returns(nextSettings);
|
||||||
|
|
||||||
repository.Setup(r => r.TryLoadSettings(It.IsAny<Uri>(), out currentSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
|
repository.Setup(r => r.TryLoadSettings(It.IsAny<Uri>(), out currentSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
|
||||||
repository.Setup(r => r.TryLoadSettings(It.Is<Uri>(u => u.AbsoluteUri == url), out nextSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
|
repository.Setup(r => r.TryLoadSettings(It.Is<Uri>(u => u.AbsoluteUri == url), out nextSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
|
||||||
repository.Setup(r => r.ConfigureClientWith(It.IsAny<Uri>(), It.IsAny<PasswordParameters>())).Returns(SaveStatus.Success);
|
repository.Setup(r => r.ConfigureClientWith(It.IsAny<Uri>(), It.IsAny<PasswordParameters>())).Returns(SaveStatus.Success);
|
||||||
|
@ -394,7 +390,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Perform_MustSucceedIfSettingsPasswordCorrect()
|
public void Perform_MustSucceedIfSettingsPasswordTestdata()
|
||||||
{
|
{
|
||||||
var password = "test";
|
var password = "test";
|
||||||
var settings = new Settings { ConfigurationMode = ConfigurationMode.Exam };
|
var settings = new Settings { ConfigurationMode = ConfigurationMode.Exam };
|
||||||
|
@ -424,7 +420,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
public void Perform_MustUseCurrentPasswordIfAvailable()
|
public void Perform_MustUseCurrentPasswordIfAvailable()
|
||||||
{
|
{
|
||||||
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
||||||
var location = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations), FILE_NAME);
|
var location = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations), "Testdata", FILE_NAME);
|
||||||
var settings = new Settings { AdminPasswordHash = "1234", ConfigurationMode = ConfigurationMode.Exam };
|
var settings = new Settings { AdminPasswordHash = "1234", ConfigurationMode = ConfigurationMode.Exam };
|
||||||
|
|
||||||
appConfig.AppDataFilePath = location;
|
appConfig.AppDataFilePath = location;
|
||||||
|
@ -455,7 +451,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
var nextSettings = new Settings { AdminPasswordHash = "9876", ConfigurationMode = ConfigurationMode.ConfigureClient };
|
var nextSettings = new Settings { AdminPasswordHash = "9876", ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||||
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
var url = @"http://www.safeexambrowser.org/whatever.seb";
|
||||||
|
|
||||||
appConfig.AppDataFilePath = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations), FILE_NAME);
|
appConfig.AppDataFilePath = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations), "Testdata", FILE_NAME);
|
||||||
nextSession.SetupGet(s => s.Settings).Returns(nextSettings);
|
nextSession.SetupGet(s => s.Settings).Returns(nextSettings);
|
||||||
|
|
||||||
hashAlgorithm.Setup(h => h.GenerateHashFor(It.Is<string>(p => p == password))).Returns(currentSettings.AdminPasswordHash);
|
hashAlgorithm.Setup(h => h.GenerateHashFor(It.Is<string>(p => p == password))).Returns(currentSettings.AdminPasswordHash);
|
||||||
|
@ -501,11 +497,11 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Repeat_MustPerformForExamWithCorrectUri()
|
public void Repeat_MustPerformForExamWithTestdataUri()
|
||||||
{
|
{
|
||||||
var currentSettings = new Settings();
|
var currentSettings = new Settings();
|
||||||
var location = Path.GetDirectoryName(GetType().Assembly.Location);
|
var location = Path.GetDirectoryName(GetType().Assembly.Location);
|
||||||
var resource = new Uri(Path.Combine(location, nameof(Operations), FILE_NAME));
|
var resource = new Uri(Path.Combine(location, nameof(Operations), "Testdata", FILE_NAME));
|
||||||
var settings = new Settings { ConfigurationMode = ConfigurationMode.Exam };
|
var settings = new Settings { ConfigurationMode = ConfigurationMode.Exam };
|
||||||
|
|
||||||
currentSession.SetupGet(s => s.Settings).Returns(currentSettings);
|
currentSession.SetupGet(s => s.Settings).Returns(currentSettings);
|
||||||
|
@ -523,11 +519,11 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Repeat_MustPerformForClientConfigurationWithCorrectUri()
|
public void Repeat_MustPerformForClientConfigurationWithTestdataUri()
|
||||||
{
|
{
|
||||||
var currentSettings = new Settings();
|
var currentSettings = new Settings();
|
||||||
var location = Path.GetDirectoryName(GetType().Assembly.Location);
|
var location = Path.GetDirectoryName(GetType().Assembly.Location);
|
||||||
var resource = new Uri(Path.Combine(location, nameof(Operations), FILE_NAME));
|
var resource = new Uri(Path.Combine(location, nameof(Operations), "Testdata", FILE_NAME));
|
||||||
var settings = new Settings { ConfigurationMode = ConfigurationMode.ConfigureClient };
|
var settings = new Settings { ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||||
|
|
||||||
currentSession.SetupGet(s => s.Settings).Returns(currentSettings);
|
currentSession.SetupGet(s => s.Settings).Returns(currentSettings);
|
||||||
|
@ -572,7 +568,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
{
|
{
|
||||||
var currentSettings = new Settings();
|
var currentSettings = new Settings();
|
||||||
var location = Path.GetDirectoryName(GetType().Assembly.Location);
|
var location = Path.GetDirectoryName(GetType().Assembly.Location);
|
||||||
var resource = new Uri(Path.Combine(location, nameof(Operations), FILE_NAME));
|
var resource = new Uri(Path.Combine(location, nameof(Operations), "Testdata", FILE_NAME));
|
||||||
var settings = new Settings { ConfigurationMode = ConfigurationMode.ConfigureClient };
|
var settings = new Settings { ConfigurationMode = ConfigurationMode.ConfigureClient };
|
||||||
|
|
||||||
currentSession.SetupGet(s => s.Settings).Returns(currentSettings);
|
currentSession.SetupGet(s => s.Settings).Returns(currentSettings);
|
||||||
|
|
|
@ -121,10 +121,7 @@
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Operations\SebClientSettings.seb">
|
<None Include="Operations\Testdata\SebClientSettings.seb">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Include="Operations\WRONG\SebClientSettings.seb">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -21,41 +21,41 @@ namespace SafeExamBrowser.Runtime
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The currently active <see cref="KioskMode"/>.
|
/// The currently active <see cref="KioskMode"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public KioskMode? ActiveMode { get; set; }
|
internal KioskMode? ActiveMode { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The currently running client process.
|
/// The currently running client process.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IProcess ClientProcess { get; set; }
|
internal IProcess ClientProcess { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The communication proxy for the currently running client process.
|
/// The communication proxy for the currently running client process.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IClientProxy ClientProxy { get; set; }
|
internal IClientProxy ClientProxy { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The configuration of the currently active session.
|
/// The configuration of the currently active session.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ISessionConfiguration Current { get; set; }
|
internal ISessionConfiguration Current { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The new desktop, if <see cref="KioskMode.CreateNewDesktop"/> is currently active.
|
/// The new desktop, if <see cref="KioskMode.CreateNewDesktop"/> is currently active.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IDesktop NewDesktop { get; set; }
|
internal IDesktop NewDesktop { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The configuration of the next session to be activated.
|
/// The configuration of the next session to be activated.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ISessionConfiguration Next { get; set; }
|
internal ISessionConfiguration Next { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The original desktop, if <see cref="KioskMode.CreateNewDesktop"/> is currently active.
|
/// The original desktop, if <see cref="KioskMode.CreateNewDesktop"/> is currently active.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IDesktop OriginalDesktop { get; set; }
|
internal IDesktop OriginalDesktop { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The path of the configuration file to be used for reconfiguration.
|
/// The path of the configuration file to be used for reconfiguration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string ReconfigurationFilePath { get; set; }
|
internal string ReconfigurationFilePath { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,21 +57,49 @@
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Castle.Core.4.4.0\lib\net45\Castle.Core.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
|
<HintPath>..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
|
<HintPath>..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="Moq, Version=4.11.0.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Moq.4.11.0\lib\net45\Moq.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Configuration" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.1\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="ServiceControllerTests.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\SafeExamBrowser.Contracts\SafeExamBrowser.Contracts.csproj">
|
||||||
|
<Project>{47da5933-bef8-4729-94e6-abde2db12262}</Project>
|
||||||
|
<Name>SafeExamBrowser.Contracts</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\SafeExamBrowser.Service\SafeExamBrowser.Service.csproj">
|
||||||
|
<Project>{fa3c6692-dfed-4afa-bd58-9a3da2753c78}</Project>
|
||||||
|
<Name>SafeExamBrowser.Service</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Communication\" />
|
||||||
|
<Folder Include="Operations\" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
|
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
|
|
109
SafeExamBrowser.Service.UnitTests/ServiceControllerTests.cs
Normal file
109
SafeExamBrowser.Service.UnitTests/ServiceControllerTests.cs
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
/*
|
||||||
|
* 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.Contracts.Communication.Hosts;
|
||||||
|
using SafeExamBrowser.Contracts.Core.OperationModel;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Service.UnitTests
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
public class ServiceControllerTests
|
||||||
|
{
|
||||||
|
private Mock<IOperationSequence> bootstrapSequence;
|
||||||
|
private SessionContext sessionContext;
|
||||||
|
private Mock<IRepeatableOperationSequence> sessionSequence;
|
||||||
|
private Mock<IServiceHost> serviceHost;
|
||||||
|
private ServiceController sut;
|
||||||
|
|
||||||
|
[TestInitialize]
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
bootstrapSequence = new Mock<IOperationSequence>();
|
||||||
|
sessionContext = new SessionContext();
|
||||||
|
sessionSequence = new Mock<IRepeatableOperationSequence>();
|
||||||
|
serviceHost = new Mock<IServiceHost>();
|
||||||
|
|
||||||
|
sut = new ServiceController(bootstrapSequence.Object, sessionSequence.Object, serviceHost.Object, sessionContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Start_MustOnlyPerformBootstrapSequence()
|
||||||
|
{
|
||||||
|
bootstrapSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success);
|
||||||
|
sessionSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success);
|
||||||
|
sessionContext.Current = null;
|
||||||
|
|
||||||
|
var success = sut.TryStart();
|
||||||
|
|
||||||
|
bootstrapSequence.Verify(b => b.TryPerform(), Times.Once);
|
||||||
|
bootstrapSequence.Verify(b => b.TryRevert(), Times.Never);
|
||||||
|
sessionSequence.Verify(b => b.TryPerform(), Times.Never);
|
||||||
|
sessionSequence.Verify(b => b.TryRepeat(), Times.Never);
|
||||||
|
sessionSequence.Verify(b => b.TryRevert(), Times.Never);
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Stop_MustRevertSessionThenBootstrapSequence()
|
||||||
|
{
|
||||||
|
var order = 0;
|
||||||
|
var bootstrap = 0;
|
||||||
|
var session = 0;
|
||||||
|
|
||||||
|
sut.TryStart();
|
||||||
|
|
||||||
|
bootstrapSequence.Reset();
|
||||||
|
sessionSequence.Reset();
|
||||||
|
|
||||||
|
bootstrapSequence.Setup(b => b.TryRevert()).Returns(OperationResult.Success).Callback(() => bootstrap = ++order);
|
||||||
|
sessionSequence.Setup(b => b.TryRevert()).Returns(OperationResult.Success).Callback(() => session = ++order);
|
||||||
|
|
||||||
|
sut.Terminate();
|
||||||
|
|
||||||
|
bootstrapSequence.Verify(b => b.TryPerform(), Times.Never);
|
||||||
|
bootstrapSequence.Verify(b => b.TryRevert(), Times.Once);
|
||||||
|
sessionSequence.Verify(b => b.TryPerform(), Times.Never);
|
||||||
|
sessionSequence.Verify(b => b.TryRepeat(), Times.Never);
|
||||||
|
sessionSequence.Verify(b => b.TryRevert(), Times.Once);
|
||||||
|
|
||||||
|
Assert.AreEqual(1, session);
|
||||||
|
Assert.AreEqual(2, bootstrap);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Stop_MustNotRevertSessionSequenceIfNoSessionRunning()
|
||||||
|
{
|
||||||
|
var order = 0;
|
||||||
|
var bootstrap = 0;
|
||||||
|
var session = 0;
|
||||||
|
|
||||||
|
sut.TryStart();
|
||||||
|
|
||||||
|
bootstrapSequence.Reset();
|
||||||
|
sessionSequence.Reset();
|
||||||
|
|
||||||
|
bootstrapSequence.Setup(b => b.TryRevert()).Returns(OperationResult.Success).Callback(() => bootstrap = ++order);
|
||||||
|
sessionSequence.Setup(b => b.TryRevert()).Returns(OperationResult.Success).Callback(() => session = ++order);
|
||||||
|
sessionContext.Current = null;
|
||||||
|
|
||||||
|
sut.Terminate();
|
||||||
|
|
||||||
|
bootstrapSequence.Verify(b => b.TryPerform(), Times.Never);
|
||||||
|
bootstrapSequence.Verify(b => b.TryRevert(), Times.Once);
|
||||||
|
sessionSequence.Verify(b => b.TryPerform(), Times.Never);
|
||||||
|
sessionSequence.Verify(b => b.TryRepeat(), Times.Never);
|
||||||
|
sessionSequence.Verify(b => b.TryRevert(), Times.Never);
|
||||||
|
|
||||||
|
Assert.AreEqual(0, session);
|
||||||
|
Assert.AreEqual(1, bootstrap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,9 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
|
<package id="Castle.Core" version="4.4.0" targetFramework="net472" />
|
||||||
|
<package id="Moq" version="4.11.0" targetFramework="net472" />
|
||||||
<package id="MSTest.TestAdapter" version="1.3.2" targetFramework="net472" />
|
<package id="MSTest.TestAdapter" version="1.3.2" targetFramework="net472" />
|
||||||
<package id="MSTest.TestFramework" version="1.3.2" targetFramework="net472" />
|
<package id="MSTest.TestFramework" version="1.3.2" targetFramework="net472" />
|
||||||
|
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.0" targetFramework="net472" />
|
||||||
|
<package id="System.Threading.Tasks.Extensions" version="4.5.1" targetFramework="net472" />
|
||||||
</packages>
|
</packages>
|
43
SafeExamBrowser.Service/Communication/ServiceHost.cs
Normal file
43
SafeExamBrowser.Service/Communication/ServiceHost.cs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* 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.Communication.Hosts;
|
||||||
|
using SafeExamBrowser.Contracts.Communication.Data;
|
||||||
|
using SafeExamBrowser.Contracts.Communication.Hosts;
|
||||||
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Service.Communication
|
||||||
|
{
|
||||||
|
internal class ServiceHost : BaseHost, IServiceHost
|
||||||
|
{
|
||||||
|
internal ServiceHost(string address, IHostObjectFactory factory, ILogger logger, int timeout_ms) : base(address, factory, logger, timeout_ms)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnConnect(Guid? token)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDisconnect()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Response OnReceive(Message message)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Response OnReceive(SimpleMessagePurport message)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,10 +7,16 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using SafeExamBrowser.Communication.Hosts;
|
||||||
|
using SafeExamBrowser.Contracts.Core.OperationModel;
|
||||||
using SafeExamBrowser.Contracts.Logging;
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
using SafeExamBrowser.Contracts.Service;
|
using SafeExamBrowser.Contracts.Service;
|
||||||
|
using SafeExamBrowser.Core.OperationModel;
|
||||||
|
using SafeExamBrowser.Core.Operations;
|
||||||
using SafeExamBrowser.Logging;
|
using SafeExamBrowser.Logging;
|
||||||
|
using SafeExamBrowser.Service.Communication;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Service
|
namespace SafeExamBrowser.Service
|
||||||
{
|
{
|
||||||
|
@ -22,11 +28,30 @@ namespace SafeExamBrowser.Service
|
||||||
|
|
||||||
internal void BuildObjectGraph()
|
internal void BuildObjectGraph()
|
||||||
{
|
{
|
||||||
logger = new Logger();
|
const string SERVICE_ADDRESS = "net.pipe://localhost/safeexambrowser/service";
|
||||||
|
const int FIVE_SECONDS = 5000;
|
||||||
|
|
||||||
InitializeLogging();
|
InitializeLogging();
|
||||||
|
|
||||||
ServiceController = new ServiceController();
|
var serviceHost = new ServiceHost(SERVICE_ADDRESS, new HostObjectFactory(), new ModuleLogger(logger, nameof(ServiceHost)), FIVE_SECONDS);
|
||||||
|
var sessionContext = new SessionContext();
|
||||||
|
|
||||||
|
var bootstrapOperations = new Queue<IOperation>();
|
||||||
|
var sessionOperations = new Queue<IRepeatableOperation>();
|
||||||
|
|
||||||
|
// TODO: bootstrapOperations.Enqueue(new RestoreOperation());
|
||||||
|
bootstrapOperations.Enqueue(new CommunicationHostOperation(serviceHost, logger));
|
||||||
|
|
||||||
|
// sessionOperations.Enqueue(new RuntimeConnectionOperation());
|
||||||
|
// sessionOperations.Enqueue(new LogOperation());
|
||||||
|
// sessionOperations.Enqueue(new RegistryOperation());
|
||||||
|
// sessionOperations.Enqueue(new WindowsUpdateOperation());
|
||||||
|
// sessionOperations.Enqueue(new SessionActivationOperation());
|
||||||
|
|
||||||
|
var bootstrapSequence = new OperationSequence(logger, bootstrapOperations);
|
||||||
|
var sessionSequence = new RepeatableOperationSequence(logger, sessionOperations);
|
||||||
|
|
||||||
|
ServiceController = new ServiceController(bootstrapSequence, sessionSequence, serviceHost, sessionContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void LogStartupInformation()
|
internal void LogStartupInformation()
|
||||||
|
@ -37,6 +62,7 @@ namespace SafeExamBrowser.Service
|
||||||
|
|
||||||
internal void LogShutdownInformation()
|
internal void LogShutdownInformation()
|
||||||
{
|
{
|
||||||
|
logger?.Log(string.Empty);
|
||||||
logger?.Log($"# Service terminated at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
|
logger?.Log($"# Service terminated at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,9 +74,10 @@ namespace SafeExamBrowser.Service
|
||||||
var logFilePath = Path.Combine(logFolder, $"{logFilePrefix}_Service.log");
|
var logFilePath = Path.Combine(logFolder, $"{logFilePrefix}_Service.log");
|
||||||
var logFileWriter = new LogFileWriter(new DefaultLogFormatter(), logFilePath);
|
var logFileWriter = new LogFileWriter(new DefaultLogFormatter(), logFilePath);
|
||||||
|
|
||||||
logFileWriter.Initialize();
|
logger = new Logger();
|
||||||
logger.LogLevel = LogLevel.Debug;
|
logger.LogLevel = LogLevel.Debug;
|
||||||
logger.Subscribe(logFileWriter);
|
logger.Subscribe(logFileWriter);
|
||||||
|
logFileWriter.Initialize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace SafeExamBrowser.Service
|
||||||
service = new ServiceInstaller();
|
service = new ServiceInstaller();
|
||||||
service.Description = "Performs operations which require elevated privileges.";
|
service.Description = "Performs operations which require elevated privileges.";
|
||||||
service.DisplayName = "Safe Exam Browser Service";
|
service.DisplayName = "Safe Exam Browser Service";
|
||||||
service.ServiceName = nameof(SafeExamBrowser.Service);
|
service.ServiceName = nameof(SafeExamBrowser);
|
||||||
service.StartType = ServiceStartMode.Automatic;
|
service.StartType = ServiceStartMode.Automatic;
|
||||||
|
|
||||||
Installers.Add(process);
|
Installers.Add(process);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
// General Information about an assembly is controlled through the following
|
// General Information about an assembly is controlled through the following
|
||||||
|
@ -14,6 +15,7 @@ using System.Runtime.InteropServices;
|
||||||
// to COM components. If you need to access a type in this assembly from
|
// to COM components. If you need to access a type in this assembly from
|
||||||
// COM, set the ComVisible attribute to true on that type.
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
|
[assembly: InternalsVisibleTo("SafeExamBrowser.Service.UnitTests")]
|
||||||
|
|
||||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
[assembly: Guid("fa3c6692-dfed-4afa-bd58-9a3da2753c78")]
|
[assembly: Guid("fa3c6692-dfed-4afa-bd58-9a3da2753c78")]
|
||||||
|
|
|
@ -59,6 +59,7 @@
|
||||||
<Reference Include="System.ServiceProcess" />
|
<Reference Include="System.ServiceProcess" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Communication\ServiceHost.cs" />
|
||||||
<Compile Include="CompositionRoot.cs" />
|
<Compile Include="CompositionRoot.cs" />
|
||||||
<Compile Include="Installer.cs">
|
<Compile Include="Installer.cs">
|
||||||
<SubType>Component</SubType>
|
<SubType>Component</SubType>
|
||||||
|
@ -68,19 +69,31 @@
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="ServiceController.cs" />
|
<Compile Include="ServiceController.cs" />
|
||||||
|
<Compile Include="SessionContext.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="App.config" />
|
<None Include="App.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\SafeExamBrowser.Communication\SafeExamBrowser.Communication.csproj">
|
||||||
|
<Project>{c9416a62-0623-4d38-96aa-92516b32f02f}</Project>
|
||||||
|
<Name>SafeExamBrowser.Communication</Name>
|
||||||
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\SafeExamBrowser.Contracts\SafeExamBrowser.Contracts.csproj">
|
<ProjectReference Include="..\SafeExamBrowser.Contracts\SafeExamBrowser.Contracts.csproj">
|
||||||
<Project>{47da5933-bef8-4729-94e6-abde2db12262}</Project>
|
<Project>{47da5933-bef8-4729-94e6-abde2db12262}</Project>
|
||||||
<Name>SafeExamBrowser.Contracts</Name>
|
<Name>SafeExamBrowser.Contracts</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\SafeExamBrowser.Core\SafeExamBrowser.Core.csproj">
|
||||||
|
<Project>{3d6fdbb6-a4af-4626-bb2b-bf329d44f9cc}</Project>
|
||||||
|
<Name>SafeExamBrowser.Core</Name>
|
||||||
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\SafeExamBrowser.Logging\SafeExamBrowser.Logging.csproj">
|
<ProjectReference Include="..\SafeExamBrowser.Logging\SafeExamBrowser.Logging.csproj">
|
||||||
<Project>{e107026c-2011-4552-a7d8-3a0d37881df6}</Project>
|
<Project>{e107026c-2011-4552-a7d8-3a0d37881df6}</Project>
|
||||||
<Name>SafeExamBrowser.Logging</Name>
|
<Name>SafeExamBrowser.Logging</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Operations\" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
|
@ -18,7 +18,7 @@ namespace SafeExamBrowser.Service
|
||||||
public Service()
|
public Service()
|
||||||
{
|
{
|
||||||
CanPauseAndContinue = false;
|
CanPauseAndContinue = false;
|
||||||
ServiceName = nameof(SafeExamBrowser.Service);
|
ServiceName = nameof(SafeExamBrowser);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Main()
|
public static void Main()
|
||||||
|
|
|
@ -6,20 +6,59 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using SafeExamBrowser.Contracts.Communication.Hosts;
|
||||||
|
using SafeExamBrowser.Contracts.Core.OperationModel;
|
||||||
using SafeExamBrowser.Contracts.Service;
|
using SafeExamBrowser.Contracts.Service;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Service
|
namespace SafeExamBrowser.Service
|
||||||
{
|
{
|
||||||
internal class ServiceController : IServiceController
|
internal class ServiceController : IServiceController
|
||||||
{
|
{
|
||||||
|
private IOperationSequence bootstrapSequence;
|
||||||
|
private IRepeatableOperationSequence sessionSequence;
|
||||||
|
private IServiceHost serviceHost;
|
||||||
|
private SessionContext sessionContext;
|
||||||
|
|
||||||
|
private object Session
|
||||||
|
{
|
||||||
|
get { return sessionContext.Current; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool SessionIsRunning
|
||||||
|
{
|
||||||
|
get { return Session != null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServiceController(
|
||||||
|
IOperationSequence bootstrapSequence,
|
||||||
|
IRepeatableOperationSequence sessionSequence,
|
||||||
|
IServiceHost serviceHost,
|
||||||
|
SessionContext sessionContext)
|
||||||
|
{
|
||||||
|
this.bootstrapSequence = bootstrapSequence;
|
||||||
|
this.sessionSequence = sessionSequence;
|
||||||
|
this.serviceHost = serviceHost;
|
||||||
|
this.sessionContext = sessionContext;
|
||||||
|
}
|
||||||
|
|
||||||
public bool TryStart()
|
public bool TryStart()
|
||||||
{
|
{
|
||||||
return true;
|
var result = bootstrapSequence.TryPerform();
|
||||||
|
var success = result == OperationResult.Success;
|
||||||
|
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Terminate()
|
public void Terminate()
|
||||||
{
|
{
|
||||||
|
var result = default(OperationResult);
|
||||||
|
|
||||||
|
if (SessionIsRunning)
|
||||||
|
{
|
||||||
|
result = sessionSequence.TryRevert();
|
||||||
|
}
|
||||||
|
|
||||||
|
result = bootstrapSequence.TryRevert();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
26
SafeExamBrowser.Service/SessionContext.cs
Normal file
26
SafeExamBrowser.Service/SessionContext.cs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* 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.Service
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Holds all configuration and runtime data required for the session handling.
|
||||||
|
/// </summary>
|
||||||
|
internal class SessionContext
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The configuration of the currently active session.
|
||||||
|
/// </summary>
|
||||||
|
internal object Current { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The configuration of the next session to be activated.
|
||||||
|
/// </summary>
|
||||||
|
internal object Next { get; set; }
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue