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();
 | 
			
		||||
			logger = new Logger();
 | 
			
		||||
			nativeMethods = new NativeMethods();
 | 
			
		||||
			settings = new SettingsRepository().LoadDefaults();
 | 
			
		||||
			settings = new ConfigurationRepository().LoadDefaultSettings();
 | 
			
		||||
			systemInfo = new SystemInfo();
 | 
			
		||||
			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 string BrowserCachePath { get; set; }
 | 
			
		||||
		public string BrowserLogFile { get; set; }
 | 
			
		||||
		public string ClientAddress { get; set; }
 | 
			
		||||
		public Guid ClientId { get; set; }
 | 
			
		||||
		public string ClientLogFile { get; set; }
 | 
			
		||||
		public string DefaultSettingsFileName { get; set; }
 | 
			
		||||
		public string ProgramCopyright { get; set; }
 | 
			
		||||
		public string ProgramDataFolder { get; set; }
 | 
			
		||||
		public string ProgramTitle { get; set; }
 | 
			
		||||
		public string ProgramVersion { get; set; }
 | 
			
		||||
		public string RuntimeAddress { get; set; }
 | 
			
		||||
		public Guid RuntimeId { get; set; }
 | 
			
		||||
		public string RuntimeLogFile { get; set; }
 | 
			
		||||
		public string ServiceAddress { get; set; }
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -59,7 +59,7 @@
 | 
			
		|||
    <Compile Include="Settings\MouseSettings.cs" />
 | 
			
		||||
    <Compile Include="Settings\Settings.cs" />
 | 
			
		||||
    <Compile Include="Properties\AssemblyInfo.cs" />
 | 
			
		||||
    <Compile Include="Settings\SettingsRepository.cs" />
 | 
			
		||||
    <Compile Include="ConfigurationRepository.cs" />
 | 
			
		||||
    <Compile Include="SystemInfo.cs" />
 | 
			
		||||
    <Compile Include="Settings\TaskbarSettings.cs" />
 | 
			
		||||
  </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/.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace SafeExamBrowser.Contracts.Behaviour
 | 
			
		||||
{
 | 
			
		||||
	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 SafeExamBrowser.Contracts.Configuration.Settings;
 | 
			
		||||
 | 
			
		||||
namespace SafeExamBrowser.Contracts.Configuration.Settings
 | 
			
		||||
namespace SafeExamBrowser.Contracts.Configuration
 | 
			
		||||
{
 | 
			
		||||
	public interface ISettingsRepository
 | 
			
		||||
	public interface IConfigurationRepository
 | 
			
		||||
	{
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// 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>
 | 
			
		||||
		ISettings Current { get; }
 | 
			
		||||
		ISettings CurrentSettings { get; }
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// The runtime information for the currently running application instance.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		IRuntimeInfo RuntimeInfo { get; }
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Attempts to load settings from the specified path.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		/// <exception cref="System.ArgumentException">Thrown if the given path cannot be resolved to a settings file.</exception>
 | 
			
		||||
		ISettings Load(Uri path);
 | 
			
		||||
		/// <exception cref="ArgumentException">Thrown if the given path cannot be resolved to a settings file.</exception>
 | 
			
		||||
		ISettings LoadSettings(Uri path);
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Loads the default settings.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		ISettings LoadDefaults();
 | 
			
		||||
		ISettings LoadDefaultSettings();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -32,6 +32,22 @@ namespace SafeExamBrowser.Contracts.Configuration
 | 
			
		|||
		/// </summary>
 | 
			
		||||
		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>
 | 
			
		||||
		/// The file path under which the log of the client component is to be stored.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -62,9 +78,24 @@ namespace SafeExamBrowser.Contracts.Configuration
 | 
			
		|||
		/// </summary>
 | 
			
		||||
		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>
 | 
			
		||||
		/// The file path under which the log of the runtime component is to be stored.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		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_InitializeWindowMonitoring,
 | 
			
		||||
		ProgressIndicator_InitializeWorkingArea,
 | 
			
		||||
		ProgressIndicator_RestartCommunicationHost,
 | 
			
		||||
		ProgressIndicator_RestoreWorkingArea,
 | 
			
		||||
		ProgressIndicator_RevertKioskMode,
 | 
			
		||||
		ProgressIndicator_ShutdownProcedure,
 | 
			
		||||
		ProgressIndicator_StartCommunicationHost,
 | 
			
		||||
		ProgressIndicator_StartEventHandling,
 | 
			
		||||
		ProgressIndicator_StartKeyboardInterception,
 | 
			
		||||
		ProgressIndicator_StartMouseInterception,
 | 
			
		||||
		ProgressIndicator_StopCommunicationHost,
 | 
			
		||||
		ProgressIndicator_StopEventHandling,
 | 
			
		||||
		ProgressIndicator_StopKeyboardInterception,
 | 
			
		||||
		ProgressIndicator_StopMouseInterception,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,6 +58,8 @@
 | 
			
		|||
    <Compile Include="Behaviour\Operations\IOperationSequence.cs" />
 | 
			
		||||
    <Compile Include="Communication\ICommunication.cs" />
 | 
			
		||||
    <Compile Include="Communication\IClientProxy.cs" />
 | 
			
		||||
    <Compile Include="Communication\ICommunicationHost.cs" />
 | 
			
		||||
    <Compile Include="Communication\IRuntimeHost.cs" />
 | 
			
		||||
    <Compile Include="Communication\IRuntimeProxy.cs" />
 | 
			
		||||
    <Compile Include="Communication\IServiceProxy.cs" />
 | 
			
		||||
    <Compile Include="Communication\Messages\IMessage.cs" />
 | 
			
		||||
| 
						 | 
				
			
			@ -78,7 +80,7 @@
 | 
			
		|||
    <Compile Include="Configuration\Settings\IKeyboardSettings.cs" />
 | 
			
		||||
    <Compile Include="Configuration\Settings\IMouseSettings.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\KioskMode.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>();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		[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
 | 
			
		||||
 | 
			
		||||
		[TestMethod]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -78,6 +78,7 @@
 | 
			
		|||
    <Reference Include="System.Xml" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Compile Include="Behaviour\Operations\CommunicationOperationTests.cs" />
 | 
			
		||||
    <Compile Include="Behaviour\Operations\I18nOperationTests.cs" />
 | 
			
		||||
    <Compile Include="Behaviour\Operations\OperationSequenceTests.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)
 | 
			
		||||
				{
 | 
			
		||||
					Revert();
 | 
			
		||||
					Revert(true);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			catch (Exception e)
 | 
			
		||||
| 
						 | 
				
			
			@ -74,8 +74,8 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
 | 
			
		|||
 | 
			
		||||
			try
 | 
			
		||||
			{
 | 
			
		||||
				Initialize();
 | 
			
		||||
				success = Revert(false);
 | 
			
		||||
				Initialize(true);
 | 
			
		||||
				success = Revert();
 | 
			
		||||
			}
 | 
			
		||||
			catch (Exception e)
 | 
			
		||||
			{
 | 
			
		||||
| 
						 | 
				
			
			@ -154,7 +154,7 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
 | 
			
		|||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private bool Revert(bool regress = true)
 | 
			
		||||
		private bool Revert(bool regress = false)
 | 
			
		||||
		{
 | 
			
		||||
			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 ILogger Logger { get; private set; }
 | 
			
		||||
 | 
			
		||||
		public BaseProxy(ILogger logger, string address)
 | 
			
		||||
		public BaseProxy(string address, ILogger logger)
 | 
			
		||||
		{
 | 
			
		||||
			this.address = address;
 | 
			
		||||
			this.Logger = logger;
 | 
			
		||||
| 
						 | 
				
			
			@ -34,9 +34,11 @@ namespace SafeExamBrowser.Core.Communication
 | 
			
		|||
			var endpoint = new EndpointAddress(address);
 | 
			
		||||
 | 
			
		||||
			channel = ChannelFactory<ICommunication>.CreateChannel(new NetNamedPipeBinding(NetNamedPipeSecurityMode.Transport), endpoint);
 | 
			
		||||
			(channel as ICommunicationObject).Closed += CommunicationHostProxy_Closed;
 | 
			
		||||
			(channel as ICommunicationObject).Closing += CommunicationHostProxy_Closing;
 | 
			
		||||
			(channel as ICommunicationObject).Faulted += CommunicationHostProxy_Faulted;
 | 
			
		||||
			(channel as ICommunicationObject).Closed += BaseProxy_Closed;
 | 
			
		||||
			(channel as ICommunicationObject).Closing += BaseProxy_Closing;
 | 
			
		||||
			(channel as ICommunicationObject).Faulted += BaseProxy_Faulted;
 | 
			
		||||
			(channel as ICommunicationObject).Opened += BaseProxy_Opened;
 | 
			
		||||
			(channel as ICommunicationObject).Opening += BaseProxy_Opening;
 | 
			
		||||
 | 
			
		||||
			var response = channel.Connect(token);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -84,21 +86,31 @@ namespace SafeExamBrowser.Core.Communication
 | 
			
		|||
			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.");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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!");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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()
 | 
			
		||||
		{
 | 
			
		||||
			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 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">
 | 
			
		||||
    Initializing working area
 | 
			
		||||
  </Entry>
 | 
			
		||||
  <Entry key="ProgressIndicator_RestartCommunicationHost">
 | 
			
		||||
    Restarting communication host
 | 
			
		||||
  </Entry>
 | 
			
		||||
  <Entry key="ProgressIndicator_RestoreWorkingArea">
 | 
			
		||||
    Restoring working area
 | 
			
		||||
  </Entry>
 | 
			
		||||
| 
						 | 
				
			
			@ -69,6 +72,9 @@
 | 
			
		|||
  <Entry key="ProgressIndicator_ShutdownProcedure">
 | 
			
		||||
    Initiating shutdown procedure
 | 
			
		||||
  </Entry>
 | 
			
		||||
  <Entry key="ProgressIndicator_StartCommunicationHost">
 | 
			
		||||
    Starting communication host
 | 
			
		||||
  </Entry>
 | 
			
		||||
  <Entry key="ProgressIndicator_StartEventHandling">
 | 
			
		||||
    Starting event handling
 | 
			
		||||
  </Entry>
 | 
			
		||||
| 
						 | 
				
			
			@ -78,6 +84,9 @@
 | 
			
		|||
  <Entry key="ProgressIndicator_StartMouseInterception">
 | 
			
		||||
    Starting mouse interception
 | 
			
		||||
  </Entry>
 | 
			
		||||
  <Entry key="ProgressIndicator_StopCommunicationHost">
 | 
			
		||||
    Stopping communication host
 | 
			
		||||
  </Entry>
 | 
			
		||||
  <Entry key="ProgressIndicator_StopEventHandling">
 | 
			
		||||
    Stopping event handling
 | 
			
		||||
  </Entry>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,9 +55,11 @@
 | 
			
		|||
    <Reference Include="System.Xml.Linq" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Compile Include="Behaviour\Operations\CommunicationOperation.cs" />
 | 
			
		||||
    <Compile Include="Behaviour\Operations\I18nOperation.cs" />
 | 
			
		||||
    <Compile Include="Behaviour\Operations\OperationSequence.cs" />
 | 
			
		||||
    <Compile Include="Communication\BaseProxy.cs" />
 | 
			
		||||
    <Compile Include="Communication\BaseHost.cs" />
 | 
			
		||||
    <Compile Include="Communication\Messages\Message.cs" />
 | 
			
		||||
    <Compile Include="Communication\ServiceProxy.cs" />
 | 
			
		||||
    <Compile Include="Logging\DefaultLogFormatter.cs" />
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,7 +24,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
			
		|||
	{
 | 
			
		||||
		private Mock<ILogger> logger;
 | 
			
		||||
		private Mock<IRuntimeInfo> info;
 | 
			
		||||
		private Mock<ISettingsRepository> repository;
 | 
			
		||||
		private Mock<IConfigurationRepository> repository;
 | 
			
		||||
		private Mock<ISettings> settings;
 | 
			
		||||
		private Mock<IText> text;
 | 
			
		||||
		private Mock<IUserInterfaceFactory> uiFactory;
 | 
			
		||||
| 
						 | 
				
			
			@ -35,7 +35,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
			
		|||
		{
 | 
			
		||||
			logger = new Mock<ILogger>();
 | 
			
		||||
			info = new Mock<IRuntimeInfo>();
 | 
			
		||||
			repository = new Mock<ISettingsRepository>();
 | 
			
		||||
			repository = new Mock<IConfigurationRepository>();
 | 
			
		||||
			settings = new Mock<ISettings>();
 | 
			
		||||
			text = new Mock<IText>();
 | 
			
		||||
			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.DefaultSettingsFileName).Returns("SettingsDummy.txt");
 | 
			
		||||
			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.LoadDefaults()).Returns(settings.Object);
 | 
			
		||||
			repository.Setup(r => r.LoadSettings(It.IsAny<Uri>())).Returns(settings.Object);
 | 
			
		||||
			repository.Setup(r => r.LoadDefaultSettings()).Returns(settings.Object);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		[TestMethod]
 | 
			
		||||
		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 = 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();
 | 
			
		||||
 | 
			
		||||
			repository.Verify(r => r.LoadDefaults(), Times.Exactly(2));
 | 
			
		||||
			repository.Verify(r => r.LoadDefaultSettings(), Times.Exactly(2));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		[TestMethod]
 | 
			
		||||
| 
						 | 
				
			
			@ -68,7 +68,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
			
		|||
		{
 | 
			
		||||
			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();
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -82,11 +82,11 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
			
		|||
			info.SetupGet(r => r.ProgramDataFolder).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();
 | 
			
		||||
 | 
			
		||||
			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]
 | 
			
		||||
| 
						 | 
				
			
			@ -97,11 +97,11 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
			
		|||
			info.SetupGet(r => r.ProgramDataFolder).Returns(location);
 | 
			
		||||
			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();
 | 
			
		||||
 | 
			
		||||
			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]
 | 
			
		||||
| 
						 | 
				
			
			@ -111,21 +111,21 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
			
		|||
 | 
			
		||||
			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();
 | 
			
		||||
 | 
			
		||||
			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]
 | 
			
		||||
		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();
 | 
			
		||||
 | 
			
		||||
			repository.Verify(r => r.LoadDefaults(), Times.Once);
 | 
			
		||||
			repository.Verify(r => r.LoadDefaultSettings(), Times.Once);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		[TestMethod]
 | 
			
		||||
| 
						 | 
				
			
			@ -136,7 +136,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
			
		|||
			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);
 | 
			
		||||
 | 
			
		||||
			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();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
 | 
			
		||||
			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();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,7 +14,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
			
		|||
	public class KioskModeOperationTests
 | 
			
		||||
	{
 | 
			
		||||
		[TestMethod]
 | 
			
		||||
		public void Todo()
 | 
			
		||||
		public void TODO()
 | 
			
		||||
		{
 | 
			
		||||
			Assert.Fail();
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,7 @@ using System;
 | 
			
		|||
using Microsoft.VisualStudio.TestTools.UnitTesting;
 | 
			
		||||
using Moq;
 | 
			
		||||
using SafeExamBrowser.Contracts.Communication;
 | 
			
		||||
using SafeExamBrowser.Contracts.Configuration;
 | 
			
		||||
using SafeExamBrowser.Contracts.Configuration.Settings;
 | 
			
		||||
using SafeExamBrowser.Contracts.I18n;
 | 
			
		||||
using SafeExamBrowser.Contracts.Logging;
 | 
			
		||||
| 
						 | 
				
			
			@ -23,7 +24,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
			
		|||
	{
 | 
			
		||||
		private Mock<ILogger> logger;
 | 
			
		||||
		private Mock<IServiceProxy> service;
 | 
			
		||||
		private Mock<ISettingsRepository> settings;
 | 
			
		||||
		private Mock<IConfigurationRepository> configuration;
 | 
			
		||||
		private Mock<IProgressIndicator> progressIndicator;
 | 
			
		||||
		private Mock<IText> text;
 | 
			
		||||
		private ServiceOperation sut;
 | 
			
		||||
| 
						 | 
				
			
			@ -33,23 +34,23 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
			
		|||
		{
 | 
			
		||||
			logger = new Mock<ILogger>();
 | 
			
		||||
			service = new Mock<IServiceProxy>();
 | 
			
		||||
			settings = new Mock<ISettingsRepository>();
 | 
			
		||||
			configuration = new Mock<IConfigurationRepository>();
 | 
			
		||||
			progressIndicator = new Mock<IProgressIndicator>();
 | 
			
		||||
			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]
 | 
			
		||||
		public void MustConnectToService()
 | 
			
		||||
		{
 | 
			
		||||
			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();
 | 
			
		||||
 | 
			
		||||
			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();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -60,22 +61,22 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
			
		|||
		public void MustNotFailIfServiceNotAvailable()
 | 
			
		||||
		{
 | 
			
		||||
			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();
 | 
			
		||||
 | 
			
		||||
			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();
 | 
			
		||||
 | 
			
		||||
			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();
 | 
			
		||||
 | 
			
		||||
			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();
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -84,7 +85,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
			
		|||
		public void MustAbortIfServiceMandatoryAndNotAvailable()
 | 
			
		||||
		{
 | 
			
		||||
			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();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -95,7 +96,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
			
		|||
		public void MustNotAbortIfServiceOptionalAndNotAvailable()
 | 
			
		||||
		{
 | 
			
		||||
			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();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -107,13 +108,13 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
			
		|||
		public void MustDisconnectWhenReverting()
 | 
			
		||||
		{
 | 
			
		||||
			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.Revert();
 | 
			
		||||
 | 
			
		||||
			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.Revert();
 | 
			
		||||
| 
						 | 
				
			
			@ -126,7 +127,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
			
		|||
		{
 | 
			
		||||
			service.Setup(s => s.Connect()).Returns(true);
 | 
			
		||||
			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.Revert();
 | 
			
		||||
| 
						 | 
				
			
			@ -138,25 +139,25 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
			
		|||
		public void MustNotDisconnnectIfNotAvailable()
 | 
			
		||||
		{
 | 
			
		||||
			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.Revert();
 | 
			
		||||
 | 
			
		||||
			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.Revert();
 | 
			
		||||
 | 
			
		||||
			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.Revert();
 | 
			
		||||
 | 
			
		||||
			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.Revert();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,9 +19,9 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
 | 
			
		|||
{
 | 
			
		||||
	internal class ConfigurationOperation : IOperation
 | 
			
		||||
	{
 | 
			
		||||
		private IConfigurationRepository repository;
 | 
			
		||||
		private ILogger logger;
 | 
			
		||||
		private IRuntimeInfo runtimeInfo;
 | 
			
		||||
		private ISettingsRepository repository;
 | 
			
		||||
		private IText text;
 | 
			
		||||
		private IUserInterfaceFactory uiFactory;
 | 
			
		||||
		private string[] commandLineArgs;
 | 
			
		||||
| 
						 | 
				
			
			@ -30,16 +30,16 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
 | 
			
		|||
		public IProgressIndicator ProgressIndicator { private get; set; }
 | 
			
		||||
 | 
			
		||||
		public ConfigurationOperation(
 | 
			
		||||
			IConfigurationRepository repository,
 | 
			
		||||
			ILogger logger,
 | 
			
		||||
			IRuntimeInfo runtimeInfo,
 | 
			
		||||
			ISettingsRepository repository,
 | 
			
		||||
			IText text,
 | 
			
		||||
			IUserInterfaceFactory uiFactory,
 | 
			
		||||
			string[] commandLineArgs)
 | 
			
		||||
		{
 | 
			
		||||
			this.repository = repository;
 | 
			
		||||
			this.logger = logger;
 | 
			
		||||
			this.commandLineArgs = commandLineArgs;
 | 
			
		||||
			this.repository = repository;
 | 
			
		||||
			this.runtimeInfo = runtimeInfo;
 | 
			
		||||
			this.text = text;
 | 
			
		||||
			this.uiFactory = uiFactory;
 | 
			
		||||
| 
						 | 
				
			
			@ -56,7 +56,7 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
 | 
			
		|||
			if (isValidUri)
 | 
			
		||||
			{
 | 
			
		||||
				logger.Info($"Loading configuration from '{uri.AbsolutePath}'...");
 | 
			
		||||
				settings = repository.Load(uri);
 | 
			
		||||
				settings = repository.LoadSettings(uri);
 | 
			
		||||
 | 
			
		||||
				if (settings.ConfigurationMode == ConfigurationMode.ConfigureClient && UserWantsToAbortStartup())
 | 
			
		||||
				{
 | 
			
		||||
| 
						 | 
				
			
			@ -67,7 +67,7 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
 | 
			
		|||
			else
 | 
			
		||||
			{
 | 
			
		||||
				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.Configuration;
 | 
			
		||||
using SafeExamBrowser.Contracts.Configuration.Settings;
 | 
			
		||||
using SafeExamBrowser.Contracts.I18n;
 | 
			
		||||
using SafeExamBrowser.Contracts.Logging;
 | 
			
		||||
| 
						 | 
				
			
			@ -17,21 +18,21 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
 | 
			
		|||
	internal class KioskModeOperation : IOperation
 | 
			
		||||
	{
 | 
			
		||||
		private ILogger logger;
 | 
			
		||||
		private ISettingsRepository settingsRepository;
 | 
			
		||||
		private IConfigurationRepository configuration;
 | 
			
		||||
		private KioskMode kioskMode;
 | 
			
		||||
 | 
			
		||||
		public bool Abort { get; private set; }
 | 
			
		||||
		public IProgressIndicator ProgressIndicator { private get; set; }
 | 
			
		||||
 | 
			
		||||
		public KioskModeOperation(ILogger logger, ISettingsRepository settingsRepository)
 | 
			
		||||
		public KioskModeOperation(ILogger logger, IConfigurationRepository configuration)
 | 
			
		||||
		{
 | 
			
		||||
			this.logger = logger;
 | 
			
		||||
			this.settingsRepository = settingsRepository;
 | 
			
		||||
			this.configuration = configuration;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void Perform()
 | 
			
		||||
		{
 | 
			
		||||
			kioskMode = settingsRepository.Current.KioskMode;
 | 
			
		||||
			kioskMode = configuration.CurrentSettings.KioskMode;
 | 
			
		||||
 | 
			
		||||
			logger.Info($"Initializing kiosk mode '{kioskMode}'...");
 | 
			
		||||
			ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeKioskMode);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,7 @@
 | 
			
		|||
using System;
 | 
			
		||||
using SafeExamBrowser.Contracts.Behaviour.Operations;
 | 
			
		||||
using SafeExamBrowser.Contracts.Communication;
 | 
			
		||||
using SafeExamBrowser.Contracts.Configuration;
 | 
			
		||||
using SafeExamBrowser.Contracts.Configuration.Settings;
 | 
			
		||||
using SafeExamBrowser.Contracts.I18n;
 | 
			
		||||
using SafeExamBrowser.Contracts.Logging;
 | 
			
		||||
| 
						 | 
				
			
			@ -20,19 +21,19 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
 | 
			
		|||
	{
 | 
			
		||||
		private bool serviceAvailable;
 | 
			
		||||
		private bool serviceMandatory;
 | 
			
		||||
		private IConfigurationRepository configuration;
 | 
			
		||||
		private ILogger logger;
 | 
			
		||||
		private IServiceProxy service;
 | 
			
		||||
		private ISettingsRepository settingsRepository;
 | 
			
		||||
		private IText text;
 | 
			
		||||
 | 
			
		||||
		public bool Abort { get; private 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.logger = logger;
 | 
			
		||||
			this.settingsRepository = settingsRepository;
 | 
			
		||||
			this.text = text;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -43,7 +44,7 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
 | 
			
		|||
 | 
			
		||||
			try
 | 
			
		||||
			{
 | 
			
		||||
				serviceMandatory = settingsRepository.Current.ServicePolicy == ServicePolicy.Mandatory;
 | 
			
		||||
				serviceMandatory = configuration.CurrentSettings.ServicePolicy == ServicePolicy.Mandatory;
 | 
			
		||||
				serviceAvailable = service.Connect();
 | 
			
		||||
			}
 | 
			
		||||
			catch (Exception e)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,36 +20,41 @@ namespace SafeExamBrowser.Runtime.Behaviour
 | 
			
		|||
{
 | 
			
		||||
	internal class RuntimeController : IRuntimeController
 | 
			
		||||
	{
 | 
			
		||||
		private bool initialized;
 | 
			
		||||
 | 
			
		||||
		private IConfigurationRepository configuration;
 | 
			
		||||
		private ILogger logger;
 | 
			
		||||
		private IOperationSequence bootstrapSequence;
 | 
			
		||||
		private IOperationSequence sessionSequence;
 | 
			
		||||
		private IRuntimeHost runtimeHost;
 | 
			
		||||
		private IRuntimeInfo runtimeInfo;
 | 
			
		||||
		private IRuntimeWindow runtimeWindow;
 | 
			
		||||
		private IServiceProxy serviceProxy;
 | 
			
		||||
		private ISettingsRepository settingsRepository;
 | 
			
		||||
		private ISplashScreen splashScreen;
 | 
			
		||||
		private Action terminationCallback;
 | 
			
		||||
		private Action shutdown;
 | 
			
		||||
		private IText text;
 | 
			
		||||
		private IUserInterfaceFactory uiFactory;
 | 
			
		||||
		
 | 
			
		||||
		public RuntimeController(
 | 
			
		||||
			IConfigurationRepository configuration,
 | 
			
		||||
			ILogger logger,
 | 
			
		||||
			IOperationSequence bootstrapSequence,
 | 
			
		||||
			IOperationSequence sessionSequence,
 | 
			
		||||
			IRuntimeHost runtimeHost,
 | 
			
		||||
			IRuntimeInfo runtimeInfo,
 | 
			
		||||
			IServiceProxy serviceProxy,
 | 
			
		||||
			ISettingsRepository settingsRepository,
 | 
			
		||||
			Action terminationCallback,
 | 
			
		||||
			Action shutdown,
 | 
			
		||||
			IText text,
 | 
			
		||||
			IUserInterfaceFactory uiFactory)
 | 
			
		||||
		{
 | 
			
		||||
			this.configuration = configuration;
 | 
			
		||||
			this.logger = logger;
 | 
			
		||||
			this.bootstrapSequence = bootstrapSequence;
 | 
			
		||||
			this.sessionSequence = sessionSequence;
 | 
			
		||||
			this.runtimeHost = runtimeHost;
 | 
			
		||||
			this.runtimeInfo = runtimeInfo;
 | 
			
		||||
			this.serviceProxy = serviceProxy;
 | 
			
		||||
			this.settingsRepository = settingsRepository;
 | 
			
		||||
			this.terminationCallback = terminationCallback;
 | 
			
		||||
			this.shutdown = shutdown;
 | 
			
		||||
			this.text = text;
 | 
			
		||||
			this.uiFactory = uiFactory;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -58,19 +63,16 @@ namespace SafeExamBrowser.Runtime.Behaviour
 | 
			
		|||
		{
 | 
			
		||||
			logger.Info("--- Initiating startup procedure ---");
 | 
			
		||||
 | 
			
		||||
			runtimeWindow = uiFactory.CreateRuntimeWindow(runtimeInfo, text);
 | 
			
		||||
			splashScreen = uiFactory.CreateSplashScreen(runtimeInfo, text);
 | 
			
		||||
			splashScreen.Show();
 | 
			
		||||
 | 
			
		||||
			bootstrapSequence.ProgressIndicator = splashScreen;
 | 
			
		||||
 | 
			
		||||
			var success = bootstrapSequence.TryPerform();
 | 
			
		||||
			initialized = bootstrapSequence.TryPerform();
 | 
			
		||||
 | 
			
		||||
			System.Threading.Thread.Sleep(5000);
 | 
			
		||||
 | 
			
		||||
			if (success)
 | 
			
		||||
			if (initialized)
 | 
			
		||||
			{
 | 
			
		||||
				runtimeWindow = uiFactory.CreateRuntimeWindow(runtimeInfo, text);
 | 
			
		||||
 | 
			
		||||
				logger.Info("--- Application successfully initialized! ---");
 | 
			
		||||
				logger.Log(string.Empty);
 | 
			
		||||
				logger.Subscribe(runtimeWindow);
 | 
			
		||||
| 
						 | 
				
			
			@ -85,17 +87,19 @@ namespace SafeExamBrowser.Runtime.Behaviour
 | 
			
		|||
				logger.Log(string.Empty);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return success;
 | 
			
		||||
			return initialized;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void Terminate()
 | 
			
		||||
		{
 | 
			
		||||
			StopSession();
 | 
			
		||||
			// TODO: Necessary here? Move to App.cs as private "started" flag if not...
 | 
			
		||||
			if (!initialized)
 | 
			
		||||
			{
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// TODO:
 | 
			
		||||
			// - Disconnect from service
 | 
			
		||||
			// - Terminate runtime communication host
 | 
			
		||||
			// - Revert kiosk mode (or do that when stopping session?)
 | 
			
		||||
			// TODO: Only if session is running!
 | 
			
		||||
			StopSession();
 | 
			
		||||
 | 
			
		||||
			logger.Unsubscribe(runtimeWindow);
 | 
			
		||||
			runtimeWindow?.Close();
 | 
			
		||||
| 
						 | 
				
			
			@ -104,6 +108,10 @@ namespace SafeExamBrowser.Runtime.Behaviour
 | 
			
		|||
			logger.Log(string.Empty);
 | 
			
		||||
			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();
 | 
			
		||||
 | 
			
		||||
			if (success)
 | 
			
		||||
| 
						 | 
				
			
			@ -137,25 +145,28 @@ namespace SafeExamBrowser.Runtime.Behaviour
 | 
			
		|||
 | 
			
		||||
			if (success)
 | 
			
		||||
			{
 | 
			
		||||
 | 
			
		||||
				// TODO
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
 | 
			
		||||
				// TODO
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// TODO: Remove!
 | 
			
		||||
			System.Threading.Thread.Sleep(5000);
 | 
			
		||||
 | 
			
		||||
			runtimeWindow.HideProgressBar();
 | 
			
		||||
			runtimeWindow.UpdateText(TextKey.RuntimeWindow_ApplicationRunning);
 | 
			
		||||
 | 
			
		||||
			if (settingsRepository.Current.KioskMode == KioskMode.DisableExplorerShell)
 | 
			
		||||
			if (configuration.CurrentSettings.KioskMode == KioskMode.DisableExplorerShell)
 | 
			
		||||
			{
 | 
			
		||||
				runtimeWindow.Hide();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// TODO: Remove!
 | 
			
		||||
			System.Threading.Thread.Sleep(5000);
 | 
			
		||||
 | 
			
		||||
			terminationCallback.Invoke();
 | 
			
		||||
			shutdown.Invoke();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void StopSession()
 | 
			
		||||
| 
						 | 
				
			
			@ -163,12 +174,26 @@ namespace SafeExamBrowser.Runtime.Behaviour
 | 
			
		|||
			logger.Info("Stopping current session...");
 | 
			
		||||
			runtimeWindow.Show();
 | 
			
		||||
			runtimeWindow.BringToForeground();
 | 
			
		||||
			runtimeWindow.ShowProgressBar();
 | 
			
		||||
			runtimeWindow.UpdateText(TextKey.RuntimeWindow_StopSession, true);
 | 
			
		||||
 | 
			
		||||
			// TODO:
 | 
			
		||||
			// - Terminate client (or does it terminate itself?)
 | 
			
		||||
			// - Finalize session with service
 | 
			
		||||
			// - 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.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Windows;
 | 
			
		||||
using SafeExamBrowser.Configuration;
 | 
			
		||||
using SafeExamBrowser.Configuration.Settings;
 | 
			
		||||
using SafeExamBrowser.Contracts.Behaviour;
 | 
			
		||||
using SafeExamBrowser.Contracts.Behaviour.Operations;
 | 
			
		||||
using SafeExamBrowser.Contracts.Configuration;
 | 
			
		||||
| 
						 | 
				
			
			@ -23,6 +20,7 @@ using SafeExamBrowser.Core.I18n;
 | 
			
		|||
using SafeExamBrowser.Core.Logging;
 | 
			
		||||
using SafeExamBrowser.Runtime.Behaviour;
 | 
			
		||||
using SafeExamBrowser.Runtime.Behaviour.Operations;
 | 
			
		||||
using SafeExamBrowser.Runtime.Communication;
 | 
			
		||||
using SafeExamBrowser.UserInterface.Classic;
 | 
			
		||||
using SafeExamBrowser.WindowsApi;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -31,7 +29,7 @@ namespace SafeExamBrowser.Runtime
 | 
			
		|||
	internal class CompositionRoot
 | 
			
		||||
	{
 | 
			
		||||
		private ILogger logger;
 | 
			
		||||
		private RuntimeInfo runtimeInfo;
 | 
			
		||||
		private IRuntimeInfo runtimeInfo;
 | 
			
		||||
		private ISystemInfo systemInfo;
 | 
			
		||||
 | 
			
		||||
		internal IRuntimeController RuntimeController { get; private set; }
 | 
			
		||||
| 
						 | 
				
			
			@ -42,30 +40,30 @@ namespace SafeExamBrowser.Runtime
 | 
			
		|||
			var bootstrapOperations = new Queue<IOperation>();
 | 
			
		||||
			var sessionOperations = new Queue<IOperation>();
 | 
			
		||||
			var nativeMethods = new NativeMethods();
 | 
			
		||||
			var settingsRepository = new SettingsRepository();
 | 
			
		||||
			var configuration = new ConfigurationRepository();
 | 
			
		||||
			var uiFactory = new UserInterfaceFactory();
 | 
			
		||||
 | 
			
		||||
			logger = new Logger();
 | 
			
		||||
			runtimeInfo = new RuntimeInfo();
 | 
			
		||||
			runtimeInfo = configuration.RuntimeInfo;
 | 
			
		||||
			systemInfo = new SystemInfo();
 | 
			
		||||
 | 
			
		||||
			InitializeRuntimeInfo();
 | 
			
		||||
			InitializeLogging();
 | 
			
		||||
 | 
			
		||||
			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));
 | 
			
		||||
			// 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 ServiceOperation(logger, serviceProxy, settingsRepository, text));
 | 
			
		||||
			sessionOperations.Enqueue(new KioskModeOperation(logger, settingsRepository));
 | 
			
		||||
			sessionOperations.Enqueue(new ConfigurationOperation(configuration, logger, runtimeInfo, text, uiFactory, args));
 | 
			
		||||
			sessionOperations.Enqueue(new ServiceOperation(configuration, logger, serviceProxy, text));
 | 
			
		||||
			sessionOperations.Enqueue(new KioskModeOperation(logger, configuration));
 | 
			
		||||
 | 
			
		||||
			var bootstrapSequence = new OperationSequence(logger, bootstrapOperations);
 | 
			
		||||
			var boostrapSequence = new OperationSequence(logger, bootstrapOperations);
 | 
			
		||||
			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()
 | 
			
		||||
| 
						 | 
				
			
			@ -84,28 +82,7 @@ namespace SafeExamBrowser.Runtime
 | 
			
		|||
 | 
			
		||||
		internal void LogShutdownInformation()
 | 
			
		||||
		{
 | 
			
		||||
			logger?.Log($"{Environment.NewLine}# 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");
 | 
			
		||||
			logger?.Log($"# Application terminated at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void InitializeLogging()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -90,6 +90,7 @@
 | 
			
		|||
    <Compile Include="Behaviour\Operations\ConfigurationOperation.cs" />
 | 
			
		||||
    <Compile Include="Behaviour\Operations\KioskModeOperation.cs" />
 | 
			
		||||
    <Compile Include="Behaviour\Operations\ServiceOperation.cs" />
 | 
			
		||||
    <Compile Include="Communication\RuntimeHost.cs" />
 | 
			
		||||
    <Compile Include="CompositionRoot.cs" />
 | 
			
		||||
    <Compile Include="Properties\AssemblyInfo.cs">
 | 
			
		||||
      <SubType>Code</SubType>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue