SEBWIN-220: Moved exception handling to proxy implementations by introducing the CommunicationResult.
This commit is contained in:
		
							parent
							
								
									70f68abc8f
								
							
						
					
					
						commit
						c32028d3dd
					
				
					 24 changed files with 474 additions and 269 deletions
				
			
		| 
						 | 
					@ -101,23 +101,22 @@ namespace SafeExamBrowser.Client.Behaviour
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				RegisterEvents();
 | 
									RegisterEvents();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				try
 | 
									var communication = runtime.InformClientReady();
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					runtime.InformClientReady();
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				catch (Exception e)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					logger.Error("Failed to inform runtime that client is ready!", e);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					return false;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (communication.Success)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
					splashScreen.Hide();
 | 
										splashScreen.Hide();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					logger.Info("--- Application successfully initialized ---");
 | 
										logger.Info("--- Application successfully initialized ---");
 | 
				
			||||||
					logger.Log(string.Empty);
 | 
										logger.Log(string.Empty);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				else
 | 
									else
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										success = false;
 | 
				
			||||||
 | 
										logger.Error("Failed to inform runtime that client is ready!");
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				logger.Info("--- Application startup aborted! ---");
 | 
									logger.Info("--- Application startup aborted! ---");
 | 
				
			||||||
				logger.Log(string.Empty);
 | 
									logger.Log(string.Empty);
 | 
				
			||||||
| 
						 | 
					@ -227,14 +226,15 @@ namespace SafeExamBrowser.Client.Behaviour
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (success)
 | 
								if (success)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				try
 | 
									var communication = runtime.RequestReconfiguration(filePath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (communication.Success)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					runtime.RequestReconfiguration(filePath);
 | 
					 | 
				
			||||||
					logger.Info($"Sent reconfiguration request for '{filePath}' to the runtime.");
 | 
										logger.Info($"Sent reconfiguration request for '{filePath}' to the runtime.");
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				catch (Exception e)
 | 
									else
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					logger.Error($"Failed to communicate reconfiguration request for '{filePath}'!", e);
 | 
										logger.Error($"Failed to communicate reconfiguration request for '{filePath}'!");
 | 
				
			||||||
					messageBox.Show(TextKey.MessageBox_ReconfigurationError, TextKey.MessageBox_ReconfigurationErrorTitle, icon: MessageBoxIcon.Error);
 | 
										messageBox.Show(TextKey.MessageBox_ReconfigurationError, TextKey.MessageBox_ReconfigurationErrorTitle, icon: MessageBoxIcon.Error);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -287,13 +287,11 @@ namespace SafeExamBrowser.Client.Behaviour
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (result == MessageBoxResult.Yes)
 | 
								if (result == MessageBoxResult.Yes)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				try
 | 
									var communication = runtime.RequestShutdown();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (!communication.Success)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					runtime.RequestShutdown();
 | 
										logger.Error("Failed to communicate shutdown request to the runtime!");
 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				catch (Exception e)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					logger.Error("Failed to communicate shutdown request to the runtime!", e);
 | 
					 | 
				
			||||||
					messageBox.Show(TextKey.MessageBox_QuitError, TextKey.MessageBox_QuitErrorTitle, icon: MessageBoxIcon.Error);
 | 
										messageBox.Show(TextKey.MessageBox_QuitError, TextKey.MessageBox_QuitErrorTitle, icon: MessageBoxIcon.Error);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,7 +38,8 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			try
 | 
								try
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				var config = runtime.GetConfiguration();
 | 
									var communication = runtime.GetConfiguration();
 | 
				
			||||||
 | 
									var config = communication.Value.Configuration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				configuration.AppConfig = config.AppConfig;
 | 
									configuration.AppConfig = config.AppConfig;
 | 
				
			||||||
				configuration.SessionId = config.SessionId;
 | 
									configuration.SessionId = config.SessionId;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,25 +36,18 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
 | 
				
			||||||
			logger.Info("Initializing runtime connection...");
 | 
								logger.Info("Initializing runtime connection...");
 | 
				
			||||||
			ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeRuntimeConnection);
 | 
								ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeRuntimeConnection);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			try
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
			connected = runtime.Connect(token);
 | 
								connected = runtime.Connect(token);
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			catch (Exception e)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				logger.Error("An unexpected error occurred while trying to connect to the runtime!", e);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (!connected)
 | 
								if (connected)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									logger.Info("Successfully connected to the runtime.");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				logger.Error("Failed to connect to the runtime. Aborting startup...");
 | 
									logger.Error("Failed to connect to the runtime. Aborting startup...");
 | 
				
			||||||
 | 
					 | 
				
			||||||
				return OperationResult.Failed;
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			logger.Info("Successfully connected to the runtime.");
 | 
								return connected ? OperationResult.Success : OperationResult.Failed;
 | 
				
			||||||
 | 
					 | 
				
			||||||
			return OperationResult.Success;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public OperationResult Repeat()
 | 
							public OperationResult Repeat()
 | 
				
			||||||
| 
						 | 
					@ -69,13 +62,15 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (connected)
 | 
								if (connected)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				try
 | 
									var success = runtime.Disconnect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (success)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					runtime.Disconnect();
 | 
										logger.Info("Successfully disconnected from the runtime.");
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				catch (Exception e)
 | 
									else
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					logger.Error("Failed to disconnect from runtime host!", e);
 | 
										logger.Error("Failed to disconnect from the runtime!");
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -89,6 +89,7 @@ namespace SafeExamBrowser.Client
 | 
				
			||||||
			operations.Enqueue(new I18nOperation(logger, text));
 | 
								operations.Enqueue(new I18nOperation(logger, text));
 | 
				
			||||||
			operations.Enqueue(new RuntimeConnectionOperation(logger, runtimeProxy, startupToken));
 | 
								operations.Enqueue(new RuntimeConnectionOperation(logger, runtimeProxy, startupToken));
 | 
				
			||||||
			operations.Enqueue(new ConfigurationOperation(configuration, logger, runtimeProxy));
 | 
								operations.Enqueue(new ConfigurationOperation(configuration, logger, runtimeProxy));
 | 
				
			||||||
 | 
								operations.Enqueue(new DelegateOperation(UpdateAppConfig));
 | 
				
			||||||
			operations.Enqueue(new DelayedInitializationOperation(BuildCommunicationHostOperation));
 | 
								operations.Enqueue(new DelayedInitializationOperation(BuildCommunicationHostOperation));
 | 
				
			||||||
			// TODO
 | 
								// TODO
 | 
				
			||||||
			//operations.Enqueue(new DelayedInitializationOperation(BuildKeyboardInterceptorOperation));
 | 
								//operations.Enqueue(new DelayedInitializationOperation(BuildKeyboardInterceptorOperation));
 | 
				
			||||||
| 
						 | 
					@ -202,9 +203,13 @@ namespace SafeExamBrowser.Client
 | 
				
			||||||
			return operation;
 | 
								return operation;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private void UpdateClientControllerDependencies()
 | 
							private void UpdateAppConfig()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			ClientController.AppConfig = configuration.AppConfig;
 | 
								ClientController.AppConfig = configuration.AppConfig;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							private void UpdateClientControllerDependencies()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
			ClientController.Browser = browserController;
 | 
								ClientController.Browser = browserController;
 | 
				
			||||||
			ClientController.ClientHost = clientHost;
 | 
								ClientController.ClientHost = clientHost;
 | 
				
			||||||
			ClientController.SessionId = configuration.SessionId;
 | 
								ClientController.SessionId = configuration.SessionId;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,17 +23,14 @@ namespace SafeExamBrowser.Contracts.Communication
 | 
				
			||||||
		event CommunicationEventHandler ConnectionLost;
 | 
							event CommunicationEventHandler ConnectionLost;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/// <summary>
 | 
							/// <summary>
 | 
				
			||||||
		/// Tries to establish a connection. Returns <c>true</c> if the connection has been accepted, otherwise <c>false</c>. If a
 | 
							/// Tries to establish a connection. Returns <c>true</c> if the connection has been successful, otherwise <c>false</c>. If a
 | 
				
			||||||
		/// connection was successfully established and the auto-ping flag is set, the connection status will be periodically checked.
 | 
							/// connection was successfully established and the auto-ping flag is set, the connection status will be periodically checked.
 | 
				
			||||||
		/// </summary>
 | 
							/// </summary>
 | 
				
			||||||
		/// <exception cref="System.ServiceModel.*">If the communication failed.</exception>
 | 
					 | 
				
			||||||
		bool Connect(Guid? token = null, bool autoPing = true);
 | 
							bool Connect(Guid? token = null, bool autoPing = true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/// <summary>
 | 
							/// <summary>
 | 
				
			||||||
		/// Terminates an open connection. Returns <c>true</c> if the disconnection has been acknowledged, otherwise <c>false</c>.
 | 
							/// Terminates an open connection. Returns <c>true</c> if the disconnection has been successful, otherwise <c>false</c>.
 | 
				
			||||||
		/// </summary>
 | 
							/// </summary>
 | 
				
			||||||
		/// <exception cref="InvalidOperationException">If no connection has been established.</exception>
 | 
					 | 
				
			||||||
		/// <exception cref="System.ServiceModel.*">If the communication failed.</exception>
 | 
					 | 
				
			||||||
		bool Disconnect();
 | 
							bool Disconnect();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,43 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * 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.Proxies
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/// <summary>
 | 
				
			||||||
 | 
						/// Defines the result of a communication between an <see cref="ICommunicationProxy"/> and its <see cref="ICommunicationHost"/>.
 | 
				
			||||||
 | 
						/// </summary>
 | 
				
			||||||
 | 
						public class CommunicationResult
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/// <summary>
 | 
				
			||||||
 | 
							/// Defines whether the communication was successful or not.
 | 
				
			||||||
 | 
							/// </summary>
 | 
				
			||||||
 | 
							public bool Success { get; protected set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public CommunicationResult(bool success)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Success = success;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// <summary>
 | 
				
			||||||
 | 
						/// Defines the result of a communication between an <see cref="ICommunicationProxy"/> and its <see cref="ICommunicationHost"/>.
 | 
				
			||||||
 | 
						/// </summary>
 | 
				
			||||||
 | 
						/// <typeparam name="T">The type of the expected response value.</typeparam>
 | 
				
			||||||
 | 
						public class CommunicationResult<T> : CommunicationResult
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/// <summary>
 | 
				
			||||||
 | 
							/// The response value. Can be <c>null</c> or <c>default(T)</c> in case the communication has failed!
 | 
				
			||||||
 | 
							/// </summary>
 | 
				
			||||||
 | 
							public T Value { get; protected set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public CommunicationResult(bool success, T value) : base(success)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Value = value;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -19,24 +19,21 @@ namespace SafeExamBrowser.Contracts.Communication.Proxies
 | 
				
			||||||
		/// <summary>
 | 
							/// <summary>
 | 
				
			||||||
		/// Informs the client that the reconfiguration request for the specified file was denied.
 | 
							/// Informs the client that the reconfiguration request for the specified file was denied.
 | 
				
			||||||
		/// </summary>
 | 
							/// </summary>
 | 
				
			||||||
		void InformReconfigurationDenied(string filePath);
 | 
							CommunicationResult InformReconfigurationDenied(string filePath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/// <summary>
 | 
							/// <summary>
 | 
				
			||||||
		/// Instructs the client to initiate its shutdown procedure.
 | 
							/// Instructs the client to initiate its shutdown procedure.
 | 
				
			||||||
		/// </summary>
 | 
							/// </summary>
 | 
				
			||||||
		/// <exception cref="System.ServiceModel.*">If the communication failed.</exception>
 | 
							CommunicationResult InitiateShutdown();
 | 
				
			||||||
		void InitiateShutdown();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/// <summary>
 | 
							/// <summary>
 | 
				
			||||||
		/// Instructs the client to submit its authentication data.
 | 
							/// Instructs the client to submit its authentication data.
 | 
				
			||||||
		/// </summary>
 | 
							/// </summary>
 | 
				
			||||||
		/// <exception cref="System.ServiceModel.*">If the communication failed.</exception>
 | 
							CommunicationResult<AuthenticationResponse> RequestAuthentication();
 | 
				
			||||||
		AuthenticationResponse RequestAuthentication();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/// <summary>
 | 
							/// <summary>
 | 
				
			||||||
		/// Requests the client to render a password dialog and subsequently return the interaction result as separate message.
 | 
							/// Requests the client to render a password dialog and subsequently return the interaction result as separate message.
 | 
				
			||||||
		/// </summary>
 | 
							/// </summary>
 | 
				
			||||||
		/// <exception cref="System.ServiceModel.*">If the communication failed.</exception>
 | 
							CommunicationResult RequestPassword(PasswordRequestPurpose purpose, Guid requestId);
 | 
				
			||||||
		void RequestPassword(PasswordRequestPurpose purpose, Guid requestId);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,7 @@
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
using SafeExamBrowser.Contracts.Configuration;
 | 
					using SafeExamBrowser.Contracts.Communication.Data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace SafeExamBrowser.Contracts.Communication.Proxies
 | 
					namespace SafeExamBrowser.Contracts.Communication.Proxies
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -19,32 +19,27 @@ namespace SafeExamBrowser.Contracts.Communication.Proxies
 | 
				
			||||||
		/// <summary>
 | 
							/// <summary>
 | 
				
			||||||
		/// Retrieves the application configuration from the runtime.
 | 
							/// Retrieves the application configuration from the runtime.
 | 
				
			||||||
		/// </summary>
 | 
							/// </summary>
 | 
				
			||||||
		/// <exception cref="System.ServiceModel.*">If the communication failed.</exception>
 | 
							CommunicationResult<ConfigurationResponse> GetConfiguration();
 | 
				
			||||||
		ClientConfiguration GetConfiguration();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/// <summary>
 | 
							/// <summary>
 | 
				
			||||||
		/// Informs the runtime that the client is ready.
 | 
							/// Informs the runtime that the client is ready.
 | 
				
			||||||
		/// </summary>
 | 
							/// </summary>
 | 
				
			||||||
		/// <exception cref="System.ServiceModel.*">If the communication failed.</exception>
 | 
							CommunicationResult InformClientReady();
 | 
				
			||||||
		void InformClientReady();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/// <summary>
 | 
							/// <summary>
 | 
				
			||||||
		/// Requests the runtime to shut down the application.
 | 
							/// Requests the runtime to shut down the application.
 | 
				
			||||||
		/// </summary>
 | 
							/// </summary>
 | 
				
			||||||
		/// <exception cref="System.ServiceModel.*">If the communication failed.</exception>
 | 
							CommunicationResult RequestShutdown();
 | 
				
			||||||
		void RequestShutdown();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/// <summary>
 | 
							/// <summary>
 | 
				
			||||||
		/// Requests the runtime to reconfigure the application with the specified configuration.
 | 
							/// Requests the runtime to reconfigure the application with the specified configuration.
 | 
				
			||||||
		/// </summary>
 | 
							/// </summary>
 | 
				
			||||||
		/// <exception cref="System.ServiceModel.*">If the communication failed.</exception>
 | 
							CommunicationResult RequestReconfiguration(string filePath);
 | 
				
			||||||
		void RequestReconfiguration(string filePath);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/// <summary>
 | 
							/// <summary>
 | 
				
			||||||
		/// Submits the result of a password input previously requested by the runtime. If the procedure was aborted by the user,
 | 
							/// Submits the result of a password input previously requested by the runtime. If the procedure was aborted by the user,
 | 
				
			||||||
		/// the password parameter will be <c>null</c>!
 | 
							/// the password parameter will be <c>null</c>!
 | 
				
			||||||
		/// </summary>
 | 
							/// </summary>
 | 
				
			||||||
		/// /// <exception cref="System.ServiceModel.*">If the communication failed.</exception>
 | 
							CommunicationResult SubmitPassword(Guid requestId, bool success, string password = null);
 | 
				
			||||||
		void SubmitPassword(Guid requestId, bool success, string password = null);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,13 +25,11 @@ namespace SafeExamBrowser.Contracts.Communication.Proxies
 | 
				
			||||||
		/// <summary>
 | 
							/// <summary>
 | 
				
			||||||
		/// Instructs the service to start a new session according to the given parameters.
 | 
							/// Instructs the service to start a new session according to the given parameters.
 | 
				
			||||||
		/// </summary>
 | 
							/// </summary>
 | 
				
			||||||
		/// <exception cref="System.ServiceModel.*">If the communication failed.</exception>
 | 
							CommunicationResult StartSession(Guid sessionId, Settings settings);
 | 
				
			||||||
		void StartSession(Guid sessionId, Settings settings);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/// <summary>
 | 
							/// <summary>
 | 
				
			||||||
		/// Instructs the service to stop the specified session.
 | 
							/// Instructs the service to stop the specified session.
 | 
				
			||||||
		/// </summary>
 | 
							/// </summary>
 | 
				
			||||||
		/// <exception cref="System.ServiceModel.*">If the communication failed.</exception>
 | 
							CommunicationResult StopSession(Guid sessionId);
 | 
				
			||||||
		void StopSession(Guid sessionId);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,6 +75,7 @@
 | 
				
			||||||
    <Compile Include="Communication\Hosts\IHostObject.cs" />
 | 
					    <Compile Include="Communication\Hosts\IHostObject.cs" />
 | 
				
			||||||
    <Compile Include="Communication\Hosts\IHostObjectFactory.cs" />
 | 
					    <Compile Include="Communication\Hosts\IHostObjectFactory.cs" />
 | 
				
			||||||
    <Compile Include="Communication\ICommunication.cs" />
 | 
					    <Compile Include="Communication\ICommunication.cs" />
 | 
				
			||||||
 | 
					    <Compile Include="Communication\Proxies\CommunicationResult.cs" />
 | 
				
			||||||
    <Compile Include="Communication\Proxies\IClientProxy.cs" />
 | 
					    <Compile Include="Communication\Proxies\IClientProxy.cs" />
 | 
				
			||||||
    <Compile Include="Communication\ICommunicationHost.cs" />
 | 
					    <Compile Include="Communication\ICommunicationHost.cs" />
 | 
				
			||||||
    <Compile Include="Communication\ICommunicationProxy.cs" />
 | 
					    <Compile Include="Communication\ICommunicationProxy.cs" />
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -106,14 +106,14 @@ namespace SafeExamBrowser.Core.UnitTests.Communication.Proxies
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[TestMethod]
 | 
							[TestMethod]
 | 
				
			||||||
		[ExpectedException(typeof(InvalidOperationException))]
 | 
					 | 
				
			||||||
		public void MustFailToDisconnectIfNotConnected()
 | 
							public void MustFailToDisconnectIfNotConnected()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			sut.Disconnect();
 | 
								var success = sut.Disconnect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.IsFalse(success);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[TestMethod]
 | 
							[TestMethod]
 | 
				
			||||||
		[ExpectedException(typeof(CommunicationException))]
 | 
					 | 
				
			||||||
		public void MustFailToDisconnectIfChannelNotOpen()
 | 
							public void MustFailToDisconnectIfChannelNotOpen()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			var proxy = new Mock<IProxyObject>();
 | 
								var proxy = new Mock<IProxyObject>();
 | 
				
			||||||
| 
						 | 
					@ -130,7 +130,10 @@ namespace SafeExamBrowser.Core.UnitTests.Communication.Proxies
 | 
				
			||||||
			var token = Guid.NewGuid();
 | 
								var token = Guid.NewGuid();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			sut.Connect(token);
 | 
								sut.Connect(token);
 | 
				
			||||||
			sut.Disconnect();
 | 
					
 | 
				
			||||||
 | 
								var success = sut.Disconnect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.IsFalse(success);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[TestMethod]
 | 
							[TestMethod]
 | 
				
			||||||
| 
						 | 
					@ -141,7 +144,7 @@ namespace SafeExamBrowser.Core.UnitTests.Communication.Proxies
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[TestMethod]
 | 
							[TestMethod]
 | 
				
			||||||
		[ExpectedException(typeof(CommunicationException))]
 | 
							[ExpectedException(typeof(InvalidOperationException))]
 | 
				
			||||||
		public void MustFailToSendIfChannelNotOpen()
 | 
							public void MustFailToSendIfChannelNotOpen()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			var proxy = new Mock<IProxyObject>();
 | 
								var proxy = new Mock<IProxyObject>();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,6 @@ using System;
 | 
				
			||||||
using System.ServiceModel;
 | 
					using System.ServiceModel;
 | 
				
			||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
 | 
					using Microsoft.VisualStudio.TestTools.UnitTesting;
 | 
				
			||||||
using Moq;
 | 
					using Moq;
 | 
				
			||||||
using SafeExamBrowser.Contracts.Communication;
 | 
					 | 
				
			||||||
using SafeExamBrowser.Contracts.Communication.Data;
 | 
					using SafeExamBrowser.Contracts.Communication.Data;
 | 
				
			||||||
using SafeExamBrowser.Contracts.Communication.Proxies;
 | 
					using SafeExamBrowser.Contracts.Communication.Proxies;
 | 
				
			||||||
using SafeExamBrowser.Contracts.Logging;
 | 
					using SafeExamBrowser.Contracts.Logging;
 | 
				
			||||||
| 
						 | 
					@ -52,18 +51,20 @@ namespace SafeExamBrowser.Core.UnitTests.Communication.Proxies
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			proxy.Setup(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.Shutdown))).Returns(new SimpleResponse(SimpleResponsePurport.Acknowledged));
 | 
								proxy.Setup(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.Shutdown))).Returns(new SimpleResponse(SimpleResponsePurport.Acknowledged));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			sut.InitiateShutdown();
 | 
								var communication = sut.InitiateShutdown();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			proxy.Verify(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.Shutdown)), Times.Once);
 | 
								proxy.Verify(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.Shutdown)), Times.Once);
 | 
				
			||||||
 | 
								Assert.IsTrue(communication.Success);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[TestMethod]
 | 
							[TestMethod]
 | 
				
			||||||
		[ExpectedException(typeof(CommunicationException))]
 | 
							public void MustIndicateIfShutdownCommandNotAcknowledged()
 | 
				
			||||||
		public void MustFailIfShutdownCommandNotAcknowledged()
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			proxy.Setup(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.Shutdown))).Returns<Response>(null);
 | 
								proxy.Setup(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.Shutdown))).Returns<Response>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			sut.InitiateShutdown();
 | 
								var communication = sut.InitiateShutdown();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.IsFalse(communication.Success);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[TestMethod]
 | 
							[TestMethod]
 | 
				
			||||||
| 
						 | 
					@ -71,20 +72,24 @@ namespace SafeExamBrowser.Core.UnitTests.Communication.Proxies
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			proxy.Setup(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.Authenticate))).Returns(new AuthenticationResponse());
 | 
								proxy.Setup(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.Authenticate))).Returns(new AuthenticationResponse());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			var response = sut.RequestAuthentication();
 | 
								var communication = sut.RequestAuthentication();
 | 
				
			||||||
 | 
								var response = communication.Value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			proxy.Verify(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.Authenticate)), Times.Once);
 | 
								proxy.Verify(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.Authenticate)), Times.Once);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.IsTrue(communication.Success);
 | 
				
			||||||
			Assert.IsInstanceOfType(response, typeof(AuthenticationResponse));
 | 
								Assert.IsInstanceOfType(response, typeof(AuthenticationResponse));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[TestMethod]
 | 
							[TestMethod]
 | 
				
			||||||
		[ExpectedException(typeof(CommunicationException))]
 | 
							public void MustIndicateIfAuthenticationCommandNotAcknowledged()
 | 
				
			||||||
		public void MustFailIfAuthenticationCommandNotFollowed()
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			proxy.Setup(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.Authenticate))).Returns<Response>(null);
 | 
								proxy.Setup(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.Authenticate))).Returns<Response>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			sut.RequestAuthentication();
 | 
								var communication = sut.RequestAuthentication();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.AreEqual(default(AuthenticationResponse), communication.Value);
 | 
				
			||||||
 | 
								Assert.IsFalse(communication.Success);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,20 +57,23 @@ namespace SafeExamBrowser.Core.UnitTests.Communication.Proxies
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			proxy.Setup(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.ConfigurationNeeded))).Returns(response);
 | 
								proxy.Setup(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.ConfigurationNeeded))).Returns(response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			var configuration = sut.GetConfiguration();
 | 
								var communication = sut.GetConfiguration();
 | 
				
			||||||
 | 
								var configuration = communication.Value.Configuration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			proxy.Verify(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.ConfigurationNeeded)), Times.Once);
 | 
								proxy.Verify(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.ConfigurationNeeded)), Times.Once);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.IsTrue(communication.Success);
 | 
				
			||||||
			Assert.IsInstanceOfType(configuration, typeof(ClientConfiguration));
 | 
								Assert.IsInstanceOfType(configuration, typeof(ClientConfiguration));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[TestMethod]
 | 
							[TestMethod]
 | 
				
			||||||
		[ExpectedException(typeof(CommunicationException))]
 | 
					 | 
				
			||||||
		public void MustFailIfConfigurationNotRetrieved()
 | 
							public void MustFailIfConfigurationNotRetrieved()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			proxy.Setup(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.ConfigurationNeeded))).Returns<Response>(null);
 | 
								proxy.Setup(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.ConfigurationNeeded))).Returns<Response>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			sut.GetConfiguration();
 | 
								var communication = sut.GetConfiguration();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.IsFalse(communication.Success);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[TestMethod]
 | 
							[TestMethod]
 | 
				
			||||||
| 
						 | 
					@ -78,18 +81,20 @@ namespace SafeExamBrowser.Core.UnitTests.Communication.Proxies
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			proxy.Setup(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.ClientIsReady))).Returns(new SimpleResponse(SimpleResponsePurport.Acknowledged));
 | 
								proxy.Setup(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.ClientIsReady))).Returns(new SimpleResponse(SimpleResponsePurport.Acknowledged));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			sut.InformClientReady();
 | 
								var communication = sut.InformClientReady();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.IsTrue(communication.Success);
 | 
				
			||||||
			proxy.Verify(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.ClientIsReady)), Times.Once);
 | 
								proxy.Verify(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.ClientIsReady)), Times.Once);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[TestMethod]
 | 
							[TestMethod]
 | 
				
			||||||
		[ExpectedException(typeof(CommunicationException))]
 | 
					 | 
				
			||||||
		public void MustFailIfClientReadyNotAcknowledged()
 | 
							public void MustFailIfClientReadyNotAcknowledged()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			proxy.Setup(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.ClientIsReady))).Returns<Response>(null);
 | 
								proxy.Setup(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.ClientIsReady))).Returns<Response>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			sut.InformClientReady();
 | 
								var communication = sut.InformClientReady();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.IsFalse(communication.Success);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[TestMethod]
 | 
							[TestMethod]
 | 
				
			||||||
| 
						 | 
					@ -99,20 +104,22 @@ namespace SafeExamBrowser.Core.UnitTests.Communication.Proxies
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			proxy.Setup(p => p.Send(It.Is<ReconfigurationMessage>(m => m.ConfigurationPath == url))).Returns(new SimpleResponse(SimpleResponsePurport.Acknowledged));
 | 
								proxy.Setup(p => p.Send(It.Is<ReconfigurationMessage>(m => m.ConfigurationPath == url))).Returns(new SimpleResponse(SimpleResponsePurport.Acknowledged));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			sut.RequestReconfiguration(url);
 | 
								var communication = sut.RequestReconfiguration(url);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.IsTrue(communication.Success);
 | 
				
			||||||
			proxy.Verify(p => p.Send(It.Is<ReconfigurationMessage>(m => m.ConfigurationPath == url)), Times.Once);
 | 
								proxy.Verify(p => p.Send(It.Is<ReconfigurationMessage>(m => m.ConfigurationPath == url)), Times.Once);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[TestMethod]
 | 
							[TestMethod]
 | 
				
			||||||
		[ExpectedException(typeof(CommunicationException))]
 | 
					 | 
				
			||||||
		public void MustFailIfReconfigurationRequestNotAcknowledged()
 | 
							public void MustFailIfReconfigurationRequestNotAcknowledged()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			var url = "file:///C:/Some/file/url.seb";
 | 
								var url = "file:///C:/Some/file/url.seb";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			proxy.Setup(p => p.Send(It.Is<ReconfigurationMessage>(m => m.ConfigurationPath == url))).Returns<Response>(null);
 | 
								proxy.Setup(p => p.Send(It.Is<ReconfigurationMessage>(m => m.ConfigurationPath == url))).Returns<Response>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			sut.RequestReconfiguration(url);
 | 
								var communication = sut.RequestReconfiguration(url);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.IsFalse(communication.Success);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[TestMethod]
 | 
							[TestMethod]
 | 
				
			||||||
| 
						 | 
					@ -120,18 +127,20 @@ namespace SafeExamBrowser.Core.UnitTests.Communication.Proxies
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			proxy.Setup(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.RequestShutdown))).Returns(new SimpleResponse(SimpleResponsePurport.Acknowledged));
 | 
								proxy.Setup(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.RequestShutdown))).Returns(new SimpleResponse(SimpleResponsePurport.Acknowledged));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			sut.RequestShutdown();
 | 
								var communication = sut.RequestShutdown();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.IsTrue(communication.Success);
 | 
				
			||||||
			proxy.Verify(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.RequestShutdown)), Times.Once);
 | 
								proxy.Verify(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.RequestShutdown)), Times.Once);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[TestMethod]
 | 
							[TestMethod]
 | 
				
			||||||
		[ExpectedException(typeof(CommunicationException))]
 | 
					 | 
				
			||||||
		public void MustFailIfShutdownRequestNotAcknowledged()
 | 
							public void MustFailIfShutdownRequestNotAcknowledged()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			proxy.Setup(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.RequestShutdown))).Returns<Response>(null);
 | 
								proxy.Setup(p => p.Send(It.Is<SimpleMessage>(m => m.Purport == SimpleMessagePurport.RequestShutdown))).Returns<Response>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			sut.RequestShutdown();
 | 
								var communication = sut.RequestShutdown();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.IsFalse(communication.Success);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,6 @@ using System;
 | 
				
			||||||
using System.ServiceModel;
 | 
					using System.ServiceModel;
 | 
				
			||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
 | 
					using Microsoft.VisualStudio.TestTools.UnitTesting;
 | 
				
			||||||
using Moq;
 | 
					using Moq;
 | 
				
			||||||
using SafeExamBrowser.Contracts.Communication;
 | 
					 | 
				
			||||||
using SafeExamBrowser.Contracts.Communication.Data;
 | 
					using SafeExamBrowser.Contracts.Communication.Data;
 | 
				
			||||||
using SafeExamBrowser.Contracts.Communication.Proxies;
 | 
					using SafeExamBrowser.Contracts.Communication.Proxies;
 | 
				
			||||||
using SafeExamBrowser.Contracts.Logging;
 | 
					using SafeExamBrowser.Contracts.Logging;
 | 
				
			||||||
| 
						 | 
					@ -68,8 +67,10 @@ namespace SafeExamBrowser.Core.UnitTests.Communication.Proxies
 | 
				
			||||||
		public void MustIgnoreStartSessionIfUnavaiable()
 | 
							public void MustIgnoreStartSessionIfUnavaiable()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			sut.Ignore = true;
 | 
								sut.Ignore = true;
 | 
				
			||||||
			sut.StartSession(Guid.Empty, null);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								var communication = sut.StartSession(Guid.Empty, null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.IsTrue(communication.Success);
 | 
				
			||||||
			proxy.Verify(p => p.Send(It.IsAny<Message>()), Times.Never);
 | 
								proxy.Verify(p => p.Send(It.IsAny<Message>()), Times.Never);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -77,8 +78,10 @@ namespace SafeExamBrowser.Core.UnitTests.Communication.Proxies
 | 
				
			||||||
		public void MustIgnoreStopSessionIfUnavaiable()
 | 
							public void MustIgnoreStopSessionIfUnavaiable()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			sut.Ignore = true;
 | 
								sut.Ignore = true;
 | 
				
			||||||
			sut.StopSession(Guid.Empty);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								var communication = sut.StopSession(Guid.Empty);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.IsTrue(communication.Success);
 | 
				
			||||||
			proxy.Verify(p => p.Send(It.IsAny<Message>()), Times.Never);
 | 
								proxy.Verify(p => p.Send(It.IsAny<Message>()), Times.Never);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,6 +31,7 @@ namespace SafeExamBrowser.Core.Communication.Proxies
 | 
				
			||||||
		private Guid? communicationToken;
 | 
							private Guid? communicationToken;
 | 
				
			||||||
		private Timer timer;
 | 
							private Timer timer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							protected bool IsConnected { get { return communicationToken.HasValue; } }
 | 
				
			||||||
		protected ILogger Logger { get; private set; }
 | 
							protected ILogger Logger { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public event CommunicationEventHandler ConnectionLost;
 | 
							public event CommunicationEventHandler ConnectionLost;
 | 
				
			||||||
| 
						 | 
					@ -43,51 +44,77 @@ namespace SafeExamBrowser.Core.Communication.Proxies
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public virtual bool Connect(Guid? token = null, bool autoPing = true)
 | 
							public virtual bool Connect(Guid? token = null, bool autoPing = true)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								try
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				Logger.Debug($"Trying to connect to endpoint '{address}'{(token.HasValue ? $" with authentication token '{token}'" : string.Empty)}...");
 | 
									Logger.Debug($"Trying to connect to endpoint '{address}'{(token.HasValue ? $" with authentication token '{token}'" : string.Empty)}...");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				InitializeProxyObject();
 | 
									InitializeProxyObject();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				var response = proxy.Connect(token);
 | 
									var response = proxy.Connect(token);
 | 
				
			||||||
 | 
									var success = response.ConnectionEstablished;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				communicationToken = response.CommunicationToken;
 | 
									communicationToken = response.CommunicationToken;
 | 
				
			||||||
			Logger.Debug($"Connection was {(response.ConnectionEstablished ? "established" : "refused")}.");
 | 
									Logger.Debug($"Connection was {(success ? "established" : "refused")}.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (response.ConnectionEstablished && autoPing)
 | 
									if (success && autoPing)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					StartAutoPing();
 | 
										StartAutoPing();
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return response.ConnectionEstablished;
 | 
									return success;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								catch (Exception e)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									Logger.Error($"Failed to connect to endpoint '{address}'!", e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public virtual bool Disconnect()
 | 
							public virtual bool Disconnect()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			FailIfNotConnected(nameof(Disconnect));
 | 
								try
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									if (!IsConnected)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										Logger.Warn($"Cannot disconnect from endpoint '{address}' before being connected!");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										return false;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				StopAutoPing();
 | 
									StopAutoPing();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				var message = new DisconnectionMessage { CommunicationToken = communicationToken.Value };
 | 
									var message = new DisconnectionMessage { CommunicationToken = communicationToken.Value };
 | 
				
			||||||
				var response = proxy.Disconnect(message);
 | 
									var response = proxy.Disconnect(message);
 | 
				
			||||||
 | 
									var success = response.ConnectionTerminated;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Logger.Debug($"{(response.ConnectionTerminated ? "Disconnected" : "Failed to disconnect")} from {address}.");
 | 
									Logger.Debug($"{(success ? "Disconnected" : "Failed to disconnect")} from {address}.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return response.ConnectionTerminated;
 | 
									if (success)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										communicationToken = null;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return success;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								catch (Exception e)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									Logger.Error($"Failed to disconnect from endpoint '{address}'!", e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/// <summary>
 | 
							/// <summary>
 | 
				
			||||||
		/// Sends the given message, optionally returning a response. If no response is expected, <c>null</c> will be returned.
 | 
							/// Sends the given message, optionally returning a response. If no response is expected, <c>null</c> will be returned.
 | 
				
			||||||
		/// </summary>
 | 
							/// </summary>
 | 
				
			||||||
		/// <exception cref="ArgumentNullException">If the given message is <c>null</c>.</exception>
 | 
							/// <exception cref="ArgumentNullException">If the given message is <c>null</c>.</exception>
 | 
				
			||||||
		/// <exception cref="InvalidOperationException">If no connection has been established yet.</exception>
 | 
							/// <exception cref="InvalidOperationException">If no connection has been established yet or the connection is corrupted.</exception>
 | 
				
			||||||
		/// <exception cref="System.ServiceModel.*">If the communication failed.</exception>
 | 
					 | 
				
			||||||
		protected virtual Response Send(Message message)
 | 
							protected virtual Response Send(Message message)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (message is null)
 | 
								FailIfNull(message);
 | 
				
			||||||
			{
 | 
								FailIfNotConnected();
 | 
				
			||||||
				throw new ArgumentNullException(nameof(message));
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			FailIfNotConnected(nameof(Send));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			message.CommunicationToken = communicationToken.Value;
 | 
								message.CommunicationToken = communicationToken.Value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -195,16 +222,24 @@ namespace SafeExamBrowser.Core.Communication.Proxies
 | 
				
			||||||
			Logger.Debug("Communication channel is opening...");
 | 
								Logger.Debug("Communication channel is opening...");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private void FailIfNotConnected(string operationName)
 | 
							private void FailIfNull(Message message)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (!communicationToken.HasValue)
 | 
								if (message is null)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				throw new InvalidOperationException($"Cannot perform '{operationName}' before being connected to endpoint!");
 | 
									throw new ArgumentNullException(nameof(message));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							private void FailIfNotConnected()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (!IsConnected)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									throw new InvalidOperationException($"Cannot send message before being connected to endpoint '{address}'!");
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (proxy == null || proxy.State != CommunicationState.Opened)
 | 
								if (proxy == null || proxy.State != CommunicationState.Opened)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				throw new CommunicationException($"Tried to perform {operationName}, but channel was {GetChannelState()}!");
 | 
									throw new InvalidOperationException($"Tried to send message, but channel was {GetChannelState()}!");
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,6 @@
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.ServiceModel;
 | 
					 | 
				
			||||||
using SafeExamBrowser.Contracts.Communication.Data;
 | 
					using SafeExamBrowser.Contracts.Communication.Data;
 | 
				
			||||||
using SafeExamBrowser.Contracts.Communication.Proxies;
 | 
					using SafeExamBrowser.Contracts.Communication.Proxies;
 | 
				
			||||||
using SafeExamBrowser.Contracts.Logging;
 | 
					using SafeExamBrowser.Contracts.Logging;
 | 
				
			||||||
| 
						 | 
					@ -23,45 +22,107 @@ namespace SafeExamBrowser.Core.Communication.Proxies
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void InformReconfigurationDenied(string filePath)
 | 
							public CommunicationResult InformReconfigurationDenied(string filePath)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								try
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				var response = Send(new ReconfigurationDeniedMessage(filePath));
 | 
									var response = Send(new ReconfigurationDeniedMessage(filePath));
 | 
				
			||||||
 | 
									var success = IsAcknowledged(response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (!IsAcknowledged(response))
 | 
									if (success)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
				throw new CommunicationException($"Client did not acknowledge shutdown request! Received: {ToString(response)}.");
 | 
										Logger.Debug("Client acknowledged reconfiguration denial.");
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										Logger.Error($"Client did not acknowledge reconfiguration denial! Received: {ToString(response)}.");
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return new CommunicationResult(success);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								catch (Exception e)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									Logger.Error($"Failed to perform '{nameof(InformReconfigurationDenied)}'", e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return new CommunicationResult(false);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void InitiateShutdown()
 | 
							public CommunicationResult InitiateShutdown()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								try
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				var response = Send(SimpleMessagePurport.Shutdown);
 | 
									var response = Send(SimpleMessagePurport.Shutdown);
 | 
				
			||||||
 | 
									var success = IsAcknowledged(response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (!IsAcknowledged(response))
 | 
									if (success)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
				throw new CommunicationException($"Client did not acknowledge shutdown request! Received: {ToString(response)}.");
 | 
										Logger.Debug("Client acknowledged shutdown request.");
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										Logger.Error($"Client did not acknowledge shutdown request! Received: {ToString(response)}.");
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return new CommunicationResult(success);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								catch (Exception e)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									Logger.Error($"Failed to perform '{nameof(InitiateShutdown)}'", e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return new CommunicationResult(false);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public AuthenticationResponse RequestAuthentication()
 | 
							public CommunicationResult<AuthenticationResponse> RequestAuthentication()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								try
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				var response = Send(SimpleMessagePurport.Authenticate);
 | 
									var response = Send(SimpleMessagePurport.Authenticate);
 | 
				
			||||||
 | 
									var success = response is AuthenticationResponse;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (response is AuthenticationResponse authenticationResponse)
 | 
									if (success)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
				return authenticationResponse;
 | 
										Logger.Debug("Received authentication response.");
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										Logger.Error($"Did not receive authentication response! Received: {ToString(response)}.");
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			throw new CommunicationException($"Did not receive authentication response! Received: {ToString(response)}.");
 | 
									return new CommunicationResult<AuthenticationResponse>(success, response as AuthenticationResponse);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								catch (Exception e)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									Logger.Error($"Failed to perform '{nameof(RequestAuthentication)}'", e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return new CommunicationResult<AuthenticationResponse>(false, default(AuthenticationResponse));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void RequestPassword(PasswordRequestPurpose purpose, Guid requestId)
 | 
							public CommunicationResult RequestPassword(PasswordRequestPurpose purpose, Guid requestId)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								try
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				var response = Send(new PasswordRequestMessage(purpose, requestId));
 | 
									var response = Send(new PasswordRequestMessage(purpose, requestId));
 | 
				
			||||||
 | 
									var success = IsAcknowledged(response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (!IsAcknowledged(response))
 | 
									if (success)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
				throw new CommunicationException($"Client did not acknowledge shutdown request! Received: {ToString(response)}.");
 | 
										Logger.Debug("Client acknowledged password request.");
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										Logger.Error($"Client did not acknowledge password request! Received: {ToString(response)}.");
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return new CommunicationResult(success);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								catch (Exception e)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									Logger.Error($"Failed to perform '{nameof(RequestPassword)}'", e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return new CommunicationResult(false);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,10 +7,8 @@
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.ServiceModel;
 | 
					 | 
				
			||||||
using SafeExamBrowser.Contracts.Communication.Data;
 | 
					using SafeExamBrowser.Contracts.Communication.Data;
 | 
				
			||||||
using SafeExamBrowser.Contracts.Communication.Proxies;
 | 
					using SafeExamBrowser.Contracts.Communication.Proxies;
 | 
				
			||||||
using SafeExamBrowser.Contracts.Configuration;
 | 
					 | 
				
			||||||
using SafeExamBrowser.Contracts.Logging;
 | 
					using SafeExamBrowser.Contracts.Logging;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace SafeExamBrowser.Core.Communication.Proxies
 | 
					namespace SafeExamBrowser.Core.Communication.Proxies
 | 
				
			||||||
| 
						 | 
					@ -24,55 +22,133 @@ namespace SafeExamBrowser.Core.Communication.Proxies
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public ClientConfiguration GetConfiguration()
 | 
							public CommunicationResult<ConfigurationResponse> GetConfiguration()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								try
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				var response = Send(SimpleMessagePurport.ConfigurationNeeded);
 | 
									var response = Send(SimpleMessagePurport.ConfigurationNeeded);
 | 
				
			||||||
 | 
									var success = response is ConfigurationResponse;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (response is ConfigurationResponse configurationResponse)
 | 
									if (success)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
				return configurationResponse.Configuration;
 | 
										Logger.Debug("Received configuration response.");
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										Logger.Error($"Did not retrieve configuration response! Received: {ToString(response)}.");
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			throw new CommunicationException($"Could not retrieve client configuration! Received: {ToString(response)}.");
 | 
									return new CommunicationResult<ConfigurationResponse>(success, response as ConfigurationResponse);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								catch (Exception e)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									Logger.Error($"Failed to perform '{nameof(GetConfiguration)}'", e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return new CommunicationResult<ConfigurationResponse>(false, default(ConfigurationResponse));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void InformClientReady()
 | 
							public CommunicationResult InformClientReady()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								try
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				var response = Send(SimpleMessagePurport.ClientIsReady);
 | 
									var response = Send(SimpleMessagePurport.ClientIsReady);
 | 
				
			||||||
 | 
									var success = IsAcknowledged(response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (!IsAcknowledged(response))
 | 
									if (success)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
				throw new CommunicationException($"Runtime did not acknowledge that client is ready! Response: {ToString(response)}.");
 | 
										Logger.Debug("Runtime acknowledged that the client is ready.");
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										Logger.Error($"Runtime did not acknowledge that the client is ready! Response: {ToString(response)}.");
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return new CommunicationResult(success);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								catch (Exception e)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									Logger.Error($"Failed to perform '{nameof(InformClientReady)}'", e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return new CommunicationResult(false);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void RequestReconfiguration(string filePath)
 | 
							public CommunicationResult RequestReconfiguration(string filePath)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								try
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				var response = Send(new ReconfigurationMessage(filePath));
 | 
									var response = Send(new ReconfigurationMessage(filePath));
 | 
				
			||||||
 | 
									var success = IsAcknowledged(response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (!IsAcknowledged(response))
 | 
									if (success)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
				throw new CommunicationException($"Runtime did not acknowledge reconfiguration request! Response: {ToString(response)}.");
 | 
										Logger.Debug("Runtime acknowledged reconfiguration request.");
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										Logger.Error($"Runtime did not acknowledge reconfiguration request! Response: {ToString(response)}.");
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return new CommunicationResult(success);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								catch (Exception e)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									Logger.Error($"Failed to perform '{nameof(RequestReconfiguration)}'", e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return new CommunicationResult(false);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void RequestShutdown()
 | 
							public CommunicationResult RequestShutdown()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								try
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				var response = Send(SimpleMessagePurport.RequestShutdown);
 | 
									var response = Send(SimpleMessagePurport.RequestShutdown);
 | 
				
			||||||
 | 
									var success = IsAcknowledged(response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (!IsAcknowledged(response))
 | 
									if (success)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
				throw new CommunicationException($"Runtime did not acknowledge shutdown request! Response: {ToString(response)}.");
 | 
										Logger.Debug("Runtime acknowledged shutdown request.");
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										Logger.Error($"Runtime did not acknowledge shutdown request! Response: {ToString(response)}.");
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return new CommunicationResult(success);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								catch (Exception e)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									Logger.Error($"Failed to perform '{nameof(RequestShutdown)}'", e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return new CommunicationResult(false);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void SubmitPassword(Guid requestId, bool success, string password = null)
 | 
							public CommunicationResult SubmitPassword(Guid requestId, bool success, string password = null)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								try
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				var response = Send(new PasswordReplyMessage(requestId, success, password));
 | 
									var response = Send(new PasswordReplyMessage(requestId, success, password));
 | 
				
			||||||
 | 
									var acknowledged = IsAcknowledged(response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (!IsAcknowledged(response))
 | 
									if (acknowledged)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
				throw new CommunicationException($"Runtime did not acknowledge password submission! Response: {ToString(response)}.");
 | 
										Logger.Debug("Runtime acknowledged password transmission.");
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										Logger.Error($"Runtime did not acknowledge password transmission! Response: {ToString(response)}.");
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return new CommunicationResult(acknowledged);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								catch (Exception e)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									Logger.Error($"Failed to perform '{nameof(SubmitPassword)}'", e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return new CommunicationResult(false);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,32 +38,36 @@ namespace SafeExamBrowser.Core.Communication.Proxies
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (IgnoreOperation(nameof(Disconnect)))
 | 
								if (IgnoreOperation(nameof(Disconnect)))
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				return true;
 | 
									return false;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return base.Disconnect();
 | 
								return base.Disconnect();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void StartSession(Guid sessionId, Settings settings)
 | 
							public CommunicationResult StartSession(Guid sessionId, Settings settings)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (IgnoreOperation(nameof(StartSession)))
 | 
								if (IgnoreOperation(nameof(StartSession)))
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				return;
 | 
									return new CommunicationResult(true);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// TODO: Implement service communication
 | 
								// TODO: Implement service communication
 | 
				
			||||||
			// Send(new StartSessionMessage { Id = sessionId, Settings = settings });
 | 
								// Send(new StartSessionMessage { Id = sessionId, Settings = settings });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								throw new NotImplementedException();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void StopSession(Guid sessionId)
 | 
							public CommunicationResult StopSession(Guid sessionId)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (IgnoreOperation(nameof(StopSession)))
 | 
								if (IgnoreOperation(nameof(StopSession)))
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				return;
 | 
									return new CommunicationResult(true);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// TODO: Implement service communication
 | 
								// TODO: Implement service communication
 | 
				
			||||||
			// Send(new StopSessionMessage { SessionId = sessionId });
 | 
								// Send(new StopSessionMessage { SessionId = sessionId });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								throw new NotImplementedException();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private bool IgnoreOperation(string operationName)
 | 
							private bool IgnoreOperation(string operationName)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -67,10 +67,11 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			var result = default(OperationResult);
 | 
								var result = default(OperationResult);
 | 
				
			||||||
			var response = new AuthenticationResponse { ProcessId = 1234 };
 | 
								var response = new AuthenticationResponse { ProcessId = 1234 };
 | 
				
			||||||
 | 
								var communication = new CommunicationResult<AuthenticationResponse>(true, response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			process.SetupGet(p => p.Id).Returns(response.ProcessId);
 | 
								process.SetupGet(p => p.Id).Returns(response.ProcessId);
 | 
				
			||||||
			processFactory.Setup(f => f.StartNew(It.IsAny<string>(), It.IsAny<string[]>())).Returns(process.Object).Callback(clientReady);
 | 
								processFactory.Setup(f => f.StartNew(It.IsAny<string>(), It.IsAny<string[]>())).Returns(process.Object).Callback(clientReady);
 | 
				
			||||||
			proxy.Setup(p => p.RequestAuthentication()).Returns(response);
 | 
								proxy.Setup(p => p.RequestAuthentication()).Returns(communication);
 | 
				
			||||||
			proxy.Setup(p => p.Connect(It.IsAny<Guid>(), true)).Returns(true);
 | 
								proxy.Setup(p => p.Connect(It.IsAny<Guid>(), true)).Returns(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			result = sut.Perform();
 | 
								result = sut.Perform();
 | 
				
			||||||
| 
						 | 
					@ -86,10 +87,11 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			var result = default(OperationResult);
 | 
								var result = default(OperationResult);
 | 
				
			||||||
			var response = new AuthenticationResponse { ProcessId = 1234 };
 | 
								var response = new AuthenticationResponse { ProcessId = 1234 };
 | 
				
			||||||
 | 
								var communication = new CommunicationResult<AuthenticationResponse>(true, response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			process.SetupGet(p => p.Id).Returns(response.ProcessId);
 | 
								process.SetupGet(p => p.Id).Returns(response.ProcessId);
 | 
				
			||||||
			processFactory.Setup(f => f.StartNew(It.IsAny<string>(), It.IsAny<string[]>())).Returns(process.Object).Callback(clientReady);
 | 
								processFactory.Setup(f => f.StartNew(It.IsAny<string>(), It.IsAny<string[]>())).Returns(process.Object).Callback(clientReady);
 | 
				
			||||||
			proxy.Setup(p => p.RequestAuthentication()).Returns(response);
 | 
								proxy.Setup(p => p.RequestAuthentication()).Returns(communication);
 | 
				
			||||||
			proxy.Setup(p => p.Connect(It.IsAny<Guid>(), true)).Returns(true);
 | 
								proxy.Setup(p => p.Connect(It.IsAny<Guid>(), true)).Returns(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			result = sut.Repeat();
 | 
								result = sut.Repeat();
 | 
				
			||||||
| 
						 | 
					@ -134,10 +136,11 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			var result = default(OperationResult);
 | 
								var result = default(OperationResult);
 | 
				
			||||||
			var response = new AuthenticationResponse { ProcessId = -1 };
 | 
								var response = new AuthenticationResponse { ProcessId = -1 };
 | 
				
			||||||
 | 
								var communication = new CommunicationResult<AuthenticationResponse>(true, response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			process.SetupGet(p => p.Id).Returns(1234);
 | 
								process.SetupGet(p => p.Id).Returns(1234);
 | 
				
			||||||
			processFactory.Setup(f => f.StartNew(It.IsAny<string>(), It.IsAny<string[]>())).Returns(process.Object).Callback(clientReady);
 | 
								processFactory.Setup(f => f.StartNew(It.IsAny<string>(), It.IsAny<string[]>())).Returns(process.Object).Callback(clientReady);
 | 
				
			||||||
			proxy.Setup(p => p.RequestAuthentication()).Returns(response);
 | 
								proxy.Setup(p => p.RequestAuthentication()).Returns(communication);
 | 
				
			||||||
			proxy.Setup(p => p.Connect(It.IsAny<Guid>(), true)).Returns(true);
 | 
								proxy.Setup(p => p.Connect(It.IsAny<Guid>(), true)).Returns(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			result = sut.Perform();
 | 
								result = sut.Perform();
 | 
				
			||||||
| 
						 | 
					@ -204,10 +207,11 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
				
			||||||
		private void PerformNormally()
 | 
							private void PerformNormally()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			var response = new AuthenticationResponse { ProcessId = 1234 };
 | 
								var response = new AuthenticationResponse { ProcessId = 1234 };
 | 
				
			||||||
 | 
								var communication = new CommunicationResult<AuthenticationResponse>(true, response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			process.SetupGet(p => p.Id).Returns(response.ProcessId);
 | 
								process.SetupGet(p => p.Id).Returns(response.ProcessId);
 | 
				
			||||||
			processFactory.Setup(f => f.StartNew(It.IsAny<string>(), It.IsAny<string[]>())).Returns(process.Object).Callback(clientReady);
 | 
								processFactory.Setup(f => f.StartNew(It.IsAny<string>(), It.IsAny<string[]>())).Returns(process.Object).Callback(clientReady);
 | 
				
			||||||
			proxy.Setup(p => p.RequestAuthentication()).Returns(response);
 | 
								proxy.Setup(p => p.RequestAuthentication()).Returns(communication);
 | 
				
			||||||
			proxy.Setup(p => p.Connect(It.IsAny<Guid>(), true)).Returns(true);
 | 
								proxy.Setup(p => p.Connect(It.IsAny<Guid>(), true)).Returns(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			sut.Perform();
 | 
								sut.Perform();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -335,6 +335,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
				
			||||||
		public void MustRequestPasswordViaClientDuringReconfigurationOnNewDesktop()
 | 
							public void MustRequestPasswordViaClientDuringReconfigurationOnNewDesktop()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			var clientProxy = new Mock<IClientProxy>();
 | 
								var clientProxy = new Mock<IClientProxy>();
 | 
				
			||||||
 | 
								var communication = new CommunicationResult(true);
 | 
				
			||||||
			var passwordReceived = new Action<PasswordRequestPurpose, Guid>((p, id) =>
 | 
								var passwordReceived = new Action<PasswordRequestPurpose, Guid>((p, id) =>
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				runtimeHost.Raise(r => r.PasswordReceived += null, new PasswordReplyEventArgs { RequestId = id, Success = true });
 | 
									runtimeHost.Raise(r => r.PasswordReceived += null, new PasswordReplyEventArgs { RequestId = id, Success = true });
 | 
				
			||||||
| 
						 | 
					@ -342,7 +343,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
				
			||||||
			var session = new Mock<ISessionData>();
 | 
								var session = new Mock<ISessionData>();
 | 
				
			||||||
			var url = @"http://www.safeexambrowser.org/whatever.seb";
 | 
								var url = @"http://www.safeexambrowser.org/whatever.seb";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			clientProxy.Setup(c => c.RequestPassword(It.IsAny<PasswordRequestPurpose>(), It.IsAny<Guid>())).Callback(passwordReceived);
 | 
								clientProxy.Setup(c => c.RequestPassword(It.IsAny<PasswordRequestPurpose>(), It.IsAny<Guid>())).Returns(communication).Callback(passwordReceived);
 | 
				
			||||||
			passwordDialog.Setup(d => d.Show(null)).Returns(new PasswordDialogResultStub { Success = true });
 | 
								passwordDialog.Setup(d => d.Show(null)).Returns(new PasswordDialogResultStub { Success = true });
 | 
				
			||||||
			repository.SetupGet(r => r.CurrentSession).Returns(session.Object);
 | 
								repository.SetupGet(r => r.CurrentSession).Returns(session.Object);
 | 
				
			||||||
			repository.Setup(r => r.LoadSettings(It.IsAny<Uri>(), null, null)).Returns(LoadStatus.SettingsPasswordNeeded);
 | 
								repository.Setup(r => r.LoadSettings(It.IsAny<Uri>(), null, null)).Returns(LoadStatus.SettingsPasswordNeeded);
 | 
				
			||||||
| 
						 | 
					@ -361,6 +362,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
				
			||||||
		public void MustAbortAskingForPasswordViaClientIfDecidedByUser()
 | 
							public void MustAbortAskingForPasswordViaClientIfDecidedByUser()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			var clientProxy = new Mock<IClientProxy>();
 | 
								var clientProxy = new Mock<IClientProxy>();
 | 
				
			||||||
 | 
								var communication = new CommunicationResult(true);
 | 
				
			||||||
			var passwordReceived = new Action<PasswordRequestPurpose, Guid>((p, id) =>
 | 
								var passwordReceived = new Action<PasswordRequestPurpose, Guid>((p, id) =>
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				runtimeHost.Raise(r => r.PasswordReceived += null, new PasswordReplyEventArgs { RequestId = id, Success = false });
 | 
									runtimeHost.Raise(r => r.PasswordReceived += null, new PasswordReplyEventArgs { RequestId = id, Success = false });
 | 
				
			||||||
| 
						 | 
					@ -368,8 +370,28 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
				
			||||||
			var session = new Mock<ISessionData>();
 | 
								var session = new Mock<ISessionData>();
 | 
				
			||||||
			var url = @"http://www.safeexambrowser.org/whatever.seb";
 | 
								var url = @"http://www.safeexambrowser.org/whatever.seb";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			clientProxy.Setup(c => c.RequestPassword(It.IsAny<PasswordRequestPurpose>(), It.IsAny<Guid>())).Callback(passwordReceived);
 | 
								clientProxy.Setup(c => c.RequestPassword(It.IsAny<PasswordRequestPurpose>(), It.IsAny<Guid>())).Returns(communication).Callback(passwordReceived);
 | 
				
			||||||
			passwordDialog.Setup(d => d.Show(null)).Returns(new PasswordDialogResultStub { Success = true });
 | 
								repository.SetupGet(r => r.CurrentSession).Returns(session.Object);
 | 
				
			||||||
 | 
								repository.Setup(r => r.LoadSettings(It.IsAny<Uri>(), null, null)).Returns(LoadStatus.SettingsPasswordNeeded);
 | 
				
			||||||
 | 
								session.SetupGet(r => r.ClientProxy).Returns(clientProxy.Object);
 | 
				
			||||||
 | 
								settings.KioskMode = KioskMode.CreateNewDesktop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, messageBox.Object, resourceLoader.Object, runtimeHost.Object, text.Object, uiFactory.Object, new[] { "blubb.exe", url });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								var result = sut.Perform();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.AreEqual(OperationResult.Aborted, result);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							[TestMethod]
 | 
				
			||||||
 | 
							public void MustNotWaitForPasswordViaClientIfCommunicationHasFailed()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								var clientProxy = new Mock<IClientProxy>();
 | 
				
			||||||
 | 
								var communication = new CommunicationResult(false);
 | 
				
			||||||
 | 
								var session = new Mock<ISessionData>();
 | 
				
			||||||
 | 
								var url = @"http://www.safeexambrowser.org/whatever.seb";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								clientProxy.Setup(c => c.RequestPassword(It.IsAny<PasswordRequestPurpose>(), It.IsAny<Guid>())).Returns(communication);
 | 
				
			||||||
			repository.SetupGet(r => r.CurrentSession).Returns(session.Object);
 | 
								repository.SetupGet(r => r.CurrentSession).Returns(session.Object);
 | 
				
			||||||
			repository.Setup(r => r.LoadSettings(It.IsAny<Uri>(), null, null)).Returns(LoadStatus.SettingsPasswordNeeded);
 | 
								repository.Setup(r => r.LoadSettings(It.IsAny<Uri>(), null, null)).Returns(LoadStatus.SettingsPasswordNeeded);
 | 
				
			||||||
			session.SetupGet(r => r.ClientProxy).Returns(clientProxy.Object);
 | 
								session.SetupGet(r => r.ClientProxy).Returns(clientProxy.Object);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -97,16 +97,6 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
				
			||||||
			configuration.SetupGet(s => s.CurrentSettings).Returns(new Settings { ServicePolicy = ServicePolicy.Optional });
 | 
								configuration.SetupGet(s => s.CurrentSettings).Returns(new Settings { ServicePolicy = ServicePolicy.Optional });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			sut.Perform();
 | 
								sut.Perform();
 | 
				
			||||||
 | 
					 | 
				
			||||||
			service.Setup(s => s.Connect(null, true)).Throws<Exception>();
 | 
					 | 
				
			||||||
			configuration.SetupGet(s => s.CurrentSettings).Returns(new Settings { ServicePolicy = ServicePolicy.Mandatory });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			sut.Perform();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			service.Setup(s => s.Connect(null, true)).Throws<Exception>();
 | 
					 | 
				
			||||||
			configuration.SetupGet(s => s.CurrentSettings).Returns(new Settings { ServicePolicy = ServicePolicy.Optional });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			sut.Perform();
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[TestMethod]
 | 
							[TestMethod]
 | 
				
			||||||
| 
						 | 
					@ -177,7 +167,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
				
			||||||
		public void MustNotFailWhenDisconnecting()
 | 
							public void MustNotFailWhenDisconnecting()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			service.Setup(s => s.Connect(null, true)).Returns(true);
 | 
								service.Setup(s => s.Connect(null, true)).Returns(true);
 | 
				
			||||||
			service.Setup(s => s.Disconnect()).Throws<Exception>();
 | 
								service.Setup(s => s.Disconnect()).Returns(false);
 | 
				
			||||||
			configuration.SetupGet(s => s.CurrentSettings).Returns(new Settings { ServicePolicy = ServicePolicy.Optional });
 | 
								configuration.SetupGet(s => s.CurrentSettings).Returns(new Settings { ServicePolicy = ServicePolicy.Optional });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			sut.Perform();
 | 
								sut.Perform();
 | 
				
			||||||
| 
						 | 
					@ -201,18 +191,6 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 | 
				
			||||||
			sut.Perform();
 | 
								sut.Perform();
 | 
				
			||||||
			sut.Revert();
 | 
								sut.Revert();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			service.Setup(s => s.Connect(null, true)).Throws<Exception>();
 | 
					 | 
				
			||||||
			configuration.SetupGet(s => s.CurrentSettings).Returns(new Settings { ServicePolicy = ServicePolicy.Mandatory });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			sut.Perform();
 | 
					 | 
				
			||||||
			sut.Revert();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			service.Setup(s => s.Connect(null, true)).Throws<Exception>();
 | 
					 | 
				
			||||||
			configuration.SetupGet(s => s.CurrentSettings).Returns(new Settings { ServicePolicy = ServicePolicy.Optional });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			sut.Perform();
 | 
					 | 
				
			||||||
			sut.Revert();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			service.Verify(s => s.Disconnect(), Times.Never);
 | 
								service.Verify(s => s.Disconnect(), Times.Never);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -120,9 +120,10 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			logger.Info("Connection with client has been established. Requesting authentication...");
 | 
								logger.Info("Connection with client has been established. Requesting authentication...");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			var response = ClientProxy.RequestAuthentication();
 | 
								var communication = ClientProxy.RequestAuthentication();
 | 
				
			||||||
 | 
								var response = communication.Value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (ClientProcess.Id != response?.ProcessId)
 | 
								if (!communication.Success || ClientProcess.Id != response?.ProcessId)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				logger.Error("Failed to verify client integrity!");
 | 
									logger.Error("Failed to verify client integrity!");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -172,17 +172,11 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
 | 
				
			||||||
			var title = isAdmin ? TextKey.PasswordDialog_AdminPasswordRequiredTitle : TextKey.PasswordDialog_SettingsPasswordRequiredTitle;
 | 
								var title = isAdmin ? TextKey.PasswordDialog_AdminPasswordRequiredTitle : TextKey.PasswordDialog_SettingsPasswordRequiredTitle;
 | 
				
			||||||
			var dialog = uiFactory.CreatePasswordDialog(text.Get(message), text.Get(title));
 | 
								var dialog = uiFactory.CreatePasswordDialog(text.Get(message), text.Get(title));
 | 
				
			||||||
			var result = dialog.Show();
 | 
								var result = dialog.Show();
 | 
				
			||||||
 | 
								var success = result.Success;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (result.Success)
 | 
								password = success ? result.Password : default(string);
 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				password = result.Password;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				password = default(string);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return result.Success;
 | 
								return success;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private bool TryGetPasswordViaClient(PasswordRequestPurpose purpose, out string password)
 | 
							private bool TryGetPasswordViaClient(PasswordRequestPurpose purpose, out string password)
 | 
				
			||||||
| 
						 | 
					@ -200,20 +194,20 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			runtimeHost.PasswordReceived += responseEventHandler;
 | 
								runtimeHost.PasswordReceived += responseEventHandler;
 | 
				
			||||||
			configuration.CurrentSession.ClientProxy.RequestPassword(purpose, requestId);
 | 
					
 | 
				
			||||||
 | 
								var communication = configuration.CurrentSession.ClientProxy.RequestPassword(purpose, requestId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (communication.Success)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
				responseEvent.WaitOne();
 | 
									responseEvent.WaitOne();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								var success = response?.Success == true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			runtimeHost.PasswordReceived -= responseEventHandler;
 | 
								runtimeHost.PasswordReceived -= responseEventHandler;
 | 
				
			||||||
 | 
								password = success ? response.Password : default(string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (response.Success)
 | 
								return success;
 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				password = response.Password;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				password = default(string);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			return response.Success;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private void HandleInvalidData(ref LoadStatus status, Uri uri)
 | 
							private void HandleInvalidData(ref LoadStatus status, Uri uri)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,7 +6,6 @@
 | 
				
			||||||
 * 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.OperationModel;
 | 
					using SafeExamBrowser.Contracts.Behaviour.OperationModel;
 | 
				
			||||||
using SafeExamBrowser.Contracts.Communication.Proxies;
 | 
					using SafeExamBrowser.Contracts.Communication.Proxies;
 | 
				
			||||||
using SafeExamBrowser.Contracts.Configuration;
 | 
					using SafeExamBrowser.Contracts.Configuration;
 | 
				
			||||||
| 
						 | 
					@ -40,15 +39,8 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
 | 
				
			||||||
			logger.Info($"Initializing service session...");
 | 
								logger.Info($"Initializing service session...");
 | 
				
			||||||
			ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeServiceSession);
 | 
								ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeServiceSession);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			try
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
			mandatory = configuration.CurrentSettings.ServicePolicy == ServicePolicy.Mandatory;
 | 
								mandatory = configuration.CurrentSettings.ServicePolicy == ServicePolicy.Mandatory;
 | 
				
			||||||
			connected = service.Connect();
 | 
								connected = service.Connect();
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			catch (Exception e)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				LogException(e);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (mandatory && !connected)
 | 
								if (mandatory && !connected)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
| 
						 | 
					@ -89,13 +81,15 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				StopServiceSession();
 | 
									StopServiceSession();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				try
 | 
									var success = service.Disconnect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (success)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					service.Disconnect();
 | 
										logger.Info("Successfully disconnected from the service.");
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				catch (Exception e)
 | 
									else
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					logger.Error("Failed to disconnect from the service!", e);
 | 
										logger.Error("Failed to disconnect from the service!");
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -109,19 +103,5 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			service.StopSession(configuration.CurrentSession.Id);
 | 
								service.StopSession(configuration.CurrentSession.Id);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		private void LogException(Exception e)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			var message = "Failed to connect to the service component!";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (mandatory)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				logger.Error(message, e);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				logger.Info($"{message} Reason: {e.Message}");
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue