SEBWIN-537: Implemented new network control showing wired as well as wireless network information.

This commit is contained in:
Damian Büchel 2022-04-19 18:21:29 +02:00
parent 3dda11956e
commit 6205bef251
57 changed files with 997 additions and 949 deletions

View file

@ -18,8 +18,8 @@ using SafeExamBrowser.Settings.Applications;
using SafeExamBrowser.SystemComponents.Contracts; using SafeExamBrowser.SystemComponents.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.Audio; using SafeExamBrowser.SystemComponents.Contracts.Audio;
using SafeExamBrowser.SystemComponents.Contracts.Keyboard; using SafeExamBrowser.SystemComponents.Contracts.Keyboard;
using SafeExamBrowser.SystemComponents.Contracts.Network;
using SafeExamBrowser.SystemComponents.Contracts.PowerSupply; using SafeExamBrowser.SystemComponents.Contracts.PowerSupply;
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork;
using SafeExamBrowser.UserInterface.Contracts; using SafeExamBrowser.UserInterface.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Shell; using SafeExamBrowser.UserInterface.Contracts.Shell;
@ -41,7 +41,7 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
private Mock<ITaskview> taskview; private Mock<ITaskview> taskview;
private Mock<IText> text; private Mock<IText> text;
private Mock<IUserInterfaceFactory> uiFactory; private Mock<IUserInterfaceFactory> uiFactory;
private Mock<IWirelessAdapter> wirelessAdapter; private Mock<INetworkAdapter> networkAdapter;
private ShellOperation sut; private ShellOperation sut;
@ -55,13 +55,13 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
aboutNotification = new Mock<INotification>(); aboutNotification = new Mock<INotification>();
keyboard = new Mock<IKeyboard>(); keyboard = new Mock<IKeyboard>();
logNotification = new Mock<INotification>(); logNotification = new Mock<INotification>();
networkAdapter = new Mock<INetworkAdapter>();
powerSupply = new Mock<IPowerSupply>(); powerSupply = new Mock<IPowerSupply>();
systemInfo = new Mock<ISystemInfo>(); systemInfo = new Mock<ISystemInfo>();
taskbar = new Mock<ITaskbar>(); taskbar = new Mock<ITaskbar>();
taskview = new Mock<ITaskview>(); taskview = new Mock<ITaskview>();
text = new Mock<IText>(); text = new Mock<IText>();
uiFactory = new Mock<IUserInterfaceFactory>(); uiFactory = new Mock<IUserInterfaceFactory>();
wirelessAdapter = new Mock<IWirelessAdapter>();
context.Settings = new AppSettings(); context.Settings = new AppSettings();
@ -77,13 +77,13 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
keyboard.Object, keyboard.Object,
logger.Object, logger.Object,
logNotification.Object, logNotification.Object,
networkAdapter.Object,
powerSupply.Object, powerSupply.Object,
systemInfo.Object, systemInfo.Object,
taskbar.Object, taskbar.Object,
taskview.Object, taskview.Object,
text.Object, text.Object,
uiFactory.Object, uiFactory.Object);
wirelessAdapter.Object);
} }
[TestMethod] [TestMethod]
@ -99,7 +99,7 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
context.Settings.ActionCenter.EnableActionCenter = true; context.Settings.ActionCenter.EnableActionCenter = true;
context.Settings.Keyboard.AllowAltTab = true; context.Settings.Keyboard.AllowAltTab = true;
context.Settings.Security.AllowTermination = true; context.Settings.Security.AllowTermination = true;
sut.Perform(); sut.Perform();
actionCenter.Verify(a => a.Register(It.Is<IActionCenterActivator>(a2 => a2 == actionCenterActivator.Object)), Times.Once); actionCenter.Verify(a => a.Register(It.Is<IActionCenterActivator>(a2 => a2 == actionCenterActivator.Object)), Times.Once);
@ -281,23 +281,23 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
context.Settings.ActionCenter.EnableActionCenter = true; context.Settings.ActionCenter.EnableActionCenter = true;
context.Settings.ActionCenter.ShowAudio = true; context.Settings.ActionCenter.ShowAudio = true;
context.Settings.ActionCenter.ShowKeyboardLayout = true; context.Settings.ActionCenter.ShowKeyboardLayout = true;
context.Settings.ActionCenter.ShowWirelessNetwork = true; context.Settings.ActionCenter.ShowNetwork = true;
context.Settings.Taskbar.EnableTaskbar = true; context.Settings.Taskbar.EnableTaskbar = true;
context.Settings.Taskbar.ShowAudio = true; context.Settings.Taskbar.ShowAudio = true;
context.Settings.Taskbar.ShowKeyboardLayout = true; context.Settings.Taskbar.ShowKeyboardLayout = true;
context.Settings.Taskbar.ShowWirelessNetwork = true; context.Settings.Taskbar.ShowNetwork = true;
systemInfo.SetupGet(s => s.HasBattery).Returns(true); systemInfo.SetupGet(s => s.HasBattery).Returns(true);
uiFactory.Setup(f => f.CreateAudioControl(It.IsAny<IAudio>(), It.IsAny<Location>())).Returns(new Mock<ISystemControl>().Object); uiFactory.Setup(f => f.CreateAudioControl(It.IsAny<IAudio>(), It.IsAny<Location>())).Returns(new Mock<ISystemControl>().Object);
uiFactory.Setup(f => f.CreateKeyboardLayoutControl(It.IsAny<IKeyboard>(), It.IsAny<Location>())).Returns(new Mock<ISystemControl>().Object); uiFactory.Setup(f => f.CreateKeyboardLayoutControl(It.IsAny<IKeyboard>(), It.IsAny<Location>())).Returns(new Mock<ISystemControl>().Object);
uiFactory.Setup(f => f.CreatePowerSupplyControl(It.IsAny<IPowerSupply>(), It.IsAny<Location>())).Returns(new Mock<ISystemControl>().Object); uiFactory.Setup(f => f.CreatePowerSupplyControl(It.IsAny<IPowerSupply>(), It.IsAny<Location>())).Returns(new Mock<ISystemControl>().Object);
uiFactory.Setup(f => f.CreateWirelessNetworkControl(It.IsAny<IWirelessAdapter>(), It.IsAny<Location>())).Returns(new Mock<ISystemControl>().Object); uiFactory.Setup(f => f.CreateNetworkControl(It.IsAny<INetworkAdapter>(), It.IsAny<Location>())).Returns(new Mock<ISystemControl>().Object);
sut.Perform(); sut.Perform();
audio.Verify(a => a.Initialize(), Times.Once); audio.Verify(a => a.Initialize(), Times.Once);
powerSupply.Verify(p => p.Initialize(), Times.Once); powerSupply.Verify(p => p.Initialize(), Times.Once);
wirelessAdapter.Verify(w => w.Initialize(), Times.Once); networkAdapter.Verify(w => w.Initialize(), Times.Once);
keyboard.Verify(k => k.Initialize(), Times.Once); keyboard.Verify(k => k.Initialize(), Times.Once);
actionCenter.Verify(a => a.AddSystemControl(It.IsAny<ISystemControl>()), Times.Exactly(4)); actionCenter.Verify(a => a.AddSystemControl(It.IsAny<ISystemControl>()), Times.Exactly(4));
taskbar.Verify(t => t.AddSystemControl(It.IsAny<ISystemControl>()), Times.Exactly(4)); taskbar.Verify(t => t.AddSystemControl(It.IsAny<ISystemControl>()), Times.Exactly(4));
@ -309,23 +309,23 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
context.Settings.ActionCenter.EnableActionCenter = true; context.Settings.ActionCenter.EnableActionCenter = true;
context.Settings.ActionCenter.ShowAudio = false; context.Settings.ActionCenter.ShowAudio = false;
context.Settings.ActionCenter.ShowKeyboardLayout = false; context.Settings.ActionCenter.ShowKeyboardLayout = false;
context.Settings.ActionCenter.ShowWirelessNetwork = false; context.Settings.ActionCenter.ShowNetwork = false;
context.Settings.Taskbar.EnableTaskbar = true; context.Settings.Taskbar.EnableTaskbar = true;
context.Settings.Taskbar.ShowAudio = false; context.Settings.Taskbar.ShowAudio = false;
context.Settings.Taskbar.ShowKeyboardLayout = false; context.Settings.Taskbar.ShowKeyboardLayout = false;
context.Settings.Taskbar.ShowWirelessNetwork = false; context.Settings.Taskbar.ShowNetwork = false;
systemInfo.SetupGet(s => s.HasBattery).Returns(false); systemInfo.SetupGet(s => s.HasBattery).Returns(false);
uiFactory.Setup(f => f.CreateAudioControl(It.IsAny<IAudio>(), It.IsAny<Location>())).Returns(new Mock<ISystemControl>().Object); uiFactory.Setup(f => f.CreateAudioControl(It.IsAny<IAudio>(), It.IsAny<Location>())).Returns(new Mock<ISystemControl>().Object);
uiFactory.Setup(f => f.CreateKeyboardLayoutControl(It.IsAny<IKeyboard>(), It.IsAny<Location>())).Returns(new Mock<ISystemControl>().Object); uiFactory.Setup(f => f.CreateKeyboardLayoutControl(It.IsAny<IKeyboard>(), It.IsAny<Location>())).Returns(new Mock<ISystemControl>().Object);
uiFactory.Setup(f => f.CreatePowerSupplyControl(It.IsAny<IPowerSupply>(), It.IsAny<Location>())).Returns(new Mock<ISystemControl>().Object); uiFactory.Setup(f => f.CreatePowerSupplyControl(It.IsAny<IPowerSupply>(), It.IsAny<Location>())).Returns(new Mock<ISystemControl>().Object);
uiFactory.Setup(f => f.CreateWirelessNetworkControl(It.IsAny<IWirelessAdapter>(), It.IsAny<Location>())).Returns(new Mock<ISystemControl>().Object); uiFactory.Setup(f => f.CreateNetworkControl(It.IsAny<INetworkAdapter>(), It.IsAny<Location>())).Returns(new Mock<ISystemControl>().Object);
sut.Perform(); sut.Perform();
audio.Verify(a => a.Initialize(), Times.Once); audio.Verify(a => a.Initialize(), Times.Once);
powerSupply.Verify(p => p.Initialize(), Times.Once); powerSupply.Verify(p => p.Initialize(), Times.Once);
wirelessAdapter.Verify(w => w.Initialize(), Times.Once); networkAdapter.Verify(w => w.Initialize(), Times.Once);
keyboard.Verify(k => k.Initialize(), Times.Once); keyboard.Verify(k => k.Initialize(), Times.Once);
actionCenter.Verify(a => a.AddSystemControl(It.IsAny<ISystemControl>()), Times.Never); actionCenter.Verify(a => a.AddSystemControl(It.IsAny<ISystemControl>()), Times.Never);
taskbar.Verify(t => t.AddSystemControl(It.IsAny<ISystemControl>()), Times.Never); taskbar.Verify(t => t.AddSystemControl(It.IsAny<ISystemControl>()), Times.Never);
@ -408,7 +408,7 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
logNotification.Verify(c => c.Terminate(), Times.Once); logNotification.Verify(c => c.Terminate(), Times.Once);
powerSupply.Verify(p => p.Terminate(), Times.Once); powerSupply.Verify(p => p.Terminate(), Times.Once);
keyboard.Verify(k => k.Terminate(), Times.Once); keyboard.Verify(k => k.Terminate(), Times.Once);
wirelessAdapter.Verify(w => w.Terminate(), Times.Once); networkAdapter.Verify(w => w.Terminate(), Times.Once);
} }
} }
} }

View file

@ -38,11 +38,11 @@ using SafeExamBrowser.Settings.UserInterface;
using SafeExamBrowser.SystemComponents; using SafeExamBrowser.SystemComponents;
using SafeExamBrowser.SystemComponents.Audio; using SafeExamBrowser.SystemComponents.Audio;
using SafeExamBrowser.SystemComponents.Contracts; using SafeExamBrowser.SystemComponents.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.Network;
using SafeExamBrowser.SystemComponents.Contracts.PowerSupply; using SafeExamBrowser.SystemComponents.Contracts.PowerSupply;
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork;
using SafeExamBrowser.SystemComponents.Keyboard; using SafeExamBrowser.SystemComponents.Keyboard;
using SafeExamBrowser.SystemComponents.Network;
using SafeExamBrowser.SystemComponents.PowerSupply; using SafeExamBrowser.SystemComponents.PowerSupply;
using SafeExamBrowser.SystemComponents.WirelessNetwork;
using SafeExamBrowser.UserInterface.Contracts; using SafeExamBrowser.UserInterface.Contracts;
using SafeExamBrowser.UserInterface.Contracts.FileSystemDialog; using SafeExamBrowser.UserInterface.Contracts.FileSystemDialog;
using SafeExamBrowser.UserInterface.Contracts.MessageBox; using SafeExamBrowser.UserInterface.Contracts.MessageBox;
@ -71,6 +71,7 @@ namespace SafeExamBrowser.Client
private ILogger logger; private ILogger logger;
private IMessageBox messageBox; private IMessageBox messageBox;
private INativeMethods nativeMethods; private INativeMethods nativeMethods;
private INetworkAdapter networkAdapter;
private IPowerSupply powerSupply; private IPowerSupply powerSupply;
private IRuntimeProxy runtimeProxy; private IRuntimeProxy runtimeProxy;
private ISystemInfo systemInfo; private ISystemInfo systemInfo;
@ -79,7 +80,6 @@ namespace SafeExamBrowser.Client
private IUserInfo userInfo; private IUserInfo userInfo;
private IText text; private IText text;
private IUserInterfaceFactory uiFactory; private IUserInterfaceFactory uiFactory;
private IWirelessAdapter wirelessAdapter;
internal ClientController ClientController { get; private set; } internal ClientController ClientController { get; private set; }
@ -96,13 +96,13 @@ namespace SafeExamBrowser.Client
context = new ClientContext(); context = new ClientContext();
messageBox = BuildMessageBox(); messageBox = BuildMessageBox();
nativeMethods = new NativeMethods(); nativeMethods = new NativeMethods();
networkAdapter = new NetworkAdapter(ModuleLogger(nameof(NetworkAdapter)), nativeMethods);
powerSupply = new PowerSupply(ModuleLogger(nameof(PowerSupply))); powerSupply = new PowerSupply(ModuleLogger(nameof(PowerSupply)));
runtimeProxy = new RuntimeProxy(runtimeHostUri, new ProxyObjectFactory(), ModuleLogger(nameof(RuntimeProxy)), Interlocutor.Client); runtimeProxy = new RuntimeProxy(runtimeHostUri, new ProxyObjectFactory(), ModuleLogger(nameof(RuntimeProxy)), Interlocutor.Client);
systemInfo = new SystemInfo(); systemInfo = new SystemInfo();
taskbar = uiFactory.CreateTaskbar(ModuleLogger("Taskbar")); taskbar = uiFactory.CreateTaskbar(ModuleLogger("Taskbar"));
taskview = uiFactory.CreateTaskview(); taskview = uiFactory.CreateTaskview();
userInfo = new UserInfo(ModuleLogger(nameof(UserInfo))); userInfo = new UserInfo(ModuleLogger(nameof(UserInfo)));
wirelessAdapter = new WirelessAdapter(ModuleLogger(nameof(WirelessAdapter)));
var processFactory = new ProcessFactory(ModuleLogger(nameof(ProcessFactory))); var processFactory = new ProcessFactory(ModuleLogger(nameof(ProcessFactory)));
var applicationMonitor = new ApplicationMonitor(TWO_SECONDS, ModuleLogger(nameof(ApplicationMonitor)), nativeMethods, processFactory); var applicationMonitor = new ApplicationMonitor(TWO_SECONDS, ModuleLogger(nameof(ApplicationMonitor)), nativeMethods, processFactory);
@ -157,13 +157,13 @@ namespace SafeExamBrowser.Client
internal void LogStartupInformation() internal void LogStartupInformation()
{ {
logger.Log($"# New client instance started at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}"); logger.Log($"# New client instance started at {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}");
logger.Log(string.Empty); logger.Log(string.Empty);
} }
internal void LogShutdownInformation() internal void LogShutdownInformation()
{ {
logger?.Log($"# Client instance terminated at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}"); logger?.Log($"# Client instance terminated at {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}");
} }
private void ValidateCommandLineArguments() private void ValidateCommandLineArguments()
@ -271,7 +271,7 @@ namespace SafeExamBrowser.Client
private IOperation BuildServerOperation() private IOperation BuildServerOperation()
{ {
var server = new ServerProxy(context.AppConfig, ModuleLogger(nameof(ServerProxy)), systemInfo, userInfo, powerSupply, wirelessAdapter); var server = new ServerProxy(context.AppConfig, ModuleLogger(nameof(ServerProxy)), systemInfo, userInfo, powerSupply, networkAdapter);
var operation = new ServerOperation(context, logger, server); var operation = new ServerOperation(context, logger, server);
context.Server = server; context.Server = server;
@ -293,13 +293,13 @@ namespace SafeExamBrowser.Client
keyboard, keyboard,
logger, logger,
logNotification, logNotification,
networkAdapter,
powerSupply, powerSupply,
systemInfo, systemInfo,
taskbar, taskbar,
taskview, taskview,
text, text,
uiFactory, uiFactory);
wirelessAdapter);
context.Activators.Add(new ActionCenterKeyboardActivator(ModuleLogger(nameof(ActionCenterKeyboardActivator)), nativeMethods)); context.Activators.Add(new ActionCenterKeyboardActivator(ModuleLogger(nameof(ActionCenterKeyboardActivator)), nativeMethods));
context.Activators.Add(new ActionCenterTouchActivator(ModuleLogger(nameof(ActionCenterTouchActivator)), nativeMethods)); context.Activators.Add(new ActionCenterTouchActivator(ModuleLogger(nameof(ActionCenterTouchActivator)), nativeMethods));

View file

@ -15,8 +15,8 @@ using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.SystemComponents.Contracts; using SafeExamBrowser.SystemComponents.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.Audio; using SafeExamBrowser.SystemComponents.Contracts.Audio;
using SafeExamBrowser.SystemComponents.Contracts.Keyboard; using SafeExamBrowser.SystemComponents.Contracts.Keyboard;
using SafeExamBrowser.SystemComponents.Contracts.Network;
using SafeExamBrowser.SystemComponents.Contracts.PowerSupply; using SafeExamBrowser.SystemComponents.Contracts.PowerSupply;
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork;
using SafeExamBrowser.UserInterface.Contracts; using SafeExamBrowser.UserInterface.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Shell; using SafeExamBrowser.UserInterface.Contracts.Shell;
@ -24,19 +24,19 @@ namespace SafeExamBrowser.Client.Operations
{ {
internal class ShellOperation : ClientOperation internal class ShellOperation : ClientOperation
{ {
private IActionCenter actionCenter; private readonly IActionCenter actionCenter;
private IAudio audio; private readonly IAudio audio;
private INotification aboutNotification; private readonly INotification aboutNotification;
private IKeyboard keyboard; private readonly IKeyboard keyboard;
private ILogger logger; private readonly ILogger logger;
private INotification logNotification; private readonly INotification logNotification;
private IPowerSupply powerSupply; private readonly INetworkAdapter networkAdapter;
private ISystemInfo systemInfo; private readonly IPowerSupply powerSupply;
private ITaskbar taskbar; private readonly ISystemInfo systemInfo;
private ITaskview taskview; private readonly ITaskbar taskbar;
private IText text; private readonly ITaskview taskview;
private IUserInterfaceFactory uiFactory; private readonly IText text;
private IWirelessAdapter wirelessAdapter; private readonly IUserInterfaceFactory uiFactory;
public override event ActionRequiredEventHandler ActionRequired { add { } remove { } } public override event ActionRequiredEventHandler ActionRequired { add { } remove { } }
public override event StatusChangedEventHandler StatusChanged; public override event StatusChangedEventHandler StatusChanged;
@ -49,13 +49,13 @@ namespace SafeExamBrowser.Client.Operations
IKeyboard keyboard, IKeyboard keyboard,
ILogger logger, ILogger logger,
INotification logNotification, INotification logNotification,
INetworkAdapter networkAdapter,
IPowerSupply powerSupply, IPowerSupply powerSupply,
ISystemInfo systemInfo, ISystemInfo systemInfo,
ITaskbar taskbar, ITaskbar taskbar,
ITaskview taskview, ITaskview taskview,
IText text, IText text,
IUserInterfaceFactory uiFactory, IUserInterfaceFactory uiFactory) : base(context)
IWirelessAdapter wirelessAdapter) : base(context)
{ {
this.aboutNotification = aboutNotification; this.aboutNotification = aboutNotification;
this.actionCenter = actionCenter; this.actionCenter = actionCenter;
@ -63,13 +63,13 @@ namespace SafeExamBrowser.Client.Operations
this.keyboard = keyboard; this.keyboard = keyboard;
this.logger = logger; this.logger = logger;
this.logNotification = logNotification; this.logNotification = logNotification;
this.networkAdapter = networkAdapter;
this.powerSupply = powerSupply; this.powerSupply = powerSupply;
this.systemInfo = systemInfo; this.systemInfo = systemInfo;
this.text = text; this.text = text;
this.taskbar = taskbar; this.taskbar = taskbar;
this.taskview = taskview; this.taskview = taskview;
this.uiFactory = uiFactory; this.uiFactory = uiFactory;
this.wirelessAdapter = wirelessAdapter;
} }
public override OperationResult Perform() public override OperationResult Perform()
@ -134,7 +134,7 @@ namespace SafeExamBrowser.Client.Operations
InitializeClockForActionCenter(); InitializeClockForActionCenter();
InitializeLogNotificationForActionCenter(); InitializeLogNotificationForActionCenter();
InitializeKeyboardLayoutForActionCenter(); InitializeKeyboardLayoutForActionCenter();
InitializeWirelessNetworkForActionCenter(); InitializeNetworkForActionCenter();
InitializePowerSupplyForActionCenter(); InitializePowerSupplyForActionCenter();
InitializeQuitButtonForActionCenter(); InitializeQuitButtonForActionCenter();
} }
@ -155,7 +155,7 @@ namespace SafeExamBrowser.Client.Operations
InitializeAboutNotificationForTaskbar(); InitializeAboutNotificationForTaskbar();
InitializeLogNotificationForTaskbar(); InitializeLogNotificationForTaskbar();
InitializePowerSupplyForTaskbar(); InitializePowerSupplyForTaskbar();
InitializeWirelessNetworkForTaskbar(); InitializeNetworkForTaskbar();
InitializeAudioForTaskbar(); InitializeAudioForTaskbar();
InitializeKeyboardLayoutForTaskbar(); InitializeKeyboardLayoutForTaskbar();
InitializeClockForTaskbar(); InitializeClockForTaskbar();
@ -204,8 +204,8 @@ namespace SafeExamBrowser.Client.Operations
{ {
audio.Initialize(); audio.Initialize();
keyboard.Initialize(); keyboard.Initialize();
networkAdapter.Initialize();
powerSupply.Initialize(); powerSupply.Initialize();
wirelessAdapter.Initialize();
} }
private void InitializeAboutNotificationForActionCenter() private void InitializeAboutNotificationForActionCenter()
@ -308,19 +308,19 @@ namespace SafeExamBrowser.Client.Operations
taskbar.ShowQuitButton = Context.Settings.Security.AllowTermination; taskbar.ShowQuitButton = Context.Settings.Security.AllowTermination;
} }
private void InitializeWirelessNetworkForActionCenter() private void InitializeNetworkForActionCenter()
{ {
if (Context.Settings.ActionCenter.ShowWirelessNetwork) if (Context.Settings.ActionCenter.ShowNetwork)
{ {
actionCenter.AddSystemControl(uiFactory.CreateWirelessNetworkControl(wirelessAdapter, Location.ActionCenter)); actionCenter.AddSystemControl(uiFactory.CreateNetworkControl(networkAdapter, Location.ActionCenter));
} }
} }
private void InitializeWirelessNetworkForTaskbar() private void InitializeNetworkForTaskbar()
{ {
if (Context.Settings.Taskbar.ShowWirelessNetwork) if (Context.Settings.Taskbar.ShowNetwork)
{ {
taskbar.AddSystemControl(uiFactory.CreateWirelessNetworkControl(wirelessAdapter, Location.Taskbar)); taskbar.AddSystemControl(uiFactory.CreateNetworkControl(networkAdapter, Location.Taskbar));
} }
} }
@ -342,8 +342,8 @@ namespace SafeExamBrowser.Client.Operations
{ {
audio.Terminate(); audio.Terminate();
keyboard.Terminate(); keyboard.Terminate();
networkAdapter.Terminate();
powerSupply.Terminate(); powerSupply.Terminate();
wirelessAdapter.Terminate();
} }
} }
} }

View file

@ -30,7 +30,6 @@ namespace SafeExamBrowser.Configuration.UnitTests
private Mock<ICertificateStore> certificateStore; private Mock<ICertificateStore> certificateStore;
private Mock<IResourceLoader> fileLoader; private Mock<IResourceLoader> fileLoader;
private Mock<IResourceSaver> fileSaver; private Mock<IResourceSaver> fileSaver;
private Mock<IHashAlgorithm> hashAlgorithm;
private Mock<IModuleLogger> logger; private Mock<IModuleLogger> logger;
private Mock<IResourceLoader> networkLoader; private Mock<IResourceLoader> networkLoader;
private Mock<IDataParser> xmlParser; private Mock<IDataParser> xmlParser;
@ -44,7 +43,6 @@ namespace SafeExamBrowser.Configuration.UnitTests
certificateStore = new Mock<ICertificateStore>(); certificateStore = new Mock<ICertificateStore>();
fileLoader = new Mock<IResourceLoader>(); fileLoader = new Mock<IResourceLoader>();
fileSaver = new Mock<IResourceSaver>(); fileSaver = new Mock<IResourceSaver>();
hashAlgorithm = new Mock<IHashAlgorithm>();
logger = new Mock<IModuleLogger>(); logger = new Mock<IModuleLogger>();
networkLoader = new Mock<IResourceLoader>(); networkLoader = new Mock<IResourceLoader>();
xmlParser = new Mock<IDataParser>(); xmlParser = new Mock<IDataParser>();
@ -56,7 +54,7 @@ namespace SafeExamBrowser.Configuration.UnitTests
SetEntryAssembly(); SetEntryAssembly();
sut = new ConfigurationRepository(certificateStore.Object, hashAlgorithm.Object, logger.Object); sut = new ConfigurationRepository(certificateStore.Object, logger.Object);
sut.InitializeAppConfig(); sut.InitializeAppConfig();
} }

View file

@ -29,8 +29,8 @@ namespace SafeExamBrowser.Configuration.ConfigurationData.DataMapping
case Keys.UserInterface.ShowKeyboardLayout: case Keys.UserInterface.ShowKeyboardLayout:
MapShowKeyboardLayout(settings, value); MapShowKeyboardLayout(settings, value);
break; break;
case Keys.UserInterface.ShowWirelessNetwork: case Keys.UserInterface.ShowNetwork:
MapShowWirelessNetwork(settings, value); MapShowNetwork(settings, value);
break; break;
case Keys.UserInterface.Taskbar.EnableTaskbar: case Keys.UserInterface.Taskbar.EnableTaskbar:
MapEnableTaskbar(settings, value); MapEnableTaskbar(settings, value);
@ -79,12 +79,12 @@ namespace SafeExamBrowser.Configuration.ConfigurationData.DataMapping
} }
} }
private void MapShowWirelessNetwork(AppSettings settings, object value) private void MapShowNetwork(AppSettings settings, object value)
{ {
if (value is bool show) if (value is bool show)
{ {
settings.ActionCenter.ShowWirelessNetwork = show; settings.ActionCenter.ShowNetwork = show;
settings.Taskbar.ShowWirelessNetwork = show; settings.Taskbar.ShowNetwork = show;
} }
} }

View file

@ -101,9 +101,9 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
settings.ActionCenter.EnableActionCenter = true; settings.ActionCenter.EnableActionCenter = true;
settings.ActionCenter.ShowApplicationInfo = true; settings.ActionCenter.ShowApplicationInfo = true;
settings.ActionCenter.ShowApplicationLog = false; settings.ActionCenter.ShowApplicationLog = false;
settings.ActionCenter.ShowKeyboardLayout = true;
settings.ActionCenter.ShowWirelessNetwork = false;
settings.ActionCenter.ShowClock = true; settings.ActionCenter.ShowClock = true;
settings.ActionCenter.ShowKeyboardLayout = true;
settings.ActionCenter.ShowNetwork = false;
settings.Applications.Blacklist.Add(new BlacklistApplication { ExecutableName = "AA_v3.exe", OriginalName = "AA_v3.exe" }); settings.Applications.Blacklist.Add(new BlacklistApplication { ExecutableName = "AA_v3.exe", OriginalName = "AA_v3.exe" });
settings.Applications.Blacklist.Add(new BlacklistApplication { ExecutableName = "AeroAdmin.exe", OriginalName = "AeroAdmin.exe" }); settings.Applications.Blacklist.Add(new BlacklistApplication { ExecutableName = "AeroAdmin.exe", OriginalName = "AeroAdmin.exe" });
@ -283,12 +283,12 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
settings.Taskbar.EnableTaskbar = true; settings.Taskbar.EnableTaskbar = true;
settings.Taskbar.ShowApplicationInfo = false; settings.Taskbar.ShowApplicationInfo = false;
settings.Taskbar.ShowApplicationLog = false; settings.Taskbar.ShowApplicationLog = false;
settings.Taskbar.ShowKeyboardLayout = true;
settings.Taskbar.ShowWirelessNetwork = false;
settings.Taskbar.ShowClock = true; settings.Taskbar.ShowClock = true;
settings.Taskbar.ShowKeyboardLayout = true;
settings.Taskbar.ShowNetwork = false;
settings.UserInterfaceMode = UserInterfaceMode.Desktop; settings.UserInterfaceMode = UserInterfaceMode.Desktop;
return settings; return settings;
} }
} }

View file

@ -327,7 +327,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
internal const string ShowAudio = "audioControlEnabled"; internal const string ShowAudio = "audioControlEnabled";
internal const string ShowClock = "showTime"; internal const string ShowClock = "showTime";
internal const string ShowKeyboardLayout = "showInputLanguage"; internal const string ShowKeyboardLayout = "showInputLanguage";
internal const string ShowWirelessNetwork = "allowWlan"; internal const string ShowNetwork = "allowWlan";
internal const string UserInterfaceMode = "touchOptimized"; internal const string UserInterfaceMode = "touchOptimized";
internal static class ActionCenter internal static class ActionCenter

View file

@ -22,21 +22,19 @@ namespace SafeExamBrowser.Configuration
{ {
public class ConfigurationRepository : IConfigurationRepository public class ConfigurationRepository : IConfigurationRepository
{ {
private ICertificateStore certificateStore; private readonly ICertificateStore certificateStore;
private IList<IDataParser> dataParsers; private readonly IList<IDataParser> dataParsers;
private IList<IDataSerializer> dataSerializers; private readonly IList<IDataSerializer> dataSerializers;
private DataMapper dataMapper; private readonly DataMapper dataMapper;
private DataProcessor dataProcessor; private readonly DataProcessor dataProcessor;
private DataValues dataValues; private readonly DataValues dataValues;
private IHashAlgorithm hashAlgorithm; private readonly ILogger logger;
private ILogger logger; private readonly IList<IResourceLoader> resourceLoaders;
private IList<IResourceLoader> resourceLoaders; private readonly IList<IResourceSaver> resourceSavers;
private IList<IResourceSaver> resourceSavers;
public ConfigurationRepository(ICertificateStore certificateStore, IHashAlgorithm hashAlgorithm, IModuleLogger logger) public ConfigurationRepository(ICertificateStore certificateStore, IModuleLogger logger)
{ {
this.certificateStore = certificateStore; this.certificateStore = certificateStore;
this.hashAlgorithm = hashAlgorithm;
this.logger = logger; this.logger = logger;
dataParsers = new List<IDataParser>(); dataParsers = new List<IDataParser>();
@ -171,7 +169,7 @@ namespace SafeExamBrowser.Configuration
var status = LoadStatus.NotSupported; var status = LoadStatus.NotSupported;
var resourceLoader = resourceLoaders.FirstOrDefault(l => l.CanLoad(resource)); var resourceLoader = resourceLoaders.FirstOrDefault(l => l.CanLoad(resource));
data = default(Stream); data = default;
if (resourceLoader != null) if (resourceLoader != null)
{ {
@ -191,8 +189,8 @@ namespace SafeExamBrowser.Configuration
var parser = dataParsers.FirstOrDefault(p => p.CanParse(data)); var parser = dataParsers.FirstOrDefault(p => p.CanParse(data));
var status = LoadStatus.NotSupported; var status = LoadStatus.NotSupported;
encryption = default(EncryptionParameters); encryption = default;
format = default(FormatType); format = default;
rawData = default(Dictionary<string, object>); rawData = default(Dictionary<string, object>);
if (parser != null) if (parser != null)
@ -237,7 +235,7 @@ namespace SafeExamBrowser.Configuration
var serializer = dataSerializers.FirstOrDefault(s => s.CanSerialize(format)); var serializer = dataSerializers.FirstOrDefault(s => s.CanSerialize(format));
var status = SaveStatus.NotSupported; var status = SaveStatus.NotSupported;
serialized = default(Stream); serialized = default;
if (serializer != null) if (serializer != null)
{ {

View file

@ -213,10 +213,11 @@ namespace SafeExamBrowser.I18n.Contracts
SystemControl_BatteryChargeLowInfo, SystemControl_BatteryChargeLowInfo,
SystemControl_BatteryRemainingCharge, SystemControl_BatteryRemainingCharge,
SystemControl_KeyboardLayoutTooltip, SystemControl_KeyboardLayoutTooltip,
SystemControl_WirelessConnected, SystemControl_NetworkDisconnected,
SystemControl_WirelessConnecting, SystemControl_NetworkNotAvailable,
SystemControl_WirelessDisconnected, SystemControl_NetworkWiredConnected,
SystemControl_WirelessNotAvailable, SystemControl_NetworkWirelessConnected,
SystemControl_NetworkWirelessConnecting,
Version Version
} }
} }

View file

@ -597,17 +597,20 @@
<Entry key="SystemControl_KeyboardLayoutTooltip"> <Entry key="SystemControl_KeyboardLayoutTooltip">
Das aktuelle Tastatur-Layout ist "%%LAYOUT%%" Das aktuelle Tastatur-Layout ist "%%LAYOUT%%"
</Entry> </Entry>
<Entry key="SystemControl_WirelessConnected"> <Entry key="SystemControl_NetworkDisconnected">
Verbunden mit "%%NAME%%"
</Entry>
<Entry key="SystemControl_WirelessConnecting">
Verbinde...
</Entry>
<Entry key="SystemControl_WirelessDisconnected">
Getrennt Getrennt
</Entry> </Entry>
<Entry key="SystemControl_WirelessNotAvailable"> <Entry key="SystemControl_NetworkNotAvailable">
Kein WLAN-Netzwerkadapter verfügbar oder eingestellt Kein Netzwerkadapter verfügbar oder eingestellt
</Entry>
<Entry key="SystemControl_NetworkWiredConnected">
Verbunden
</Entry>
<Entry key="SystemControl_NetworkWirelessConnected">
Verbunden mit "%%NAME%%"
</Entry>
<Entry key="SystemControl_NetworkWirelessConnecting">
Verbinde...
</Entry> </Entry>
<Entry key="Version"> <Entry key="Version">
Version Version

View file

@ -597,18 +597,21 @@
<Entry key="SystemControl_KeyboardLayoutTooltip"> <Entry key="SystemControl_KeyboardLayoutTooltip">
The current keyboard layout is "%%LAYOUT%%" The current keyboard layout is "%%LAYOUT%%"
</Entry> </Entry>
<Entry key="SystemControl_WirelessConnected"> <Entry key="SystemControl_NetworkDisconnected">
Connected to "%%NAME%%"
</Entry>
<Entry key="SystemControl_WirelessConnecting">
Connecting...
</Entry>
<Entry key="SystemControl_WirelessDisconnected">
Disconnected Disconnected
</Entry> </Entry>
<Entry key="SystemControl_WirelessNotAvailable"> <Entry key="SystemControl_NetworkNotAvailable">
No wireless network adapter available or turned on No wireless network adapter available or turned on
</Entry> </Entry>
<Entry key="SystemControl_NetworkWiredConnected">
Connected
</Entry>
<Entry key="SystemControl_NetworkWirelessConnected">
Connected to "%%NAME%%"
</Entry>
<Entry key="SystemControl_NetworkWirelessConnecting">
Connecting...
</Entry>
<Entry key="Version"> <Entry key="Version">
Version Version
</Entry> </Entry>

View file

@ -597,18 +597,21 @@
<Entry key="SystemControl_KeyboardLayoutTooltip"> <Entry key="SystemControl_KeyboardLayoutTooltip">
La disposition actuelle du clavier est "%%LAYOUT%%" La disposition actuelle du clavier est "%%LAYOUT%%"
</Entry> </Entry>
<Entry key="SystemControl_WirelessConnected"> <Entry key="SystemControl_NetworkDisconnected">
Connecté à "%%NAME%%"
</Entry>
<Entry key="SystemControl_WirelessConnecting">
Connection en cours...
</Entry>
<Entry key="SystemControl_WirelessDisconnected">
Déconnecté Déconnecté
</Entry> </Entry>
<Entry key="SystemControl_WirelessNotAvailable"> <Entry key="SystemControl_NetworkNotAvailable">
Pas d'adaptateur réseau sans fil disponible ou allumé Pas d'adaptateur réseau sans fil disponible ou allumé
</Entry> </Entry>
<Entry key="SystemControl_NetworkWiredConnected">
Connecté
</Entry>
<Entry key="SystemControl_NetworkWirelessConnected">
Connecté à "%%NAME%%"
</Entry>
<Entry key="SystemControl_NetworkWirelessConnecting">
Connection en cours...
</Entry>
<Entry key="Version"> <Entry key="Version">
Version Version
</Entry> </Entry>

View file

@ -597,18 +597,21 @@
<Entry key="SystemControl_KeyboardLayoutTooltip"> <Entry key="SystemControl_KeyboardLayoutTooltip">
L'attuale layout della tastiera è "%%LAYOUT%%" L'attuale layout della tastiera è "%%LAYOUT%%"
</Entry> </Entry>
<Entry key="SystemControl_WirelessConnected"> <Entry key="SystemControl_NetworkDisconnected">
Collegato a "%%NAME%%"
</Entry>
<Entry key="SystemControl_WirelessConnecting">
Collegamento...
</Entry>
<Entry key="SystemControl_WirelessDisconnected">
Disconnesso Disconnesso
</Entry> </Entry>
<Entry key="SystemControl_WirelessNotAvailable"> <Entry key="SystemControl_NetworkNotAvailable">
Nessun adattatore di rete wireless disponibile o attivato Nessun adattatore di rete wireless disponibile o attivato
</Entry> </Entry>
<Entry key="SystemControl_NetworkWiredConnected">
Collegato
</Entry>
<Entry key="SystemControl_NetworkWirelessConnected">
Collegato a "%%NAME%%"
</Entry>
<Entry key="SystemControl_NetworkWirelessConnecting">
Collegamento...
</Entry>
<Entry key="Version"> <Entry key="Version">
Versione Versione
</Entry> </Entry>

View file

@ -531,18 +531,21 @@
<Entry key="SystemControl_KeyboardLayoutTooltip"> <Entry key="SystemControl_KeyboardLayoutTooltip">
当前键盘布局是 "%%LAYOUT%%" 当前键盘布局是 "%%LAYOUT%%"
</Entry> </Entry>
<Entry key="SystemControl_WirelessConnected"> <Entry key="SystemControl_NetworkDisconnected">
已连接到 "%%NAME%%"
</Entry>
<Entry key="SystemControl_WirelessConnecting">
正在连接...
</Entry>
<Entry key="SystemControl_WirelessDisconnected">
连接已断开 连接已断开
</Entry> </Entry>
<Entry key="SystemControl_WirelessNotAvailable"> <Entry key="SystemControl_NetworkNotAvailable">
没有无线网卡或未启用无线网卡 没有无线网卡或未启用无线网卡
</Entry> </Entry>
<Entry key="SystemControl_NetworkWiredConnected">
连接的
</Entry>
<Entry key="SystemControl_NetworkWirelessConnected">
已连接到 "%%NAME%%"
</Entry>
<Entry key="SystemControl_NetworkWirelessConnecting">
正在连接...
</Entry>
<Entry key="Version"> <Entry key="Version">
版本 版本
</Entry> </Entry>

View file

@ -149,7 +149,7 @@ namespace SafeExamBrowser.Runtime
var xmlParser = new XmlParser(compressor, ModuleLogger(nameof(XmlParser))); var xmlParser = new XmlParser(compressor, ModuleLogger(nameof(XmlParser)));
var xmlSerializer = new XmlSerializer(ModuleLogger(nameof(XmlSerializer))); var xmlSerializer = new XmlSerializer(ModuleLogger(nameof(XmlSerializer)));
configuration = new ConfigurationRepository(certificateStore, new HashAlgorithm(), repositoryLogger); configuration = new ConfigurationRepository(certificateStore, repositoryLogger);
appConfig = configuration.InitializeAppConfig(); appConfig = configuration.InitializeAppConfig();
configuration.Register(new BinaryParser( configuration.Register(new BinaryParser(

View file

@ -26,8 +26,8 @@ using SafeExamBrowser.Server.Data;
using SafeExamBrowser.Settings.Logging; using SafeExamBrowser.Settings.Logging;
using SafeExamBrowser.Settings.Server; using SafeExamBrowser.Settings.Server;
using SafeExamBrowser.SystemComponents.Contracts; using SafeExamBrowser.SystemComponents.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.Network;
using SafeExamBrowser.SystemComponents.Contracts.PowerSupply; using SafeExamBrowser.SystemComponents.Contracts.PowerSupply;
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork;
using Timer = System.Timers.Timer; using Timer = System.Timers.Timer;
namespace SafeExamBrowser.Server namespace SafeExamBrowser.Server
@ -45,7 +45,7 @@ namespace SafeExamBrowser.Server
private readonly IPowerSupply powerSupply; private readonly IPowerSupply powerSupply;
private readonly ISystemInfo systemInfo; private readonly ISystemInfo systemInfo;
private readonly IUserInfo userInfo; private readonly IUserInfo userInfo;
private readonly IWirelessAdapter wirelessAdapter; private readonly INetworkAdapter networkAdapter;
private ApiVersion1 api; private ApiVersion1 api;
private string connectionToken; private string connectionToken;
@ -70,7 +70,7 @@ namespace SafeExamBrowser.Server
ISystemInfo systemInfo, ISystemInfo systemInfo,
IUserInfo userInfo, IUserInfo userInfo,
IPowerSupply powerSupply = default, IPowerSupply powerSupply = default,
IWirelessAdapter wirelessAdapter = default) INetworkAdapter networkAdapter = default)
{ {
this.api = new ApiVersion1(); this.api = new ApiVersion1();
this.appConfig = appConfig; this.appConfig = appConfig;
@ -79,12 +79,12 @@ namespace SafeExamBrowser.Server
this.logger = logger; this.logger = logger;
this.logContent = new ConcurrentQueue<ILogContent>(); this.logContent = new ConcurrentQueue<ILogContent>();
this.logTimer = new Timer(); this.logTimer = new Timer();
this.networkAdapter = networkAdapter;
this.parser = new Parser(logger); this.parser = new Parser(logger);
this.pingTimer = new Timer(); this.pingTimer = new Timer();
this.powerSupply = powerSupply; this.powerSupply = powerSupply;
this.systemInfo = systemInfo; this.systemInfo = systemInfo;
this.userInfo = userInfo; this.userInfo = userInfo;
this.wirelessAdapter = wirelessAdapter;
} }
public ServerResponse Connect() public ServerResponse Connect()
@ -226,7 +226,7 @@ namespace SafeExamBrowser.Server
public void Initialize(ServerSettings settings) public void Initialize(ServerSettings settings)
{ {
this.settings = settings; this.settings = settings;
httpClient = new HttpClient(); httpClient = new HttpClient();
httpClient.BaseAddress = new Uri(settings.ServerUrl); httpClient.BaseAddress = new Uri(settings.ServerUrl);
@ -348,20 +348,20 @@ namespace SafeExamBrowser.Server
pingTimer.Start(); pingTimer.Start();
logger.Info("Started sending pings."); logger.Info("Started sending pings.");
if (powerSupply != default(IPowerSupply) && wirelessAdapter != default(IWirelessAdapter)) if (powerSupply != default && networkAdapter != default)
{ {
powerSupply.StatusChanged += PowerSupply_StatusChanged; powerSupply.StatusChanged += PowerSupply_StatusChanged;
wirelessAdapter.NetworksChanged += WirelessAdapter_NetworksChanged; networkAdapter.Changed += NetworkAdapter_Changed;
logger.Info("Started monitoring system components."); logger.Info("Started monitoring system components.");
} }
} }
public void StopConnectivity() public void StopConnectivity()
{ {
if (powerSupply != default(IPowerSupply) && wirelessAdapter != default(IWirelessAdapter)) if (powerSupply != default && networkAdapter != default)
{ {
powerSupply.StatusChanged -= PowerSupply_StatusChanged; powerSupply.StatusChanged -= PowerSupply_StatusChanged;
wirelessAdapter.NetworksChanged -= WirelessAdapter_NetworksChanged; networkAdapter.Changed -= NetworkAdapter_Changed;
logger.Info("Stopped monitoring system components."); logger.Info("Stopped monitoring system components.");
} }
@ -477,7 +477,7 @@ namespace SafeExamBrowser.Server
SendPowerSupplyStatus(text, value); SendPowerSupplyStatus(text, value);
currentPowerSupplyValue = value; currentPowerSupplyValue = value;
} }
else if (connected != connectedToPowergrid) else if (connected != connectedToPowergrid)
{ {
var text = $"<battery> Device has been {(connected ? "connected to" : "disconnected from")} power grid"; var text = $"<battery> Device has been {(connected ? "connected to" : "disconnected from")} power grid";
SendPowerSupplyStatus(text, value); SendPowerSupplyStatus(text, value);
@ -507,13 +507,13 @@ namespace SafeExamBrowser.Server
TryExecute(HttpMethod.Post, api.LogEndpoint, out _, content, contentType, authorization, token); TryExecute(HttpMethod.Post, api.LogEndpoint, out _, content, contentType, authorization, token);
} }
private void WirelessAdapter_NetworksChanged() private void NetworkAdapter_Changed()
{ {
const int NOT_CONNECTED = -1; const int NOT_CONNECTED = -1;
try try
{ {
var network = wirelessAdapter.GetNetworks().FirstOrDefault(n => n.Status == WirelessNetworkStatus.Connected); var network = networkAdapter.GetWirelessNetworks().FirstOrDefault(n => n.Status == ConnectionStatus.Connected);
if (network?.SignalStrength != currentWlanValue) if (network?.SignalStrength != currentWlanValue)
{ {

View file

@ -30,7 +30,7 @@ namespace SafeExamBrowser.Settings.UserInterface
/// Determines whether the application log is accessible via the action center. /// Determines whether the application log is accessible via the action center.
/// </summary> /// </summary>
public bool ShowApplicationLog { get; set; } public bool ShowApplicationLog { get; set; }
/// <summary> /// <summary>
/// Determines whether the system control for audio is accessible via the action center. /// Determines whether the system control for audio is accessible via the action center.
/// </summary> /// </summary>
@ -47,8 +47,8 @@ namespace SafeExamBrowser.Settings.UserInterface
public bool ShowKeyboardLayout { get; set; } public bool ShowKeyboardLayout { get; set; }
/// <summary> /// <summary>
/// Determines whether the system control for the wireless network is accessible via the action center. /// Determines whether the system control for the network is accessible via the action center.
/// </summary> /// </summary>
public bool ShowWirelessNetwork { get; set; } public bool ShowNetwork { get; set; }
} }
} }

View file

@ -47,8 +47,8 @@ namespace SafeExamBrowser.Settings.UserInterface
public bool ShowKeyboardLayout { get; set; } public bool ShowKeyboardLayout { get; set; }
/// <summary> /// <summary>
/// Determines whether the system control for the wireless network is accessible via the taskbar. /// Determines whether the system control for the network is accessible via the taskbar.
/// </summary> /// </summary>
public bool ShowWirelessNetwork { get; set; } public bool ShowNetwork { get; set; }
} }
} }

View file

@ -6,13 +6,16 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
namespace SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork namespace SafeExamBrowser.SystemComponents.Contracts.Network
{ {
/// <summary> /// <summary>
/// Defines all possible wireless network statuses which can be determined by the application. /// Defines all possible connection statuses which can be determined by the application.
/// </summary> /// </summary>
public enum WirelessNetworkStatus public enum ConnectionStatus
{ {
/// <summary>
/// The connection status is not determinable.
/// </summary>
Undefined = 0, Undefined = 0,
/// <summary> /// <summary>

View file

@ -0,0 +1,31 @@
/*
* Copyright (c) 2022 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.SystemComponents.Contracts.Network
{
/// <summary>
/// Defines all possible connection types which can be determined by the application.
/// </summary>
public enum ConnectionType
{
/// <summary>
/// The connection type cannot be determined.
/// </summary>
Undefined = 0,
/// <summary>
/// A wired network connection.
/// </summary>
Wired,
/// <summary>
/// A wireless network connection.
/// </summary>
Wireless
}
}

View file

@ -6,10 +6,10 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
namespace SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork.Events namespace SafeExamBrowser.SystemComponents.Contracts.Network.Events
{ {
/// <summary> /// <summary>
/// Indicates that the available wireless networks have changed. /// Indicates that the network adapter has changed.
/// </summary> /// </summary>
public delegate void NetworksChangedEventHandler(); public delegate void ChangedEventHandler();
} }

View file

@ -0,0 +1,45 @@
/*
* Copyright (c) 2022 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using System.Collections.Generic;
using SafeExamBrowser.SystemComponents.Contracts.Network.Events;
namespace SafeExamBrowser.SystemComponents.Contracts.Network
{
/// <summary>
/// Defines the functionality of the network adapter system component.
/// </summary>
public interface INetworkAdapter : ISystemComponent
{
/// <summary>
/// The connection status of the network adapter.
/// </summary>
ConnectionStatus Status { get; }
/// <summary>
/// The type of the current network connection.
/// </summary>
ConnectionType Type { get; }
/// <summary>
/// Fired when the network adapter has changed.
/// </summary>
event ChangedEventHandler Changed;
/// <summary>
/// Attempts to connect to the wireless network with the given ID.
/// </summary>
void ConnectToWirelessNetwork(Guid id);
/// <summary>
/// Retrieves all currently available wireless networks.
/// </summary>
IEnumerable<IWirelessNetwork> GetWirelessNetworks();
}
}

View file

@ -8,7 +8,7 @@
using System; using System;
namespace SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork namespace SafeExamBrowser.SystemComponents.Contracts.Network
{ {
/// <summary> /// <summary>
/// Defines a wireless network which can be connected to by the application. /// Defines a wireless network which can be connected to by the application.
@ -33,6 +33,6 @@ namespace SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork
/// <summary> /// <summary>
/// The connection status of this network. /// The connection status of this network.
/// </summary> /// </summary>
WirelessNetworkStatus Status { get; } ConnectionStatus Status { get; }
} }
} }

View file

@ -59,6 +59,7 @@
<Compile Include="IFileSystem.cs" /> <Compile Include="IFileSystem.cs" />
<Compile Include="IRemoteSessionDetector.cs" /> <Compile Include="IRemoteSessionDetector.cs" />
<Compile Include="IVirtualMachineDetector.cs" /> <Compile Include="IVirtualMachineDetector.cs" />
<Compile Include="Network\ConnectionType.cs" />
<Compile Include="PowerSupply\Events\StatusChangedEventHandler.cs" /> <Compile Include="PowerSupply\Events\StatusChangedEventHandler.cs" />
<Compile Include="PowerSupply\IPowerSupply.cs" /> <Compile Include="PowerSupply\IPowerSupply.cs" />
<Compile Include="PowerSupply\BatteryChargeStatus.cs" /> <Compile Include="PowerSupply\BatteryChargeStatus.cs" />
@ -68,14 +69,13 @@
<Compile Include="ISystemComponent.cs" /> <Compile Include="ISystemComponent.cs" />
<Compile Include="ISystemInfo.cs" /> <Compile Include="ISystemInfo.cs" />
<Compile Include="IUserInfo.cs" /> <Compile Include="IUserInfo.cs" />
<Compile Include="WirelessNetwork\Events\NetworksChangedEventHandler.cs" /> <Compile Include="Network\Events\ChangedEventHandler.cs" />
<Compile Include="WirelessNetwork\Events\StatusChangedEventHandler.cs" /> <Compile Include="Network\INetworkAdapter.cs" />
<Compile Include="WirelessNetwork\IWirelessAdapter.cs" /> <Compile Include="Network\IWirelessNetwork.cs" />
<Compile Include="WirelessNetwork\IWirelessNetwork.cs" />
<Compile Include="OperatingSystem.cs" /> <Compile Include="OperatingSystem.cs" />
<Compile Include="PowerSupply\IPowerSupplyStatus.cs" /> <Compile Include="PowerSupply\IPowerSupplyStatus.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="WirelessNetwork\WirelessNetworkStatus.cs" /> <Compile Include="Network\ConnectionStatus.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

View file

@ -1,15 +0,0 @@
/*
* Copyright (c) 2022 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.SystemComponents.Contracts.WirelessNetwork.Events
{
/// <summary>
/// Indicates that the wireless network status has changed.
/// </summary>
public delegate void StatusChangedEventHandler(WirelessNetworkStatus status);
}

View file

@ -1,42 +0,0 @@
/*
* Copyright (c) 2022 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using System.Collections.Generic;
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork.Events;
namespace SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork
{
public interface IWirelessAdapter : ISystemComponent
{
/// <summary>
/// Fired when the available wireless networks changed.
/// </summary>
event NetworksChangedEventHandler NetworksChanged;
/// <summary>
/// Fired when the wireless network status changed.
/// </summary>
event StatusChangedEventHandler StatusChanged;
/// <summary>
/// Indicates whether the system has an active wireless network adapter.
/// </summary>
bool IsAvailable { get; }
/// <summary>
/// Attempts to connect to the wireless network with the given ID.
/// </summary>
void Connect(Guid id);
/// <summary>
/// Retrieves all currently available networks.
/// </summary>
IEnumerable<IWirelessNetwork> GetNetworks();
}
}

View file

@ -0,0 +1,215 @@
/*
* Copyright (c) 2022 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Timers;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.Network;
using SafeExamBrowser.SystemComponents.Contracts.Network.Events;
using SafeExamBrowser.WindowsApi.Contracts;
using SimpleWifi;
using SimpleWifi.Win32;
using SimpleWifi.Win32.Interop;
namespace SafeExamBrowser.SystemComponents.Network
{
public class NetworkAdapter : INetworkAdapter
{
private readonly object @lock = new object();
private readonly ILogger logger;
private readonly INativeMethods nativeMethods;
private readonly List<WirelessNetwork> wirelessNetworks;
private Timer timer;
private Wifi wifi;
public ConnectionStatus Status { get; private set; }
public ConnectionType Type { get; private set; }
public event ChangedEventHandler Changed;
public NetworkAdapter(ILogger logger, INativeMethods nativeMethods)
{
this.logger = logger;
this.nativeMethods = nativeMethods;
this.wirelessNetworks = new List<WirelessNetwork>();
}
public void ConnectToWirelessNetwork(Guid id)
{
lock (@lock)
{
var network = wirelessNetworks.FirstOrDefault(n => n.Id == id);
if (network != default)
{
try
{
var request = new AuthRequest(network.AccessPoint);
logger.Info($"Attempting to connect to '{network.Name}'...");
network.AccessPoint.ConnectAsync(request, false, (success) => AccessPoint_OnConnectCompleted(network.Name, success));
Status = ConnectionStatus.Connecting;
}
catch (Exception e)
{
logger.Error($"Failed to connect to wireless network '{network.Name}!'", e);
}
}
else
{
logger.Warn($"Could not find network with id '{id}'!");
}
}
Changed?.Invoke();
}
public IEnumerable<IWirelessNetwork> GetWirelessNetworks()
{
lock (@lock)
{
return new List<WirelessNetwork>(wirelessNetworks);
}
}
public void Initialize()
{
const int FIVE_SECONDS = 5000;
NetworkChange.NetworkAddressChanged += (o, args) => Update();
NetworkChange.NetworkAvailabilityChanged += (o, args) => Update();
wifi = new Wifi();
wifi.ConnectionStatusChanged += (o, args) => Update();
timer = new Timer(FIVE_SECONDS);
timer.Elapsed += (o, args) => Update();
timer.AutoReset = true;
timer.Start();
Update();
logger.Info("Started monitoring the network adapter.");
}
public void Terminate()
{
if (timer != null)
{
timer.Stop();
logger.Info("Stopped monitoring the network adapter.");
}
}
private void AccessPoint_OnConnectCompleted(string name, bool success)
{
lock (@lock)
{
// This handler seems to be called before the connection has been fully established, thus we don't yet set the status to connected...
Status = success ? ConnectionStatus.Connecting : ConnectionStatus.Disconnected;
}
if (success)
{
logger.Info($"Successfully connected to wireless network '{name}'.");
}
else
{
logger.Error($"Failed to connect to wireless network '{name}!'");
}
}
private void Update()
{
try
{
lock (@lock)
{
var hasInternet = nativeMethods.HasInternetConnection();
var hasWireless = !wifi.NoWifiAvailable && !IsTurnedOff();
var isConnecting = Status == ConnectionStatus.Connecting;
var previousStatus = Status;
wirelessNetworks.Clear();
if (hasWireless)
{
foreach (var accessPoint in wifi.GetAccessPoints())
{
// The user may only connect to an already configured or connected wireless network!
if (accessPoint.HasProfile || accessPoint.IsConnected)
{
wirelessNetworks.Add(ToWirelessNetwork(accessPoint));
}
}
}
Type = hasWireless ? ConnectionType.Wireless : (hasInternet ? ConnectionType.Wired : ConnectionType.Undefined);
Status = hasInternet ? ConnectionStatus.Connected : (hasWireless && isConnecting ? ConnectionStatus.Connecting : ConnectionStatus.Disconnected);
if (previousStatus != ConnectionStatus.Connected && Status == ConnectionStatus.Connected)
{
logger.Info("Connection established.");
}
if (previousStatus != ConnectionStatus.Disconnected && Status == ConnectionStatus.Disconnected)
{
logger.Info("Connection lost.");
}
}
}
catch (Exception e)
{
logger.Error("Failed to update network adapter!", e);
}
Changed?.Invoke();
}
private bool IsTurnedOff()
{
try
{
var client = new WlanClient();
foreach (var @interface in client.Interfaces)
{
foreach (var state in @interface.RadioState.PhyRadioState)
{
if (state.dot11SoftwareRadioState == Dot11RadioState.On && state.dot11HardwareRadioState == Dot11RadioState.On)
{
return false;
}
}
}
}
catch (Exception e)
{
logger.Error("Failed to determine the radio state of the wireless adapter(s)! Assuming it is (all are) turned off...", e);
}
return true;
}
private WirelessNetwork ToWirelessNetwork(AccessPoint accessPoint)
{
return new WirelessNetwork
{
AccessPoint = accessPoint,
Name = accessPoint.Name,
SignalStrength = Convert.ToInt32(accessPoint.SignalStrength),
Status = accessPoint.IsConnected ? ConnectionStatus.Connected : ConnectionStatus.Disconnected
};
}
}
}

View file

@ -7,10 +7,10 @@
*/ */
using System; using System;
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork; using SafeExamBrowser.SystemComponents.Contracts.Network;
using SimpleWifi; using SimpleWifi;
namespace SafeExamBrowser.SystemComponents.WirelessNetwork namespace SafeExamBrowser.SystemComponents.Network
{ {
internal class WirelessNetwork : IWirelessNetwork internal class WirelessNetwork : IWirelessNetwork
{ {
@ -19,7 +19,7 @@ namespace SafeExamBrowser.SystemComponents.WirelessNetwork
public Guid Id { get; } public Guid Id { get; }
public string Name { get; set; } public string Name { get; set; }
public int SignalStrength { get; set; } public int SignalStrength { get; set; }
public WirelessNetworkStatus Status { get; set; } public ConnectionStatus Status { get; set; }
public WirelessNetwork() public WirelessNetwork()
{ {

View file

@ -101,8 +101,8 @@
<Compile Include="SystemInfo.cs" /> <Compile Include="SystemInfo.cs" />
<Compile Include="UserInfo.cs" /> <Compile Include="UserInfo.cs" />
<Compile Include="VirtualMachineDetector.cs" /> <Compile Include="VirtualMachineDetector.cs" />
<Compile Include="WirelessNetwork\WirelessAdapter.cs" /> <Compile Include="Network\NetworkAdapter.cs" />
<Compile Include="WirelessNetwork\WirelessNetwork.cs" /> <Compile Include="Network\WirelessNetwork.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\SafeExamBrowser.Logging.Contracts\SafeExamBrowser.Logging.Contracts.csproj"> <ProjectReference Include="..\SafeExamBrowser.Logging.Contracts\SafeExamBrowser.Logging.Contracts.csproj">
@ -117,6 +117,10 @@
<Project>{903129c6-e236-493b-9ad6-c6a57f647a3a}</Project> <Project>{903129c6-e236-493b-9ad6-c6a57f647a3a}</Project>
<Name>SafeExamBrowser.SystemComponents.Contracts</Name> <Name>SafeExamBrowser.SystemComponents.Contracts</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\SafeExamBrowser.WindowsApi.Contracts\SafeExamBrowser.WindowsApi.Contracts.csproj">
<Project>{7016f080-9aa5-41b2-a225-385ad877c171}</Project>
<Name>SafeExamBrowser.WindowsApi.Contracts</Name>
</ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="app.config" /> <None Include="app.config" />

View file

@ -1,203 +0,0 @@
/*
* Copyright (c) 2022 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Timers;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork;
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork.Events;
using SimpleWifi;
using SimpleWifi.Win32;
using SimpleWifi.Win32.Interop;
namespace SafeExamBrowser.SystemComponents.WirelessNetwork
{
public class WirelessAdapter : IWirelessAdapter
{
private readonly object @lock = new object();
private List<WirelessNetwork> networks;
private ILogger logger;
private Timer timer;
private Wifi wifi;
public bool IsAvailable { get; private set; }
public event NetworksChangedEventHandler NetworksChanged;
public event StatusChangedEventHandler StatusChanged;
public WirelessAdapter(ILogger logger)
{
this.logger = logger;
this.networks = new List<WirelessNetwork>();
}
public void Connect(Guid id)
{
lock (@lock)
{
var network = networks.FirstOrDefault(n => n.Id == id);
if (network != default(WirelessNetwork))
{
try
{
var request = new AuthRequest(network.AccessPoint);
logger.Info($"Attempting to connect to '{network.Name}'...");
network.AccessPoint.ConnectAsync(request, false, (success) => AccessPoint_OnConnectCompleted(network.Name, success));
StatusChanged?.Invoke(WirelessNetworkStatus.Connecting);
}
catch (Exception e)
{
logger.Error($"Failed to connect to wireless network '{network.Name}!'", e);
}
}
else
{
logger.Warn($"Could not find network with id '{id}'!");
}
}
}
public IEnumerable<IWirelessNetwork> GetNetworks()
{
lock (@lock)
{
return new List<WirelessNetwork>(networks);
}
}
public void Initialize()
{
const int FIVE_SECONDS = 5000;
wifi = new Wifi();
wifi.ConnectionStatusChanged += Wifi_ConnectionStatusChanged;
IsAvailable = !wifi.NoWifiAvailable && !IsTurnedOff();
if (IsAvailable)
{
UpdateAvailableNetworks();
timer = new Timer(FIVE_SECONDS);
timer.Elapsed += Timer_Elapsed;
timer.AutoReset = true;
timer.Start();
logger.Info("Started monitoring the wireless network adapter.");
}
else
{
logger.Info("Wireless networks cannot be monitored, as there is no hardware adapter available or it is turned off.");
}
}
public void Terminate()
{
if (timer != null)
{
timer.Stop();
logger.Info("Stopped monitoring the wireless network adapter.");
}
}
private void AccessPoint_OnConnectCompleted(string name, bool success)
{
if (success)
{
logger.Info($"Successfully connected to wireless network '{name}'.");
}
else
{
logger.Error($"Failed to connect to wireless network '{name}!'");
}
UpdateAvailableNetworks();
}
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
UpdateAvailableNetworks();
}
private void Wifi_ConnectionStatusChanged(object sender, WifiStatusEventArgs e)
{
UpdateAvailableNetworks();
}
private bool IsTurnedOff()
{
try
{
var client = new WlanClient();
foreach (var @interface in client.Interfaces)
{
foreach (var state in @interface.RadioState.PhyRadioState)
{
if (state.dot11SoftwareRadioState == Dot11RadioState.On && state.dot11HardwareRadioState == Dot11RadioState.On)
{
return false;
}
}
}
}
catch (Exception e)
{
logger.Error("Failed to determine the radio state of the wireless adapter(s)! Assuming it is (all are) turned off...", e);
}
return true;
}
private void UpdateAvailableNetworks()
{
lock (@lock)
{
try
{
networks.Clear();
foreach (var accessPoint in wifi.GetAccessPoints())
{
// The user may only connect to an already configured or connected wireless network!
if (accessPoint.HasProfile || accessPoint.IsConnected)
{
networks.Add(ToNetwork(accessPoint));
}
}
NetworksChanged?.Invoke();
}
catch (Exception e)
{
logger.Error("Failed to update available networks!", e);
}
}
}
private WirelessNetwork ToNetwork(AccessPoint accessPoint)
{
return new WirelessNetwork
{
AccessPoint = accessPoint,
Name = accessPoint.Name,
SignalStrength = Convert.ToInt32(accessPoint.SignalStrength),
Status = accessPoint.IsConnected ? WirelessNetworkStatus.Connected : WirelessNetworkStatus.Disconnected
};
}
private WirelessNetworkStatus ToStatus(WifiStatus status)
{
return status == WifiStatus.Connected ? WirelessNetworkStatus.Connected : WirelessNetworkStatus.Disconnected;
}
}
}

View file

@ -18,8 +18,8 @@ using SafeExamBrowser.Settings.Browser;
using SafeExamBrowser.Settings.Proctoring; using SafeExamBrowser.Settings.Proctoring;
using SafeExamBrowser.SystemComponents.Contracts.Audio; using SafeExamBrowser.SystemComponents.Contracts.Audio;
using SafeExamBrowser.SystemComponents.Contracts.Keyboard; using SafeExamBrowser.SystemComponents.Contracts.Keyboard;
using SafeExamBrowser.SystemComponents.Contracts.Network;
using SafeExamBrowser.SystemComponents.Contracts.PowerSupply; using SafeExamBrowser.SystemComponents.Contracts.PowerSupply;
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork;
using SafeExamBrowser.UserInterface.Contracts.Browser; using SafeExamBrowser.UserInterface.Contracts.Browser;
using SafeExamBrowser.UserInterface.Contracts.Proctoring; using SafeExamBrowser.UserInterface.Contracts.Proctoring;
using SafeExamBrowser.UserInterface.Contracts.Shell; using SafeExamBrowser.UserInterface.Contracts.Shell;
@ -78,6 +78,11 @@ namespace SafeExamBrowser.UserInterface.Contracts
/// </summary> /// </summary>
IWindow CreateLogWindow(ILogger logger); IWindow CreateLogWindow(ILogger logger);
/// <summary>
/// Creates a system control which allows to view and/or change the network connection of the computer.
/// </summary>
ISystemControl CreateNetworkControl(INetworkAdapter adapter, Location location);
/// <summary> /// <summary>
/// Creates a notification control for the given notification, initialized for the specified location. /// Creates a notification control for the given notification, initialized for the specified location.
/// </summary> /// </summary>
@ -132,10 +137,5 @@ namespace SafeExamBrowser.UserInterface.Contracts
/// Creates a new taskview. /// Creates a new taskview.
/// </summary> /// </summary>
ITaskview CreateTaskview(); ITaskview CreateTaskview();
/// <summary>
/// Creates a system control which allows to change the wireless network connection of the computer.
/// </summary>
ISystemControl CreateWirelessNetworkControl(IWirelessAdapter wirelessAdapter, Location location);
} }
} }

View file

@ -1,4 +1,4 @@
<UserControl x:Class="SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter.WirelessNetworkButton" x:ClassModifier="internal" <UserControl x:Class="SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter.NetworkButton" x:ClassModifier="internal"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

View file

@ -9,17 +9,17 @@
using System; using System;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork; using SafeExamBrowser.SystemComponents.Contracts.Network;
namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter
{ {
internal partial class WirelessNetworkButton : UserControl internal partial class NetworkButton : UserControl
{ {
private IWirelessNetwork network; private readonly IWirelessNetwork network;
internal event EventHandler NetworkSelected; internal event EventHandler NetworkSelected;
internal WirelessNetworkButton(IWirelessNetwork network) internal NetworkButton(IWirelessNetwork network)
{ {
this.network = network; this.network = network;
@ -30,7 +30,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter
private void InitializeNetworkButton() private void InitializeNetworkButton()
{ {
Button.Click += (o, args) => NetworkSelected?.Invoke(this, EventArgs.Empty); Button.Click += (o, args) => NetworkSelected?.Invoke(this, EventArgs.Empty);
IsCurrentTextBlock.Visibility = network.Status == WirelessNetworkStatus.Connected ? Visibility.Visible : Visibility.Hidden; IsCurrentTextBlock.Visibility = network.Status == ConnectionStatus.Connected ? Visibility.Visible : Visibility.Hidden;
NetworkNameTextBlock.Text = network.Name; NetworkNameTextBlock.Text = network.Name;
SignalStrengthTextBlock.Text = $"{network.SignalStrength}%"; SignalStrengthTextBlock.Text = $"{network.SignalStrength}%";
} }

View file

@ -1,4 +1,4 @@
<UserControl x:Class="SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter.WirelessNetworkControl" x:ClassModifier="internal" <UserControl x:Class="SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter.NetworkControl" x:ClassModifier="internal"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@ -19,7 +19,7 @@
<Popup x:Name="Popup" IsOpen="False" Placement="Top" PlacementTarget="{Binding ElementName=Button}"> <Popup x:Name="Popup" IsOpen="False" Placement="Top" PlacementTarget="{Binding ElementName=Button}">
<Border Background="Gray"> <Border Background="Gray">
<ScrollViewer MaxHeight="250" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}"> <ScrollViewer MaxHeight="250" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}">
<StackPanel x:Name="NetworksStackPanel" /> <StackPanel x:Name="WirelessNetworksStackPanel" />
</ScrollViewer> </ScrollViewer>
</Border> </Border>
</Popup> </Popup>
@ -30,10 +30,11 @@
<RowDefinition Height="3*" /> <RowDefinition Height="3*" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center"> <Grid Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center">
<Viewbox x:Name="SignalStrengthIcon" Stretch="Uniform" Width="Auto" /> <Viewbox x:Name="WirelessIcon" Stretch="Uniform" Width="Auto" Visibility="Collapsed" />
<fa:ImageAwesome x:Name="NoAdapterIcon" Foreground="Red" Icon="Ban" Margin="1" Opacity="0.3" Visibility="Collapsed" /> <fa:ImageAwesome x:Name="WiredIcon" Icon="Tv" Margin="0,2,4,4" Visibility="Collapsed" />
<fa:ImageAwesome x:Name="LoadingIcon" Foreground="Black" Icon="Cog" Margin="5" Spin="True" SpinDuration="2" Visibility="Collapsed" /> <Border Background="White" CornerRadius="6" Height="12" HorizontalAlignment="Right" Margin="-3,0" Panel.ZIndex="10" VerticalAlignment="Bottom">
<Image x:Name="NetworkStatusIcon" Height="7" HorizontalAlignment="Right" Margin="-2,0" Panel.ZIndex="10" VerticalAlignment="Bottom" /> <fa:ImageAwesome x:Name="NetworkStatusIcon" />
</Border>
</Grid> </Grid>
<TextBlock Grid.Row="1" x:Name="Text" FontSize="11" Foreground="White" TextAlignment="Center" TextTrimming="CharacterEllipsis" TextWrapping="Wrap" VerticalAlignment="Bottom" /> <TextBlock Grid.Row="1" x:Name="Text" FontSize="11" Foreground="White" TextAlignment="Center" TextTrimming="CharacterEllipsis" TextWrapping="Wrap" VerticalAlignment="Bottom" />
</Grid> </Grid>

View file

@ -0,0 +1,135 @@
/*
* Copyright (c) 2022 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using FontAwesome.WPF;
using SafeExamBrowser.Core.Contracts.Resources.Icons;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.Network;
using SafeExamBrowser.UserInterface.Contracts.Shell;
using SafeExamBrowser.UserInterface.Shared.Utilities;
namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter
{
internal partial class NetworkControl : UserControl, ISystemControl
{
private readonly INetworkAdapter adapter;
private readonly IText text;
internal NetworkControl(INetworkAdapter adapter, IText text)
{
this.adapter = adapter;
this.text = text;
InitializeComponent();
InitializeWirelessNetworkControl();
}
public void Close()
{
Dispatcher.InvokeAsync(() => Popup.IsOpen = false);
}
private void InitializeWirelessNetworkControl()
{
var originalBrush = Grid.Background;
adapter.Changed += () => Dispatcher.InvokeAsync(Update);
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
Popup.Opened += (o, args) => Grid.Background = Brushes.Gray;
Popup.Closed += (o, args) => Grid.Background = originalBrush;
WirelessIcon.Child = GetWirelessIcon(0);
Update();
}
private void Update()
{
WirelessNetworksStackPanel.Children.Clear();
foreach (var network in adapter.GetWirelessNetworks())
{
var button = new NetworkButton(network);
button.NetworkSelected += (o, args) => adapter.ConnectToWirelessNetwork(network.Id);
if (network.Status == ConnectionStatus.Connected)
{
WirelessIcon.Child = GetWirelessIcon(network.SignalStrength);
UpdateText(text.Get(TextKey.SystemControl_NetworkWirelessConnected).Replace("%%NAME%%", network.Name));
}
WirelessNetworksStackPanel.Children.Add(button);
}
switch (adapter.Type)
{
case ConnectionType.Wired:
Button.IsEnabled = false;
UpdateText(text.Get(TextKey.SystemControl_NetworkWiredConnected));
WiredIcon.Visibility = Visibility.Visible;
WirelessIcon.Visibility = Visibility.Collapsed;
break;
case ConnectionType.Wireless:
Button.IsEnabled = true;
WiredIcon.Visibility = Visibility.Collapsed;
WirelessIcon.Visibility = Visibility.Visible;
break;
default:
Button.IsEnabled = false;
UpdateText(text.Get(TextKey.SystemControl_NetworkNotAvailable));
WiredIcon.Visibility = Visibility.Visible;
WirelessIcon.Visibility = Visibility.Collapsed;
break;
}
switch (adapter.Status)
{
case ConnectionStatus.Connected:
NetworkStatusIcon.Rotation = 0;
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Globe, Brushes.Green);
NetworkStatusIcon.Spin = false;
break;
case ConnectionStatus.Connecting:
UpdateText(text.Get(TextKey.SystemControl_NetworkWirelessConnecting));
NetworkStatusIcon.Rotation = 0;
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Cog, Brushes.DimGray);
NetworkStatusIcon.Spin = true;
NetworkStatusIcon.SpinDuration = 2;
break;
default:
UpdateText(text.Get(TextKey.SystemControl_NetworkDisconnected));
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Ban, Brushes.DarkOrange);
NetworkStatusIcon.Spin = false;
WirelessIcon.Child = GetWirelessIcon(0);
break;
}
}
private void UpdateText(string text)
{
Button.ToolTip = text;
Text.Text = text;
}
private UIElement GetWirelessIcon(int signalStrength)
{
var icon = signalStrength > 66 ? "100" : (signalStrength > 33 ? "66" : (signalStrength > 0 ? "33" : "0"));
var uri = new Uri($"pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/WiFi_Light_{icon}.xaml");
var resource = new XamlIconResource { Uri = uri };
return IconResourceLoader.Load(resource);
}
}
}

View file

@ -1,142 +0,0 @@
/*
* Copyright (c) 2022 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using FontAwesome.WPF;
using SafeExamBrowser.Core.Contracts.Resources.Icons;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork;
using SafeExamBrowser.UserInterface.Contracts.Shell;
using SafeExamBrowser.UserInterface.Shared.Utilities;
namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter
{
internal partial class WirelessNetworkControl : UserControl, ISystemControl
{
private IWirelessAdapter wirelessAdapter;
private IText text;
internal WirelessNetworkControl(IWirelessAdapter wirelessAdapter, IText text)
{
this.wirelessAdapter = wirelessAdapter;
this.text = text;
InitializeComponent();
InitializeWirelessNetworkControl();
}
public void Close()
{
Dispatcher.InvokeAsync(() => Popup.IsOpen = false);
}
private void InitializeWirelessNetworkControl()
{
var originalBrush = Grid.Background;
SignalStrengthIcon.Child = GetIcon(0);
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
Popup.Opened += (o, args) => Grid.Background = Brushes.Gray;
Popup.Closed += (o, args) => Grid.Background = originalBrush;
if (wirelessAdapter.IsAvailable)
{
wirelessAdapter.NetworksChanged += WirelessAdapter_NetworksChanged;
wirelessAdapter.StatusChanged += WirelessAdapter_StatusChanged;
UpdateNetworks();
}
else
{
Button.IsEnabled = false;
NoAdapterIcon.Visibility = Visibility.Visible;
UpdateText(text.Get(TextKey.SystemControl_WirelessNotAvailable));
}
}
private void WirelessAdapter_NetworksChanged()
{
Dispatcher.InvokeAsync(UpdateNetworks);
}
private void WirelessAdapter_StatusChanged(WirelessNetworkStatus status)
{
Dispatcher.InvokeAsync(() => UpdateStatus(status));
}
private void UpdateNetworks()
{
var status = WirelessNetworkStatus.Disconnected;
NetworksStackPanel.Children.Clear();
foreach (var network in wirelessAdapter.GetNetworks())
{
var button = new WirelessNetworkButton(network);
button.NetworkSelected += (o, args) => wirelessAdapter.Connect(network.Id);
if (network.Status == WirelessNetworkStatus.Connected)
{
status = WirelessNetworkStatus.Connected;
SignalStrengthIcon.Child = GetIcon(network.SignalStrength);
UpdateText(text.Get(TextKey.SystemControl_WirelessConnected).Replace("%%NAME%%", network.Name));
}
NetworksStackPanel.Children.Add(button);
}
UpdateStatus(status);
}
private void UpdateStatus(WirelessNetworkStatus status)
{
LoadingIcon.Visibility = Visibility.Collapsed;
SignalStrengthIcon.Visibility = Visibility.Visible;
NetworkStatusIcon.Visibility = Visibility.Visible;
switch (status)
{
case WirelessNetworkStatus.Connected:
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Check, Brushes.Green);
break;
case WirelessNetworkStatus.Connecting:
LoadingIcon.Visibility = Visibility.Visible;
SignalStrengthIcon.Visibility = Visibility.Collapsed;
NetworkStatusIcon.Visibility = Visibility.Collapsed;
UpdateText(text.Get(TextKey.SystemControl_WirelessConnecting));
break;
default:
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Close, Brushes.Orange);
SignalStrengthIcon.Child = GetIcon(0);
UpdateText(text.Get(TextKey.SystemControl_WirelessDisconnected));
break;
}
}
private void UpdateText(string text)
{
Button.ToolTip = text;
Text.Text = text;
}
private UIElement GetIcon(int signalStrength)
{
var icon = signalStrength > 66 ? "100" : (signalStrength > 33 ? "66" : (signalStrength > 0 ? "33" : "0"));
var uri = new Uri($"pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/WiFi_Light_{icon}.xaml");
var resource = new XamlIconResource { Uri = uri };
return IconResourceLoader.Load(resource);
}
}
}

View file

@ -1,4 +1,4 @@
<UserControl x:Class="SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar.WirelessNetworkButton" x:ClassModifier="internal" <UserControl x:Class="SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar.NetworkButton" x:ClassModifier="internal"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

View file

@ -9,17 +9,17 @@
using System; using System;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork; using SafeExamBrowser.SystemComponents.Contracts.Network;
namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
{ {
internal partial class WirelessNetworkButton : UserControl internal partial class NetworkButton : UserControl
{ {
private IWirelessNetwork network; private readonly IWirelessNetwork network;
internal event EventHandler NetworkSelected; internal event EventHandler NetworkSelected;
internal WirelessNetworkButton(IWirelessNetwork network) internal NetworkButton(IWirelessNetwork network)
{ {
this.network = network; this.network = network;
@ -30,7 +30,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
private void InitializeNetworkButton() private void InitializeNetworkButton()
{ {
Button.Click += (o, args) => NetworkSelected?.Invoke(this, EventArgs.Empty); Button.Click += (o, args) => NetworkSelected?.Invoke(this, EventArgs.Empty);
IsCurrentTextBlock.Visibility = network.Status == WirelessNetworkStatus.Connected ? Visibility.Visible : Visibility.Hidden; IsCurrentTextBlock.Visibility = network.Status == ConnectionStatus.Connected ? Visibility.Visible : Visibility.Hidden;
NetworkNameTextBlock.Text = network.Name; NetworkNameTextBlock.Text = network.Name;
SignalStrengthTextBlock.Text = $"{network.SignalStrength}%"; SignalStrengthTextBlock.Text = $"{network.SignalStrength}%";
} }

View file

@ -1,4 +1,4 @@
<UserControl x:Class="SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar.WirelessNetworkControl" x:ClassModifier="internal" <UserControl x:Class="SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar.NetworkControl" x:ClassModifier="internal"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@ -20,16 +20,17 @@
<Popup x:Name="Popup" IsOpen="False" Placement="Custom" PlacementTarget="{Binding ElementName=Button}"> <Popup x:Name="Popup" IsOpen="False" Placement="Custom" PlacementTarget="{Binding ElementName=Button}">
<Border Background="LightGray" BorderBrush="Gray" BorderThickness="1,1,1,0"> <Border Background="LightGray" BorderBrush="Gray" BorderThickness="1,1,1,0">
<ScrollViewer MaxHeight="250" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}"> <ScrollViewer MaxHeight="250" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}">
<StackPanel x:Name="NetworksStackPanel" /> <StackPanel x:Name="WirelessNetworksStackPanel" />
</ScrollViewer> </ScrollViewer>
</Border> </Border>
</Popup> </Popup>
<Button x:Name="Button" Background="Transparent" Padding="5" Template="{StaticResource TaskbarButton}" ToolTipService.ShowOnDisabled="True" Width="40"> <Button x:Name="Button" Background="Transparent" Padding="5" Template="{StaticResource TaskbarButton}" ToolTipService.ShowOnDisabled="True" Width="40">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center"> <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Viewbox x:Name="SignalStrengthIcon" Stretch="Uniform" Width="Auto" /> <Viewbox x:Name="WirelessIcon" Stretch="Uniform" Width="Auto" Visibility="Collapsed" />
<fa:ImageAwesome x:Name="NoAdapterIcon" Foreground="Red" Icon="Ban" Margin="1" Opacity="0.3" Visibility="Collapsed" /> <fa:ImageAwesome x:Name="WiredIcon" Icon="Tv" Margin="0,2,4,4" Visibility="Collapsed" />
<fa:ImageAwesome x:Name="LoadingIcon" Foreground="Gray" Icon="Cog" Margin="5" Spin="True" SpinDuration="2" Visibility="Collapsed" /> <Border Background="{StaticResource BackgroundBrush}" CornerRadius="6" Height="12" HorizontalAlignment="Right" Margin="0,0,-1,1" Panel.ZIndex="10" VerticalAlignment="Bottom">
<Image x:Name="NetworkStatusIcon" Height="7" HorizontalAlignment="Right" Margin="0,2" Panel.ZIndex="10" VerticalAlignment="Bottom" /> <fa:ImageAwesome x:Name="NetworkStatusIcon" />
</Border>
</Grid> </Grid>
</Button> </Button>
</Grid> </Grid>

View file

@ -15,20 +15,20 @@ using System.Windows.Media;
using FontAwesome.WPF; using FontAwesome.WPF;
using SafeExamBrowser.Core.Contracts.Resources.Icons; using SafeExamBrowser.Core.Contracts.Resources.Icons;
using SafeExamBrowser.I18n.Contracts; using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork; using SafeExamBrowser.SystemComponents.Contracts.Network;
using SafeExamBrowser.UserInterface.Contracts.Shell; using SafeExamBrowser.UserInterface.Contracts.Shell;
using SafeExamBrowser.UserInterface.Shared.Utilities; using SafeExamBrowser.UserInterface.Shared.Utilities;
namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
{ {
internal partial class WirelessNetworkControl : UserControl, ISystemControl internal partial class NetworkControl : UserControl, ISystemControl
{ {
private IWirelessAdapter wirelessAdapter; private readonly INetworkAdapter adapter;
private IText text; private readonly IText text;
internal WirelessNetworkControl(IWirelessAdapter wirelessAdapter, IText text) internal NetworkControl(INetworkAdapter adapter, IText text)
{ {
this.wirelessAdapter = wirelessAdapter; this.adapter = adapter;
this.text = text; this.text = text;
InitializeComponent(); InitializeComponent();
@ -44,11 +44,12 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
{ {
var originalBrush = Button.Background; var originalBrush = Button.Background;
SignalStrengthIcon.Child = GetIcon(0); adapter.Changed += () => Dispatcher.InvokeAsync(Update);
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen; Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver)); Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
Popup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(Popup_PlacementCallback); Popup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(Popup_PlacementCallback);
Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver)); Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
WirelessIcon.Child = GetWirelessIcon(0);
Popup.Opened += (o, args) => Popup.Opened += (o, args) =>
{ {
@ -62,18 +63,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
Button.Background = originalBrush; Button.Background = originalBrush;
}; };
if (wirelessAdapter.IsAvailable) Update();
{
wirelessAdapter.NetworksChanged += WirelessAdapter_NetworksChanged;
wirelessAdapter.StatusChanged += WirelessAdapter_StatusChanged;
UpdateNetworks();
}
else
{
Button.IsEnabled = false;
NoAdapterIcon.Visibility = Visibility.Visible;
UpdateText(text.Get(TextKey.SystemControl_WirelessNotAvailable));
}
} }
private CustomPopupPlacement[] Popup_PlacementCallback(Size popupSize, Size targetSize, Point offset) private CustomPopupPlacement[] Popup_PlacementCallback(Size popupSize, Size targetSize, Point offset)
@ -84,72 +74,70 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
}; };
} }
private void WirelessAdapter_NetworksChanged() private void Update()
{ {
Dispatcher.InvokeAsync(UpdateNetworks); WirelessNetworksStackPanel.Children.Clear();
}
private void WirelessAdapter_StatusChanged(WirelessNetworkStatus status) foreach (var network in adapter.GetWirelessNetworks())
{
Dispatcher.InvokeAsync(() => UpdateStatus(status));
}
private void UpdateNetworks()
{
var status = WirelessNetworkStatus.Disconnected;
NetworksStackPanel.Children.Clear();
foreach (var network in wirelessAdapter.GetNetworks())
{ {
var button = new WirelessNetworkButton(network); var button = new NetworkButton(network);
button.NetworkSelected += (o, args) => wirelessAdapter.Connect(network.Id); button.NetworkSelected += (o, args) => adapter.ConnectToWirelessNetwork(network.Id);
if (network.Status == WirelessNetworkStatus.Connected) if (network.Status == ConnectionStatus.Connected)
{ {
status = WirelessNetworkStatus.Connected; WirelessIcon.Child = GetWirelessIcon(network.SignalStrength);
SignalStrengthIcon.Child = GetIcon(network.SignalStrength); Button.ToolTip = text.Get(TextKey.SystemControl_NetworkWirelessConnected).Replace("%%NAME%%", network.Name);
UpdateText(text.Get(TextKey.SystemControl_WirelessConnected).Replace("%%NAME%%", network.Name));
} }
NetworksStackPanel.Children.Add(button); WirelessNetworksStackPanel.Children.Add(button);
} }
UpdateStatus(status); switch (adapter.Type)
}
private void UpdateStatus(WirelessNetworkStatus status)
{
LoadingIcon.Visibility = Visibility.Collapsed;
SignalStrengthIcon.Visibility = Visibility.Visible;
NetworkStatusIcon.Visibility = Visibility.Visible;
switch (status)
{ {
case WirelessNetworkStatus.Connected: case ConnectionType.Wired:
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Check, Brushes.Green); Button.IsEnabled = false;
Button.ToolTip = text.Get(TextKey.SystemControl_NetworkWiredConnected);
WiredIcon.Visibility = Visibility.Visible;
WirelessIcon.Visibility = Visibility.Collapsed;
break; break;
case WirelessNetworkStatus.Connecting: case ConnectionType.Wireless:
LoadingIcon.Visibility = Visibility.Visible; Button.IsEnabled = true;
SignalStrengthIcon.Visibility = Visibility.Collapsed; WiredIcon.Visibility = Visibility.Collapsed;
NetworkStatusIcon.Visibility = Visibility.Collapsed; WirelessIcon.Visibility = Visibility.Visible;
UpdateText(text.Get(TextKey.SystemControl_WirelessConnecting));
break; break;
default: default:
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Close, Brushes.Orange); Button.IsEnabled = false;
SignalStrengthIcon.Child = GetIcon(0); Button.ToolTip = text.Get(TextKey.SystemControl_NetworkNotAvailable);
UpdateText(text.Get(TextKey.SystemControl_WirelessDisconnected)); WiredIcon.Visibility = Visibility.Visible;
WirelessIcon.Visibility = Visibility.Collapsed;
break;
}
switch (adapter.Status)
{
case ConnectionStatus.Connected:
NetworkStatusIcon.Rotation = 0;
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Globe, Brushes.Green);
NetworkStatusIcon.Spin = false;
break;
case ConnectionStatus.Connecting:
Button.ToolTip = text.Get(TextKey.SystemControl_NetworkWirelessConnecting);
NetworkStatusIcon.Rotation = 0;
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Cog, Brushes.DimGray);
NetworkStatusIcon.Spin = true;
NetworkStatusIcon.SpinDuration = 2;
break;
default:
Button.ToolTip = text.Get(TextKey.SystemControl_NetworkDisconnected);
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Ban, Brushes.DarkOrange);
NetworkStatusIcon.Spin = false;
WirelessIcon.Child = GetWirelessIcon(0);
break; break;
} }
} }
private void UpdateText(string text) private UIElement GetWirelessIcon(int signalStrength)
{
Button.ToolTip = text;
}
private UIElement GetIcon(int signalStrength)
{ {
var icon = signalStrength > 66 ? "100" : (signalStrength > 33 ? "66" : (signalStrength > 0 ? "33" : "0")); var icon = signalStrength > 66 ? "100" : (signalStrength > 33 ? "66" : (signalStrength > 0 ? "33" : "0"));
var uri = new Uri($"pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/WiFi_{icon}.xaml"); var uri = new Uri($"pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/WiFi_{icon}.xaml");

View file

@ -109,11 +109,11 @@
<Compile Include="Controls\ActionCenter\QuitButton.xaml.cs"> <Compile Include="Controls\ActionCenter\QuitButton.xaml.cs">
<DependentUpon>QuitButton.xaml</DependentUpon> <DependentUpon>QuitButton.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Controls\ActionCenter\WirelessNetworkButton.xaml.cs"> <Compile Include="Controls\ActionCenter\NetworkButton.xaml.cs">
<DependentUpon>WirelessNetworkButton.xaml</DependentUpon> <DependentUpon>NetworkButton.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Controls\ActionCenter\WirelessNetworkControl.xaml.cs"> <Compile Include="Controls\ActionCenter\NetworkControl.xaml.cs">
<DependentUpon>WirelessNetworkControl.xaml</DependentUpon> <DependentUpon>NetworkControl.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Controls\Browser\DownloadItemControl.xaml.cs"> <Compile Include="Controls\Browser\DownloadItemControl.xaml.cs">
<DependentUpon>DownloadItemControl.xaml</DependentUpon> <DependentUpon>DownloadItemControl.xaml</DependentUpon>
@ -145,11 +145,11 @@
<Compile Include="Controls\Taskbar\QuitButton.xaml.cs"> <Compile Include="Controls\Taskbar\QuitButton.xaml.cs">
<DependentUpon>QuitButton.xaml</DependentUpon> <DependentUpon>QuitButton.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Controls\Taskbar\WirelessNetworkButton.xaml.cs"> <Compile Include="Controls\Taskbar\NetworkButton.xaml.cs">
<DependentUpon>WirelessNetworkButton.xaml</DependentUpon> <DependentUpon>NetworkButton.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Controls\Taskbar\WirelessNetworkControl.xaml.cs"> <Compile Include="Controls\Taskbar\NetworkControl.xaml.cs">
<DependentUpon>WirelessNetworkControl.xaml</DependentUpon> <DependentUpon>NetworkControl.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Controls\Taskview\WindowControl.xaml.cs"> <Compile Include="Controls\Taskview\WindowControl.xaml.cs">
<DependentUpon>WindowControl.xaml</DependentUpon> <DependentUpon>WindowControl.xaml</DependentUpon>
@ -263,11 +263,11 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Controls\ActionCenter\WirelessNetworkButton.xaml"> <Page Include="Controls\ActionCenter\NetworkButton.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Controls\ActionCenter\WirelessNetworkControl.xaml"> <Page Include="Controls\ActionCenter\NetworkControl.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
@ -451,11 +451,11 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Resource> </Resource>
<Page Include="Controls\Taskbar\WirelessNetworkButton.xaml"> <Page Include="Controls\Taskbar\NetworkButton.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Controls\Taskbar\WirelessNetworkControl.xaml"> <Page Include="Controls\Taskbar\NetworkControl.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>

View file

@ -22,8 +22,8 @@ using SafeExamBrowser.Settings.Browser;
using SafeExamBrowser.Settings.Proctoring; using SafeExamBrowser.Settings.Proctoring;
using SafeExamBrowser.SystemComponents.Contracts.Audio; using SafeExamBrowser.SystemComponents.Contracts.Audio;
using SafeExamBrowser.SystemComponents.Contracts.Keyboard; using SafeExamBrowser.SystemComponents.Contracts.Keyboard;
using SafeExamBrowser.SystemComponents.Contracts.Network;
using SafeExamBrowser.SystemComponents.Contracts.PowerSupply; using SafeExamBrowser.SystemComponents.Contracts.PowerSupply;
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork;
using SafeExamBrowser.UserInterface.Contracts; using SafeExamBrowser.UserInterface.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Browser; using SafeExamBrowser.UserInterface.Contracts.Browser;
using SafeExamBrowser.UserInterface.Contracts.Proctoring; using SafeExamBrowser.UserInterface.Contracts.Proctoring;
@ -37,7 +37,7 @@ namespace SafeExamBrowser.UserInterface.Desktop
{ {
public class UserInterfaceFactory : IUserInterfaceFactory public class UserInterfaceFactory : IUserInterfaceFactory
{ {
private IText text; private readonly IText text;
public UserInterfaceFactory(IText text) public UserInterfaceFactory(IText text)
{ {
@ -131,6 +131,18 @@ namespace SafeExamBrowser.UserInterface.Desktop
return window; return window;
} }
public ISystemControl CreateNetworkControl(INetworkAdapter adapter, Location location)
{
if (location == Location.ActionCenter)
{
return new Controls.ActionCenter.NetworkControl(adapter, text);
}
else
{
return new Controls.Taskbar.NetworkControl(adapter, text);
}
}
public INotificationControl CreateNotificationControl(INotification notification, Location location) public INotificationControl CreateNotificationControl(INotification notification, Location location)
{ {
if (location == Location.ActionCenter) if (location == Location.ActionCenter)
@ -226,18 +238,6 @@ namespace SafeExamBrowser.UserInterface.Desktop
return new Taskview(); return new Taskview();
} }
public ISystemControl CreateWirelessNetworkControl(IWirelessAdapter wirelessAdapter, Location location)
{
if (location == Location.ActionCenter)
{
return new Controls.ActionCenter.WirelessNetworkControl(wirelessAdapter, text);
}
else
{
return new Controls.Taskbar.WirelessNetworkControl(wirelessAdapter, text);
}
}
private void InitializeFontAwesome() private void InitializeFontAwesome()
{ {
// To be able to use FontAwesome in XAML icon resources, we need to make sure that the FontAwesome.WPF assembly is loaded into // To be able to use FontAwesome in XAML icon resources, we need to make sure that the FontAwesome.WPF assembly is loaded into

View file

@ -1,4 +1,4 @@
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenter.WirelessNetworkButton" x:ClassModifier="internal" <UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenter.NetworkButton" x:ClassModifier="internal"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

View file

@ -9,17 +9,17 @@
using System; using System;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork; using SafeExamBrowser.SystemComponents.Contracts.Network;
namespace SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenter namespace SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenter
{ {
internal partial class WirelessNetworkButton : UserControl internal partial class NetworkButton : UserControl
{ {
private IWirelessNetwork network; private readonly IWirelessNetwork network;
internal event EventHandler NetworkSelected; internal event EventHandler NetworkSelected;
internal WirelessNetworkButton(IWirelessNetwork network) internal NetworkButton(IWirelessNetwork network)
{ {
this.network = network; this.network = network;
@ -30,7 +30,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenter
private void InitializeNetworkButton() private void InitializeNetworkButton()
{ {
Button.Click += (o, args) => NetworkSelected?.Invoke(this, EventArgs.Empty); Button.Click += (o, args) => NetworkSelected?.Invoke(this, EventArgs.Empty);
IsCurrentTextBlock.Visibility = network.Status == WirelessNetworkStatus.Connected ? Visibility.Visible : Visibility.Hidden; IsCurrentTextBlock.Visibility = network.Status == ConnectionStatus.Connected ? Visibility.Visible : Visibility.Hidden;
NetworkNameTextBlock.Text = network.Name; NetworkNameTextBlock.Text = network.Name;
SignalStrengthTextBlock.Text = $"{network.SignalStrength}%"; SignalStrengthTextBlock.Text = $"{network.SignalStrength}%";
} }

View file

@ -1,4 +1,4 @@
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenter.WirelessNetworkControl" x:ClassModifier="internal" <UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenter.NetworkControl" x:ClassModifier="internal"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@ -19,7 +19,7 @@
<Popup x:Name="Popup" IsOpen="False" Placement="Top" PlacementTarget="{Binding ElementName=Button}"> <Popup x:Name="Popup" IsOpen="False" Placement="Top" PlacementTarget="{Binding ElementName=Button}">
<Border Background="Gray"> <Border Background="Gray">
<ScrollViewer MaxHeight="250" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}"> <ScrollViewer MaxHeight="250" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}">
<StackPanel x:Name="NetworksStackPanel" /> <StackPanel x:Name="WirelessNetworksStackPanel" />
</ScrollViewer> </ScrollViewer>
</Border> </Border>
</Popup> </Popup>
@ -30,10 +30,11 @@
<RowDefinition Height="3*" /> <RowDefinition Height="3*" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center"> <Grid Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center">
<Viewbox x:Name="SignalStrengthIcon" Stretch="Uniform" Width="Auto" /> <Viewbox x:Name="WirelessIcon" Stretch="Uniform" Width="Auto" Visibility="Collapsed" />
<fa:ImageAwesome x:Name="NoAdapterIcon" Foreground="Red" Icon="Ban" Margin="1" Opacity="0.3" Visibility="Collapsed" /> <fa:ImageAwesome x:Name="WiredIcon" Icon="Tv" Margin="0,2,4,4" Visibility="Collapsed" />
<fa:ImageAwesome x:Name="LoadingIcon" Foreground="Black" Icon="Cog" Margin="5" Spin="True" SpinDuration="2" Visibility="Collapsed" /> <Border Background="White" CornerRadius="6" Height="14" HorizontalAlignment="Right" Margin="-3,0" Panel.ZIndex="10" VerticalAlignment="Bottom">
<Image x:Name="NetworkStatusIcon" Height="8" HorizontalAlignment="Right" Margin="-2,0" Panel.ZIndex="10" VerticalAlignment="Bottom" /> <fa:ImageAwesome x:Name="NetworkStatusIcon" />
</Border>
</Grid> </Grid>
<TextBlock Grid.Row="1" x:Name="Text" FontSize="15" Foreground="White" TextAlignment="Center" TextTrimming="CharacterEllipsis" TextWrapping="Wrap" VerticalAlignment="Bottom" /> <TextBlock Grid.Row="1" x:Name="Text" FontSize="15" Foreground="White" TextAlignment="Center" TextTrimming="CharacterEllipsis" TextWrapping="Wrap" VerticalAlignment="Bottom" />
</Grid> </Grid>

View file

@ -0,0 +1,135 @@
/*
* Copyright (c) 2022 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using FontAwesome.WPF;
using SafeExamBrowser.Core.Contracts.Resources.Icons;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.Network;
using SafeExamBrowser.UserInterface.Contracts.Shell;
using SafeExamBrowser.UserInterface.Shared.Utilities;
namespace SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenter
{
internal partial class NetworkControl : UserControl, ISystemControl
{
private readonly INetworkAdapter adapter;
private readonly IText text;
internal NetworkControl(INetworkAdapter adapter, IText text)
{
this.adapter = adapter;
this.text = text;
InitializeComponent();
InitializeWirelessNetworkControl();
}
public void Close()
{
Dispatcher.InvokeAsync(() => Popup.IsOpen = false);
}
private void InitializeWirelessNetworkControl()
{
var originalBrush = Grid.Background;
adapter.Changed += () => Dispatcher.InvokeAsync(Update);
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
Popup.Opened += (o, args) => Grid.Background = Brushes.Gray;
Popup.Closed += (o, args) => Grid.Background = originalBrush;
WirelessIcon.Child = GetWirelessIcon(0);
Update();
}
private void Update()
{
WirelessNetworksStackPanel.Children.Clear();
foreach (var network in adapter.GetWirelessNetworks())
{
var button = new NetworkButton(network);
button.NetworkSelected += (o, args) => adapter.ConnectToWirelessNetwork(network.Id);
if (network.Status == ConnectionStatus.Connected)
{
WirelessIcon.Child = GetWirelessIcon(network.SignalStrength);
UpdateText(text.Get(TextKey.SystemControl_NetworkWirelessConnected).Replace("%%NAME%%", network.Name));
}
WirelessNetworksStackPanel.Children.Add(button);
}
switch (adapter.Type)
{
case ConnectionType.Wired:
Button.IsEnabled = false;
UpdateText(text.Get(TextKey.SystemControl_NetworkWiredConnected));
WiredIcon.Visibility = Visibility.Visible;
WirelessIcon.Visibility = Visibility.Collapsed;
break;
case ConnectionType.Wireless:
Button.IsEnabled = true;
WiredIcon.Visibility = Visibility.Collapsed;
WirelessIcon.Visibility = Visibility.Visible;
break;
default:
Button.IsEnabled = false;
UpdateText(text.Get(TextKey.SystemControl_NetworkNotAvailable));
WiredIcon.Visibility = Visibility.Visible;
WirelessIcon.Visibility = Visibility.Collapsed;
break;
}
switch (adapter.Status)
{
case ConnectionStatus.Connected:
NetworkStatusIcon.Rotation = 0;
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Globe, Brushes.Green);
NetworkStatusIcon.Spin = false;
break;
case ConnectionStatus.Connecting:
UpdateText(text.Get(TextKey.SystemControl_NetworkWirelessConnecting));
NetworkStatusIcon.Rotation = 0;
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Cog, Brushes.DimGray);
NetworkStatusIcon.Spin = true;
NetworkStatusIcon.SpinDuration = 2;
break;
default:
UpdateText(text.Get(TextKey.SystemControl_NetworkDisconnected));
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Ban, Brushes.DarkOrange);
NetworkStatusIcon.Spin = false;
WirelessIcon.Child = GetWirelessIcon(0);
break;
}
}
private void UpdateText(string text)
{
Button.ToolTip = text;
Text.Text = text;
}
private UIElement GetWirelessIcon(int signalStrength)
{
var icon = signalStrength > 66 ? "100" : (signalStrength > 33 ? "66" : (signalStrength > 0 ? "33" : "0"));
var uri = new Uri($"pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/WiFi_Light_{icon}.xaml");
var resource = new XamlIconResource { Uri = uri };
return IconResourceLoader.Load(resource);
}
}
}

View file

@ -1,142 +0,0 @@
/*
* Copyright (c) 2022 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using FontAwesome.WPF;
using SafeExamBrowser.Core.Contracts.Resources.Icons;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork;
using SafeExamBrowser.UserInterface.Contracts.Shell;
using SafeExamBrowser.UserInterface.Shared.Utilities;
namespace SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenter
{
internal partial class WirelessNetworkControl : UserControl, ISystemControl
{
private IWirelessAdapter wirelessAdapter;
private IText text;
internal WirelessNetworkControl(IWirelessAdapter wirelessAdapter, IText text)
{
this.wirelessAdapter = wirelessAdapter;
this.text = text;
InitializeComponent();
InitializeWirelessNetworkControl();
}
public void Close()
{
Dispatcher.InvokeAsync(() => Popup.IsOpen = false);
}
private void InitializeWirelessNetworkControl()
{
var originalBrush = Grid.Background;
SignalStrengthIcon.Child = GetIcon(0);
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
Popup.Opened += (o, args) => Grid.Background = Brushes.Gray;
Popup.Closed += (o, args) => Grid.Background = originalBrush;
if (wirelessAdapter.IsAvailable)
{
wirelessAdapter.NetworksChanged += WirelessAdapter_NetworksChanged;
wirelessAdapter.StatusChanged += WirelessAdapter_StatusChanged;
UpdateNetworks();
}
else
{
Button.IsEnabled = false;
NoAdapterIcon.Visibility = Visibility.Visible;
UpdateText(text.Get(TextKey.SystemControl_WirelessNotAvailable));
}
}
private void WirelessAdapter_NetworksChanged()
{
Dispatcher.InvokeAsync(UpdateNetworks);
}
private void WirelessAdapter_StatusChanged(WirelessNetworkStatus status)
{
Dispatcher.InvokeAsync(() => UpdateStatus(status));
}
private void UpdateNetworks()
{
var status = WirelessNetworkStatus.Disconnected;
NetworksStackPanel.Children.Clear();
foreach (var network in wirelessAdapter.GetNetworks())
{
var button = new WirelessNetworkButton(network);
button.NetworkSelected += (o, args) => wirelessAdapter.Connect(network.Id);
if (network.Status == WirelessNetworkStatus.Connected)
{
status = WirelessNetworkStatus.Connected;
SignalStrengthIcon.Child = GetIcon(network.SignalStrength);
UpdateText(text.Get(TextKey.SystemControl_WirelessConnected).Replace("%%NAME%%", network.Name));
}
NetworksStackPanel.Children.Add(button);
}
UpdateStatus(status);
}
private void UpdateStatus(WirelessNetworkStatus status)
{
LoadingIcon.Visibility = Visibility.Collapsed;
SignalStrengthIcon.Visibility = Visibility.Visible;
NetworkStatusIcon.Visibility = Visibility.Visible;
switch (status)
{
case WirelessNetworkStatus.Connected:
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Check, Brushes.Green);
break;
case WirelessNetworkStatus.Connecting:
LoadingIcon.Visibility = Visibility.Visible;
SignalStrengthIcon.Visibility = Visibility.Collapsed;
NetworkStatusIcon.Visibility = Visibility.Collapsed;
UpdateText(text.Get(TextKey.SystemControl_WirelessConnecting));
break;
default:
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Close, Brushes.Orange);
SignalStrengthIcon.Child = GetIcon(0);
UpdateText(text.Get(TextKey.SystemControl_WirelessDisconnected));
break;
}
}
private void UpdateText(string text)
{
Button.ToolTip = text;
Text.Text = text;
}
private UIElement GetIcon(int signalStrength)
{
var icon = signalStrength > 66 ? "100" : (signalStrength > 33 ? "66" : (signalStrength > 0 ? "33" : "0"));
var uri = new Uri($"pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/WiFi_Light_{icon}.xaml");
var resource = new XamlIconResource { Uri = uri };
return IconResourceLoader.Load(resource);
}
}
}

View file

@ -1,4 +1,4 @@
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar.WirelessNetworkButton" x:ClassModifier="internal" <UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar.NetworkButton" x:ClassModifier="internal"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

View file

@ -9,17 +9,17 @@
using System; using System;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork; using SafeExamBrowser.SystemComponents.Contracts.Network;
namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar
{ {
internal partial class WirelessNetworkButton : UserControl internal partial class NetworkButton : UserControl
{ {
private IWirelessNetwork network; private readonly IWirelessNetwork network;
internal event EventHandler NetworkSelected; internal event EventHandler NetworkSelected;
internal WirelessNetworkButton(IWirelessNetwork network) internal NetworkButton(IWirelessNetwork network)
{ {
this.network = network; this.network = network;
@ -30,7 +30,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar
private void InitializeNetworkButton() private void InitializeNetworkButton()
{ {
Button.Click += (o, args) => NetworkSelected?.Invoke(this, EventArgs.Empty); Button.Click += (o, args) => NetworkSelected?.Invoke(this, EventArgs.Empty);
IsCurrentTextBlock.Visibility = network.Status == WirelessNetworkStatus.Connected ? Visibility.Visible : Visibility.Hidden; IsCurrentTextBlock.Visibility = network.Status == ConnectionStatus.Connected ? Visibility.Visible : Visibility.Hidden;
NetworkNameTextBlock.Text = network.Name; NetworkNameTextBlock.Text = network.Name;
SignalStrengthTextBlock.Text = $"{network.SignalStrength}%"; SignalStrengthTextBlock.Text = $"{network.SignalStrength}%";
} }

View file

@ -1,4 +1,4 @@
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar.WirelessNetworkControl" x:ClassModifier="internal" <UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar.NetworkControl" x:ClassModifier="internal"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@ -20,16 +20,17 @@
<Popup x:Name="Popup" IsOpen="False" Placement="Custom" PlacementTarget="{Binding ElementName=Button}"> <Popup x:Name="Popup" IsOpen="False" Placement="Custom" PlacementTarget="{Binding ElementName=Button}">
<Border Background="LightGray" BorderBrush="Gray" BorderThickness="1,1,1,0"> <Border Background="LightGray" BorderBrush="Gray" BorderThickness="1,1,1,0">
<ScrollViewer MaxHeight="250" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}"> <ScrollViewer MaxHeight="250" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}">
<StackPanel x:Name="NetworksStackPanel" /> <StackPanel x:Name="WirelessNetworksStackPanel" />
</ScrollViewer> </ScrollViewer>
</Border> </Border>
</Popup> </Popup>
<Button x:Name="Button" Background="Transparent" Padding="5" Template="{StaticResource TaskbarButton}" ToolTipService.ShowOnDisabled="True" Width="60"> <Button x:Name="Button" Background="Transparent" Padding="5" Template="{StaticResource TaskbarButton}" ToolTipService.ShowOnDisabled="True" Width="60">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center"> <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Viewbox x:Name="SignalStrengthIcon" Stretch="Uniform" Width="Auto" /> <Viewbox x:Name="WirelessIcon" Stretch="Uniform" Width="Auto" Visibility="Collapsed" />
<fa:ImageAwesome x:Name="NoAdapterIcon" Foreground="Red" Icon="Ban" Margin="1" Opacity="0.3" Visibility="Collapsed" /> <fa:ImageAwesome x:Name="WiredIcon" Icon="Tv" Margin="0,2,4,4" Visibility="Collapsed" />
<fa:ImageAwesome x:Name="LoadingIcon" Foreground="Gray" Icon="Cog" Margin="5" Spin="True" SpinDuration="2" Visibility="Collapsed" /> <Border Background="{StaticResource BackgroundBrush}" CornerRadius="6" Height="18" HorizontalAlignment="Right" Margin="0,0,-1,1" Panel.ZIndex="10" VerticalAlignment="Bottom">
<Image x:Name="NetworkStatusIcon" Height="12" HorizontalAlignment="Right" Margin="0,2" Panel.ZIndex="10" VerticalAlignment="Bottom" /> <fa:ImageAwesome x:Name="NetworkStatusIcon" />
</Border>
</Grid> </Grid>
</Button> </Button>
</Grid> </Grid>

View file

@ -15,20 +15,20 @@ using System.Windows.Media;
using FontAwesome.WPF; using FontAwesome.WPF;
using SafeExamBrowser.Core.Contracts.Resources.Icons; using SafeExamBrowser.Core.Contracts.Resources.Icons;
using SafeExamBrowser.I18n.Contracts; using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork; using SafeExamBrowser.SystemComponents.Contracts.Network;
using SafeExamBrowser.UserInterface.Contracts.Shell; using SafeExamBrowser.UserInterface.Contracts.Shell;
using SafeExamBrowser.UserInterface.Shared.Utilities; using SafeExamBrowser.UserInterface.Shared.Utilities;
namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar
{ {
internal partial class WirelessNetworkControl : UserControl, ISystemControl internal partial class NetworkControl : UserControl, ISystemControl
{ {
private IWirelessAdapter wirelessAdapter; private readonly INetworkAdapter adapter;
private IText text; private readonly IText text;
internal WirelessNetworkControl(IWirelessAdapter wirelessAdapter, IText text) internal NetworkControl(INetworkAdapter adapter, IText text)
{ {
this.wirelessAdapter = wirelessAdapter; this.adapter = adapter;
this.text = text; this.text = text;
InitializeComponent(); InitializeComponent();
@ -44,11 +44,12 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar
{ {
var originalBrush = Button.Background; var originalBrush = Button.Background;
SignalStrengthIcon.Child = GetIcon(0); adapter.Changed += () => Dispatcher.InvokeAsync(Update);
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen; Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver)); Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
Popup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(Popup_PlacementCallback); Popup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(Popup_PlacementCallback);
Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver)); Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
WirelessIcon.Child = GetWirelessIcon(0);
Popup.Opened += (o, args) => Popup.Opened += (o, args) =>
{ {
@ -62,18 +63,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar
Button.Background = originalBrush; Button.Background = originalBrush;
}; };
if (wirelessAdapter.IsAvailable) Update();
{
wirelessAdapter.NetworksChanged += WirelessAdapter_NetworksChanged;
wirelessAdapter.StatusChanged += WirelessAdapter_StatusChanged;
UpdateNetworks();
}
else
{
Button.IsEnabled = false;
NoAdapterIcon.Visibility = Visibility.Visible;
UpdateText(text.Get(TextKey.SystemControl_WirelessNotAvailable));
}
} }
private CustomPopupPlacement[] Popup_PlacementCallback(Size popupSize, Size targetSize, Point offset) private CustomPopupPlacement[] Popup_PlacementCallback(Size popupSize, Size targetSize, Point offset)
@ -84,72 +74,70 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar
}; };
} }
private void WirelessAdapter_NetworksChanged() private void Update()
{ {
Dispatcher.InvokeAsync(UpdateNetworks); WirelessNetworksStackPanel.Children.Clear();
}
private void WirelessAdapter_StatusChanged(WirelessNetworkStatus status) foreach (var network in adapter.GetWirelessNetworks())
{
Dispatcher.InvokeAsync(() => UpdateStatus(status));
}
private void UpdateNetworks()
{
var status = WirelessNetworkStatus.Disconnected;
NetworksStackPanel.Children.Clear();
foreach (var network in wirelessAdapter.GetNetworks())
{ {
var button = new WirelessNetworkButton(network); var button = new NetworkButton(network);
button.NetworkSelected += (o, args) => wirelessAdapter.Connect(network.Id); button.NetworkSelected += (o, args) => adapter.ConnectToWirelessNetwork(network.Id);
if (network.Status == WirelessNetworkStatus.Connected) if (network.Status == ConnectionStatus.Connected)
{ {
status = WirelessNetworkStatus.Connected; WirelessIcon.Child = GetWirelessIcon(network.SignalStrength);
SignalStrengthIcon.Child = GetIcon(network.SignalStrength); Button.ToolTip = text.Get(TextKey.SystemControl_NetworkWirelessConnected).Replace("%%NAME%%", network.Name);
UpdateText(text.Get(TextKey.SystemControl_WirelessConnected).Replace("%%NAME%%", network.Name));
} }
NetworksStackPanel.Children.Add(button); WirelessNetworksStackPanel.Children.Add(button);
} }
UpdateStatus(status); switch (adapter.Type)
}
private void UpdateStatus(WirelessNetworkStatus status)
{
LoadingIcon.Visibility = Visibility.Collapsed;
SignalStrengthIcon.Visibility = Visibility.Visible;
NetworkStatusIcon.Visibility = Visibility.Visible;
switch (status)
{ {
case WirelessNetworkStatus.Connected: case ConnectionType.Wired:
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Check, Brushes.Green); Button.IsEnabled = false;
Button.ToolTip = text.Get(TextKey.SystemControl_NetworkWiredConnected);
WiredIcon.Visibility = Visibility.Visible;
WirelessIcon.Visibility = Visibility.Collapsed;
break; break;
case WirelessNetworkStatus.Connecting: case ConnectionType.Wireless:
LoadingIcon.Visibility = Visibility.Visible; Button.IsEnabled = true;
SignalStrengthIcon.Visibility = Visibility.Collapsed; WiredIcon.Visibility = Visibility.Collapsed;
NetworkStatusIcon.Visibility = Visibility.Collapsed; WirelessIcon.Visibility = Visibility.Visible;
UpdateText(text.Get(TextKey.SystemControl_WirelessConnecting));
break; break;
default: default:
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Close, Brushes.Orange); Button.IsEnabled = false;
SignalStrengthIcon.Child = GetIcon(0); Button.ToolTip = text.Get(TextKey.SystemControl_NetworkNotAvailable);
UpdateText(text.Get(TextKey.SystemControl_WirelessDisconnected)); WiredIcon.Visibility = Visibility.Visible;
WirelessIcon.Visibility = Visibility.Collapsed;
break;
}
switch (adapter.Status)
{
case ConnectionStatus.Connected:
NetworkStatusIcon.Rotation = 0;
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Globe, Brushes.Green);
NetworkStatusIcon.Spin = false;
break;
case ConnectionStatus.Connecting:
Button.ToolTip = text.Get(TextKey.SystemControl_NetworkWirelessConnecting);
NetworkStatusIcon.Rotation = 0;
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Cog, Brushes.DimGray);
NetworkStatusIcon.Spin = true;
NetworkStatusIcon.SpinDuration = 2;
break;
default:
Button.ToolTip = text.Get(TextKey.SystemControl_NetworkDisconnected);
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Ban, Brushes.DarkOrange);
NetworkStatusIcon.Spin = false;
WirelessIcon.Child = GetWirelessIcon(0);
break; break;
} }
} }
private void UpdateText(string text) private UIElement GetWirelessIcon(int signalStrength)
{
Button.ToolTip = text;
}
private UIElement GetIcon(int signalStrength)
{ {
var icon = signalStrength > 66 ? "100" : (signalStrength > 33 ? "66" : (signalStrength > 0 ? "33" : "0")); var icon = signalStrength > 66 ? "100" : (signalStrength > 33 ? "66" : (signalStrength > 0 ? "33" : "0"));
var uri = new Uri($"pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/WiFi_{icon}.xaml"); var uri = new Uri($"pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/WiFi_{icon}.xaml");

View file

@ -110,11 +110,11 @@
<Compile Include="Controls\ActionCenter\QuitButton.xaml.cs"> <Compile Include="Controls\ActionCenter\QuitButton.xaml.cs">
<DependentUpon>QuitButton.xaml</DependentUpon> <DependentUpon>QuitButton.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Controls\ActionCenter\WirelessNetworkButton.xaml.cs"> <Compile Include="Controls\ActionCenter\NetworkButton.xaml.cs">
<DependentUpon>WirelessNetworkButton.xaml</DependentUpon> <DependentUpon>NetworkButton.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Controls\ActionCenter\WirelessNetworkControl.xaml.cs"> <Compile Include="Controls\ActionCenter\NetworkControl.xaml.cs">
<DependentUpon>WirelessNetworkControl.xaml</DependentUpon> <DependentUpon>NetworkControl.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Controls\Browser\DownloadItemControl.xaml.cs"> <Compile Include="Controls\Browser\DownloadItemControl.xaml.cs">
<DependentUpon>DownloadItemControl.xaml</DependentUpon> <DependentUpon>DownloadItemControl.xaml</DependentUpon>
@ -146,11 +146,11 @@
<Compile Include="Controls\Taskbar\QuitButton.xaml.cs"> <Compile Include="Controls\Taskbar\QuitButton.xaml.cs">
<DependentUpon>QuitButton.xaml</DependentUpon> <DependentUpon>QuitButton.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Controls\Taskbar\WirelessNetworkButton.xaml.cs"> <Compile Include="Controls\Taskbar\NetworkButton.xaml.cs">
<DependentUpon>WirelessNetworkButton.xaml</DependentUpon> <DependentUpon>NetworkButton.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Controls\Taskbar\WirelessNetworkControl.xaml.cs"> <Compile Include="Controls\Taskbar\NetworkControl.xaml.cs">
<DependentUpon>WirelessNetworkControl.xaml</DependentUpon> <DependentUpon>NetworkControl.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Controls\Taskview\WindowControl.xaml.cs"> <Compile Include="Controls\Taskview\WindowControl.xaml.cs">
<DependentUpon>WindowControl.xaml</DependentUpon> <DependentUpon>WindowControl.xaml</DependentUpon>
@ -321,11 +321,11 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Include="Controls\ActionCenter\WirelessNetworkButton.xaml"> <Page Include="Controls\ActionCenter\NetworkButton.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Include="Controls\ActionCenter\WirelessNetworkControl.xaml"> <Page Include="Controls\ActionCenter\NetworkControl.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
@ -369,11 +369,11 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Include="Controls\Taskbar\WirelessNetworkButton.xaml"> <Page Include="Controls\Taskbar\NetworkButton.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Include="Controls\Taskbar\WirelessNetworkControl.xaml"> <Page Include="Controls\Taskbar\NetworkControl.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>

View file

@ -22,8 +22,8 @@ using SafeExamBrowser.Settings.Browser;
using SafeExamBrowser.Settings.Proctoring; using SafeExamBrowser.Settings.Proctoring;
using SafeExamBrowser.SystemComponents.Contracts.Audio; using SafeExamBrowser.SystemComponents.Contracts.Audio;
using SafeExamBrowser.SystemComponents.Contracts.Keyboard; using SafeExamBrowser.SystemComponents.Contracts.Keyboard;
using SafeExamBrowser.SystemComponents.Contracts.Network;
using SafeExamBrowser.SystemComponents.Contracts.PowerSupply; using SafeExamBrowser.SystemComponents.Contracts.PowerSupply;
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork;
using SafeExamBrowser.UserInterface.Contracts; using SafeExamBrowser.UserInterface.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Browser; using SafeExamBrowser.UserInterface.Contracts.Browser;
using SafeExamBrowser.UserInterface.Contracts.Proctoring; using SafeExamBrowser.UserInterface.Contracts.Proctoring;
@ -37,7 +37,7 @@ namespace SafeExamBrowser.UserInterface.Mobile
{ {
public class UserInterfaceFactory : IUserInterfaceFactory public class UserInterfaceFactory : IUserInterfaceFactory
{ {
private IText text; private readonly IText text;
public UserInterfaceFactory(IText text) public UserInterfaceFactory(IText text)
{ {
@ -131,6 +131,18 @@ namespace SafeExamBrowser.UserInterface.Mobile
return window; return window;
} }
public ISystemControl CreateNetworkControl(INetworkAdapter adapter, Location location)
{
if (location == Location.ActionCenter)
{
return new Controls.ActionCenter.NetworkControl(adapter, text);
}
else
{
return new Controls.Taskbar.NetworkControl(adapter, text);
}
}
public INotificationControl CreateNotificationControl(INotification notification, Location location) public INotificationControl CreateNotificationControl(INotification notification, Location location)
{ {
if (location == Location.ActionCenter) if (location == Location.ActionCenter)
@ -226,18 +238,6 @@ namespace SafeExamBrowser.UserInterface.Mobile
return new Taskview(); return new Taskview();
} }
public ISystemControl CreateWirelessNetworkControl(IWirelessAdapter wirelessAdapter, Location location)
{
if (location == Location.ActionCenter)
{
return new Controls.ActionCenter.WirelessNetworkControl(wirelessAdapter, text);
}
else
{
return new Controls.Taskbar.WirelessNetworkControl(wirelessAdapter, text);
}
}
private void InitializeFontAwesome() private void InitializeFontAwesome()
{ {
// To be able to use FontAwesome in XAML icon resources, we need to make sure that the FontAwesome.WPF assembly is loaded into // To be able to use FontAwesome in XAML icon resources, we need to make sure that the FontAwesome.WPF assembly is loaded into

View file

@ -108,6 +108,11 @@ namespace SafeExamBrowser.WindowsApi.Contracts
/// </exception> /// </exception>
IBounds GetWorkingArea(); IBounds GetWorkingArea();
/// <summary>
/// Determines whether this computer is connected to the internet. Returns <c>true</c> if successful, otherwise <c>false</c>.
/// </summary>
bool HasInternetConnection();
/// <summary> /// <summary>
/// Hides the given window. Returns <c>true</c> if successful, otherwise <c>false</c>. /// Hides the given window. Returns <c>true</c> if successful, otherwise <c>false</c>.
/// </summary> /// </summary>

View file

@ -24,9 +24,9 @@ namespace SafeExamBrowser.WindowsApi
{ {
public class NativeMethods : INativeMethods public class NativeMethods : INativeMethods
{ {
private ConcurrentDictionary<Guid, KeyboardHook> KeyboardHooks = new ConcurrentDictionary<Guid, KeyboardHook>(); private readonly ConcurrentDictionary<Guid, KeyboardHook> KeyboardHooks = new ConcurrentDictionary<Guid, KeyboardHook>();
private ConcurrentDictionary<Guid, MouseHook> MouseHooks = new ConcurrentDictionary<Guid, MouseHook>(); private readonly ConcurrentDictionary<Guid, MouseHook> MouseHooks = new ConcurrentDictionary<Guid, MouseHook>();
private ConcurrentDictionary<Guid, SystemHook> SystemHooks = new ConcurrentDictionary<Guid, SystemHook>(); private readonly ConcurrentDictionary<Guid, SystemHook> SystemHooks = new ConcurrentDictionary<Guid, SystemHook>();
/// <summary> /// <summary>
/// Upon finalization, unregister all active system events and hooks... /// Upon finalization, unregister all active system events and hooks...
@ -245,6 +245,11 @@ namespace SafeExamBrowser.WindowsApi
return workingArea.ToBounds(); return workingArea.ToBounds();
} }
public bool HasInternetConnection()
{
return WinInet.InternetGetConnectedState(out _, 0);
}
public bool HideWindow(IntPtr window) public bool HideWindow(IntPtr window)
{ {
return User32.ShowWindow(window, (int) ShowWindowCommand.Hide); return User32.ShowWindow(window, (int) ShowWindowCommand.Hide);

View file

@ -92,6 +92,7 @@
<Compile Include="Types\Window.cs" /> <Compile Include="Types\Window.cs" />
<Compile Include="Types\WINDOWPLACEMENT.cs" /> <Compile Include="Types\WINDOWPLACEMENT.cs" />
<Compile Include="User32.cs" /> <Compile Include="User32.cs" />
<Compile Include="WinInet.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\SafeExamBrowser.Logging.Contracts\SafeExamBrowser.Logging.Contracts.csproj"> <ProjectReference Include="..\SafeExamBrowser.Logging.Contracts\SafeExamBrowser.Logging.Contracts.csproj">

View file

@ -0,0 +1,21 @@
/*
* Copyright (c) 2022 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.Runtime.InteropServices;
namespace SafeExamBrowser.WindowsApi
{
/// <summary>
/// Provides access to the native Windows API exposed by <c>wininet.dll</c>.
/// </summary>
internal static class WinInet
{
[DllImport("wininet.dll", SetLastError = true)]
internal static extern bool InternetGetConnectedState(out int description, int reservedValue);
}
}