SEBWIN-220: Replaced guid with abstact InstanceIdentifier for application instances and started to implement logging for browser component.

This commit is contained in:
dbuechel 2018-08-31 07:49:41 +02:00
parent d521e2d3c0
commit ef31db9920
22 changed files with 159 additions and 48 deletions

View file

@ -24,6 +24,8 @@ namespace SafeExamBrowser.Browser
{
public class BrowserApplicationController : IBrowserApplicationController
{
private int instanceIdCounter = default(int);
private AppConfig appConfig;
private IApplicationButton button;
private IList<IApplicationInstance> instances;
@ -57,6 +59,8 @@ namespace SafeExamBrowser.Browser
var cefSettings = InitializeCefSettings();
var success = Cef.Initialize(cefSettings, true, null);
logger.Info("Initialized CEF.");
if (!success)
{
throw new Exception("Failed to initialize the browser engine!");
@ -75,14 +79,20 @@ namespace SafeExamBrowser.Browser
{
instance.Terminated -= Instance_Terminated;
instance.Window.Close();
logger.Info($"Terminated browser instance {instance.Id}.");
}
Cef.Shutdown();
logger.Info("Terminated CEF.");
}
private void CreateNewInstance()
{
var instance = new BrowserApplicationInstance(appConfig, settings, text, uiFactory, instances.Count == 0);
var id = new BrowserInstanceIdentifier(++instanceIdCounter);
var isMainInstance = instances.Count == 0;
var instance = new BrowserApplicationInstance(appConfig, settings, id, isMainInstance, text, uiFactory);
instance.Initialize();
instance.ConfigurationDownloadRequested += (fileName, args) => ConfigurationDownloadRequested?.Invoke(fileName, args);
@ -91,36 +101,44 @@ namespace SafeExamBrowser.Browser
button.RegisterInstance(instance);
instances.Add(instance);
instance.Window.Show();
logger.Info($"Created browser instance {instance.Id}.");
}
private CefSettings InitializeCefSettings()
{
var warning = appConfig.LogLevel == LogLevel.Warning;
var error = appConfig.LogLevel == LogLevel.Error;
var cefSettings = new CefSettings
{
CachePath = appConfig.BrowserCachePath,
LogFile = appConfig.BrowserLogFile,
// TODO: Set according to current application LogLevel, but avoid verbose!
LogSeverity = LogSeverity.Info
LogSeverity = error ? LogSeverity.Error : (warning ? LogSeverity.Warning : LogSeverity.Info)
};
logger.Debug($"CEF cache path is '{cefSettings.CachePath}'.");
logger.Debug($"CEF log file is '{cefSettings.LogFile}'.");
logger.Debug($"CEF log severity is '{cefSettings.LogSeverity}'.");
return cefSettings;
}
private void Button_OnClick(Guid? instanceId = null)
private void Button_OnClick(InstanceIdentifier id = null)
{
if (instanceId.HasValue)
{
instances.FirstOrDefault(i => i.Id == instanceId)?.Window?.BringToForeground();
}
else
if (id is null)
{
CreateNewInstance();
}
else
{
instances.FirstOrDefault(i => i.Id == id)?.Window?.BringToForeground();
}
}
private void Instance_Terminated(Guid id)
private void Instance_Terminated(InstanceIdentifier id)
{
instances.Remove(instances.FirstOrDefault(i => i.Id == id));
logger.Info($"Browser instance {id} was terminated.");
}
}
}

View file

@ -6,7 +6,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using SafeExamBrowser.Browser.Handlers;
using SafeExamBrowser.Contracts.Behaviour;
using SafeExamBrowser.Contracts.Behaviour.Events;
@ -30,7 +29,7 @@ namespace SafeExamBrowser.Browser
private IText text;
private IUserInterfaceFactory uiFactory;
public Guid Id { get; private set; }
public InstanceIdentifier Id { get; private set; }
public string Name { get; private set; }
public IWindow Window { get { return window; } }
@ -41,11 +40,13 @@ namespace SafeExamBrowser.Browser
public BrowserApplicationInstance(
AppConfig appConfig,
BrowserSettings settings,
InstanceIdentifier id,
bool isMainInstance,
IText text,
IUserInterfaceFactory uiFactory,
bool isMainInstance)
IUserInterfaceFactory uiFactory)
{
this.appConfig = appConfig;
this.Id = id;
this.isMainInstance = isMainInstance;
this.settings = settings;
this.text = text;
@ -56,7 +57,6 @@ namespace SafeExamBrowser.Browser
{
var downloadHandler = new DownloadHandler(appConfig, settings);
Id = Guid.NewGuid();
downloadHandler.ConfigurationDownloadRequested += (fileName, args) => ConfigurationDownloadRequested?.Invoke(fileName, args);
control = new BrowserControl(appConfig, settings, text);

View file

@ -0,0 +1,42 @@
/*
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using SafeExamBrowser.Contracts.Behaviour;
namespace SafeExamBrowser.Browser
{
internal class BrowserInstanceIdentifier : InstanceIdentifier
{
public int Value { get; private set; }
public BrowserInstanceIdentifier(int id)
{
Value = id;
}
public override bool Equals(object other)
{
if (other is BrowserInstanceIdentifier id)
{
return Value == id.Value;
}
return false;
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
public override string ToString()
{
return $"#{Value}";
}
}
}

View file

@ -65,6 +65,7 @@
<Compile Include="BrowserApplicationController.cs" />
<Compile Include="BrowserApplicationInfo.cs" />
<Compile Include="BrowserApplicationInstance.cs" />
<Compile Include="BrowserInstanceIdentifier.cs" />
<Compile Include="Handlers\ContextMenuHandler.cs" />
<Compile Include="BrowserControl.cs">
<SubType>Component</SubType>

View file

@ -155,7 +155,7 @@ namespace SafeExamBrowser.Client
private IOperation BuildBrowserOperation()
{
var moduleLogger = new ModuleLogger(logger, typeof(BrowserApplicationController));
var moduleLogger = new ModuleLogger(logger, "BrowserController");
var browserController = new BrowserApplicationController(configuration.AppConfig, configuration.Settings.Browser, moduleLogger, messageBox, text, uiFactory);
var browserInfo = new BrowserApplicationInfo();
var operation = new BrowserOperation(browserController, browserInfo, logger, Taskbar, uiFactory);

View file

@ -11,6 +11,7 @@ using System.IO;
using System.Reflection;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Configuration.Settings;
using SafeExamBrowser.Contracts.Logging;
namespace SafeExamBrowser.Configuration
{
@ -81,7 +82,7 @@ namespace SafeExamBrowser.Configuration
CurrentSettings = new Settings();
CurrentSettings.KioskMode = KioskMode.DisableExplorerShell;
CurrentSettings.KioskMode = KioskMode.None;
CurrentSettings.ServicePolicy = ServicePolicy.Optional;
CurrentSettings.Browser.StartUrl = "https://www.safeexambrowser.org/testing";
@ -117,6 +118,7 @@ namespace SafeExamBrowser.Configuration
appConfig.ConfigurationFileExtension = ".seb";
appConfig.DefaultSettingsFileName = "SebClientSettings.seb";
appConfig.DownloadDirectory = Path.Combine(appDataFolder, "Downloads");
appConfig.LogLevel = LogLevel.Debug;
appConfig.ProgramCopyright = executable.GetCustomAttribute<AssemblyCopyrightAttribute>().Copyright;
appConfig.ProgramDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), nameof(SafeExamBrowser));
appConfig.ProgramTitle = executable.GetCustomAttribute<AssemblyTitleAttribute>().Title;

View file

@ -6,12 +6,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
namespace SafeExamBrowser.Contracts.Behaviour.Events
{
/// <summary>
/// Event handler used to indicate that an application instance with a particular ID has terminated.
/// </summary>
public delegate void InstanceTerminatedEventHandler(Guid id);
public delegate void InstanceTerminatedEventHandler(InstanceIdentifier id);
}

View file

@ -6,7 +6,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using SafeExamBrowser.Contracts.Behaviour.Events;
using SafeExamBrowser.Contracts.UserInterface.Windows;
@ -20,7 +19,7 @@ namespace SafeExamBrowser.Contracts.Behaviour
/// <summary>
/// The unique identifier for the application instance.
/// </summary>
Guid Id { get; }
InstanceIdentifier Id { get; }
/// <summary>
/// The name or (document) title of the application instance.

View file

@ -0,0 +1,41 @@
/*
* 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.Behaviour
{
/// <summary>
/// Defines an identifier which uniquely identifies an <see cref="IApplicationInstance"/> in the context of a (third-party) application.
/// </summary>
public abstract class InstanceIdentifier
{
/// <summary>
/// Determines whether two identifiers are equal (i.e. whether they identify the same <see cref="IApplicationInstance"/>).
/// </summary>
public static bool operator ==(InstanceIdentifier a, InstanceIdentifier b) => Equals(a, b);
/// <summary>
/// Determines whether two identifiers are different (i.e. whether they identify different <see cref="IApplicationInstance"/>s).
/// </summary>
public static bool operator !=(InstanceIdentifier a, InstanceIdentifier b) => !Equals(a, b);
/// <summary>
/// Indicates whether the given object is an <see cref="InstanceIdentifier"/> for the same <see cref="IApplicationInstance"/>.
/// </summary>
public abstract override bool Equals(object other);
/// <summary>
/// Returns a hash code for the identifier.
/// </summary>
public abstract override int GetHashCode();
/// <summary>
/// Returns a human-readable string representation of the identifier.
/// </summary>
public abstract override string ToString();
}
}

View file

@ -7,6 +7,7 @@
*/
using System;
using SafeExamBrowser.Contracts.Logging;
namespace SafeExamBrowser.Contracts.Configuration
{
@ -71,6 +72,11 @@ namespace SafeExamBrowser.Contracts.Configuration
/// </summary>
public string DownloadDirectory { get; set; }
/// <summary>
/// The currently active, global log severity threshold.
/// </summary>
public LogLevel LogLevel { get; set; }
/// <summary>
/// The copyright information for the application (i.e. the executing assembly).
/// </summary>

View file

@ -17,32 +17,32 @@ namespace SafeExamBrowser.Contracts.Logging
public interface ILogger
{
/// <summary>
/// Logs the given message with severity <b>DEBUG</b>.
/// Logs the given message with severity <see cref="LogLevel.Debug"/>.
/// </summary>
/// <exception cref="ArgumentNullException" />
void Debug(string message);
/// <summary>
/// Logs the given message with severity <b>INFO</b>.
/// Logs the given message with severity <see cref="LogLevel.Info"/>.
/// </summary>
/// <exception cref="ArgumentNullException" />
void Info(string message);
/// <summary>
/// Logs the given message with severity <b>WARNING</b>.
/// Logs the given message with severity <see cref="LogLevel.Warning"/>.
/// </summary>
/// <exception cref="ArgumentNullException" />
void Warn(string message);
/// <summary>
/// Logs the given message with severity <b>ERROR</b>.
/// Logs the given message with severity <see cref="LogLevel.Error"/>.
/// </summary>
/// <exception cref="ArgumentNullException" />
void Error(string message);
/// <summary>
/// Logs the given message with severity <b>ERROR</b> and includes information about
/// the specified exception (i.e. type, message and stacktrace).
/// Logs the given message with severity <see cref="LogLevel.Error"/> and includes
/// information about the specified exception (i.e. type, message and stacktrace).
/// </summary>
/// <exception cref="ArgumentNullException" />
void Error(string message, Exception exception);
@ -60,7 +60,7 @@ namespace SafeExamBrowser.Contracts.Logging
void Log(ILogContent content);
/// <summary>
/// Suscribes an observer to the application log.
/// Subscribes an observer to the application log.
/// </summary>
/// <exception cref="ArgumentNullException" />
void Subscribe(ILogObserver observer);

View file

@ -55,6 +55,7 @@
<Compile Include="Behaviour\Events\InstanceTerminatedEventHandler.cs" />
<Compile Include="Behaviour\Events\NameChangedEventHandler.cs" />
<Compile Include="Behaviour\IApplicationController.cs" />
<Compile Include="Behaviour\InstanceIdentifier.cs" />
<Compile Include="Behaviour\IRuntimeController.cs" />
<Compile Include="Behaviour\OperationModel\IOperationSequence.cs" />
<Compile Include="Behaviour\OperationModel\OperationResult.cs" />

View file

@ -6,7 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using SafeExamBrowser.Contracts.Behaviour;
namespace SafeExamBrowser.Contracts.UserInterface.Taskbar.Events
{
@ -14,5 +14,5 @@ namespace SafeExamBrowser.Contracts.UserInterface.Taskbar.Events
/// Indicates that an <see cref="IApplicationButton"/> has been clicked, optionally specifying the ID of the selected instance (if
/// multiple instances of the same application are running).
/// </summary>
public delegate void ApplicationButtonClickedEventHandler(Guid? instanceId = null);
public delegate void ApplicationButtonClickedEventHandler(InstanceIdentifier id = null);
}

View file

@ -8,6 +8,9 @@
namespace SafeExamBrowser.Contracts.WindowsApi
{
/// <summary>
/// Defines an abstraction of the Windows explorer shell (i.e. the process controlling the GUI of the operating system).
/// </summary>
public interface IExplorerShell
{
/// <summary>

View file

@ -23,7 +23,7 @@ namespace SafeExamBrowser.Core.Communication.Proxies
public abstract class BaseProxy : ICommunicationProxy
{
private const int ONE_MINUTE = 60000;
private static readonly object @lock = new object();
private readonly object @lock = new object();
private string address;
private IProxyObject proxy;

View file

@ -17,7 +17,7 @@ namespace SafeExamBrowser.Core.Logging
/// </summary>
public class LogFileWriter : ILogObserver
{
private static readonly object @lock = new object();
private readonly object @lock = new object();
private readonly string filePath;
private readonly ILogContentFormatter formatter;

View file

@ -20,7 +20,7 @@ namespace SafeExamBrowser.Core.Logging
/// </summary>
public class Logger : ILogger
{
private static readonly object @lock = new object();
private readonly object @lock = new object();
private readonly IList<ILogContent> log = new List<ILogContent>();
private readonly IList<ILogObserver> observers = new List<ILogObserver>();

View file

@ -18,12 +18,16 @@ namespace SafeExamBrowser.Core.Logging
public class ModuleLogger : ILogger
{
private ILogger logger;
private Type module;
private string moduleInfo;
public ModuleLogger(ILogger logger, Type module)
public ModuleLogger(ILogger logger, string moduleInfo)
{
this.logger = logger;
this.module = module;
this.moduleInfo = moduleInfo;
}
public ModuleLogger(ILogger logger, Type module) : this(logger, module.Name)
{
}
public void Debug(string message)
@ -78,7 +82,7 @@ namespace SafeExamBrowser.Core.Logging
private string AppendModuleInfo(string message)
{
return $"[{module.Name}] {message}";
return $"[{moduleInfo}] {message}";
}
}
}

View file

@ -6,7 +6,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
@ -90,7 +89,7 @@ namespace SafeExamBrowser.UserInterface.Classic.Controls
}
}
private void Instance_OnTerminated(Guid id, ApplicationInstanceButton instanceButton)
private void Instance_OnTerminated(InstanceIdentifier id, ApplicationInstanceButton instanceButton)
{
instances.Remove(instances.FirstOrDefault(i => i.Id == id));
InstanceStackPanel.Children.Remove(instanceButton);

View file

@ -6,23 +6,21 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using System.Windows;
using System.Windows.Controls;
using SafeExamBrowser.Contracts.Behaviour;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.UserInterface.Taskbar.Events;
using SafeExamBrowser.UserInterface.Classic.Utilities;
namespace SafeExamBrowser.UserInterface.Classic.Controls
{
internal delegate void InstanceButtonClickedEventHandler(Guid instanceId);
public partial class ApplicationInstanceButton : UserControl
{
private IApplicationInfo info;
private IApplicationInstance instance;
internal event InstanceButtonClickedEventHandler Clicked;
internal event ApplicationButtonClickedEventHandler Clicked;
public ApplicationInstanceButton(IApplicationInstance instance, IApplicationInfo info)
{

View file

@ -91,7 +91,7 @@ namespace SafeExamBrowser.UserInterface.Windows10.Controls
}
}
private void Instance_OnTerminated(Guid id, ApplicationInstanceButton instanceButton)
private void Instance_OnTerminated(InstanceIdentifier id, ApplicationInstanceButton instanceButton)
{
instances.Remove(instances.FirstOrDefault(i => i.Id == id));
InstanceStackPanel.Children.Remove(instanceButton);

View file

@ -6,23 +6,21 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using System.Windows;
using System.Windows.Controls;
using SafeExamBrowser.Contracts.Behaviour;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.UserInterface.Taskbar.Events;
using SafeExamBrowser.UserInterface.Windows10.Utilities;
namespace SafeExamBrowser.UserInterface.Windows10.Controls
{
internal delegate void InstanceButtonClickedEventHandler(Guid instanceId);
public partial class ApplicationInstanceButton : UserControl
{
private IApplicationInfo info;
private IApplicationInstance instance;
internal event InstanceButtonClickedEventHandler Clicked;
internal event ApplicationButtonClickedEventHandler Clicked;
public ApplicationInstanceButton(IApplicationInstance instance, IApplicationInfo info)
{