SEBWIN-219: Implemented basic service operation.
This commit is contained in:
parent
7d5c6a1b0b
commit
ebc12934bf
22 changed files with 389 additions and 36 deletions
|
@ -15,6 +15,7 @@ namespace SafeExamBrowser.Configuration.Settings
|
||||||
internal class Settings : ISettings
|
internal class Settings : ISettings
|
||||||
{
|
{
|
||||||
public ConfigurationMode ConfigurationMode { get; set; }
|
public ConfigurationMode ConfigurationMode { get; set; }
|
||||||
|
public ServicePolicy ServicePolicy { get; set; }
|
||||||
|
|
||||||
public IBrowserSettings Browser { get; set; }
|
public IBrowserSettings Browser { get; set; }
|
||||||
public IKeyboardSettings Keyboard { get; set; }
|
public IKeyboardSettings Keyboard { get; set; }
|
||||||
|
|
17
SafeExamBrowser.Contracts/Communication/IClientProxy.cs
Normal file
17
SafeExamBrowser.Contracts/Communication/IClientProxy.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Contracts.Communication
|
||||||
|
{
|
||||||
|
public interface IClientProxy
|
||||||
|
{
|
||||||
|
bool Connect(Guid token);
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,7 +14,7 @@ using SafeExamBrowser.Contracts.Communication.Responses;
|
||||||
namespace SafeExamBrowser.Contracts.Communication
|
namespace SafeExamBrowser.Contracts.Communication
|
||||||
{
|
{
|
||||||
[ServiceContract(SessionMode = SessionMode.Required)]
|
[ServiceContract(SessionMode = SessionMode.Required)]
|
||||||
public interface ICommunicationHost
|
public interface ICommunication
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initiates a connection to the host and must thus be called before any other opertion. To authenticate itself to the host, the
|
/// Initiates a connection to the host and must thus be called before any other opertion. To authenticate itself to the host, the
|
17
SafeExamBrowser.Contracts/Communication/IRuntimeProxy.cs
Normal file
17
SafeExamBrowser.Contracts/Communication/IRuntimeProxy.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Contracts.Communication
|
||||||
|
{
|
||||||
|
public interface IRuntimeProxy
|
||||||
|
{
|
||||||
|
bool Connect(Guid token);
|
||||||
|
}
|
||||||
|
}
|
23
SafeExamBrowser.Contracts/Communication/IServiceProxy.cs
Normal file
23
SafeExamBrowser.Contracts/Communication/IServiceProxy.cs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* 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 IServiceProxy
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to connect to the service host.
|
||||||
|
/// </summary>
|
||||||
|
bool Connect();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disconnects from the service host.
|
||||||
|
/// </summary>
|
||||||
|
void Disconnect();
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,11 +7,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.Serialization;
|
|
||||||
|
|
||||||
namespace SafeExamBrowser.Contracts.Communication.Messages
|
namespace SafeExamBrowser.Contracts.Communication.Messages
|
||||||
{
|
{
|
||||||
public interface IMessage : ISerializable
|
public interface IMessage
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The communication token needed for authentication with the host.
|
/// The communication token needed for authentication with the host.
|
||||||
|
|
|
@ -6,11 +6,9 @@
|
||||||
* 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 System.Runtime.Serialization;
|
|
||||||
|
|
||||||
namespace SafeExamBrowser.Contracts.Communication.Responses
|
namespace SafeExamBrowser.Contracts.Communication.Responses
|
||||||
{
|
{
|
||||||
public interface IResponse : ISerializable
|
public interface IResponse
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,16 @@ namespace SafeExamBrowser.Contracts.Configuration.Settings
|
||||||
{
|
{
|
||||||
public enum ConfigurationMode
|
public enum ConfigurationMode
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// In this mode, the application settings shall be used to configure the local client settings of a user. When running in this
|
||||||
|
/// mode, the user has the possiblity to re-configure the application during runtime.
|
||||||
|
/// </summary>
|
||||||
ConfigureClient,
|
ConfigureClient,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// In this mode, the application settings shall only be used to start an exam. When running in this mode, the user cannot re-
|
||||||
|
/// configure the application during runtime.
|
||||||
|
/// </summary>
|
||||||
Exam
|
Exam
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,11 @@ namespace SafeExamBrowser.Contracts.Configuration.Settings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IMouseSettings Mouse { get; }
|
IMouseSettings Mouse { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The active service policy.
|
||||||
|
/// </summary>
|
||||||
|
ServicePolicy ServicePolicy { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// All taskbar-related settings.
|
/// All taskbar-related settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* 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.Configuration.Settings
|
||||||
|
{
|
||||||
|
public enum ServicePolicy
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The service component must be running. If it is not running, the user won't be able to start the application.
|
||||||
|
/// </summary>
|
||||||
|
Mandatory,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The service component is optional. If it is not running, all service-related actions are simply skipped.
|
||||||
|
/// </summary>
|
||||||
|
Optional
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,10 +25,12 @@ namespace SafeExamBrowser.Contracts.I18n
|
||||||
MessageBox_StartupErrorTitle,
|
MessageBox_StartupErrorTitle,
|
||||||
Notification_AboutTooltip,
|
Notification_AboutTooltip,
|
||||||
Notification_LogTooltip,
|
Notification_LogTooltip,
|
||||||
|
SplashScreen_CloseServiceConnection,
|
||||||
SplashScreen_EmptyClipboard,
|
SplashScreen_EmptyClipboard,
|
||||||
SplashScreen_InitializeBrowser,
|
SplashScreen_InitializeBrowser,
|
||||||
SplashScreen_InitializeConfiguration,
|
SplashScreen_InitializeConfiguration,
|
||||||
SplashScreen_InitializeProcessMonitoring,
|
SplashScreen_InitializeProcessMonitoring,
|
||||||
|
SplashScreen_InitializeServiceConnection,
|
||||||
SplashScreen_InitializeTaskbar,
|
SplashScreen_InitializeTaskbar,
|
||||||
SplashScreen_InitializeWindowMonitoring,
|
SplashScreen_InitializeWindowMonitoring,
|
||||||
SplashScreen_InitializeWorkingArea,
|
SplashScreen_InitializeWorkingArea,
|
||||||
|
|
|
@ -55,7 +55,10 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Behaviour\IApplicationController.cs" />
|
<Compile Include="Behaviour\IApplicationController.cs" />
|
||||||
<Compile Include="Behaviour\IRuntimeController.cs" />
|
<Compile Include="Behaviour\IRuntimeController.cs" />
|
||||||
<Compile Include="Communication\ICommunicationHost.cs" />
|
<Compile Include="Communication\ICommunication.cs" />
|
||||||
|
<Compile Include="Communication\IClientProxy.cs" />
|
||||||
|
<Compile Include="Communication\IRuntimeProxy.cs" />
|
||||||
|
<Compile Include="Communication\IServiceProxy.cs" />
|
||||||
<Compile Include="Communication\Messages\IMessage.cs" />
|
<Compile Include="Communication\Messages\IMessage.cs" />
|
||||||
<Compile Include="Communication\Responses\IResponse.cs" />
|
<Compile Include="Communication\Responses\IResponse.cs" />
|
||||||
<Compile Include="Communication\Responses\IConnectResponse.cs" />
|
<Compile Include="Communication\Responses\IConnectResponse.cs" />
|
||||||
|
@ -78,6 +81,7 @@
|
||||||
<Compile Include="Behaviour\IStartupController.cs" />
|
<Compile Include="Behaviour\IStartupController.cs" />
|
||||||
<Compile Include="Configuration\Settings\ISettingsRepository.cs" />
|
<Compile Include="Configuration\Settings\ISettingsRepository.cs" />
|
||||||
<Compile Include="Configuration\Settings\ITaskbarSettings.cs" />
|
<Compile Include="Configuration\Settings\ITaskbarSettings.cs" />
|
||||||
|
<Compile Include="Configuration\Settings\ServicePolicy.cs" />
|
||||||
<Compile Include="I18n\IText.cs" />
|
<Compile Include="I18n\IText.cs" />
|
||||||
<Compile Include="I18n\TextKey.cs" />
|
<Compile Include="I18n\TextKey.cs" />
|
||||||
<Compile Include="Logging\ILogContent.cs" />
|
<Compile Include="Logging\ILogContent.cs" />
|
||||||
|
|
|
@ -15,30 +15,33 @@ using SafeExamBrowser.Contracts.Logging;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Core.Communication
|
namespace SafeExamBrowser.Core.Communication
|
||||||
{
|
{
|
||||||
public class CommunicationHostProxy : ICommunicationHost
|
public abstract class BaseProxy : ICommunication
|
||||||
{
|
{
|
||||||
private string address;
|
private string address;
|
||||||
private ILogger logger;
|
private ICommunication channel;
|
||||||
private ICommunicationHost channel;
|
|
||||||
|
|
||||||
public CommunicationHostProxy(ILogger logger, string address)
|
protected Guid? CommunicationToken { get; private set; }
|
||||||
|
protected ILogger Logger { get; private set; }
|
||||||
|
|
||||||
|
public BaseProxy(ILogger logger, string address)
|
||||||
{
|
{
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.logger = logger;
|
this.Logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IConnectResponse Connect(Guid? token = null)
|
public IConnectResponse Connect(Guid? token = null)
|
||||||
{
|
{
|
||||||
var endpoint = new EndpointAddress(address);
|
var endpoint = new EndpointAddress(address);
|
||||||
|
|
||||||
channel = ChannelFactory<ICommunicationHost>.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 += CommunicationHostProxy_Closed;
|
||||||
(channel as ICommunicationObject).Closing += CommunicationHostProxy_Closing;
|
(channel as ICommunicationObject).Closing += CommunicationHostProxy_Closing;
|
||||||
(channel as ICommunicationObject).Faulted += CommunicationHostProxy_Faulted;
|
(channel as ICommunicationObject).Faulted += CommunicationHostProxy_Faulted;
|
||||||
|
|
||||||
var response = channel.Connect(token);
|
var response = channel.Connect(token);
|
||||||
|
|
||||||
logger.Debug($"Tried to connect to {address}, connection was {(response.ConnectionEstablished ? "established" : "refused")}.");
|
CommunicationToken = response.CommunicationToken;
|
||||||
|
Logger.Debug($"Tried to connect to {address}, connection was {(response.ConnectionEstablished ? "established" : "refused")}.");
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
@ -48,7 +51,7 @@ namespace SafeExamBrowser.Core.Communication
|
||||||
if (ChannelIsReady())
|
if (ChannelIsReady())
|
||||||
{
|
{
|
||||||
channel.Disconnect(message);
|
channel.Disconnect(message);
|
||||||
logger.Debug($"Disconnected from {address}, transmitting {ToString(message)}.");
|
Logger.Debug($"Disconnected from {address}, transmitting {ToString(message)}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new CommunicationException($"Tried to disconnect from host, but channel was {GetChannelState()}!");
|
throw new CommunicationException($"Tried to disconnect from host, but channel was {GetChannelState()}!");
|
||||||
|
@ -60,7 +63,7 @@ namespace SafeExamBrowser.Core.Communication
|
||||||
{
|
{
|
||||||
var response = channel.Send(message);
|
var response = channel.Send(message);
|
||||||
|
|
||||||
logger.Debug($"Sent {ToString(message)}, got {ToString(response)}.");
|
Logger.Debug($"Sent {ToString(message)}, got {ToString(response)}.");
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
@ -68,6 +71,14 @@ namespace SafeExamBrowser.Core.Communication
|
||||||
throw new CommunicationException($"Tried to send {ToString(message)}, but channel was {GetChannelState()}!");
|
throw new CommunicationException($"Tried to send {ToString(message)}, but channel was {GetChannelState()}!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void FailIfNotConnected(string operationName)
|
||||||
|
{
|
||||||
|
if (!CommunicationToken.HasValue)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Cannot perform '{operationName}' before being connected to endpoint!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private bool ChannelIsReady()
|
private bool ChannelIsReady()
|
||||||
{
|
{
|
||||||
return channel != null && (channel as ICommunicationObject).State == CommunicationState.Opened;
|
return channel != null && (channel as ICommunicationObject).State == CommunicationState.Opened;
|
||||||
|
@ -75,17 +86,17 @@ namespace SafeExamBrowser.Core.Communication
|
||||||
|
|
||||||
private void CommunicationHostProxy_Closed(object sender, EventArgs e)
|
private void CommunicationHostProxy_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 CommunicationHostProxy_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 CommunicationHostProxy_Faulted(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
logger.Error("Communication channel has faulted!");
|
Logger.Error("Communication channel has faulted!");
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetChannelState()
|
private string GetChannelState()
|
19
SafeExamBrowser.Core/Communication/Messages/Message.cs
Normal file
19
SafeExamBrowser.Core/Communication/Messages/Message.cs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* 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.Messages;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Core.Communication.Messages
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
internal class Message : IMessage
|
||||||
|
{
|
||||||
|
public Guid CommunicationToken { get; set; }
|
||||||
|
}
|
||||||
|
}
|
34
SafeExamBrowser.Core/Communication/ServiceProxy.cs
Normal file
34
SafeExamBrowser.Core/Communication/ServiceProxy.cs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* 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.Logging;
|
||||||
|
using SafeExamBrowser.Core.Communication.Messages;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Core.Communication
|
||||||
|
{
|
||||||
|
public class ServiceProxy : BaseProxy, IServiceProxy
|
||||||
|
{
|
||||||
|
public ServiceProxy(ILogger logger, string address) : base(logger, address)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Connect()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Disconnect()
|
||||||
|
{
|
||||||
|
FailIfNotConnected(nameof(Disconnect));
|
||||||
|
|
||||||
|
Disconnect(new Message { CommunicationToken = CommunicationToken.Value });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,6 +30,9 @@
|
||||||
<Entry key="Notification_LogTooltip">
|
<Entry key="Notification_LogTooltip">
|
||||||
Application Log
|
Application Log
|
||||||
</Entry>
|
</Entry>
|
||||||
|
<Entry key="SplashScreen_CloseServiceConnection">
|
||||||
|
Closing service connection
|
||||||
|
</Entry>
|
||||||
<Entry key="SplashScreen_EmptyClipboard">
|
<Entry key="SplashScreen_EmptyClipboard">
|
||||||
Emptying clipboard
|
Emptying clipboard
|
||||||
</Entry>
|
</Entry>
|
||||||
|
@ -42,6 +45,9 @@
|
||||||
<Entry key="SplashScreen_InitializeProcessMonitoring">
|
<Entry key="SplashScreen_InitializeProcessMonitoring">
|
||||||
Initializing process monitoring
|
Initializing process monitoring
|
||||||
</Entry>
|
</Entry>
|
||||||
|
<Entry key="SplashScreen_InitializeServiceConnection">
|
||||||
|
Initializing service connection
|
||||||
|
</Entry>
|
||||||
<Entry key="SplashScreen_InitializeTaskbar">
|
<Entry key="SplashScreen_InitializeTaskbar">
|
||||||
Initializing taskbar
|
Initializing taskbar
|
||||||
</Entry>
|
</Entry>
|
||||||
|
|
|
@ -58,7 +58,9 @@
|
||||||
<Compile Include="Behaviour\Operations\I18nOperation.cs" />
|
<Compile Include="Behaviour\Operations\I18nOperation.cs" />
|
||||||
<Compile Include="Behaviour\ShutdownController.cs" />
|
<Compile Include="Behaviour\ShutdownController.cs" />
|
||||||
<Compile Include="Behaviour\StartupController.cs" />
|
<Compile Include="Behaviour\StartupController.cs" />
|
||||||
<Compile Include="Communication\CommunicationHostProxy.cs" />
|
<Compile Include="Communication\BaseProxy.cs" />
|
||||||
|
<Compile Include="Communication\Messages\Message.cs" />
|
||||||
|
<Compile Include="Communication\ServiceProxy.cs" />
|
||||||
<Compile Include="Logging\DefaultLogFormatter.cs" />
|
<Compile Include="Logging\DefaultLogFormatter.cs" />
|
||||||
<Compile Include="Logging\LogFileWriter.cs" />
|
<Compile Include="Logging\LogFileWriter.cs" />
|
||||||
<Compile Include="Logging\LogMessage.cs" />
|
<Compile Include="Logging\LogMessage.cs" />
|
||||||
|
@ -82,6 +84,8 @@
|
||||||
<Name>SafeExamBrowser.Contracts</Name>
|
<Name>SafeExamBrowser.Contracts</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup />
|
<ItemGroup>
|
||||||
|
<Folder Include="Communication\Responses\" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
|
@ -6,17 +6,151 @@
|
||||||
* 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 System;
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using Moq;
|
||||||
|
using SafeExamBrowser.Contracts.Communication;
|
||||||
|
using SafeExamBrowser.Contracts.Configuration.Settings;
|
||||||
|
using SafeExamBrowser.Contracts.I18n;
|
||||||
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
|
using SafeExamBrowser.Contracts.UserInterface;
|
||||||
|
using SafeExamBrowser.Runtime.Behaviour.Operations;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
||||||
{
|
{
|
||||||
[TestClass]
|
[TestClass]
|
||||||
public class ServiceOperationTests
|
public class ServiceOperationTests
|
||||||
{
|
{
|
||||||
[TestMethod]
|
private Mock<ILogger> logger;
|
||||||
public void Test()
|
private Mock<IServiceProxy> service;
|
||||||
|
private Mock<ISettingsRepository> settings;
|
||||||
|
private Mock<ISplashScreen> splashScreen;
|
||||||
|
private Mock<IText> text;
|
||||||
|
private ServiceOperation sut;
|
||||||
|
|
||||||
|
[TestInitialize]
|
||||||
|
public void Initialize()
|
||||||
{
|
{
|
||||||
Assert.Fail();
|
logger = new Mock<ILogger>();
|
||||||
|
service = new Mock<IServiceProxy>();
|
||||||
|
settings = new Mock<ISettingsRepository>();
|
||||||
|
splashScreen = new Mock<ISplashScreen>();
|
||||||
|
text = new Mock<IText>();
|
||||||
|
|
||||||
|
sut = new ServiceOperation(logger.Object, service.Object, settings.Object, text.Object)
|
||||||
|
{
|
||||||
|
SplashScreen = splashScreen.Object
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void MustConnectToService()
|
||||||
|
{
|
||||||
|
service.Setup(s => s.Connect()).Returns(true);
|
||||||
|
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Mandatory);
|
||||||
|
|
||||||
|
sut.Perform();
|
||||||
|
|
||||||
|
service.Setup(s => s.Connect()).Returns(true);
|
||||||
|
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Optional);
|
||||||
|
|
||||||
|
sut.Perform();
|
||||||
|
|
||||||
|
service.Verify(s => s.Connect(), Times.Exactly(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void MustNotFailIfServiceNotAvailable()
|
||||||
|
{
|
||||||
|
service.Setup(s => s.Connect()).Returns(false);
|
||||||
|
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Mandatory);
|
||||||
|
|
||||||
|
sut.Perform();
|
||||||
|
|
||||||
|
service.Setup(s => s.Connect()).Returns(false);
|
||||||
|
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Optional);
|
||||||
|
|
||||||
|
sut.Perform();
|
||||||
|
|
||||||
|
service.Setup(s => s.Connect()).Throws<Exception>();
|
||||||
|
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Mandatory);
|
||||||
|
|
||||||
|
sut.Perform();
|
||||||
|
|
||||||
|
service.Setup(s => s.Connect()).Throws<Exception>();
|
||||||
|
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Optional);
|
||||||
|
|
||||||
|
sut.Perform();
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void MustAbortIfServiceMandatoryAndNotAvailable()
|
||||||
|
{
|
||||||
|
service.Setup(s => s.Connect()).Returns(false);
|
||||||
|
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Mandatory);
|
||||||
|
|
||||||
|
sut.Perform();
|
||||||
|
|
||||||
|
Assert.IsTrue(sut.AbortStartup);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void MustNotAbortIfServiceOptionalAndNotAvailable()
|
||||||
|
{
|
||||||
|
service.Setup(s => s.Connect()).Returns(false);
|
||||||
|
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Optional);
|
||||||
|
|
||||||
|
sut.Perform();
|
||||||
|
|
||||||
|
Assert.IsFalse(sut.AbortStartup);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void MustDisconnectWhenReverting()
|
||||||
|
{
|
||||||
|
service.Setup(s => s.Connect()).Returns(true);
|
||||||
|
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Mandatory);
|
||||||
|
|
||||||
|
sut.Perform();
|
||||||
|
sut.Revert();
|
||||||
|
|
||||||
|
service.Setup(s => s.Connect()).Returns(true);
|
||||||
|
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Optional);
|
||||||
|
|
||||||
|
sut.Perform();
|
||||||
|
sut.Revert();
|
||||||
|
|
||||||
|
service.Verify(s => s.Disconnect(), Times.Exactly(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void MustNotDisconnnectIfNotAvailable()
|
||||||
|
{
|
||||||
|
service.Setup(s => s.Connect()).Returns(false);
|
||||||
|
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Mandatory);
|
||||||
|
|
||||||
|
sut.Perform();
|
||||||
|
sut.Revert();
|
||||||
|
|
||||||
|
service.Setup(s => s.Connect()).Returns(false);
|
||||||
|
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Optional);
|
||||||
|
|
||||||
|
sut.Perform();
|
||||||
|
sut.Revert();
|
||||||
|
|
||||||
|
service.Setup(s => s.Connect()).Throws<Exception>();
|
||||||
|
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Mandatory);
|
||||||
|
|
||||||
|
sut.Perform();
|
||||||
|
sut.Revert();
|
||||||
|
|
||||||
|
service.Setup(s => s.Connect()).Throws<Exception>();
|
||||||
|
settings.SetupGet(s => s.Current.ServicePolicy).Returns(ServicePolicy.Optional);
|
||||||
|
|
||||||
|
sut.Perform();
|
||||||
|
sut.Revert();
|
||||||
|
|
||||||
|
service.Verify(s => s.Disconnect(), Times.Never);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour
|
||||||
public class RuntimeControllerTests
|
public class RuntimeControllerTests
|
||||||
{
|
{
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Test()
|
public void TODO()
|
||||||
{
|
{
|
||||||
Assert.Fail();
|
Assert.Fail();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,11 @@
|
||||||
* 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 System;
|
||||||
using SafeExamBrowser.Contracts.Behaviour;
|
using SafeExamBrowser.Contracts.Behaviour;
|
||||||
using SafeExamBrowser.Contracts.Communication;
|
using SafeExamBrowser.Contracts.Communication;
|
||||||
using SafeExamBrowser.Contracts.Configuration.Settings;
|
using SafeExamBrowser.Contracts.Configuration.Settings;
|
||||||
|
using SafeExamBrowser.Contracts.I18n;
|
||||||
using SafeExamBrowser.Contracts.Logging;
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
using SafeExamBrowser.Contracts.UserInterface;
|
using SafeExamBrowser.Contracts.UserInterface;
|
||||||
|
|
||||||
|
@ -16,31 +18,76 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
|
||||||
{
|
{
|
||||||
internal class ServiceOperation : IOperation
|
internal class ServiceOperation : IOperation
|
||||||
{
|
{
|
||||||
private ICommunicationHost serviceHost;
|
private bool serviceAvailable;
|
||||||
|
private bool serviceMandatory;
|
||||||
private ILogger logger;
|
private ILogger logger;
|
||||||
|
private IServiceProxy service;
|
||||||
private ISettingsRepository settingsRepository;
|
private ISettingsRepository settingsRepository;
|
||||||
|
private IText text;
|
||||||
|
|
||||||
public bool AbortStartup { get; private set; }
|
public bool AbortStartup { get; private set; }
|
||||||
public ISplashScreen SplashScreen { private get; set; }
|
public ISplashScreen SplashScreen { private get; set; }
|
||||||
|
|
||||||
public ServiceOperation(ICommunicationHost serviceHost, ILogger logger, ISettingsRepository settingsRepository)
|
public ServiceOperation(ILogger logger, IServiceProxy service, ISettingsRepository settingsRepository, IText text)
|
||||||
{
|
{
|
||||||
this.serviceHost = serviceHost;
|
this.service = service;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.settingsRepository = settingsRepository;
|
this.settingsRepository = settingsRepository;
|
||||||
|
this.text = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Perform()
|
public void Perform()
|
||||||
{
|
{
|
||||||
logger.Info("Initializing service connection...");
|
logger.Info($"Initializing service connection...");
|
||||||
// SplashScreen.UpdateText(...)
|
SplashScreen.UpdateText(TextKey.SplashScreen_InitializeServiceConnection);
|
||||||
|
|
||||||
// TODO
|
try
|
||||||
|
{
|
||||||
|
serviceMandatory = settingsRepository.Current.ServicePolicy == ServicePolicy.Mandatory;
|
||||||
|
serviceAvailable = service.Connect();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
var message = "Failed to connect to the service component!";
|
||||||
|
|
||||||
|
if (serviceMandatory)
|
||||||
|
{
|
||||||
|
logger.Error(message, e);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.Info($"{message} Reason: {e.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AbortStartup = serviceMandatory && !serviceAvailable;
|
||||||
|
|
||||||
|
if (AbortStartup)
|
||||||
|
{
|
||||||
|
logger.Info("Aborting startup because the service is mandatory but not available!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.Info($"The service is {(serviceMandatory ? "mandatory" : "optional")} and {(!serviceAvailable ? "not" : "")} available.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Revert()
|
public void Revert()
|
||||||
{
|
{
|
||||||
// TODO
|
logger.Info("Closing service connection...");
|
||||||
|
SplashScreen.UpdateText(TextKey.SplashScreen_CloseServiceConnection);
|
||||||
|
|
||||||
|
if (serviceAvailable)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
service.Disconnect();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.Error("Failed to disconnect from service component!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
{
|
{
|
||||||
internal class RuntimeController : IRuntimeController
|
internal class RuntimeController : IRuntimeController
|
||||||
{
|
{
|
||||||
private ICommunicationHost serviceProxy;
|
private ICommunication serviceProxy;
|
||||||
private Queue<IOperation> operations;
|
private Queue<IOperation> operations;
|
||||||
private ILogger logger;
|
private ILogger logger;
|
||||||
private ISettingsRepository settingsRepository;
|
private ISettingsRepository settingsRepository;
|
||||||
|
@ -27,7 +27,7 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
public ISettings Settings { private get; set; }
|
public ISettings Settings { private get; set; }
|
||||||
|
|
||||||
public RuntimeController(
|
public RuntimeController(
|
||||||
ICommunicationHost serviceProxy,
|
ICommunication serviceProxy,
|
||||||
ILogger logger,
|
ILogger logger,
|
||||||
ISettingsRepository settingsRepository,
|
ISettingsRepository settingsRepository,
|
||||||
IShutdownController shutdownController,
|
IShutdownController shutdownController,
|
||||||
|
|
|
@ -51,7 +51,7 @@ namespace SafeExamBrowser.Runtime
|
||||||
InitializeLogging();
|
InitializeLogging();
|
||||||
|
|
||||||
var text = new Text(logger);
|
var text = new Text(logger);
|
||||||
var serviceProxy = new CommunicationHostProxy(new ModuleLogger(logger, typeof(CommunicationHostProxy)), "net.pipe://localhost/safeexambrowser/service");
|
var serviceProxy = new ServiceProxy(new ModuleLogger(logger, typeof(ServiceProxy)), "net.pipe://localhost/safeexambrowser/service");
|
||||||
var shutdownController = new ShutdownController(logger, runtimeInfo, text, uiFactory);
|
var shutdownController = new ShutdownController(logger, runtimeInfo, text, uiFactory);
|
||||||
var startupController = new StartupController(logger, runtimeInfo, systemInfo, text, uiFactory);
|
var startupController = new StartupController(logger, runtimeInfo, systemInfo, text, uiFactory);
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ namespace SafeExamBrowser.Runtime
|
||||||
StartupOperations = new Queue<IOperation>();
|
StartupOperations = new Queue<IOperation>();
|
||||||
StartupOperations.Enqueue(new I18nOperation(logger, text));
|
StartupOperations.Enqueue(new I18nOperation(logger, text));
|
||||||
StartupOperations.Enqueue(new ConfigurationOperation(logger, runtimeInfo, settingsRepository, text, uiFactory, args));
|
StartupOperations.Enqueue(new ConfigurationOperation(logger, runtimeInfo, settingsRepository, text, uiFactory, args));
|
||||||
StartupOperations.Enqueue(new ServiceOperation(serviceProxy, logger, settingsRepository));
|
StartupOperations.Enqueue(new ServiceOperation(logger, serviceProxy, settingsRepository, text));
|
||||||
//StartupOperations.Enqueue(new KioskModeOperation());
|
//StartupOperations.Enqueue(new KioskModeOperation());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue