SEBWIN-221: Fixed implementation of session sequence to correctly handle initialization, transition and termination of sessions by introducing the SessionContext.
This commit is contained in:
parent
f4631a1a3d
commit
95ad176047
25 changed files with 551 additions and 375 deletions
|
@ -74,7 +74,7 @@ namespace SafeExamBrowser.Communication.Proxies
|
||||||
{
|
{
|
||||||
if (Ignore)
|
if (Ignore)
|
||||||
{
|
{
|
||||||
Logger.Debug($"Skipping {operationName} because the ignore flag is set.");
|
Logger.Debug($"Skipping '{operationName}' operation because the ignore flag is set.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ignore;
|
return Ignore;
|
||||||
|
|
|
@ -25,86 +25,15 @@ namespace SafeExamBrowser.Configuration
|
||||||
|
|
||||||
private AppConfig appConfig;
|
private AppConfig appConfig;
|
||||||
|
|
||||||
public ISessionData CurrentSession { get; private set; }
|
|
||||||
public Settings CurrentSettings { get; private set; }
|
|
||||||
public string ReconfigurationFilePath { get; set; }
|
|
||||||
|
|
||||||
public AppConfig AppConfig
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (appConfig == null)
|
|
||||||
{
|
|
||||||
InitializeAppConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
return appConfig;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigurationRepository(string executablePath, string programCopyright, string programTitle, string programVersion)
|
public ConfigurationRepository(string executablePath, string programCopyright, string programTitle, string programVersion)
|
||||||
{
|
{
|
||||||
this.executablePath = executablePath ?? throw new ArgumentNullException(nameof(executablePath));
|
this.executablePath = executablePath ?? string.Empty;
|
||||||
this.programCopyright = programCopyright ?? throw new ArgumentNullException(nameof(programCopyright));
|
this.programCopyright = programCopyright ?? string.Empty;
|
||||||
this.programTitle = programTitle ?? throw new ArgumentNullException(nameof(programTitle));
|
this.programTitle = programTitle ?? string.Empty;
|
||||||
this.programVersion = programVersion ?? throw new ArgumentNullException(nameof(programVersion));
|
this.programVersion = programVersion ?? string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClientConfiguration BuildClientConfiguration()
|
public AppConfig InitializeAppConfig()
|
||||||
{
|
|
||||||
return new ClientConfiguration
|
|
||||||
{
|
|
||||||
AppConfig = AppConfig,
|
|
||||||
SessionId = CurrentSession.Id,
|
|
||||||
Settings = CurrentSettings
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public void InitializeSessionConfiguration()
|
|
||||||
{
|
|
||||||
CurrentSession = new SessionData
|
|
||||||
{
|
|
||||||
Id = Guid.NewGuid(),
|
|
||||||
NewDesktop = CurrentSession?.NewDesktop,
|
|
||||||
OriginalDesktop = CurrentSession?.OriginalDesktop,
|
|
||||||
StartupToken = Guid.NewGuid()
|
|
||||||
};
|
|
||||||
|
|
||||||
UpdateAppConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
public LoadStatus LoadSettings(Uri resource, string settingsPassword = null, string adminPassword = null)
|
|
||||||
{
|
|
||||||
// TODO: Implement loading mechanism
|
|
||||||
|
|
||||||
LoadDefaultSettings();
|
|
||||||
|
|
||||||
return LoadStatus.Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LoadDefaultSettings()
|
|
||||||
{
|
|
||||||
// TODO: Implement default settings
|
|
||||||
|
|
||||||
CurrentSettings = new Settings();
|
|
||||||
|
|
||||||
CurrentSettings.KioskMode = KioskMode.None;
|
|
||||||
CurrentSettings.ServicePolicy = ServicePolicy.Optional;
|
|
||||||
|
|
||||||
CurrentSettings.Browser.StartUrl = "https://www.safeexambrowser.org/testing";
|
|
||||||
CurrentSettings.Browser.AllowAddressBar = true;
|
|
||||||
CurrentSettings.Browser.AllowBackwardNavigation = true;
|
|
||||||
CurrentSettings.Browser.AllowDeveloperConsole = true;
|
|
||||||
CurrentSettings.Browser.AllowForwardNavigation = true;
|
|
||||||
CurrentSettings.Browser.AllowReloading = true;
|
|
||||||
CurrentSettings.Browser.AllowDownloads = true;
|
|
||||||
|
|
||||||
CurrentSettings.Taskbar.AllowApplicationLog = true;
|
|
||||||
CurrentSettings.Taskbar.AllowKeyboardLayout = true;
|
|
||||||
CurrentSettings.Taskbar.AllowWirelessNetwork = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitializeAppConfig()
|
|
||||||
{
|
{
|
||||||
var appDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), nameof(SafeExamBrowser));
|
var appDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), nameof(SafeExamBrowser));
|
||||||
var startTime = DateTime.Now;
|
var startTime = DateTime.Now;
|
||||||
|
@ -134,12 +63,89 @@ namespace SafeExamBrowser.Configuration
|
||||||
appConfig.SebUriScheme = "seb";
|
appConfig.SebUriScheme = "seb";
|
||||||
appConfig.SebUriSchemeSecure = "sebs";
|
appConfig.SebUriSchemeSecure = "sebs";
|
||||||
appConfig.ServiceAddress = $"{BASE_ADDRESS}/service";
|
appConfig.ServiceAddress = $"{BASE_ADDRESS}/service";
|
||||||
|
|
||||||
|
return appConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ISessionConfiguration InitializeSessionConfiguration()
|
||||||
|
{
|
||||||
|
var configuration = new SessionConfiguration();
|
||||||
|
|
||||||
|
UpdateAppConfig();
|
||||||
|
|
||||||
|
configuration.AppConfig = CloneAppConfig();
|
||||||
|
configuration.Id = Guid.NewGuid();
|
||||||
|
configuration.StartupToken = Guid.NewGuid();
|
||||||
|
|
||||||
|
return configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoadStatus TryLoadSettings(Uri resource, out Settings settings, string adminPassword = null, string settingsPassword = null)
|
||||||
|
{
|
||||||
|
// TODO: Implement loading mechanism
|
||||||
|
|
||||||
|
settings = LoadDefaultSettings();
|
||||||
|
|
||||||
|
return LoadStatus.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Settings LoadDefaultSettings()
|
||||||
|
{
|
||||||
|
// TODO: Implement default settings
|
||||||
|
|
||||||
|
var settings = new Settings();
|
||||||
|
|
||||||
|
settings.KioskMode = new Random().Next(10) < 5 ? KioskMode.CreateNewDesktop : KioskMode.DisableExplorerShell;
|
||||||
|
settings.ServicePolicy = ServicePolicy.Optional;
|
||||||
|
|
||||||
|
settings.Browser.StartUrl = "https://www.safeexambrowser.org/testing";
|
||||||
|
settings.Browser.AllowAddressBar = true;
|
||||||
|
settings.Browser.AllowBackwardNavigation = true;
|
||||||
|
settings.Browser.AllowDeveloperConsole = true;
|
||||||
|
settings.Browser.AllowForwardNavigation = true;
|
||||||
|
settings.Browser.AllowReloading = true;
|
||||||
|
settings.Browser.AllowDownloads = true;
|
||||||
|
|
||||||
|
settings.Taskbar.AllowApplicationLog = true;
|
||||||
|
settings.Taskbar.AllowKeyboardLayout = true;
|
||||||
|
settings.Taskbar.AllowWirelessNetwork = true;
|
||||||
|
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AppConfig CloneAppConfig()
|
||||||
|
{
|
||||||
|
return new AppConfig
|
||||||
|
{
|
||||||
|
AppDataFolder = appConfig.AppDataFolder,
|
||||||
|
ApplicationStartTime = appConfig.ApplicationStartTime,
|
||||||
|
BrowserCachePath = appConfig.BrowserCachePath,
|
||||||
|
BrowserLogFile = appConfig.BrowserLogFile,
|
||||||
|
ClientAddress = appConfig.ClientAddress,
|
||||||
|
ClientExecutablePath = appConfig.ClientExecutablePath,
|
||||||
|
ClientId = appConfig.ClientId,
|
||||||
|
ClientLogFile = appConfig.ClientLogFile,
|
||||||
|
ConfigurationFileExtension = appConfig.ConfigurationFileExtension,
|
||||||
|
DefaultSettingsFileName = appConfig.DefaultSettingsFileName,
|
||||||
|
DownloadDirectory = appConfig.DownloadDirectory,
|
||||||
|
LogLevel = appConfig.LogLevel,
|
||||||
|
ProgramCopyright = appConfig.ProgramCopyright,
|
||||||
|
ProgramDataFolder = appConfig.ProgramDataFolder,
|
||||||
|
ProgramTitle = appConfig.ProgramTitle,
|
||||||
|
ProgramVersion = appConfig.ProgramVersion,
|
||||||
|
RuntimeAddress = appConfig.RuntimeAddress,
|
||||||
|
RuntimeId = appConfig.RuntimeId,
|
||||||
|
RuntimeLogFile = appConfig.RuntimeLogFile,
|
||||||
|
SebUriScheme = appConfig.SebUriScheme,
|
||||||
|
SebUriSchemeSecure = appConfig.SebUriSchemeSecure,
|
||||||
|
ServiceAddress = appConfig.ServiceAddress
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateAppConfig()
|
private void UpdateAppConfig()
|
||||||
{
|
{
|
||||||
AppConfig.ClientId = Guid.NewGuid();
|
appConfig.ClientId = Guid.NewGuid();
|
||||||
AppConfig.ClientAddress = $"{BASE_ADDRESS}/client/{Guid.NewGuid()}";
|
appConfig.ClientAddress = $"{BASE_ADDRESS}/client/{Guid.NewGuid()}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace SafeExamBrowser.Configuration
|
||||||
{
|
{
|
||||||
public bool IsHtmlResource(Uri resource)
|
public bool IsHtmlResource(Uri resource)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO: Implement resource loader
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,9 +53,9 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="ResourceLoader.cs" />
|
<Compile Include="ResourceLoader.cs" />
|
||||||
<Compile Include="SessionData.cs" />
|
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="ConfigurationRepository.cs" />
|
<Compile Include="ConfigurationRepository.cs" />
|
||||||
|
<Compile Include="SessionConfiguration.cs" />
|
||||||
<Compile Include="SystemInfo.cs" />
|
<Compile Include="SystemInfo.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -7,19 +7,16 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using SafeExamBrowser.Contracts.Communication.Proxies;
|
|
||||||
using SafeExamBrowser.Contracts.Configuration;
|
using SafeExamBrowser.Contracts.Configuration;
|
||||||
using SafeExamBrowser.Contracts.WindowsApi;
|
using SafeExamBrowser.Contracts.Configuration.Settings;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Configuration
|
namespace SafeExamBrowser.Configuration
|
||||||
{
|
{
|
||||||
public class SessionData : ISessionData
|
internal class SessionConfiguration : ISessionConfiguration
|
||||||
{
|
{
|
||||||
public IClientProxy ClientProxy { get; set; }
|
public AppConfig AppConfig { get; set; }
|
||||||
public IProcess ClientProcess { get; set; }
|
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
public IDesktop NewDesktop { get; set; }
|
public Settings Settings { get; set; }
|
||||||
public IDesktop OriginalDesktop { get; set; }
|
|
||||||
public Guid StartupToken { get; set; }
|
public Guid StartupToken { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using SafeExamBrowser.Contracts.Configuration;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Contracts.Communication.Events
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The event arguments used for the client configuration event fired by the <see cref="Hosts.IRuntimeHost"/>.
|
||||||
|
/// </summary>
|
||||||
|
public class ClientConfigurationEventArgs : CommunicationEventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The configuration to be sent to the client.
|
||||||
|
/// </summary>
|
||||||
|
public ClientConfiguration ClientConfiguration { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,6 +31,11 @@ namespace SafeExamBrowser.Contracts.Communication.Hosts
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event CommunicationEventHandler ClientReady;
|
event CommunicationEventHandler ClientReady;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event fired when the client requested its configuration data.
|
||||||
|
/// </summary>
|
||||||
|
event CommunicationEventHandler<ClientConfigurationEventArgs> ClientConfigurationNeeded;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event fired when the client submitted a password entered by the user.
|
/// Event fired when the client submitted a password entered by the user.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -16,46 +16,25 @@ namespace SafeExamBrowser.Contracts.Configuration
|
||||||
public interface IConfigurationRepository
|
public interface IConfigurationRepository
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The global configuration information for the currently running application instance.
|
/// Initializes the global configuration information for the currently running application instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
AppConfig AppConfig { get; }
|
AppConfig InitializeAppConfig();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the current session data, i.e. the last one which was initialized. If no session has been initialized yet, this
|
/// Initializes all relevant configuration data for a new session.
|
||||||
/// property will be <c>null</c>!
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ISessionData CurrentSession { get; }
|
ISessionConfiguration InitializeSessionConfiguration();
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Retrieves the current settings, i.e. the last ones which were loaded. If no settings have been loaded yet, this property will
|
|
||||||
/// be <c>null</c>!
|
|
||||||
/// </summary>
|
|
||||||
Settings.Settings CurrentSettings { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The path of the settings file to be used when reconfiguring the application.
|
|
||||||
/// </summary>
|
|
||||||
string ReconfigurationFilePath { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Builds a configuration for the client component, given the currently loaded settings, session and runtime information.
|
|
||||||
/// </summary>
|
|
||||||
ClientConfiguration BuildClientConfiguration();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes all relevant data for a new session.
|
|
||||||
/// </summary>
|
|
||||||
void InitializeSessionConfiguration();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attempts to load settings from the specified resource, using the optional passwords. Returns a <see cref="LoadStatus"/>
|
/// Attempts to load settings from the specified resource, using the optional passwords. Returns a <see cref="LoadStatus"/>
|
||||||
/// indicating the result of the operation.
|
/// indicating the result of the operation. As long as the result is not <see cref="LoadStatus.Success"/>, the declared
|
||||||
|
/// <paramref name="settings"/> will be <c>null</c>!
|
||||||
/// </summary>
|
/// </summary>
|
||||||
LoadStatus LoadSettings(Uri resource, string adminPassword = null, string settingsPassword = null);
|
LoadStatus TryLoadSettings(Uri resource, out Settings.Settings settings, string adminPassword = null, string settingsPassword = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Loads the default settings.
|
/// Loads the default settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void LoadDefaultSettings();
|
Settings.Settings LoadDefaultSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Contracts.Configuration
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Holds all session-related configuration data.
|
||||||
|
/// </summary>
|
||||||
|
public interface ISessionConfiguration
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The active application configuration for this session.
|
||||||
|
/// </summary>
|
||||||
|
AppConfig AppConfig { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The unique session identifier.
|
||||||
|
/// </summary>
|
||||||
|
Guid Id { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The settings used for this session.
|
||||||
|
/// </summary>
|
||||||
|
Settings.Settings Settings { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The startup token used by the client and runtime components for initial authentication.
|
||||||
|
/// </summary>
|
||||||
|
Guid StartupToken { get; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,50 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
|
||||||
*
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using SafeExamBrowser.Contracts.Communication.Proxies;
|
|
||||||
using SafeExamBrowser.Contracts.WindowsApi;
|
|
||||||
|
|
||||||
namespace SafeExamBrowser.Contracts.Configuration
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Holds all session-related configuration and runtime data.
|
|
||||||
/// </summary>
|
|
||||||
public interface ISessionData
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The communication proxy for the client instance associated to this session.
|
|
||||||
/// </summary>
|
|
||||||
IClientProxy ClientProxy { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The process information of the client instance associated to this session.
|
|
||||||
/// </summary>
|
|
||||||
IProcess ClientProcess { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The unique session identifier.
|
|
||||||
/// </summary>
|
|
||||||
Guid Id { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The new desktop, if <see cref="Settings.KioskMode.CreateNewDesktop"/> is active for this session.
|
|
||||||
/// </summary>
|
|
||||||
IDesktop NewDesktop { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The original desktop, if <see cref="Settings.KioskMode.CreateNewDesktop"/> is active for this session.
|
|
||||||
/// </summary>
|
|
||||||
IDesktop OriginalDesktop { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The startup token used by the client and runtime components for initial authentication.
|
|
||||||
/// </summary>
|
|
||||||
Guid StartupToken { get; }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -52,6 +52,7 @@
|
||||||
<Reference Include="System.ServiceModel" />
|
<Reference Include="System.ServiceModel" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Communication\Events\ClientConfigurationEventArgs.cs" />
|
||||||
<Compile Include="Core\Events\InstanceTerminatedEventHandler.cs" />
|
<Compile Include="Core\Events\InstanceTerminatedEventHandler.cs" />
|
||||||
<Compile Include="Core\Events\NameChangedEventHandler.cs" />
|
<Compile Include="Core\Events\NameChangedEventHandler.cs" />
|
||||||
<Compile Include="Core\IApplicationController.cs" />
|
<Compile Include="Core\IApplicationController.cs" />
|
||||||
|
@ -109,7 +110,7 @@
|
||||||
<Compile Include="Configuration\IResourceLoader.cs" />
|
<Compile Include="Configuration\IResourceLoader.cs" />
|
||||||
<Compile Include="Configuration\LoadStatus.cs" />
|
<Compile Include="Configuration\LoadStatus.cs" />
|
||||||
<Compile Include="Configuration\AppConfig.cs" />
|
<Compile Include="Configuration\AppConfig.cs" />
|
||||||
<Compile Include="Configuration\ISessionData.cs" />
|
<Compile Include="Configuration\ISessionConfiguration.cs" />
|
||||||
<Compile Include="Configuration\Settings\ConfigurationMode.cs" />
|
<Compile Include="Configuration\Settings\ConfigurationMode.cs" />
|
||||||
<Compile Include="Core\INotificationController.cs" />
|
<Compile Include="Core\INotificationController.cs" />
|
||||||
<Compile Include="Core\OperationModel\IOperation.cs" />
|
<Compile Include="Core\OperationModel\IOperation.cs" />
|
||||||
|
|
|
@ -11,7 +11,6 @@ using SafeExamBrowser.Communication.Hosts;
|
||||||
using SafeExamBrowser.Contracts.Communication.Data;
|
using SafeExamBrowser.Contracts.Communication.Data;
|
||||||
using SafeExamBrowser.Contracts.Communication.Events;
|
using SafeExamBrowser.Contracts.Communication.Events;
|
||||||
using SafeExamBrowser.Contracts.Communication.Hosts;
|
using SafeExamBrowser.Contracts.Communication.Hosts;
|
||||||
using SafeExamBrowser.Contracts.Configuration;
|
|
||||||
using SafeExamBrowser.Contracts.Logging;
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Runtime.Communication
|
namespace SafeExamBrowser.Runtime.Communication
|
||||||
|
@ -19,24 +18,18 @@ namespace SafeExamBrowser.Runtime.Communication
|
||||||
internal class RuntimeHost : BaseHost, IRuntimeHost
|
internal class RuntimeHost : BaseHost, IRuntimeHost
|
||||||
{
|
{
|
||||||
private bool allowConnection = true;
|
private bool allowConnection = true;
|
||||||
private IConfigurationRepository configuration;
|
|
||||||
|
|
||||||
public Guid StartupToken { private get; set; }
|
public Guid StartupToken { private get; set; }
|
||||||
|
|
||||||
public event CommunicationEventHandler ClientDisconnected;
|
public event CommunicationEventHandler ClientDisconnected;
|
||||||
public event CommunicationEventHandler ClientReady;
|
public event CommunicationEventHandler ClientReady;
|
||||||
|
public event CommunicationEventHandler<ClientConfigurationEventArgs> ClientConfigurationNeeded;
|
||||||
public event CommunicationEventHandler<PasswordReplyEventArgs> PasswordReceived;
|
public event CommunicationEventHandler<PasswordReplyEventArgs> PasswordReceived;
|
||||||
public event CommunicationEventHandler<ReconfigurationEventArgs> ReconfigurationRequested;
|
public event CommunicationEventHandler<ReconfigurationEventArgs> ReconfigurationRequested;
|
||||||
public event CommunicationEventHandler ShutdownRequested;
|
public event CommunicationEventHandler ShutdownRequested;
|
||||||
|
|
||||||
public RuntimeHost(
|
public RuntimeHost(string address, IHostObjectFactory factory, ILogger logger, int timeout_ms) : base(address, factory, logger, timeout_ms)
|
||||||
string address,
|
|
||||||
IConfigurationRepository configuration,
|
|
||||||
IHostObjectFactory factory,
|
|
||||||
ILogger logger,
|
|
||||||
int timeout_ms) : base(address, factory, logger, timeout_ms)
|
|
||||||
{
|
{
|
||||||
this.configuration = configuration;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnConnect(Guid? token = null)
|
protected override bool OnConnect(Guid? token = null)
|
||||||
|
@ -87,8 +80,7 @@ namespace SafeExamBrowser.Runtime.Communication
|
||||||
ClientReady?.Invoke();
|
ClientReady?.Invoke();
|
||||||
return new SimpleResponse(SimpleResponsePurport.Acknowledged);
|
return new SimpleResponse(SimpleResponsePurport.Acknowledged);
|
||||||
case SimpleMessagePurport.ConfigurationNeeded:
|
case SimpleMessagePurport.ConfigurationNeeded:
|
||||||
// TODO: Not the job of the host, fire event or alike!
|
return HandleConfigurationRequest();
|
||||||
return new ConfigurationResponse { Configuration = configuration.BuildClientConfiguration() };
|
|
||||||
case SimpleMessagePurport.RequestShutdown:
|
case SimpleMessagePurport.RequestShutdown:
|
||||||
ShutdownRequested?.Invoke();
|
ShutdownRequested?.Invoke();
|
||||||
return new SimpleResponse(SimpleResponsePurport.Acknowledged);
|
return new SimpleResponse(SimpleResponsePurport.Acknowledged);
|
||||||
|
@ -96,5 +88,14 @@ namespace SafeExamBrowser.Runtime.Communication
|
||||||
|
|
||||||
return new SimpleResponse(SimpleResponsePurport.UnknownMessage);
|
return new SimpleResponse(SimpleResponsePurport.UnknownMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Response HandleConfigurationRequest()
|
||||||
|
{
|
||||||
|
var args = new ClientConfigurationEventArgs();
|
||||||
|
|
||||||
|
ClientConfigurationNeeded?.Invoke(args);
|
||||||
|
|
||||||
|
return new ConfigurationResponse { Configuration = args.ClientConfiguration };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace SafeExamBrowser.Runtime
|
||||||
var nativeMethods = new NativeMethods();
|
var nativeMethods = new NativeMethods();
|
||||||
|
|
||||||
logger = new Logger();
|
logger = new Logger();
|
||||||
appConfig = configuration.AppConfig;
|
appConfig = configuration.InitializeAppConfig();
|
||||||
systemInfo = new SystemInfo();
|
systemInfo = new SystemInfo();
|
||||||
|
|
||||||
InitializeLogging();
|
InitializeLogging();
|
||||||
|
@ -61,8 +61,9 @@ namespace SafeExamBrowser.Runtime
|
||||||
var processFactory = new ProcessFactory(new ModuleLogger(logger, nameof(ProcessFactory)));
|
var processFactory = new ProcessFactory(new ModuleLogger(logger, nameof(ProcessFactory)));
|
||||||
var proxyFactory = new ProxyFactory(new ProxyObjectFactory(), logger);
|
var proxyFactory = new ProxyFactory(new ProxyObjectFactory(), logger);
|
||||||
var resourceLoader = new ResourceLoader();
|
var resourceLoader = new ResourceLoader();
|
||||||
var runtimeHost = new RuntimeHost(appConfig.RuntimeAddress, configuration, new HostObjectFactory(), new ModuleLogger(logger, nameof(RuntimeHost)), FIVE_SECONDS);
|
var runtimeHost = new RuntimeHost(appConfig.RuntimeAddress, new HostObjectFactory(), new ModuleLogger(logger, nameof(RuntimeHost)), FIVE_SECONDS);
|
||||||
var serviceProxy = new ServiceProxy(appConfig.ServiceAddress, new ProxyObjectFactory(), new ModuleLogger(logger, nameof(ServiceProxy)));
|
var serviceProxy = new ServiceProxy(appConfig.ServiceAddress, new ProxyObjectFactory(), new ModuleLogger(logger, nameof(ServiceProxy)));
|
||||||
|
var sessionContext = new SessionContext();
|
||||||
var uiFactory = new UserInterfaceFactory(text);
|
var uiFactory = new UserInterfaceFactory(text);
|
||||||
|
|
||||||
var bootstrapOperations = new Queue<IOperation>();
|
var bootstrapOperations = new Queue<IOperation>();
|
||||||
|
@ -71,18 +72,19 @@ namespace SafeExamBrowser.Runtime
|
||||||
bootstrapOperations.Enqueue(new I18nOperation(logger, text, textResource));
|
bootstrapOperations.Enqueue(new I18nOperation(logger, text, textResource));
|
||||||
bootstrapOperations.Enqueue(new CommunicationHostOperation(runtimeHost, logger));
|
bootstrapOperations.Enqueue(new CommunicationHostOperation(runtimeHost, logger));
|
||||||
|
|
||||||
sessionOperations.Enqueue(new ConfigurationOperation(appConfig, configuration, logger, resourceLoader, args));
|
sessionOperations.Enqueue(new SessionInitializationOperation(configuration, logger, runtimeHost, sessionContext));
|
||||||
sessionOperations.Enqueue(new ClientTerminationOperation(configuration, logger, processFactory, proxyFactory, runtimeHost, FIFTEEN_SECONDS));
|
sessionOperations.Enqueue(new ConfigurationOperation(args, configuration, logger, resourceLoader, sessionContext));
|
||||||
sessionOperations.Enqueue(new KioskModeTerminationOperation(configuration, desktopFactory, explorerShell, logger, processFactory));
|
sessionOperations.Enqueue(new ClientTerminationOperation(logger, processFactory, proxyFactory, runtimeHost, sessionContext, FIFTEEN_SECONDS));
|
||||||
sessionOperations.Enqueue(new SessionInitializationOperation(configuration, logger, runtimeHost));
|
sessionOperations.Enqueue(new KioskModeTerminationOperation(desktopFactory, explorerShell, logger, processFactory, sessionContext));
|
||||||
sessionOperations.Enqueue(new ServiceOperation(configuration, logger, serviceProxy));
|
sessionOperations.Enqueue(new ServiceOperation(logger, serviceProxy, sessionContext));
|
||||||
sessionOperations.Enqueue(new KioskModeOperation(configuration, desktopFactory, explorerShell, logger, processFactory));
|
sessionOperations.Enqueue(new KioskModeOperation(desktopFactory, explorerShell, logger, processFactory, sessionContext));
|
||||||
sessionOperations.Enqueue(new ClientOperation(configuration, logger, processFactory, proxyFactory, runtimeHost, FIFTEEN_SECONDS));
|
sessionOperations.Enqueue(new ClientOperation(logger, processFactory, proxyFactory, runtimeHost, sessionContext, FIFTEEN_SECONDS));
|
||||||
|
sessionOperations.Enqueue(new SessionActivationOperation(logger, sessionContext));
|
||||||
|
|
||||||
var bootstrapSequence = new OperationSequence(logger, bootstrapOperations);
|
var bootstrapSequence = new OperationSequence(logger, bootstrapOperations);
|
||||||
var sessionSequence = new RepeatableOperationSequence(logger, sessionOperations);
|
var sessionSequence = new RepeatableOperationSequence(logger, sessionOperations);
|
||||||
|
|
||||||
RuntimeController = new RuntimeController(appConfig, configuration, logger, messageBox, bootstrapSequence, sessionSequence, runtimeHost, serviceProxy, shutdown, text, uiFactory);
|
RuntimeController = new RuntimeController(appConfig, logger, messageBox, bootstrapSequence, sessionSequence, runtimeHost, serviceProxy, sessionContext, shutdown, text, uiFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void LogStartupInformation()
|
internal void LogStartupInformation()
|
||||||
|
@ -103,7 +105,7 @@ namespace SafeExamBrowser.Runtime
|
||||||
logger?.Log($"# Application terminated at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
|
logger?.Log($"# Application terminated at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConfigurationRepository BuildConfigurationRepository()
|
private IConfigurationRepository BuildConfigurationRepository()
|
||||||
{
|
{
|
||||||
var executable = Assembly.GetExecutingAssembly();
|
var executable = Assembly.GetExecutingAssembly();
|
||||||
var programCopyright = executable.GetCustomAttribute<AssemblyCopyrightAttribute>().Copyright;
|
var programCopyright = executable.GetCustomAttribute<AssemblyCopyrightAttribute>().Copyright;
|
||||||
|
|
|
@ -10,7 +10,6 @@ using System.Threading;
|
||||||
using SafeExamBrowser.Contracts.Communication.Events;
|
using SafeExamBrowser.Contracts.Communication.Events;
|
||||||
using SafeExamBrowser.Contracts.Communication.Hosts;
|
using SafeExamBrowser.Contracts.Communication.Hosts;
|
||||||
using SafeExamBrowser.Contracts.Communication.Proxies;
|
using SafeExamBrowser.Contracts.Communication.Proxies;
|
||||||
using SafeExamBrowser.Contracts.Configuration;
|
|
||||||
using SafeExamBrowser.Contracts.Core.OperationModel;
|
using SafeExamBrowser.Contracts.Core.OperationModel;
|
||||||
using SafeExamBrowser.Contracts.Core.OperationModel.Events;
|
using SafeExamBrowser.Contracts.Core.OperationModel.Events;
|
||||||
using SafeExamBrowser.Contracts.I18n;
|
using SafeExamBrowser.Contracts.I18n;
|
||||||
|
@ -20,40 +19,38 @@ using SafeExamBrowser.Contracts.WindowsApi.Events;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Runtime.Operations
|
namespace SafeExamBrowser.Runtime.Operations
|
||||||
{
|
{
|
||||||
internal class ClientOperation : IRepeatableOperation
|
internal class ClientOperation : SessionOperation
|
||||||
{
|
{
|
||||||
private readonly int timeout_ms;
|
private readonly int timeout_ms;
|
||||||
|
|
||||||
private IConfigurationRepository configuration;
|
|
||||||
private ILogger logger;
|
private ILogger logger;
|
||||||
private IProcessFactory processFactory;
|
private IProcessFactory processFactory;
|
||||||
private IProxyFactory proxyFactory;
|
private IProxyFactory proxyFactory;
|
||||||
private IRuntimeHost runtimeHost;
|
private IRuntimeHost runtimeHost;
|
||||||
|
|
||||||
public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
|
|
||||||
public event StatusChangedEventHandler StatusChanged;
|
|
||||||
|
|
||||||
private IProcess ClientProcess
|
private IProcess ClientProcess
|
||||||
{
|
{
|
||||||
get { return configuration.CurrentSession.ClientProcess; }
|
get { return Context.ClientProcess; }
|
||||||
set { configuration.CurrentSession.ClientProcess = value; }
|
set { Context.ClientProcess = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private IClientProxy ClientProxy
|
private IClientProxy ClientProxy
|
||||||
{
|
{
|
||||||
get { return configuration.CurrentSession.ClientProxy; }
|
get { return Context.ClientProxy; }
|
||||||
set { configuration.CurrentSession.ClientProxy = value; }
|
set { Context.ClientProxy = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override event ActionRequiredEventHandler ActionRequired { add { } remove { } }
|
||||||
|
public override event StatusChangedEventHandler StatusChanged;
|
||||||
|
|
||||||
public ClientOperation(
|
public ClientOperation(
|
||||||
IConfigurationRepository configuration,
|
|
||||||
ILogger logger,
|
ILogger logger,
|
||||||
IProcessFactory processFactory,
|
IProcessFactory processFactory,
|
||||||
IProxyFactory proxyFactory,
|
IProxyFactory proxyFactory,
|
||||||
IRuntimeHost runtimeHost,
|
IRuntimeHost runtimeHost,
|
||||||
int timeout_ms)
|
SessionContext sessionContext,
|
||||||
|
int timeout_ms) : base(sessionContext)
|
||||||
{
|
{
|
||||||
this.configuration = configuration;
|
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.processFactory = processFactory;
|
this.processFactory = processFactory;
|
||||||
this.proxyFactory = proxyFactory;
|
this.proxyFactory = proxyFactory;
|
||||||
|
@ -61,7 +58,7 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
this.timeout_ms = timeout_ms;
|
this.timeout_ms = timeout_ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual OperationResult Perform()
|
public override OperationResult Perform()
|
||||||
{
|
{
|
||||||
StatusChanged?.Invoke(TextKey.OperationStatus_StartClient);
|
StatusChanged?.Invoke(TextKey.OperationStatus_StartClient);
|
||||||
|
|
||||||
|
@ -79,12 +76,12 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
return success ? OperationResult.Success : OperationResult.Failed;
|
return success ? OperationResult.Success : OperationResult.Failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual OperationResult Repeat()
|
public override OperationResult Repeat()
|
||||||
{
|
{
|
||||||
return Perform();
|
return Perform();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual OperationResult Revert()
|
public override OperationResult Revert()
|
||||||
{
|
{
|
||||||
var success = true;
|
var success = true;
|
||||||
|
|
||||||
|
@ -103,10 +100,10 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
var clientReadyEvent = new AutoResetEvent(false);
|
var clientReadyEvent = new AutoResetEvent(false);
|
||||||
var clientReadyEventHandler = new CommunicationEventHandler(() => clientReadyEvent.Set());
|
var clientReadyEventHandler = new CommunicationEventHandler(() => clientReadyEvent.Set());
|
||||||
|
|
||||||
var clientExecutable = configuration.AppConfig.ClientExecutablePath;
|
var clientExecutable = Context.Next.AppConfig.ClientExecutablePath;
|
||||||
var clientLogFile = $"{'"' + configuration.AppConfig.ClientLogFile + '"'}";
|
var clientLogFile = $"{'"' + Context.Next.AppConfig.ClientLogFile + '"'}";
|
||||||
var hostUri = configuration.AppConfig.RuntimeAddress;
|
var hostUri = Context.Next.AppConfig.RuntimeAddress;
|
||||||
var token = configuration.CurrentSession.StartupToken.ToString("D");
|
var token = Context.Next.StartupToken.ToString("D");
|
||||||
|
|
||||||
logger.Info("Starting new client process...");
|
logger.Info("Starting new client process...");
|
||||||
runtimeHost.ClientReady += clientReadyEventHandler;
|
runtimeHost.ClientReady += clientReadyEventHandler;
|
||||||
|
@ -124,9 +121,9 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("Client has been successfully started and initialized. Creating communication proxy for client host...");
|
logger.Info("Client has been successfully started and initialized. Creating communication proxy for client host...");
|
||||||
ClientProxy = proxyFactory.CreateClientProxy(configuration.AppConfig.ClientAddress);
|
ClientProxy = proxyFactory.CreateClientProxy(Context.Next.AppConfig.ClientAddress);
|
||||||
|
|
||||||
if (!ClientProxy.Connect(configuration.CurrentSession.StartupToken))
|
if (!ClientProxy.Connect(Context.Next.StartupToken))
|
||||||
{
|
{
|
||||||
logger.Error("Failed to connect to client!");
|
logger.Error("Failed to connect to client!");
|
||||||
|
|
||||||
|
|
|
@ -8,22 +8,21 @@
|
||||||
|
|
||||||
using SafeExamBrowser.Contracts.Communication.Hosts;
|
using SafeExamBrowser.Contracts.Communication.Hosts;
|
||||||
using SafeExamBrowser.Contracts.Communication.Proxies;
|
using SafeExamBrowser.Contracts.Communication.Proxies;
|
||||||
using SafeExamBrowser.Contracts.Configuration;
|
|
||||||
using SafeExamBrowser.Contracts.Core.OperationModel;
|
using SafeExamBrowser.Contracts.Core.OperationModel;
|
||||||
using SafeExamBrowser.Contracts.Logging;
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
using SafeExamBrowser.Contracts.WindowsApi;
|
using SafeExamBrowser.Contracts.WindowsApi;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Runtime.Operations
|
namespace SafeExamBrowser.Runtime.Operations
|
||||||
{
|
{
|
||||||
internal class ClientTerminationOperation : ClientOperation, IRepeatableOperation
|
internal class ClientTerminationOperation : ClientOperation
|
||||||
{
|
{
|
||||||
public ClientTerminationOperation(
|
public ClientTerminationOperation(
|
||||||
IConfigurationRepository configuration,
|
|
||||||
ILogger logger,
|
ILogger logger,
|
||||||
IProcessFactory processFactory,
|
IProcessFactory processFactory,
|
||||||
IProxyFactory proxyFactory,
|
IProxyFactory proxyFactory,
|
||||||
IRuntimeHost runtimeHost,
|
IRuntimeHost runtimeHost,
|
||||||
int timeout_ms) : base(configuration, logger, processFactory, proxyFactory, runtimeHost, timeout_ms)
|
SessionContext sessionContext,
|
||||||
|
int timeout_ms) : base(logger, processFactory, proxyFactory, runtimeHost, sessionContext, timeout_ms)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,32 +19,30 @@ using SafeExamBrowser.Runtime.Operations.Events;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Runtime.Operations
|
namespace SafeExamBrowser.Runtime.Operations
|
||||||
{
|
{
|
||||||
internal class ConfigurationOperation : IRepeatableOperation
|
internal class ConfigurationOperation : SessionOperation
|
||||||
{
|
{
|
||||||
|
private string[] commandLineArgs;
|
||||||
private IConfigurationRepository configuration;
|
private IConfigurationRepository configuration;
|
||||||
private ILogger logger;
|
private ILogger logger;
|
||||||
private IResourceLoader resourceLoader;
|
private IResourceLoader resourceLoader;
|
||||||
private AppConfig appConfig;
|
|
||||||
private string[] commandLineArgs;
|
|
||||||
|
|
||||||
public event ActionRequiredEventHandler ActionRequired;
|
public override event ActionRequiredEventHandler ActionRequired;
|
||||||
public event StatusChangedEventHandler StatusChanged;
|
public override event StatusChangedEventHandler StatusChanged;
|
||||||
|
|
||||||
public ConfigurationOperation(
|
public ConfigurationOperation(
|
||||||
AppConfig appConfig,
|
string[] commandLineArgs,
|
||||||
IConfigurationRepository configuration,
|
IConfigurationRepository configuration,
|
||||||
ILogger logger,
|
ILogger logger,
|
||||||
IResourceLoader resourceLoader,
|
IResourceLoader resourceLoader,
|
||||||
string[] commandLineArgs)
|
SessionContext sessionContext) : base(sessionContext)
|
||||||
{
|
{
|
||||||
this.appConfig = appConfig;
|
this.commandLineArgs = commandLineArgs;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.configuration = configuration;
|
this.configuration = configuration;
|
||||||
this.resourceLoader = resourceLoader;
|
this.resourceLoader = resourceLoader;
|
||||||
this.commandLineArgs = commandLineArgs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public OperationResult Perform()
|
public override OperationResult Perform()
|
||||||
{
|
{
|
||||||
logger.Info("Initializing application configuration...");
|
logger.Info("Initializing application configuration...");
|
||||||
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeConfiguration);
|
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeConfiguration);
|
||||||
|
@ -69,12 +67,12 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
return OperationResult.Success;
|
return OperationResult.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OperationResult Repeat()
|
public override OperationResult Repeat()
|
||||||
{
|
{
|
||||||
logger.Info("Initializing new application configuration...");
|
logger.Info("Initializing new application configuration...");
|
||||||
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeConfiguration);
|
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeConfiguration);
|
||||||
|
|
||||||
var isValidUri = TryValidateSettingsUri(configuration.ReconfigurationFilePath, out Uri uri);
|
var isValidUri = TryValidateSettingsUri(Context.ReconfigurationFilePath, out Uri uri);
|
||||||
|
|
||||||
if (isValidUri)
|
if (isValidUri)
|
||||||
{
|
{
|
||||||
|
@ -92,7 +90,7 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
return OperationResult.Failed;
|
return OperationResult.Failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OperationResult Revert()
|
public override OperationResult Revert()
|
||||||
{
|
{
|
||||||
return OperationResult.Success;
|
return OperationResult.Success;
|
||||||
}
|
}
|
||||||
|
@ -101,11 +99,12 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
{
|
{
|
||||||
var adminPassword = default(string);
|
var adminPassword = default(string);
|
||||||
var settingsPassword = default(string);
|
var settingsPassword = default(string);
|
||||||
|
var settings = default(Settings);
|
||||||
var status = default(LoadStatus);
|
var status = default(LoadStatus);
|
||||||
|
|
||||||
for (int adminAttempts = 0, settingsAttempts = 0; adminAttempts < 5 && settingsAttempts < 5;)
|
for (int adminAttempts = 0, settingsAttempts = 0; adminAttempts < 5 && settingsAttempts < 5;)
|
||||||
{
|
{
|
||||||
status = configuration.LoadSettings(uri, adminPassword, settingsPassword);
|
status = configuration.TryLoadSettings(uri, out settings, adminPassword, settingsPassword);
|
||||||
|
|
||||||
if (status == LoadStatus.AdminPasswordNeeded || status == LoadStatus.SettingsPasswordNeeded)
|
if (status == LoadStatus.AdminPasswordNeeded || status == LoadStatus.SettingsPasswordNeeded)
|
||||||
{
|
{
|
||||||
|
@ -132,7 +131,15 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
HandleInvalidData(ref status, uri);
|
HandleInvalidData(ref status, uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
return status == LoadStatus.Success ? OperationResult.Success : OperationResult.Failed;
|
if (status == LoadStatus.Success)
|
||||||
|
{
|
||||||
|
Context.Next.Settings = settings;
|
||||||
|
|
||||||
|
return OperationResult.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return OperationResult.Failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PasswordRequiredEventArgs TryGetPassword(LoadStatus status)
|
private PasswordRequiredEventArgs TryGetPassword(LoadStatus status)
|
||||||
|
@ -150,7 +157,7 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
if (resourceLoader.IsHtmlResource(uri))
|
if (resourceLoader.IsHtmlResource(uri))
|
||||||
{
|
{
|
||||||
configuration.LoadDefaultSettings();
|
configuration.LoadDefaultSettings();
|
||||||
configuration.CurrentSettings.Browser.StartUrl = uri.AbsoluteUri;
|
Context.Next.Settings.Browser.StartUrl = uri.AbsoluteUri;
|
||||||
logger.Info($"The specified URI '{uri.AbsoluteUri}' appears to point to a HTML resource, setting it as startup URL.");
|
logger.Info($"The specified URI '{uri.AbsoluteUri}' appears to point to a HTML resource, setting it as startup URL.");
|
||||||
|
|
||||||
status = LoadStatus.Success;
|
status = LoadStatus.Success;
|
||||||
|
@ -165,8 +172,8 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
{
|
{
|
||||||
var path = string.Empty;
|
var path = string.Empty;
|
||||||
var isValidUri = false;
|
var isValidUri = false;
|
||||||
var programDataSettings = Path.Combine(appConfig.ProgramDataFolder, appConfig.DefaultSettingsFileName);
|
var programDataSettings = Path.Combine(Context.Next.AppConfig.ProgramDataFolder, Context.Next.AppConfig.DefaultSettingsFileName);
|
||||||
var appDataSettings = Path.Combine(appConfig.AppDataFolder, appConfig.DefaultSettingsFileName);
|
var appDataSettings = Path.Combine(Context.Next.AppConfig.AppDataFolder, Context.Next.AppConfig.DefaultSettingsFileName);
|
||||||
|
|
||||||
uri = null;
|
uri = null;
|
||||||
|
|
||||||
|
@ -206,7 +213,7 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
|
|
||||||
private void HandleClientConfiguration(ref OperationResult result)
|
private void HandleClientConfiguration(ref OperationResult result)
|
||||||
{
|
{
|
||||||
if (result == OperationResult.Success && configuration.CurrentSettings.ConfigurationMode == ConfigurationMode.ConfigureClient)
|
if (result == OperationResult.Success && Context.Next.Settings.ConfigurationMode == ConfigurationMode.ConfigureClient)
|
||||||
{
|
{
|
||||||
var args = new ConfigurationCompletedEventArgs();
|
var args = new ConfigurationCompletedEventArgs();
|
||||||
|
|
||||||
|
|
|
@ -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 SafeExamBrowser.Contracts.Configuration;
|
|
||||||
using SafeExamBrowser.Contracts.Configuration.Settings;
|
using SafeExamBrowser.Contracts.Configuration.Settings;
|
||||||
using SafeExamBrowser.Contracts.Core.OperationModel;
|
using SafeExamBrowser.Contracts.Core.OperationModel;
|
||||||
using SafeExamBrowser.Contracts.Core.OperationModel.Events;
|
using SafeExamBrowser.Contracts.Core.OperationModel.Events;
|
||||||
|
@ -16,52 +15,40 @@ using SafeExamBrowser.Contracts.WindowsApi;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Runtime.Operations
|
namespace SafeExamBrowser.Runtime.Operations
|
||||||
{
|
{
|
||||||
internal class KioskModeOperation : IRepeatableOperation
|
internal class KioskModeOperation : SessionOperation
|
||||||
{
|
{
|
||||||
private IConfigurationRepository configuration;
|
protected IDesktopFactory desktopFactory;
|
||||||
private IDesktopFactory desktopFactory;
|
protected IExplorerShell explorerShell;
|
||||||
private IExplorerShell explorerShell;
|
protected ILogger logger;
|
||||||
private KioskMode kioskMode;
|
protected IProcessFactory processFactory;
|
||||||
private ILogger logger;
|
|
||||||
private IProcessFactory processFactory;
|
|
||||||
|
|
||||||
public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
|
private static IDesktop newDesktop;
|
||||||
public event StatusChangedEventHandler StatusChanged;
|
private static IDesktop originalDesktop;
|
||||||
|
|
||||||
private IDesktop NewDesktop
|
protected static KioskMode? ActiveMode { get; private set; }
|
||||||
{
|
|
||||||
get { return configuration.CurrentSession.NewDesktop; }
|
|
||||||
set { configuration.CurrentSession.NewDesktop = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private IDesktop OriginalDesktop
|
public override event ActionRequiredEventHandler ActionRequired { add { } remove { } }
|
||||||
{
|
public override event StatusChangedEventHandler StatusChanged;
|
||||||
get { return configuration.CurrentSession.OriginalDesktop; }
|
|
||||||
set { configuration.CurrentSession.OriginalDesktop = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public KioskModeOperation(
|
public KioskModeOperation(
|
||||||
IConfigurationRepository configuration,
|
|
||||||
IDesktopFactory desktopFactory,
|
IDesktopFactory desktopFactory,
|
||||||
IExplorerShell explorerShell,
|
IExplorerShell explorerShell,
|
||||||
ILogger logger,
|
ILogger logger,
|
||||||
IProcessFactory processFactory)
|
IProcessFactory processFactory,
|
||||||
|
SessionContext sessionContext) : base(sessionContext)
|
||||||
{
|
{
|
||||||
this.configuration = configuration;
|
|
||||||
this.desktopFactory = desktopFactory;
|
this.desktopFactory = desktopFactory;
|
||||||
this.explorerShell = explorerShell;
|
this.explorerShell = explorerShell;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.processFactory = processFactory;
|
this.processFactory = processFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual OperationResult Perform()
|
public override OperationResult Perform()
|
||||||
{
|
{
|
||||||
kioskMode = configuration.CurrentSettings.KioskMode;
|
logger.Info($"Initializing kiosk mode '{Context.Next.Settings.KioskMode}'...");
|
||||||
|
|
||||||
logger.Info($"Initializing kiosk mode '{kioskMode}'...");
|
|
||||||
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeKioskMode);
|
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeKioskMode);
|
||||||
|
|
||||||
switch (kioskMode)
|
switch (Context.Next.Settings.KioskMode)
|
||||||
{
|
{
|
||||||
case KioskMode.CreateNewDesktop:
|
case KioskMode.CreateNewDesktop:
|
||||||
CreateNewDesktop();
|
CreateNewDesktop();
|
||||||
|
@ -71,17 +58,18 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ActiveMode = Context.Next.Settings.KioskMode;
|
||||||
|
|
||||||
return OperationResult.Success;
|
return OperationResult.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual OperationResult Repeat()
|
public override OperationResult Repeat()
|
||||||
{
|
{
|
||||||
var oldMode = kioskMode;
|
var newMode = Context.Next.Settings.KioskMode;
|
||||||
var newMode = configuration.CurrentSettings.KioskMode;
|
|
||||||
|
|
||||||
if (newMode == oldMode)
|
if (ActiveMode == newMode)
|
||||||
{
|
{
|
||||||
logger.Info($"New kiosk mode '{newMode}' is equal to the currently active '{oldMode}', skipping re-initialization...");
|
logger.Info($"New kiosk mode '{newMode}' is already active, skipping initialization...");
|
||||||
|
|
||||||
return OperationResult.Success;
|
return OperationResult.Success;
|
||||||
}
|
}
|
||||||
|
@ -89,12 +77,12 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
return Perform();
|
return Perform();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual OperationResult Revert()
|
public override OperationResult Revert()
|
||||||
{
|
{
|
||||||
logger.Info($"Reverting kiosk mode '{kioskMode}'...");
|
logger.Info($"Reverting kiosk mode '{ActiveMode}'...");
|
||||||
StatusChanged?.Invoke(TextKey.OperationStatus_RevertKioskMode);
|
StatusChanged?.Invoke(TextKey.OperationStatus_RevertKioskMode);
|
||||||
|
|
||||||
switch (kioskMode)
|
switch (ActiveMode)
|
||||||
{
|
{
|
||||||
case KioskMode.CreateNewDesktop:
|
case KioskMode.CreateNewDesktop:
|
||||||
CloseNewDesktop();
|
CloseNewDesktop();
|
||||||
|
@ -109,14 +97,14 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
|
|
||||||
private void CreateNewDesktop()
|
private void CreateNewDesktop()
|
||||||
{
|
{
|
||||||
OriginalDesktop = desktopFactory.GetCurrent();
|
originalDesktop = desktopFactory.GetCurrent();
|
||||||
logger.Info($"Current desktop is {OriginalDesktop}.");
|
logger.Info($"Current desktop is {originalDesktop}.");
|
||||||
|
|
||||||
NewDesktop = desktopFactory.CreateNew(nameof(SafeExamBrowser));
|
newDesktop = desktopFactory.CreateNew(nameof(SafeExamBrowser));
|
||||||
logger.Info($"Created new desktop {NewDesktop}.");
|
logger.Info($"Created new desktop {newDesktop}.");
|
||||||
|
|
||||||
NewDesktop.Activate();
|
newDesktop.Activate();
|
||||||
processFactory.StartupDesktop = NewDesktop;
|
processFactory.StartupDesktop = newDesktop;
|
||||||
logger.Info("Successfully activated new desktop.");
|
logger.Info("Successfully activated new desktop.");
|
||||||
|
|
||||||
explorerShell.Suspend();
|
explorerShell.Suspend();
|
||||||
|
@ -124,21 +112,21 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
|
|
||||||
private void CloseNewDesktop()
|
private void CloseNewDesktop()
|
||||||
{
|
{
|
||||||
if (OriginalDesktop != null)
|
if (originalDesktop != null)
|
||||||
{
|
{
|
||||||
OriginalDesktop.Activate();
|
originalDesktop.Activate();
|
||||||
processFactory.StartupDesktop = OriginalDesktop;
|
processFactory.StartupDesktop = originalDesktop;
|
||||||
logger.Info($"Switched back to original desktop {OriginalDesktop}.");
|
logger.Info($"Switched back to original desktop {originalDesktop}.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger.Warn($"No original desktop found when attempting to close new desktop!");
|
logger.Warn($"No original desktop found when attempting to close new desktop!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NewDesktop != null)
|
if (newDesktop != null)
|
||||||
{
|
{
|
||||||
NewDesktop.Close();
|
newDesktop.Close();
|
||||||
logger.Info($"Closed new desktop {NewDesktop}.");
|
logger.Info($"Closed new desktop {newDesktop}.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -151,6 +139,9 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
private void TerminateExplorerShell()
|
private void TerminateExplorerShell()
|
||||||
{
|
{
|
||||||
StatusChanged?.Invoke(TextKey.OperationStatus_WaitExplorerTermination);
|
StatusChanged?.Invoke(TextKey.OperationStatus_WaitExplorerTermination);
|
||||||
|
|
||||||
|
// TODO: Hiding all windows must be done here, as the explorer shell is needed to do so!
|
||||||
|
|
||||||
explorerShell.Terminate();
|
explorerShell.Terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,6 +149,8 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
{
|
{
|
||||||
StatusChanged?.Invoke(TextKey.OperationStatus_WaitExplorerStartup);
|
StatusChanged?.Invoke(TextKey.OperationStatus_WaitExplorerStartup);
|
||||||
explorerShell.Start();
|
explorerShell.Start();
|
||||||
|
|
||||||
|
// TODO: Restore all hidden windows!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +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 SafeExamBrowser.Contracts.Configuration;
|
|
||||||
using SafeExamBrowser.Contracts.Configuration.Settings;
|
|
||||||
using SafeExamBrowser.Contracts.Core.OperationModel;
|
using SafeExamBrowser.Contracts.Core.OperationModel;
|
||||||
using SafeExamBrowser.Contracts.Logging;
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
using SafeExamBrowser.Contracts.WindowsApi;
|
using SafeExamBrowser.Contracts.WindowsApi;
|
||||||
|
@ -16,36 +14,27 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
{
|
{
|
||||||
internal class KioskModeTerminationOperation : KioskModeOperation, IRepeatableOperation
|
internal class KioskModeTerminationOperation : KioskModeOperation, IRepeatableOperation
|
||||||
{
|
{
|
||||||
private IConfigurationRepository configuration;
|
|
||||||
private KioskMode kioskMode;
|
|
||||||
private ILogger logger;
|
|
||||||
|
|
||||||
public KioskModeTerminationOperation(
|
public KioskModeTerminationOperation(
|
||||||
IConfigurationRepository configuration,
|
|
||||||
IDesktopFactory desktopFactory,
|
IDesktopFactory desktopFactory,
|
||||||
IExplorerShell explorerShell,
|
IExplorerShell explorerShell,
|
||||||
ILogger logger,
|
ILogger logger,
|
||||||
IProcessFactory processFactory) : base(configuration, desktopFactory, explorerShell, logger, processFactory)
|
IProcessFactory processFactory,
|
||||||
|
SessionContext sessionContext) : base(desktopFactory, explorerShell, logger, processFactory, sessionContext)
|
||||||
{
|
{
|
||||||
this.configuration = configuration;
|
|
||||||
this.logger = logger;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override OperationResult Perform()
|
public override OperationResult Perform()
|
||||||
{
|
{
|
||||||
kioskMode = configuration.CurrentSettings.KioskMode;
|
|
||||||
|
|
||||||
return OperationResult.Success;
|
return OperationResult.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override OperationResult Repeat()
|
public override OperationResult Repeat()
|
||||||
{
|
{
|
||||||
var oldMode = kioskMode;
|
var newMode = Context.Next.Settings.KioskMode;
|
||||||
var newMode = configuration.CurrentSettings.KioskMode;
|
|
||||||
|
|
||||||
if (newMode == oldMode)
|
if (ActiveMode == newMode)
|
||||||
{
|
{
|
||||||
logger.Info($"New kiosk mode '{newMode}' is equal to the currently active '{oldMode}', skipping termination...");
|
logger.Info($"New kiosk mode '{newMode}' is the same as the currently active, skipping termination...");
|
||||||
|
|
||||||
return OperationResult.Success;
|
return OperationResult.Success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using SafeExamBrowser.Contracts.Communication.Proxies;
|
using SafeExamBrowser.Contracts.Communication.Proxies;
|
||||||
using SafeExamBrowser.Contracts.Configuration;
|
|
||||||
using SafeExamBrowser.Contracts.Configuration.Settings;
|
using SafeExamBrowser.Contracts.Configuration.Settings;
|
||||||
using SafeExamBrowser.Contracts.Core.OperationModel;
|
using SafeExamBrowser.Contracts.Core.OperationModel;
|
||||||
using SafeExamBrowser.Contracts.Core.OperationModel.Events;
|
using SafeExamBrowser.Contracts.Core.OperationModel.Events;
|
||||||
|
@ -16,29 +15,27 @@ using SafeExamBrowser.Contracts.Logging;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Runtime.Operations
|
namespace SafeExamBrowser.Runtime.Operations
|
||||||
{
|
{
|
||||||
internal class ServiceOperation : IRepeatableOperation
|
internal class ServiceOperation : SessionOperation
|
||||||
{
|
{
|
||||||
private bool connected, mandatory;
|
private bool connected, mandatory;
|
||||||
private IConfigurationRepository configuration;
|
|
||||||
private ILogger logger;
|
private ILogger logger;
|
||||||
private IServiceProxy service;
|
private IServiceProxy service;
|
||||||
|
|
||||||
public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
|
public override event ActionRequiredEventHandler ActionRequired { add { } remove { } }
|
||||||
public event StatusChangedEventHandler StatusChanged;
|
public override event StatusChangedEventHandler StatusChanged;
|
||||||
|
|
||||||
public ServiceOperation(IConfigurationRepository configuration, ILogger logger, IServiceProxy service)
|
public ServiceOperation(ILogger logger, IServiceProxy service, SessionContext sessionContext) : base(sessionContext)
|
||||||
{
|
{
|
||||||
this.configuration = configuration;
|
|
||||||
this.service = service;
|
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
|
this.service = service;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OperationResult Perform()
|
public override OperationResult Perform()
|
||||||
{
|
{
|
||||||
logger.Info($"Initializing service session...");
|
logger.Info($"Initializing service session...");
|
||||||
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeServiceSession);
|
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeServiceSession);
|
||||||
|
|
||||||
mandatory = configuration.CurrentSettings.ServicePolicy == ServicePolicy.Mandatory;
|
mandatory = Context.Next.Settings.ServicePolicy == ServicePolicy.Mandatory;
|
||||||
connected = service.Connect();
|
connected = service.Connect();
|
||||||
|
|
||||||
if (mandatory && !connected)
|
if (mandatory && !connected)
|
||||||
|
@ -59,7 +56,7 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
return OperationResult.Success;
|
return OperationResult.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OperationResult Repeat()
|
public override OperationResult Repeat()
|
||||||
{
|
{
|
||||||
var result = Revert();
|
var result = Revert();
|
||||||
|
|
||||||
|
@ -71,7 +68,7 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
return Perform();
|
return Perform();
|
||||||
}
|
}
|
||||||
|
|
||||||
public OperationResult Revert()
|
public override OperationResult Revert()
|
||||||
{
|
{
|
||||||
logger.Info("Finalizing service session...");
|
logger.Info("Finalizing service session...");
|
||||||
StatusChanged?.Invoke(TextKey.OperationStatus_FinalizeServiceSession);
|
StatusChanged?.Invoke(TextKey.OperationStatus_FinalizeServiceSession);
|
||||||
|
@ -97,12 +94,12 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
|
|
||||||
private void StartServiceSession()
|
private void StartServiceSession()
|
||||||
{
|
{
|
||||||
service.StartSession(configuration.CurrentSession.Id, configuration.CurrentSettings);
|
service.StartSession(Context.Next.Id, Context.Next.Settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StopServiceSession()
|
private void StopServiceSession()
|
||||||
{
|
{
|
||||||
service.StopSession(configuration.CurrentSession.Id);
|
service.StopSession(Context.Current.Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using SafeExamBrowser.Contracts.Core.OperationModel;
|
||||||
|
using SafeExamBrowser.Contracts.Core.OperationModel.Events;
|
||||||
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Runtime.Operations
|
||||||
|
{
|
||||||
|
internal class SessionActivationOperation : SessionOperation
|
||||||
|
{
|
||||||
|
private ILogger logger;
|
||||||
|
|
||||||
|
public override event ActionRequiredEventHandler ActionRequired { add { } remove { } }
|
||||||
|
public override event StatusChangedEventHandler StatusChanged { add { } remove { } }
|
||||||
|
|
||||||
|
public SessionActivationOperation(ILogger logger, SessionContext sessionContext) : base(sessionContext)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override OperationResult Perform()
|
||||||
|
{
|
||||||
|
ActivateNewSession();
|
||||||
|
|
||||||
|
return OperationResult.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override OperationResult Repeat()
|
||||||
|
{
|
||||||
|
ActivateNewSession();
|
||||||
|
|
||||||
|
return OperationResult.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override OperationResult Revert()
|
||||||
|
{
|
||||||
|
return OperationResult.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ActivateNewSession()
|
||||||
|
{
|
||||||
|
var isFirstSession = Context.Current == null;
|
||||||
|
|
||||||
|
if (isFirstSession)
|
||||||
|
{
|
||||||
|
logger.Info($"Successfully activated first session '{Context.Next.Id}'.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.Info($"Successfully terminated old session '{Context.Current.Id}' and activated new session '{Context.Next.Id}'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Context.Current = Context.Next;
|
||||||
|
Context.Next = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,35 +15,41 @@ using SafeExamBrowser.Contracts.Logging;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Runtime.Operations
|
namespace SafeExamBrowser.Runtime.Operations
|
||||||
{
|
{
|
||||||
internal class SessionInitializationOperation : IRepeatableOperation
|
internal class SessionInitializationOperation : SessionOperation
|
||||||
{
|
{
|
||||||
private IConfigurationRepository configuration;
|
private IConfigurationRepository configuration;
|
||||||
private ILogger logger;
|
private ILogger logger;
|
||||||
private IRuntimeHost runtimeHost;
|
private IRuntimeHost runtimeHost;
|
||||||
|
|
||||||
public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
|
public override event ActionRequiredEventHandler ActionRequired { add { } remove { } }
|
||||||
public event StatusChangedEventHandler StatusChanged;
|
public override event StatusChangedEventHandler StatusChanged;
|
||||||
|
|
||||||
public SessionInitializationOperation(IConfigurationRepository configuration, ILogger logger, IRuntimeHost runtimeHost)
|
public SessionInitializationOperation(
|
||||||
|
IConfigurationRepository configuration,
|
||||||
|
ILogger logger,
|
||||||
|
IRuntimeHost runtimeHost,
|
||||||
|
SessionContext sessionContext) : base(sessionContext)
|
||||||
{
|
{
|
||||||
this.configuration = configuration;
|
this.configuration = configuration;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.runtimeHost = runtimeHost;
|
this.runtimeHost = runtimeHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OperationResult Perform()
|
public override OperationResult Perform()
|
||||||
{
|
{
|
||||||
InitializeSessionConfiguration();
|
InitializeSessionConfiguration();
|
||||||
|
|
||||||
return OperationResult.Success;
|
return OperationResult.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OperationResult Repeat()
|
public override OperationResult Repeat()
|
||||||
{
|
{
|
||||||
return Perform();
|
InitializeSessionConfiguration();
|
||||||
|
|
||||||
|
return OperationResult.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OperationResult Revert()
|
public override OperationResult Revert()
|
||||||
{
|
{
|
||||||
return OperationResult.Success;
|
return OperationResult.Success;
|
||||||
}
|
}
|
||||||
|
@ -53,12 +59,12 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
logger.Info("Initializing new session configuration...");
|
logger.Info("Initializing new session configuration...");
|
||||||
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeSession);
|
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeSession);
|
||||||
|
|
||||||
configuration.InitializeSessionConfiguration();
|
Context.Next = configuration.InitializeSessionConfiguration();
|
||||||
runtimeHost.StartupToken = configuration.CurrentSession.StartupToken;
|
runtimeHost.StartupToken = Context.Next.StartupToken;
|
||||||
|
|
||||||
logger.Info($" -> Client-ID: {configuration.AppConfig.ClientId}");
|
logger.Info($" -> Client-ID: {Context.Next.AppConfig.ClientId}");
|
||||||
logger.Info($" -> Runtime-ID: {configuration.AppConfig.RuntimeId}");
|
logger.Info($" -> Runtime-ID: {Context.Next.AppConfig.RuntimeId}");
|
||||||
logger.Info($" -> Session-ID: {configuration.CurrentSession.Id}");
|
logger.Info($" -> Session-ID: {Context.Next.Id}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
25
SafeExamBrowser.Runtime/Operations/SessionOperation.cs
Normal file
25
SafeExamBrowser.Runtime/Operations/SessionOperation.cs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
using SafeExamBrowser.Contracts.Core.OperationModel;
|
||||||
|
using SafeExamBrowser.Contracts.Core.OperationModel.Events;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Runtime.Operations
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The base implementation to be used for all operations in the session operation sequence.
|
||||||
|
/// </summary>
|
||||||
|
internal abstract class SessionOperation : IRepeatableOperation
|
||||||
|
{
|
||||||
|
protected SessionContext Context { get; private set; }
|
||||||
|
|
||||||
|
public abstract event ActionRequiredEventHandler ActionRequired;
|
||||||
|
public abstract event StatusChangedEventHandler StatusChanged;
|
||||||
|
|
||||||
|
public SessionOperation(SessionContext sessionContext)
|
||||||
|
{
|
||||||
|
Context = sessionContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract OperationResult Perform();
|
||||||
|
public abstract OperationResult Repeat();
|
||||||
|
public abstract OperationResult Revert();
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,10 +28,7 @@ namespace SafeExamBrowser.Runtime
|
||||||
{
|
{
|
||||||
internal class RuntimeController : IRuntimeController
|
internal class RuntimeController : IRuntimeController
|
||||||
{
|
{
|
||||||
private bool sessionRunning;
|
|
||||||
|
|
||||||
private AppConfig appConfig;
|
private AppConfig appConfig;
|
||||||
private IConfigurationRepository configuration;
|
|
||||||
private ILogger logger;
|
private ILogger logger;
|
||||||
private IMessageBox messageBox;
|
private IMessageBox messageBox;
|
||||||
private IOperationSequence bootstrapSequence;
|
private IOperationSequence bootstrapSequence;
|
||||||
|
@ -39,32 +36,43 @@ namespace SafeExamBrowser.Runtime
|
||||||
private IRuntimeHost runtimeHost;
|
private IRuntimeHost runtimeHost;
|
||||||
private IRuntimeWindow runtimeWindow;
|
private IRuntimeWindow runtimeWindow;
|
||||||
private IServiceProxy service;
|
private IServiceProxy service;
|
||||||
|
private SessionContext sessionContext;
|
||||||
private ISplashScreen splashScreen;
|
private ISplashScreen splashScreen;
|
||||||
private Action shutdown;
|
private Action shutdown;
|
||||||
private IText text;
|
private IText text;
|
||||||
private IUserInterfaceFactory uiFactory;
|
private IUserInterfaceFactory uiFactory;
|
||||||
|
|
||||||
|
private ISessionConfiguration Session
|
||||||
|
{
|
||||||
|
get { return sessionContext.Current; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool SessionIsRunning
|
||||||
|
{
|
||||||
|
get { return Session != null; }
|
||||||
|
}
|
||||||
|
|
||||||
public RuntimeController(
|
public RuntimeController(
|
||||||
AppConfig appConfig,
|
AppConfig appConfig,
|
||||||
IConfigurationRepository configuration,
|
|
||||||
ILogger logger,
|
ILogger logger,
|
||||||
IMessageBox messageBox,
|
IMessageBox messageBox,
|
||||||
IOperationSequence bootstrapSequence,
|
IOperationSequence bootstrapSequence,
|
||||||
IRepeatableOperationSequence sessionSequence,
|
IRepeatableOperationSequence sessionSequence,
|
||||||
IRuntimeHost runtimeHost,
|
IRuntimeHost runtimeHost,
|
||||||
IServiceProxy service,
|
IServiceProxy service,
|
||||||
|
SessionContext sessionContext,
|
||||||
Action shutdown,
|
Action shutdown,
|
||||||
IText text,
|
IText text,
|
||||||
IUserInterfaceFactory uiFactory)
|
IUserInterfaceFactory uiFactory)
|
||||||
{
|
{
|
||||||
this.appConfig = appConfig;
|
this.appConfig = appConfig;
|
||||||
this.configuration = configuration;
|
|
||||||
this.bootstrapSequence = bootstrapSequence;
|
this.bootstrapSequence = bootstrapSequence;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.messageBox = messageBox;
|
this.messageBox = messageBox;
|
||||||
this.runtimeHost = runtimeHost;
|
this.runtimeHost = runtimeHost;
|
||||||
this.sessionSequence = sessionSequence;
|
this.sessionSequence = sessionSequence;
|
||||||
this.service = service;
|
this.service = service;
|
||||||
|
this.sessionContext = sessionContext;
|
||||||
this.shutdown = shutdown;
|
this.shutdown = shutdown;
|
||||||
this.text = text;
|
this.text = text;
|
||||||
this.uiFactory = uiFactory;
|
this.uiFactory = uiFactory;
|
||||||
|
@ -96,7 +104,7 @@ namespace SafeExamBrowser.Runtime
|
||||||
logger.Subscribe(runtimeWindow);
|
logger.Subscribe(runtimeWindow);
|
||||||
splashScreen.Close();
|
splashScreen.Close();
|
||||||
|
|
||||||
StartSession(true);
|
StartSession();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -106,14 +114,14 @@ namespace SafeExamBrowser.Runtime
|
||||||
messageBox.Show(TextKey.MessageBox_StartupError, TextKey.MessageBox_StartupErrorTitle, icon: MessageBoxIcon.Error, parent: splashScreen);
|
messageBox.Show(TextKey.MessageBox_StartupError, TextKey.MessageBox_StartupErrorTitle, icon: MessageBoxIcon.Error, parent: splashScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
return initialized && sessionRunning;
|
return initialized && SessionIsRunning;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Terminate()
|
public void Terminate()
|
||||||
{
|
{
|
||||||
DeregisterEvents();
|
DeregisterEvents();
|
||||||
|
|
||||||
if (sessionRunning)
|
if (SessionIsRunning)
|
||||||
{
|
{
|
||||||
StopSession();
|
StopSession();
|
||||||
}
|
}
|
||||||
|
@ -145,51 +153,79 @@ namespace SafeExamBrowser.Runtime
|
||||||
splashScreen.Close();
|
splashScreen.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StartSession(bool initial = false)
|
private void StartSession()
|
||||||
{
|
{
|
||||||
runtimeWindow.Show();
|
runtimeWindow.Show();
|
||||||
runtimeWindow.BringToForeground();
|
runtimeWindow.BringToForeground();
|
||||||
runtimeWindow.ShowProgressBar();
|
runtimeWindow.ShowProgressBar();
|
||||||
logger.Info("### --- Session Start Procedure --- ###");
|
logger.Info("### --- Session Start Procedure --- ###");
|
||||||
|
|
||||||
if (sessionRunning)
|
if (SessionIsRunning)
|
||||||
{
|
{
|
||||||
DeregisterSessionEvents();
|
DeregisterSessionEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = initial ? sessionSequence.TryPerform() : sessionSequence.TryRepeat();
|
var result = SessionIsRunning ? sessionSequence.TryRepeat() : sessionSequence.TryPerform();
|
||||||
|
|
||||||
if (result == OperationResult.Success)
|
if (result == OperationResult.Success)
|
||||||
{
|
{
|
||||||
RegisterSessionEvents();
|
|
||||||
|
|
||||||
logger.Info("### --- Session Running --- ###");
|
logger.Info("### --- Session Running --- ###");
|
||||||
|
|
||||||
|
HandleSessionStartSuccess();
|
||||||
|
}
|
||||||
|
else if (result == OperationResult.Failed)
|
||||||
|
{
|
||||||
|
logger.Info("### --- Session Start Failed --- ###");
|
||||||
|
|
||||||
|
HandleSessionStartFailure();
|
||||||
|
}
|
||||||
|
else if (result == OperationResult.Aborted)
|
||||||
|
{
|
||||||
|
logger.Info("### --- Session Start Aborted --- ###");
|
||||||
|
|
||||||
|
HandleSessionStartAbortion();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleSessionStartSuccess()
|
||||||
|
{
|
||||||
|
RegisterSessionEvents();
|
||||||
|
|
||||||
|
runtimeWindow.HideProgressBar();
|
||||||
|
runtimeWindow.UpdateStatus(TextKey.RuntimeWindow_ApplicationRunning);
|
||||||
|
runtimeWindow.TopMost = Session.Settings.KioskMode != KioskMode.None;
|
||||||
|
|
||||||
|
if (Session.Settings.KioskMode == KioskMode.DisableExplorerShell)
|
||||||
|
{
|
||||||
|
runtimeWindow.Hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleSessionStartFailure()
|
||||||
|
{
|
||||||
|
if (SessionIsRunning)
|
||||||
|
{
|
||||||
|
StopSession();
|
||||||
|
|
||||||
|
messageBox.Show(TextKey.MessageBox_SessionStartError, TextKey.MessageBox_SessionStartErrorTitle, icon: MessageBoxIcon.Error, parent: runtimeWindow);
|
||||||
|
logger.Info("Terminating application...");
|
||||||
|
|
||||||
|
shutdown.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleSessionStartAbortion()
|
||||||
|
{
|
||||||
|
if (SessionIsRunning)
|
||||||
|
{
|
||||||
runtimeWindow.HideProgressBar();
|
runtimeWindow.HideProgressBar();
|
||||||
runtimeWindow.UpdateStatus(TextKey.RuntimeWindow_ApplicationRunning);
|
runtimeWindow.UpdateStatus(TextKey.RuntimeWindow_ApplicationRunning);
|
||||||
runtimeWindow.TopMost = configuration.CurrentSettings.KioskMode != KioskMode.None;
|
runtimeWindow.TopMost = Session.Settings.KioskMode != KioskMode.None;
|
||||||
|
|
||||||
if (configuration.CurrentSettings.KioskMode == KioskMode.DisableExplorerShell)
|
if (Session.Settings.KioskMode == KioskMode.DisableExplorerShell)
|
||||||
{
|
{
|
||||||
runtimeWindow.Hide();
|
runtimeWindow.Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionRunning = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
logger.Info($"### --- Session Start {(result == OperationResult.Aborted ? "Aborted" : "Failed")} --- ###");
|
|
||||||
|
|
||||||
if (result == OperationResult.Failed)
|
|
||||||
{
|
|
||||||
// TODO: Find solution for this; maybe manually switch back to original desktop?
|
|
||||||
// messageBox.Show(TextKey.MessageBox_SessionStartError, TextKey.MessageBox_SessionStartErrorTitle, icon: MessageBoxIcon.Error, parent: runtimeWindow);
|
|
||||||
|
|
||||||
if (!initial)
|
|
||||||
{
|
|
||||||
logger.Info("Terminating application...");
|
|
||||||
shutdown.Invoke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,7 +243,6 @@ namespace SafeExamBrowser.Runtime
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
logger.Info("### --- Session Terminated --- ###");
|
logger.Info("### --- Session Terminated --- ###");
|
||||||
sessionRunning = false;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -218,32 +253,34 @@ namespace SafeExamBrowser.Runtime
|
||||||
|
|
||||||
private void RegisterEvents()
|
private void RegisterEvents()
|
||||||
{
|
{
|
||||||
|
runtimeHost.ClientConfigurationNeeded += RuntimeHost_ClientConfigurationNeeded;
|
||||||
runtimeHost.ReconfigurationRequested += RuntimeHost_ReconfigurationRequested;
|
runtimeHost.ReconfigurationRequested += RuntimeHost_ReconfigurationRequested;
|
||||||
runtimeHost.ShutdownRequested += RuntimeHost_ShutdownRequested;
|
runtimeHost.ShutdownRequested += RuntimeHost_ShutdownRequested;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DeregisterEvents()
|
private void DeregisterEvents()
|
||||||
{
|
{
|
||||||
|
runtimeHost.ClientConfigurationNeeded -= RuntimeHost_ClientConfigurationNeeded;
|
||||||
runtimeHost.ReconfigurationRequested -= RuntimeHost_ReconfigurationRequested;
|
runtimeHost.ReconfigurationRequested -= RuntimeHost_ReconfigurationRequested;
|
||||||
runtimeHost.ShutdownRequested -= RuntimeHost_ShutdownRequested;
|
runtimeHost.ShutdownRequested -= RuntimeHost_ShutdownRequested;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RegisterSessionEvents()
|
private void RegisterSessionEvents()
|
||||||
{
|
{
|
||||||
configuration.CurrentSession.ClientProcess.Terminated += ClientProcess_Terminated;
|
sessionContext.ClientProcess.Terminated += ClientProcess_Terminated;
|
||||||
configuration.CurrentSession.ClientProxy.ConnectionLost += Client_ConnectionLost;
|
sessionContext.ClientProxy.ConnectionLost += Client_ConnectionLost;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DeregisterSessionEvents()
|
private void DeregisterSessionEvents()
|
||||||
{
|
{
|
||||||
if (configuration.CurrentSession.ClientProcess != null)
|
if (sessionContext.ClientProcess != null)
|
||||||
{
|
{
|
||||||
configuration.CurrentSession.ClientProcess.Terminated -= ClientProcess_Terminated;
|
sessionContext.ClientProcess.Terminated -= ClientProcess_Terminated;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (configuration.CurrentSession.ClientProxy != null)
|
if (sessionContext.ClientProxy != null)
|
||||||
{
|
{
|
||||||
configuration.CurrentSession.ClientProxy.ConnectionLost -= Client_ConnectionLost;
|
sessionContext.ClientProxy.ConnectionLost -= Client_ConnectionLost;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,7 +298,7 @@ namespace SafeExamBrowser.Runtime
|
||||||
{
|
{
|
||||||
logger.Error($"Client application has unexpectedly terminated with exit code {exitCode}!");
|
logger.Error($"Client application has unexpectedly terminated with exit code {exitCode}!");
|
||||||
|
|
||||||
if (sessionRunning)
|
if (SessionIsRunning)
|
||||||
{
|
{
|
||||||
StopSession();
|
StopSession();
|
||||||
}
|
}
|
||||||
|
@ -275,7 +312,7 @@ namespace SafeExamBrowser.Runtime
|
||||||
{
|
{
|
||||||
logger.Error("Lost connection to the client application!");
|
logger.Error("Lost connection to the client application!");
|
||||||
|
|
||||||
if (sessionRunning)
|
if (SessionIsRunning)
|
||||||
{
|
{
|
||||||
StopSession();
|
StopSession();
|
||||||
}
|
}
|
||||||
|
@ -285,21 +322,31 @@ namespace SafeExamBrowser.Runtime
|
||||||
shutdown.Invoke();
|
shutdown.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void RuntimeHost_ClientConfigurationNeeded(ClientConfigurationEventArgs args)
|
||||||
|
{
|
||||||
|
args.ClientConfiguration = new ClientConfiguration
|
||||||
|
{
|
||||||
|
AppConfig = sessionContext.Next.AppConfig,
|
||||||
|
SessionId = sessionContext.Next.Id,
|
||||||
|
Settings = sessionContext.Next.Settings
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private void RuntimeHost_ReconfigurationRequested(ReconfigurationEventArgs args)
|
private void RuntimeHost_ReconfigurationRequested(ReconfigurationEventArgs args)
|
||||||
{
|
{
|
||||||
var mode = configuration.CurrentSettings.ConfigurationMode;
|
var mode = Session.Settings.ConfigurationMode;
|
||||||
|
|
||||||
if (mode == ConfigurationMode.ConfigureClient)
|
if (mode == ConfigurationMode.ConfigureClient)
|
||||||
{
|
{
|
||||||
logger.Info($"Accepted request for reconfiguration with '{args.ConfigurationPath}'.");
|
logger.Info($"Accepted request for reconfiguration with '{args.ConfigurationPath}'.");
|
||||||
configuration.ReconfigurationFilePath = args.ConfigurationPath;
|
sessionContext.ReconfigurationFilePath = args.ConfigurationPath;
|
||||||
|
|
||||||
StartSession();
|
StartSession();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger.Info($"Denied request for reconfiguration with '{args.ConfigurationPath}' due to '{mode}' mode!");
|
logger.Info($"Denied request for reconfiguration with '{args.ConfigurationPath}' due to '{mode}' mode!");
|
||||||
configuration.CurrentSession.ClientProxy.InformReconfigurationDenied(args.ConfigurationPath);
|
sessionContext.ClientProxy.InformReconfigurationDenied(args.ConfigurationPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,8 +380,8 @@ namespace SafeExamBrowser.Runtime
|
||||||
|
|
||||||
private void AskForPassword(PasswordRequiredEventArgs args)
|
private void AskForPassword(PasswordRequiredEventArgs args)
|
||||||
{
|
{
|
||||||
var isStartup = configuration.CurrentSession == null;
|
var isStartup = !SessionIsRunning;
|
||||||
var isRunningOnDefaultDesktop = configuration.CurrentSettings?.KioskMode == KioskMode.DisableExplorerShell;
|
var isRunningOnDefaultDesktop = SessionIsRunning && Session.Settings.KioskMode == KioskMode.DisableExplorerShell;
|
||||||
|
|
||||||
if (isStartup || isRunningOnDefaultDesktop)
|
if (isStartup || isRunningOnDefaultDesktop)
|
||||||
{
|
{
|
||||||
|
@ -374,7 +421,7 @@ namespace SafeExamBrowser.Runtime
|
||||||
|
|
||||||
runtimeHost.PasswordReceived += responseEventHandler;
|
runtimeHost.PasswordReceived += responseEventHandler;
|
||||||
|
|
||||||
var communication = configuration.CurrentSession.ClientProxy.RequestPassword(args.Purpose, requestId);
|
var communication = sessionContext.ClientProxy.RequestPassword(args.Purpose, requestId);
|
||||||
|
|
||||||
if (communication.Success)
|
if (communication.Success)
|
||||||
{
|
{
|
||||||
|
@ -401,6 +448,9 @@ namespace SafeExamBrowser.Runtime
|
||||||
runtimeWindow?.UpdateStatus(status, true);
|
runtimeWindow?.UpdateStatus(status, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TODO: Move to utility in core library and use in client controller!
|
||||||
|
/// </summary>
|
||||||
private void MapProgress(IProgressIndicator progressIndicator, ProgressChangedEventArgs args)
|
private void MapProgress(IProgressIndicator progressIndicator, ProgressChangedEventArgs args)
|
||||||
{
|
{
|
||||||
if (args.CurrentValue.HasValue)
|
if (args.CurrentValue.HasValue)
|
||||||
|
|
|
@ -94,6 +94,8 @@
|
||||||
<Compile Include="Operations\KioskModeOperation.cs" />
|
<Compile Include="Operations\KioskModeOperation.cs" />
|
||||||
<Compile Include="Operations\KioskModeTerminationOperation.cs" />
|
<Compile Include="Operations\KioskModeTerminationOperation.cs" />
|
||||||
<Compile Include="Operations\ServiceOperation.cs" />
|
<Compile Include="Operations\ServiceOperation.cs" />
|
||||||
|
<Compile Include="Operations\SessionActivationOperation.cs" />
|
||||||
|
<Compile Include="Operations\SessionOperation.cs" />
|
||||||
<Compile Include="Operations\SessionInitializationOperation.cs" />
|
<Compile Include="Operations\SessionInitializationOperation.cs" />
|
||||||
<Compile Include="Communication\ProxyFactory.cs" />
|
<Compile Include="Communication\ProxyFactory.cs" />
|
||||||
<Compile Include="Communication\RuntimeHost.cs" />
|
<Compile Include="Communication\RuntimeHost.cs" />
|
||||||
|
@ -112,6 +114,7 @@
|
||||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="RuntimeController.cs" />
|
<Compile Include="RuntimeController.cs" />
|
||||||
|
<Compile Include="SessionContext.cs" />
|
||||||
<EmbeddedResource Include="Properties\Resources.resx">
|
<EmbeddedResource Include="Properties\Resources.resx">
|
||||||
<Generator>ResXFileCodeGenerator</Generator>
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
|
|
45
SafeExamBrowser.Runtime/SessionContext.cs
Normal file
45
SafeExamBrowser.Runtime/SessionContext.cs
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using SafeExamBrowser.Contracts.Communication.Proxies;
|
||||||
|
using SafeExamBrowser.Contracts.Configuration;
|
||||||
|
using SafeExamBrowser.Contracts.WindowsApi;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Runtime
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Holds all configuration and runtime data required for the session handling.
|
||||||
|
/// </summary>
|
||||||
|
internal class SessionContext
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The currently running client process.
|
||||||
|
/// </summary>
|
||||||
|
public IProcess ClientProcess { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The communication proxy for the currently running client process.
|
||||||
|
/// </summary>
|
||||||
|
public IClientProxy ClientProxy { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The configuration of the currently active session.
|
||||||
|
/// </summary>
|
||||||
|
public ISessionConfiguration Current { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The configuration of the next session to be activated.
|
||||||
|
/// </summary>
|
||||||
|
public ISessionConfiguration Next { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The path of the configuration file to be used for reconfiguration.
|
||||||
|
/// </summary>
|
||||||
|
public string ReconfigurationFilePath { get; set; }
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue