SEBWIN-788: Implemented scaffolding for wireless network credentials.
This commit is contained in:
parent
e4a82e2f63
commit
4015e9a574
24 changed files with 395 additions and 35 deletions
|
@ -33,6 +33,7 @@ using SafeExamBrowser.Server.Contracts;
|
|||
using SafeExamBrowser.Server.Contracts.Data;
|
||||
using SafeExamBrowser.Settings;
|
||||
using SafeExamBrowser.Settings.Monitoring;
|
||||
using SafeExamBrowser.SystemComponents.Contracts.Network;
|
||||
using SafeExamBrowser.SystemComponents.Contracts.Registry;
|
||||
using SafeExamBrowser.UserInterface.Contracts;
|
||||
using SafeExamBrowser.UserInterface.Contracts.FileSystemDialog;
|
||||
|
@ -61,6 +62,7 @@ namespace SafeExamBrowser.Client.UnitTests
|
|||
private Mock<IIntegrityModule> integrityModule;
|
||||
private Mock<ILogger> logger;
|
||||
private Mock<IMessageBox> messageBox;
|
||||
private Mock<INetworkAdapter> networkAdapter;
|
||||
private Mock<IOperationSequence> operationSequence;
|
||||
private Mock<IRegistry> registry;
|
||||
private Mock<IRuntimeProxy> runtimeProxy;
|
||||
|
@ -94,6 +96,7 @@ namespace SafeExamBrowser.Client.UnitTests
|
|||
integrityModule = new Mock<IIntegrityModule>();
|
||||
logger = new Mock<ILogger>();
|
||||
messageBox = new Mock<IMessageBox>();
|
||||
networkAdapter = new Mock<INetworkAdapter>();
|
||||
operationSequence = new Mock<IOperationSequence>();
|
||||
registry = new Mock<IRegistry>();
|
||||
runtimeProxy = new Mock<IRuntimeProxy>();
|
||||
|
@ -122,6 +125,7 @@ namespace SafeExamBrowser.Client.UnitTests
|
|||
hashAlgorithm.Object,
|
||||
logger.Object,
|
||||
messageBox.Object,
|
||||
networkAdapter.Object,
|
||||
operationSequence.Object,
|
||||
registry.Object,
|
||||
runtimeProxy.Object,
|
||||
|
|
|
@ -35,6 +35,8 @@ using SafeExamBrowser.Proctoring.Contracts.Events;
|
|||
using SafeExamBrowser.Server.Contracts;
|
||||
using SafeExamBrowser.Server.Contracts.Data;
|
||||
using SafeExamBrowser.Settings;
|
||||
using SafeExamBrowser.SystemComponents.Contracts.Network;
|
||||
using SafeExamBrowser.SystemComponents.Contracts.Network.Events;
|
||||
using SafeExamBrowser.SystemComponents.Contracts.Registry;
|
||||
using SafeExamBrowser.UserInterface.Contracts;
|
||||
using SafeExamBrowser.UserInterface.Contracts.FileSystemDialog;
|
||||
|
@ -57,6 +59,7 @@ namespace SafeExamBrowser.Client
|
|||
private readonly IHashAlgorithm hashAlgorithm;
|
||||
private readonly ILogger logger;
|
||||
private readonly IMessageBox messageBox;
|
||||
private readonly INetworkAdapter networkAdapter;
|
||||
private readonly IOperationSequence operations;
|
||||
private readonly IRegistry registry;
|
||||
private readonly IRuntimeProxy runtime;
|
||||
|
@ -87,6 +90,7 @@ namespace SafeExamBrowser.Client
|
|||
IHashAlgorithm hashAlgorithm,
|
||||
ILogger logger,
|
||||
IMessageBox messageBox,
|
||||
INetworkAdapter networkAdapter,
|
||||
IOperationSequence operations,
|
||||
IRegistry registry,
|
||||
IRuntimeProxy runtime,
|
||||
|
@ -106,6 +110,7 @@ namespace SafeExamBrowser.Client
|
|||
this.hashAlgorithm = hashAlgorithm;
|
||||
this.logger = logger;
|
||||
this.messageBox = messageBox;
|
||||
this.networkAdapter = networkAdapter;
|
||||
this.operations = operations;
|
||||
this.registry = registry;
|
||||
this.runtime = runtime;
|
||||
|
@ -214,6 +219,7 @@ namespace SafeExamBrowser.Client
|
|||
ClientHost.ServerFailureActionRequested += ClientHost_ServerFailureActionRequested;
|
||||
ClientHost.Shutdown += ClientHost_Shutdown;
|
||||
displayMonitor.DisplayChanged += DisplayMonitor_DisplaySettingsChanged;
|
||||
networkAdapter.CredentialsRequired += NetworkAdapter_CredentialsRequired;
|
||||
registry.ValueChanged += Registry_ValueChanged;
|
||||
runtime.ConnectionLost += Runtime_ConnectionLost;
|
||||
systemMonitor.SessionChanged += SystemMonitor_SessionChanged;
|
||||
|
@ -690,6 +696,16 @@ namespace SafeExamBrowser.Client
|
|||
}
|
||||
}
|
||||
|
||||
private void NetworkAdapter_CredentialsRequired(CredentialsRequiredEventArgs args)
|
||||
{
|
||||
var dialog = uiFactory.CreateNetworkDialog("TODO", "TODO");
|
||||
var result = dialog.Show();
|
||||
|
||||
args.Password = result.Password;
|
||||
args.Success = result.Success;
|
||||
args.Username = result.Username;
|
||||
}
|
||||
|
||||
private void Operations_ActionRequired(ActionRequiredEventArgs args)
|
||||
{
|
||||
switch (args)
|
||||
|
|
|
@ -154,6 +154,7 @@ namespace SafeExamBrowser.Client
|
|||
hashAlgorithm,
|
||||
logger,
|
||||
messageBox,
|
||||
networkAdapter,
|
||||
sequence,
|
||||
registry,
|
||||
runtimeProxy,
|
||||
|
|
|
@ -26,6 +26,26 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
InitializeClipboardSettings(settings);
|
||||
InitializeProctoringSettings(settings);
|
||||
RemoveLegacyBrowsers(settings);
|
||||
|
||||
settings.Applications.Blacklist.Clear();
|
||||
settings.Applications.Whitelist.Add(new WhitelistApplication { ExecutableName = "mspaint.exe", ShowInShell = true });
|
||||
settings.Browser.AdditionalWindow.AllowAddressBar = true;
|
||||
settings.Browser.MainWindow.AllowAddressBar = true;
|
||||
settings.Browser.MainWindow.AllowDeveloperConsole = true;
|
||||
settings.Browser.MainWindow.AllowBackwardNavigation = true;
|
||||
settings.Browser.MainWindow.AllowForwardNavigation = true;
|
||||
settings.Browser.MainWindow.ShowHomeButton = true;
|
||||
settings.Browser.MainWindow.UrlPolicy = Settings.Browser.UrlPolicy.BeforeTitle;
|
||||
settings.Keyboard.AllowPrintScreen = true;
|
||||
settings.LogLevel = Settings.Logging.LogLevel.Debug;
|
||||
settings.Security.AllowApplicationLogAccess = true;
|
||||
settings.Security.ClipboardPolicy = ClipboardPolicy.Allow;
|
||||
settings.Security.KioskMode = KioskMode.CreateNewDesktop;
|
||||
settings.Security.QuitPasswordHash = default;
|
||||
settings.Service.IgnoreService = true;
|
||||
settings.Service.Policy = Settings.Service.ServicePolicy.Optional;
|
||||
settings.Security.VersionRestrictions.Clear();
|
||||
settings.Taskbar.ShowApplicationLog = true;
|
||||
}
|
||||
|
||||
private void AllowBrowserToolbarForReloading(AppSettings settings)
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2024 ETH Zürich, IT Services
|
||||
*
|
||||
* 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.Events
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class CredentialsRequiredEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool Success { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Username { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright (c) 2024 ETH Zürich, IT Services
|
||||
*
|
||||
* 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.Events
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public delegate void CredentialsRequiredEventHandler(CredentialsRequiredEventArgs args);
|
||||
}
|
|
@ -6,7 +6,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SafeExamBrowser.SystemComponents.Contracts.Network.Events;
|
||||
|
||||
|
@ -33,9 +32,14 @@ namespace SafeExamBrowser.SystemComponents.Contracts.Network
|
|||
event ChangedEventHandler Changed;
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to connect to the wireless network with the given ID.
|
||||
/// Fired when credentials are required to connect to a network.
|
||||
/// </summary>
|
||||
void ConnectToWirelessNetwork(Guid id);
|
||||
event CredentialsRequiredEventHandler CredentialsRequired;
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to connect to the wireless network with the given name.
|
||||
/// </summary>
|
||||
void ConnectToWirelessNetwork(string name);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all currently available wireless networks.
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace SafeExamBrowser.SystemComponents.Contracts.Network
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -15,11 +13,6 @@ namespace SafeExamBrowser.SystemComponents.Contracts.Network
|
|||
/// </summary>
|
||||
public interface IWirelessNetwork
|
||||
{
|
||||
/// <summary>
|
||||
/// The unique identifier of the network.
|
||||
/// </summary>
|
||||
Guid Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The network name.
|
||||
/// </summary>
|
||||
|
|
|
@ -58,6 +58,8 @@
|
|||
<Compile Include="Audio\Events\VolumeChangedEventHandler.cs" />
|
||||
<Compile Include="Audio\IAudio.cs" />
|
||||
<Compile Include="IFileSystem.cs" />
|
||||
<Compile Include="Network\Events\CredentialsRequiredEventArgs.cs" />
|
||||
<Compile Include="Network\Events\CredentialsRequiredEventHandler.cs" />
|
||||
<Compile Include="Registry\Events\RegistryValueChangedEventHandler.cs" />
|
||||
<Compile Include="Registry\IRegistry.cs" />
|
||||
<Compile Include="IRemoteSessionDetector.cs" />
|
||||
|
|
|
@ -10,7 +10,6 @@ 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;
|
||||
|
@ -18,12 +17,22 @@ using SafeExamBrowser.WindowsApi.Contracts;
|
|||
using SimpleWifi;
|
||||
using SimpleWifi.Win32;
|
||||
using SimpleWifi.Win32.Interop;
|
||||
using Timer = System.Timers.Timer;
|
||||
|
||||
namespace SafeExamBrowser.SystemComponents.Network
|
||||
{
|
||||
/// <summary>
|
||||
/// Switch to the following WiFi library:
|
||||
/// https://github.com/emoacht/ManagedNativeWifi
|
||||
/// https://www.nuget.org/packages/ManagedNativeWifi
|
||||
///
|
||||
/// Potentially useful:
|
||||
/// https://learn.microsoft.com/en-us/dotnet/api/system.net.networkinformation.networkinterface?view=netframework-4.8
|
||||
/// </summary>
|
||||
public class NetworkAdapter : INetworkAdapter
|
||||
{
|
||||
private readonly object @lock = new object();
|
||||
|
||||
private readonly ILogger logger;
|
||||
private readonly INativeMethods nativeMethods;
|
||||
private readonly List<WirelessNetwork> wirelessNetworks;
|
||||
|
@ -35,6 +44,7 @@ namespace SafeExamBrowser.SystemComponents.Network
|
|||
public ConnectionType Type { get; private set; }
|
||||
|
||||
public event ChangedEventHandler Changed;
|
||||
public event CredentialsRequiredEventHandler CredentialsRequired;
|
||||
|
||||
public NetworkAdapter(ILogger logger, INativeMethods nativeMethods)
|
||||
{
|
||||
|
@ -43,22 +53,27 @@ namespace SafeExamBrowser.SystemComponents.Network
|
|||
this.wirelessNetworks = new List<WirelessNetwork>();
|
||||
}
|
||||
|
||||
public void ConnectToWirelessNetwork(Guid id)
|
||||
public void ConnectToWirelessNetwork(string name)
|
||||
{
|
||||
lock (@lock)
|
||||
{
|
||||
var network = wirelessNetworks.FirstOrDefault(n => n.Id == id);
|
||||
var network = wirelessNetworks.FirstOrDefault(n => n.Name == name);
|
||||
|
||||
if (network != default)
|
||||
{
|
||||
try
|
||||
{
|
||||
var request = new AuthRequest(network.AccessPoint);
|
||||
var accessPoint = network.AccessPoint;
|
||||
var request = new AuthRequest(accessPoint);
|
||||
|
||||
logger.Info($"Attempting to connect to '{network.Name}'...");
|
||||
if (accessPoint.HasProfile || accessPoint.IsConnected || TryGetCredentials(request))
|
||||
{
|
||||
logger.Info($"Attempting to connect to wireless network '{network.Name}' with{(request.Password == default ? "out" : "")} credentials...");
|
||||
|
||||
network.AccessPoint.ConnectAsync(request, false, (success) => AccessPoint_OnConnectCompleted(network.Name, success));
|
||||
Status = ConnectionStatus.Connecting;
|
||||
// TODO: Retry resp. alert of password error on failure and then ignore profile?!
|
||||
accessPoint.ConnectAsync(request, false, (success) => ConnectionAttemptCompleted(network.Name, success));
|
||||
Status = ConnectionStatus.Connecting;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -67,7 +82,7 @@ namespace SafeExamBrowser.SystemComponents.Network
|
|||
}
|
||||
else
|
||||
{
|
||||
logger.Warn($"Could not find network with id '{id}'!");
|
||||
logger.Warn($"Could not find wireless network '{name}'!");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,7 +126,7 @@ namespace SafeExamBrowser.SystemComponents.Network
|
|||
}
|
||||
}
|
||||
|
||||
private void AccessPoint_OnConnectCompleted(string name, bool success)
|
||||
private void ConnectionAttemptCompleted(string name, bool success)
|
||||
{
|
||||
lock (@lock)
|
||||
{
|
||||
|
@ -129,12 +144,28 @@ namespace SafeExamBrowser.SystemComponents.Network
|
|||
}
|
||||
}
|
||||
|
||||
private bool TryGetCredentials(AuthRequest request)
|
||||
{
|
||||
var args = new CredentialsRequiredEventArgs();
|
||||
|
||||
CredentialsRequired?.Invoke(args);
|
||||
|
||||
if (args.Success)
|
||||
{
|
||||
request.Password = args.Password;
|
||||
request.Username = args.Username;
|
||||
}
|
||||
|
||||
return args.Success;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (@lock)
|
||||
{
|
||||
var current = default(WirelessNetwork);
|
||||
var hasInternet = nativeMethods.HasInternetConnection();
|
||||
var hasWireless = !wifi.NoWifiAvailable && !IsTurnedOff();
|
||||
var isConnecting = Status == ConnectionStatus.Connecting;
|
||||
|
@ -144,12 +175,13 @@ namespace SafeExamBrowser.SystemComponents.Network
|
|||
|
||||
if (hasWireless)
|
||||
{
|
||||
foreach (var accessPoint in wifi.GetAccessPoints())
|
||||
foreach (var wirelessNetwork in wifi.GetAccessPoints().Select(a => ToWirelessNetwork(a)))
|
||||
{
|
||||
// The user may only connect to an already configured or connected wireless network!
|
||||
if (accessPoint.HasProfile || accessPoint.IsConnected)
|
||||
wirelessNetworks.Add(wirelessNetwork);
|
||||
|
||||
if (wirelessNetwork.Status == ConnectionStatus.Connected)
|
||||
{
|
||||
wirelessNetworks.Add(ToWirelessNetwork(accessPoint));
|
||||
current = wirelessNetwork;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -159,7 +191,7 @@ namespace SafeExamBrowser.SystemComponents.Network
|
|||
|
||||
if (previousStatus != ConnectionStatus.Connected && Status == ConnectionStatus.Connected)
|
||||
{
|
||||
logger.Info("Connection established.");
|
||||
logger.Info($"Connection established ({Type}{(current != default ? $", {current.Name}" : "")}).");
|
||||
}
|
||||
|
||||
if (previousStatus != ConnectionStatus.Disconnected && Status == ConnectionStatus.Disconnected)
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using SafeExamBrowser.SystemComponents.Contracts.Network;
|
||||
using SimpleWifi;
|
||||
|
||||
|
@ -16,14 +15,8 @@ namespace SafeExamBrowser.SystemComponents.Network
|
|||
{
|
||||
internal AccessPoint AccessPoint { get; set; }
|
||||
|
||||
public Guid Id { get; }
|
||||
public string Name { get; set; }
|
||||
public int SignalStrength { get; set; }
|
||||
public ConnectionStatus Status { get; set; }
|
||||
|
||||
public WirelessNetwork()
|
||||
{
|
||||
Id = Guid.NewGuid();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,6 +83,11 @@ namespace SafeExamBrowser.UserInterface.Contracts
|
|||
/// </summary>
|
||||
ISystemControl CreateNetworkControl(INetworkAdapter adapter, Location location);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a network dialog with the given message and title.
|
||||
/// </summary>
|
||||
INetworkDialog CreateNetworkDialog(string message, string title);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a notification control for the given notification, initialized for the specified location.
|
||||
/// </summary>
|
||||
|
|
|
@ -96,11 +96,13 @@
|
|||
<Compile Include="Windows\Data\ExamSelectionDialogResult.cs" />
|
||||
<Compile Include="Windows\Data\LockScreenOption.cs" />
|
||||
<Compile Include="Windows\Data\LockScreenResult.cs" />
|
||||
<Compile Include="Windows\Data\NetworkDialogResult.cs" />
|
||||
<Compile Include="Windows\Data\ServerFailureDialogResult.cs" />
|
||||
<Compile Include="Windows\Events\WindowClosedEventHandler.cs" />
|
||||
<Compile Include="Windows\Events\WindowClosingEventHandler.cs" />
|
||||
<Compile Include="Windows\IExamSelectionDialog.cs" />
|
||||
<Compile Include="Windows\ILockScreen.cs" />
|
||||
<Compile Include="Windows\INetworkDialog.cs" />
|
||||
<Compile Include="Windows\IPasswordDialog.cs" />
|
||||
<Compile Include="Windows\Data\PasswordDialogResult.cs" />
|
||||
<Compile Include="Proctoring\IProctoringFinalizationDialog.cs" />
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2024 ETH Zürich, IT Services
|
||||
*
|
||||
* 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.UserInterface.Contracts.Windows.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the user interaction result of an <see cref="INetworkDialog"/>.
|
||||
/// </summary>
|
||||
public class NetworkDialogResult
|
||||
{
|
||||
/// <summary>
|
||||
/// The password entered by the user, or <c>default(string)</c> if the interaction was unsuccessful.
|
||||
/// </summary>
|
||||
public string Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the user confirmed the dialog or not.
|
||||
/// </summary>
|
||||
public bool Success { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The username entered by the user, or <c>default(string)</c> if no username is required or the interaction was unsuccessful.
|
||||
/// </summary>
|
||||
public string Username { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (c) 2024 ETH Zürich, IT Services
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using SafeExamBrowser.UserInterface.Contracts.Windows.Data;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Contracts.Windows
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the functionality of a network dialog.
|
||||
/// </summary>
|
||||
public interface INetworkDialog : IWindow
|
||||
{
|
||||
/// <summary>
|
||||
/// Shows the dialog as topmost window. If a parent window is specified, the dialog is rendered modally for the given parent.
|
||||
/// </summary>
|
||||
NetworkDialogResult Show(IWindow parent = null);
|
||||
}
|
||||
}
|
|
@ -100,7 +100,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter
|
|||
{
|
||||
var button = new NetworkButton(network);
|
||||
|
||||
button.NetworkSelected += (o, args) => adapter.ConnectToWirelessNetwork(network.Id);
|
||||
button.NetworkSelected += (o, args) => adapter.ConnectToWirelessNetwork(network.Name);
|
||||
|
||||
if (network.Status == ConnectionStatus.Connected)
|
||||
{
|
||||
|
|
|
@ -112,7 +112,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
|
|||
{
|
||||
var button = new NetworkButton(network);
|
||||
|
||||
button.NetworkSelected += (o, args) => adapter.ConnectToWirelessNetwork(network.Id);
|
||||
button.NetworkSelected += (o, args) => adapter.ConnectToWirelessNetwork(network.Name);
|
||||
|
||||
if (network.Status == ConnectionStatus.Connected)
|
||||
{
|
||||
|
|
|
@ -168,6 +168,9 @@
|
|||
<DependentUpon>LogWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="MessageBoxFactory.cs" />
|
||||
<Compile Include="Windows\NetworkDialog.xaml.cs">
|
||||
<DependentUpon>NetworkDialog.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Windows\PasswordDialog.xaml.cs">
|
||||
<DependentUpon>PasswordDialog.xaml</DependentUpon>
|
||||
</Compile>
|
||||
|
@ -394,6 +397,10 @@
|
|||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Windows\NetworkDialog.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Windows\ProctoringFinalizationDialog.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
|
|
@ -143,6 +143,11 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
|||
}
|
||||
}
|
||||
|
||||
public INetworkDialog CreateNetworkDialog(string message, string title)
|
||||
{
|
||||
return Application.Current.Dispatcher.Invoke(() => new NetworkDialog(message, title, text));
|
||||
}
|
||||
|
||||
public INotificationControl CreateNotificationControl(INotification notification, Location location)
|
||||
{
|
||||
if (location == Location.ActionCenter)
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
<Window x:Class="SafeExamBrowser.UserInterface.Desktop.Windows.NetworkDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:fa="http://schemas.fontawesome.io/icons/"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Desktop.Windows"
|
||||
mc:Ignorable="d" Height="350" Width="450" ResizeMode="NoResize" Topmost="True">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="../Templates/Colors.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
<Grid FocusManager.FocusedElement="{Binding ElementName=Password}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="2*" />
|
||||
<RowDefinition Height="1*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="0">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<fa:ImageAwesome Grid.Column="0" Foreground="LightGray" Icon="Wifi" Margin="25" Width="50" />
|
||||
<Grid Grid.Column="1" Margin="0,0,25,25">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="0" Name="Message" Margin="0,0,0,5" TextWrapping="WrapWithOverflow" VerticalAlignment="Bottom" />
|
||||
<StackPanel Grid.Row="1" Orientation="Vertical">
|
||||
<Label Name="UsernameLabel" Target="{Binding ElementName=Username}" />
|
||||
<TextBox Name="Username" Height="25" Margin="0,0,0,5" VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="2" Orientation="Vertical">
|
||||
<Label Name="PasswordLabel" Target="{Binding ElementName=Password}" />
|
||||
<PasswordBox Grid.Row="2" Name="Password" Height="25" VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid Grid.Row="1" Background="{StaticResource BackgroundBrush}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
||||
<WrapPanel Orientation="Horizontal" Margin="25,0" HorizontalAlignment="Right" VerticalAlignment="Center">
|
||||
<Button Name="ConfirmButton" Cursor="Hand" Margin="10,0" Padding="10,5" MinWidth="75" />
|
||||
<Button Name="CancelButton" Cursor="Hand" Padding="10,5" MinWidth="75" />
|
||||
</WrapPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Window>
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Copyright (c) 2024 ETH Zürich, IT Services
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using SafeExamBrowser.I18n.Contracts;
|
||||
using SafeExamBrowser.UserInterface.Contracts.Windows;
|
||||
using SafeExamBrowser.UserInterface.Contracts.Windows.Data;
|
||||
using SafeExamBrowser.UserInterface.Contracts.Windows.Events;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop.Windows
|
||||
{
|
||||
public partial class NetworkDialog : Window, INetworkDialog
|
||||
{
|
||||
private readonly IText text;
|
||||
|
||||
private WindowClosedEventHandler closed;
|
||||
private WindowClosingEventHandler closing;
|
||||
|
||||
event WindowClosedEventHandler IWindow.Closed
|
||||
{
|
||||
add { closed += value; }
|
||||
remove { closed -= value; }
|
||||
}
|
||||
|
||||
event WindowClosingEventHandler IWindow.Closing
|
||||
{
|
||||
add { closing += value; }
|
||||
remove { closing -= value; }
|
||||
}
|
||||
|
||||
internal NetworkDialog(string message, string title, IText text)
|
||||
{
|
||||
this.text = text;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeNetworkDialog(message, title);
|
||||
}
|
||||
|
||||
public void BringToForeground()
|
||||
{
|
||||
Dispatcher.Invoke(Activate);
|
||||
}
|
||||
|
||||
public NetworkDialogResult Show(IWindow parent = null)
|
||||
{
|
||||
return Dispatcher.Invoke(() =>
|
||||
{
|
||||
var result = new NetworkDialogResult { Success = false };
|
||||
|
||||
if (parent is Window)
|
||||
{
|
||||
Owner = parent as Window;
|
||||
WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
||||
}
|
||||
|
||||
if (ShowDialog() is true)
|
||||
{
|
||||
result.Password = Password.Password;
|
||||
result.Success = true;
|
||||
result.Username = Username.Text;
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
private void InitializeNetworkDialog(string message, string title)
|
||||
{
|
||||
Message.Text = message;
|
||||
// TODO
|
||||
PasswordLabel.Content = "Password";
|
||||
Title = title;
|
||||
// TODO
|
||||
UsernameLabel.Content = "Username";
|
||||
WindowStartupLocation = WindowStartupLocation.CenterScreen;
|
||||
|
||||
Closed += (o, args) => closed?.Invoke();
|
||||
Closing += (o, args) => closing?.Invoke();
|
||||
Loaded += (o, args) => Activate();
|
||||
|
||||
CancelButton.Content = text.Get(TextKey.PasswordDialog_Cancel);
|
||||
CancelButton.Click += CancelButton_Click;
|
||||
|
||||
ConfirmButton.Content = text.Get(TextKey.PasswordDialog_Confirm);
|
||||
ConfirmButton.Click += ConfirmButton_Click;
|
||||
|
||||
Password.KeyDown += Password_KeyDown;
|
||||
}
|
||||
|
||||
private void CancelButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
DialogResult = false;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void ConfirmButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
DialogResult = true;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void Password_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Enter)
|
||||
{
|
||||
DialogResult = true;
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -100,7 +100,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenter
|
|||
{
|
||||
var button = new NetworkButton(network);
|
||||
|
||||
button.NetworkSelected += (o, args) => adapter.ConnectToWirelessNetwork(network.Id);
|
||||
button.NetworkSelected += (o, args) => adapter.ConnectToWirelessNetwork(network.Name);
|
||||
|
||||
if (network.Status == ConnectionStatus.Connected)
|
||||
{
|
||||
|
|
|
@ -112,7 +112,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar
|
|||
{
|
||||
var button = new NetworkButton(network);
|
||||
|
||||
button.NetworkSelected += (o, args) => adapter.ConnectToWirelessNetwork(network.Id);
|
||||
button.NetworkSelected += (o, args) => adapter.ConnectToWirelessNetwork(network.Name);
|
||||
|
||||
if (network.Status == ConnectionStatus.Connected)
|
||||
{
|
||||
|
|
|
@ -143,6 +143,12 @@ namespace SafeExamBrowser.UserInterface.Mobile
|
|||
}
|
||||
}
|
||||
|
||||
public INetworkDialog CreateNetworkDialog(string message, string title)
|
||||
{
|
||||
// TODO
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public INotificationControl CreateNotificationControl(INotification notification, Location location)
|
||||
{
|
||||
if (location == Location.ActionCenter)
|
||||
|
|
Loading…
Reference in a new issue