diff --git a/SafeExamBrowser.Configuration/SafeExamBrowser.Configuration.csproj b/SafeExamBrowser.Configuration/SafeExamBrowser.Configuration.csproj index 2aaba73b..3c55ea1f 100644 --- a/SafeExamBrowser.Configuration/SafeExamBrowser.Configuration.csproj +++ b/SafeExamBrowser.Configuration/SafeExamBrowser.Configuration.csproj @@ -50,7 +50,6 @@ - @@ -65,6 +64,7 @@ + diff --git a/SafeExamBrowser.Configuration/SystemInfo.cs b/SafeExamBrowser.Configuration/SystemInfo.cs new file mode 100644 index 00000000..3904f1d9 --- /dev/null +++ b/SafeExamBrowser.Configuration/SystemInfo.cs @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2017 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.Windows.Forms; +using SafeExamBrowser.Contracts.Configuration; + +namespace SafeExamBrowser.Configuration +{ + public class SystemInfo : ISystemInfo + { + public bool HasBattery { get; private set; } + public OperatingSystem OperatingSystem { get; private set; } + + public string OperatingSystemInfo + { + get { return $"{OperatingSystemName()}, {System.Environment.OSVersion.VersionString} ({Architecture()})"; } + } + + public SystemInfo() + { + InitializeBattery(); + InitializeOperatingSystem(); + } + + private void InitializeBattery() + { + var status = SystemInformation.PowerStatus.BatteryChargeStatus; + + HasBattery = !status.HasFlag(BatteryChargeStatus.NoSystemBattery) && !status.HasFlag(BatteryChargeStatus.Unknown); + } + + private void InitializeOperatingSystem() + { + // See https://en.wikipedia.org/wiki/List_of_Microsoft_Windows_versions for mapping source... + var major = System.Environment.OSVersion.Version.Major; + var minor = System.Environment.OSVersion.Version.Minor; + + if (major == 6) + { + if (minor == 1) + { + OperatingSystem = OperatingSystem.Windows7; + } + else if (minor == 2) + { + OperatingSystem = OperatingSystem.Windows8; + } + else if (minor == 3) + { + OperatingSystem = OperatingSystem.Windows8_1; + } + } + else if (major == 10) + { + OperatingSystem = OperatingSystem.Windows10; + } + } + + private string OperatingSystemName() + { + switch (OperatingSystem) + { + case OperatingSystem.Windows7: + return "Windows 7"; + case OperatingSystem.Windows8: + return "Windows 8"; + case OperatingSystem.Windows8_1: + return "Windows 8.1"; + case OperatingSystem.Windows10: + return "Windows 10"; + default: + return "Unknown Windows Version"; + } + } + + private string Architecture() + { + return System.Environment.Is64BitOperatingSystem ? "x64" : "x86"; + } + } +} diff --git a/SafeExamBrowser.Contracts/Configuration/ISystemInfo.cs b/SafeExamBrowser.Contracts/Configuration/ISystemInfo.cs new file mode 100644 index 00000000..2a807429 --- /dev/null +++ b/SafeExamBrowser.Contracts/Configuration/ISystemInfo.cs @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +namespace SafeExamBrowser.Contracts.Configuration +{ + public interface ISystemInfo + { + /// + /// Reveals whether the computer system contains a battery. + /// + bool HasBattery { get; } + + /// + /// Reveals the version of the currently running operating system. + /// + OperatingSystem OperatingSystem { get; } + + /// + /// Provides detailed version information about the currently running operating system. + /// + string OperatingSystemInfo { get; } + } +} diff --git a/SafeExamBrowser.Contracts/Configuration/OperatingSystem.cs b/SafeExamBrowser.Contracts/Configuration/OperatingSystem.cs new file mode 100644 index 00000000..2d1c3795 --- /dev/null +++ b/SafeExamBrowser.Contracts/Configuration/OperatingSystem.cs @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +namespace SafeExamBrowser.Contracts.Configuration +{ + public enum OperatingSystem + { + Unknown = 0, + Windows7, + Windows8, + Windows8_1, + Windows10 + } +} diff --git a/SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj b/SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj index 29432ff7..144b83d4 100644 --- a/SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj +++ b/SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj @@ -66,6 +66,8 @@ + + diff --git a/SafeExamBrowser.Core.UnitTests/Behaviour/StartupControllerTests.cs b/SafeExamBrowser.Core.UnitTests/Behaviour/StartupControllerTests.cs index 24aa21e4..2454f00d 100644 --- a/SafeExamBrowser.Core.UnitTests/Behaviour/StartupControllerTests.cs +++ b/SafeExamBrowser.Core.UnitTests/Behaviour/StartupControllerTests.cs @@ -11,6 +11,7 @@ using System.Collections.Generic; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using SafeExamBrowser.Contracts.Behaviour; +using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Configuration.Settings; using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.Logging; @@ -24,6 +25,7 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour { private Mock loggerMock; private Mock settingsMock; + private Mock systemInfoMock; private Mock textMock; private Mock uiFactoryMock; @@ -34,12 +36,13 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour { loggerMock = new Mock(); settingsMock = new Mock(); + systemInfoMock = new Mock(); textMock = new Mock(); uiFactoryMock = new Mock(); uiFactoryMock.Setup(f => f.CreateSplashScreen(settingsMock.Object, textMock.Object)).Returns(new Mock().Object); - sut = new StartupController(loggerMock.Object, settingsMock.Object, textMock.Object, uiFactoryMock.Object); + sut = new StartupController(loggerMock.Object, settingsMock.Object, systemInfoMock.Object, textMock.Object, uiFactoryMock.Object); } [TestMethod] diff --git a/SafeExamBrowser.Core/Behaviour/Operations/TaskbarOperation.cs b/SafeExamBrowser.Core/Behaviour/Operations/TaskbarOperation.cs index f751e39e..1470ea37 100644 --- a/SafeExamBrowser.Core/Behaviour/Operations/TaskbarOperation.cs +++ b/SafeExamBrowser.Core/Behaviour/Operations/TaskbarOperation.cs @@ -7,6 +7,7 @@ */ using SafeExamBrowser.Contracts.Behaviour; +using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Configuration.Settings; using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.Logging; @@ -19,22 +20,25 @@ namespace SafeExamBrowser.Core.Behaviour.Operations { private ILogger logger; private INotificationController aboutController, logController; + private ISettings settings; + private ISystemInfo systemInfo; private ITaskbar taskbar; private IUserInterfaceFactory uiFactory; private IText text; - private ISettings settings; public ISplashScreen SplashScreen { private get; set; } public TaskbarOperation( ILogger logger, ISettings settings, + ISystemInfo systemInfo, ITaskbar taskbar, IText text, IUserInterfaceFactory uiFactory) { this.logger = logger; this.settings = settings; + this.systemInfo = systemInfo; this.taskbar = taskbar; this.text = text; this.uiFactory = uiFactory; @@ -51,12 +55,32 @@ namespace SafeExamBrowser.Core.Behaviour.Operations } CreateAboutNotification(); + + if (systemInfo.HasBattery) + { + CreateBatteryNotification(); + } + + CreateNetworkNotification(); + CreateAudioNotification(); + CreateKeyboardNotification(); } public void Revert() { logController?.Terminate(); - aboutController.Terminate(); + aboutController?.Terminate(); + } + + private void CreateLogNotification() + { + var logInfo = new LogNotificationInfo(text); + var logNotification = uiFactory.CreateNotification(logInfo); + + logController = new LogNotificationController(logger, text, uiFactory); + logController.RegisterNotification(logNotification); + + taskbar.AddNotification(logNotification); } private void CreateAboutNotification() @@ -70,15 +94,25 @@ namespace SafeExamBrowser.Core.Behaviour.Operations taskbar.AddNotification(aboutNotification); } - private void CreateLogNotification() + private void CreateBatteryNotification() { - var logInfo = new LogNotificationInfo(text); - var logNotification = uiFactory.CreateNotification(logInfo); + // TODO: Are these specializations of INotification -> ISystemNotification? If yes, is this the right place, or do they + // need to go to a separate assembly? + } - logController = new LogNotificationController(logger, text, uiFactory); - logController.RegisterNotification(logNotification); + private void CreateNetworkNotification() + { + // TODO + } - taskbar.AddNotification(logNotification); + private void CreateAudioNotification() + { + // TODO + } + + private void CreateKeyboardNotification() + { + // TODO } } } diff --git a/SafeExamBrowser.Core/Behaviour/StartupController.cs b/SafeExamBrowser.Core/Behaviour/StartupController.cs index c4cd3729..80a3b75e 100644 --- a/SafeExamBrowser.Core/Behaviour/StartupController.cs +++ b/SafeExamBrowser.Core/Behaviour/StartupController.cs @@ -10,6 +10,7 @@ using System; using System.Collections.Generic; using System.Linq; using SafeExamBrowser.Contracts.Behaviour; +using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Configuration.Settings; using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.Logging; @@ -22,15 +23,17 @@ namespace SafeExamBrowser.Core.Behaviour private ILogger logger; private ISettings settings; private ISplashScreen splashScreen; + private ISystemInfo systemInfo; private IText text; private IUserInterfaceFactory uiFactory; private Stack stack = new Stack(); - public StartupController(ILogger logger, ISettings settings, IText text, IUserInterfaceFactory uiFactory) + public StartupController(ILogger logger, ISettings settings, ISystemInfo systemInfo, IText text, IUserInterfaceFactory uiFactory) { this.logger = logger; this.settings = settings; + this.systemInfo = systemInfo; this.text = text; this.uiFactory = uiFactory; } @@ -87,7 +90,8 @@ namespace SafeExamBrowser.Core.Behaviour var githubLine = $"/* Please visit https://github.com/SafeExamBrowser for more information."; logger.Log($"{titleLine}{copyrightLine}{emptyLine}{githubLine}"); - logger.Log($"{Environment.NewLine}# Application started at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}{Environment.NewLine}"); + logger.Log($"{Environment.NewLine}# Application started at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}"); + logger.Log($"# Operating system: {systemInfo.OperatingSystemInfo}{Environment.NewLine}"); logger.Info("--- Initiating startup procedure ---"); splashScreen = uiFactory.CreateSplashScreen(settings, text); diff --git a/SafeExamBrowser.UserInterface/Controls/NotificationIcon.xaml b/SafeExamBrowser.UserInterface/Controls/NotificationIcon.xaml index 81c32bde..2f00d863 100644 --- a/SafeExamBrowser.UserInterface/Controls/NotificationIcon.xaml +++ b/SafeExamBrowser.UserInterface/Controls/NotificationIcon.xaml @@ -4,8 +4,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Controls" - mc:Ignorable="d" - d:DesignHeight="16" d:DesignWidth="16" Margin="5,0"> + mc:Ignorable="d" d:DesignHeight="16" d:DesignWidth="16" Margin="5,0">