diff --git a/SafeExamBrowser.Browser/BrowserApplicationController.cs b/SafeExamBrowser.Browser/BrowserApplicationController.cs index 977b5534..c36d6c94 100644 --- a/SafeExamBrowser.Browser/BrowserApplicationController.cs +++ b/SafeExamBrowser.Browser/BrowserApplicationController.cs @@ -11,12 +11,14 @@ using System.Collections.Generic; using System.Linq; using CefSharp; using CefSharp.WinForms; +using SafeExamBrowser.Browser.Events; using SafeExamBrowser.Contracts.Browser; using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Core; using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.UserInterface; +using SafeExamBrowser.Contracts.UserInterface.MessageBox; using SafeExamBrowser.Contracts.UserInterface.Taskbar; using BrowserSettings = SafeExamBrowser.Contracts.Configuration.Settings.BrowserSettings; @@ -29,6 +31,7 @@ namespace SafeExamBrowser.Browser private AppConfig appConfig; private IApplicationButton button; private IList instances; + private IMessageBox messageBox; private IModuleLogger logger; private BrowserSettings settings; private IText text; @@ -39,6 +42,7 @@ namespace SafeExamBrowser.Browser public BrowserApplicationController( AppConfig appConfig, BrowserSettings settings, + IMessageBox messageBox, IModuleLogger logger, IText text, IUserInterfaceFactory uiFactory) @@ -46,6 +50,7 @@ namespace SafeExamBrowser.Browser this.appConfig = appConfig; this.instances = new List(); this.logger = logger; + this.messageBox = messageBox; this.settings = settings; this.text = text; this.uiFactory = uiFactory; @@ -56,7 +61,7 @@ namespace SafeExamBrowser.Browser var cefSettings = InitializeCefSettings(); var success = Cef.Initialize(cefSettings, true, null); - logger.Info("Initialized CEF."); + logger.Info("Initialized browser engine."); if (!success) { @@ -87,18 +92,20 @@ namespace SafeExamBrowser.Browser Cef.Shutdown(); - logger.Info("Terminated CEF."); + logger.Info("Terminated browser engine."); } - private void CreateNewInstance() + private void CreateNewInstance(BrowserSettings custom = null) { var id = new BrowserInstanceIdentifier(++instanceIdCounter); var isMainInstance = instances.Count == 0; var instanceLogger = logger.CloneFor($"BrowserInstance {id}"); - var instance = new BrowserApplicationInstance(appConfig, settings, id, isMainInstance, instanceLogger, text, uiFactory); + var instanceSettings = custom ?? settings; + var instance = new BrowserApplicationInstance(appConfig, instanceSettings, id, isMainInstance, messageBox, instanceLogger, text, uiFactory); instance.Initialize(); instance.ConfigurationDownloadRequested += (fileName, args) => ConfigurationDownloadRequested?.Invoke(fileName, args); + instance.PopupRequested += Instance_PopupRequested; instance.Terminated += Instance_Terminated; button.RegisterInstance(instance); @@ -120,9 +127,10 @@ namespace SafeExamBrowser.Browser UserAgent = settings.UseCustomUserAgent ? settings.CustomUserAgent : string.Empty }; - logger.Debug($"CEF cache path is '{cefSettings.CachePath}'."); - logger.Debug($"CEF log file is '{cefSettings.LogFile}'."); - logger.Debug($"CEF log severity is '{cefSettings.LogSeverity}'."); + logger.Debug($"Browser cache path: {cefSettings.CachePath}"); + logger.Debug($"Browser log file: {cefSettings.LogFile}"); + logger.Debug($"Browser log severity: {cefSettings.LogSeverity}"); + logger.Debug($"Browser engine version: Chromium {Cef.ChromiumVersion}, CEF {Cef.CefVersion}, CefSharp {Cef.CefSharpVersion}"); return cefSettings; } @@ -139,6 +147,27 @@ namespace SafeExamBrowser.Browser } } + private void Instance_PopupRequested(PopupRequestedEventArgs args) + { + var popupSettings = new BrowserSettings + { + AllowAddressBar = false, + AllowBackwardNavigation = false, + AllowConfigurationDownloads = settings.AllowConfigurationDownloads, + AllowDeveloperConsole = settings.AllowDeveloperConsole, + AllowDownloads = settings.AllowDownloads, + AllowForwardNavigation = false, + AllowPageZoom = settings.AllowPageZoom, + AllowPopups = settings.AllowPopups, + AllowReloading = settings.AllowReloading, + ShowReloadWarning = settings.ShowReloadWarning, + StartUrl = args.Url + }; + + logger.Info($"Received request to create new instance for '{args.Url}'..."); + CreateNewInstance(popupSettings); + } + private void Instance_Terminated(InstanceIdentifier id) { instances.Remove(instances.FirstOrDefault(i => i.Id == id)); diff --git a/SafeExamBrowser.Browser/BrowserApplicationInstance.cs b/SafeExamBrowser.Browser/BrowserApplicationInstance.cs index 34fe2b04..66700cd8 100644 --- a/SafeExamBrowser.Browser/BrowserApplicationInstance.cs +++ b/SafeExamBrowser.Browser/BrowserApplicationInstance.cs @@ -6,6 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +using SafeExamBrowser.Browser.Events; using SafeExamBrowser.Browser.Handlers; using SafeExamBrowser.Contracts.Browser; using SafeExamBrowser.Contracts.Configuration; @@ -16,6 +17,7 @@ using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.UserInterface; using SafeExamBrowser.Contracts.UserInterface.Browser; +using SafeExamBrowser.Contracts.UserInterface.MessageBox; using SafeExamBrowser.Contracts.UserInterface.Windows; namespace SafeExamBrowser.Browser @@ -26,6 +28,7 @@ namespace SafeExamBrowser.Browser private IBrowserControl control; private IBrowserWindow window; private bool isMainInstance; + private IMessageBox messageBox; private IModuleLogger logger; private BrowserSettings settings; private IText text; @@ -36,14 +39,16 @@ namespace SafeExamBrowser.Browser public IWindow Window { get { return window; } } public event DownloadRequestedEventHandler ConfigurationDownloadRequested; - public event NameChangedEventHandler NameChanged; public event InstanceTerminatedEventHandler Terminated; + public event NameChangedEventHandler NameChanged; + public event PopupRequestedEventHandler PopupRequested; public BrowserApplicationInstance( AppConfig appConfig, BrowserSettings settings, InstanceIdentifier id, bool isMainInstance, + IMessageBox messageBox, IModuleLogger logger, IText text, IUserInterfaceFactory uiFactory) @@ -51,6 +56,7 @@ namespace SafeExamBrowser.Browser this.appConfig = appConfig; this.Id = id; this.isMainInstance = isMainInstance; + this.messageBox = messageBox; this.logger = logger; this.settings = settings; this.text = text; @@ -59,13 +65,18 @@ namespace SafeExamBrowser.Browser internal void Initialize() { - var controlLogger = logger.CloneFor($"{nameof(BrowserControl)} {Id}"); + var contextMenuHandler = new ContextMenuHandler(settings, text); var downloadLogger = logger.CloneFor($"{nameof(DownloadHandler)} {Id}"); var downloadHandler = new DownloadHandler(appConfig, settings, downloadLogger); + var keyboardHandler = new KeyboardHandler(); + var lifeSpanHandler = new LifeSpanHandler(); + var requestHandler = new RequestHandler(appConfig); downloadHandler.ConfigurationDownloadRequested += DownloadHandler_ConfigurationDownloadRequested; + keyboardHandler.ReloadRequested += KeyboardHandler_ReloadRequested; + lifeSpanHandler.PopupRequested += LifeSpanHandler_PopupRequested; - control = new BrowserControl(appConfig, settings, downloadHandler, controlLogger, text); + control = new BrowserControl(contextMenuHandler, downloadHandler, keyboardHandler, lifeSpanHandler, requestHandler, settings.StartUrl); control.AddressChanged += Control_AddressChanged; control.LoadingStateChanged += Control_LoadingStateChanged; control.TitleChanged += Control_TitleChanged; @@ -84,8 +95,36 @@ namespace SafeExamBrowser.Browser logger.Debug("Initialized browser window."); } + private void HandleReloadRequest() + { + if (settings.AllowReloading && settings.ShowReloadWarning) + { + var result = messageBox.Show(TextKey.MessageBox_ReloadConfirmation, TextKey.MessageBox_ReloadConfirmationTitle, MessageBoxAction.YesNo, MessageBoxIcon.Question, window); + + if (result == MessageBoxResult.Yes) + { + logger.Debug("The user confirmed reloading the current page..."); + control.Reload(); + } + else + { + logger.Debug("The user aborted reloading the current page."); + } + } + else if (settings.AllowReloading) + { + logger.Debug("Reloading current page..."); + control.Reload(); + } + else + { + logger.Debug("Blocked reload attempt, as the user is not allowed to reload web pages."); + } + } + private void Control_AddressChanged(string address) { + logger.Debug($"Navigated to '{address}'."); window.UpdateAddress(address); } @@ -106,7 +145,6 @@ namespace SafeExamBrowser.Browser { args.BrowserWindow = window; logger.Debug($"Forwarding download request for configuration file '{fileName}'."); - ConfigurationDownloadRequested?.Invoke(fileName, args); } else @@ -115,6 +153,24 @@ namespace SafeExamBrowser.Browser } } + private void KeyboardHandler_ReloadRequested() + { + HandleReloadRequest(); + } + + private void LifeSpanHandler_PopupRequested(PopupRequestedEventArgs args) + { + if (settings.AllowPopups) + { + logger.Debug($"Forwarding request to open new window for '{args.Url}'..."); + PopupRequested?.Invoke(args); + } + else + { + logger.Debug($"Blocked attempt to open new window for '{args.Url}'."); + } + } + private void Window_AddressChanged(string address) { logger.Debug($"The user requested to navigate to '{address}'."); @@ -123,19 +179,18 @@ namespace SafeExamBrowser.Browser private void Window_ReloadRequested() { - logger.Debug($"The user requested to reload the current page."); - control.Reload(); + HandleReloadRequest(); } private void Window_BackwardNavigationRequested() { - logger.Debug($"The user requested to navigate backwards."); + logger.Debug($"Navigating forwards..."); control.NavigateBackwards(); } private void Window_ForwardNavigationRequested() { - logger.Debug($"The user requested to navigate forwards."); + logger.Debug($"Navigating backwards..."); control.NavigateForwards(); } } diff --git a/SafeExamBrowser.Browser/BrowserControl.cs b/SafeExamBrowser.Browser/BrowserControl.cs index d214ec95..01f22a77 100644 --- a/SafeExamBrowser.Browser/BrowserControl.cs +++ b/SafeExamBrowser.Browser/BrowserControl.cs @@ -6,27 +6,20 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -using System; -using System.Windows.Forms; using CefSharp; using CefSharp.WinForms; -using SafeExamBrowser.Browser.Handlers; -using SafeExamBrowser.Contracts.Configuration; -using SafeExamBrowser.Contracts.I18n; -using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.UserInterface.Browser; using SafeExamBrowser.Contracts.UserInterface.Browser.Events; -using BrowserSettings = SafeExamBrowser.Contracts.Configuration.Settings.BrowserSettings; namespace SafeExamBrowser.Browser { internal class BrowserControl : ChromiumWebBrowser, IBrowserControl { - private AppConfig appConfig; - private BrowserSettings settings; + private IContextMenuHandler contextMenuHandler; private IDownloadHandler downloadHandler; - private ILogger logger; - private IText text; + private IKeyboardHandler keyboardHandler; + private ILifeSpanHandler lifeSpanHandler; + private IRequestHandler requestHandler; private AddressChangedEventHandler addressChanged; private LoadingStateChangedEventHandler loadingStateChanged; @@ -51,30 +44,31 @@ namespace SafeExamBrowser.Browser } public BrowserControl( - AppConfig appConfig, - BrowserSettings settings, + IContextMenuHandler contextMenuHandler, IDownloadHandler downloadHandler, - ILogger logger, - IText text) : base(settings.StartUrl) + IKeyboardHandler keyboardHandler, + ILifeSpanHandler lifeSpanHandler, + IRequestHandler requestHandler, + string url) : base(url) { - this.appConfig = appConfig; + this.contextMenuHandler = contextMenuHandler; this.downloadHandler = downloadHandler; - this.logger = logger; - this.settings = settings; - this.text = text; + this.keyboardHandler = keyboardHandler; + this.lifeSpanHandler = lifeSpanHandler; + this.requestHandler = requestHandler; } public void Initialize() { - AddressChanged += BrowserControl_AddressChanged; + AddressChanged += (o, args) => addressChanged?.Invoke(args.Address); LoadingStateChanged += (o, args) => loadingStateChanged?.Invoke(args.IsLoading); - MouseWheel += BrowserControl_MouseWheel; TitleChanged += (o, args) => titleChanged?.Invoke(args.Title); DownloadHandler = downloadHandler; - KeyboardHandler = new KeyboardHandler(settings); - MenuHandler = new ContextMenuHandler(settings, text); - RequestHandler = new RequestHandler(appConfig); + KeyboardHandler = keyboardHandler; + LifeSpanHandler = lifeSpanHandler; + MenuHandler = contextMenuHandler; + RequestHandler = requestHandler; } public void NavigateBackwards() @@ -89,37 +83,12 @@ namespace SafeExamBrowser.Browser public void NavigateTo(string address) { - if (!String.IsNullOrWhiteSpace(address)) - { - Load(address); - } + Load(address); } public void Reload() { GetBrowser().Reload(); } - - private void BrowserControl_AddressChanged(object sender, AddressChangedEventArgs args) - { - logger.Debug($"Navigated to '{args.Address}'."); - addressChanged?.Invoke(args.Address); - } - - private void BrowserControl_MouseWheel(object sender, MouseEventArgs e) - { - if (settings.AllowPageZoom && ModifierKeys == Keys.Control) - { - var browser = GetBrowser(); - - browser.GetZoomLevelAsync().ContinueWith(task => - { - if (task.IsCompleted) - { - browser.SetZoomLevel(task.Result + e.Delta * 0.1); - } - }); - } - } } } diff --git a/SafeExamBrowser.Browser/Events/PopupRequestedEventArgs.cs b/SafeExamBrowser.Browser/Events/PopupRequestedEventArgs.cs new file mode 100644 index 00000000..c15709b2 --- /dev/null +++ b/SafeExamBrowser.Browser/Events/PopupRequestedEventArgs.cs @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2019 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.Browser.Events +{ + internal class PopupRequestedEventArgs + { + public string Url { get; set; } + } +} diff --git a/SafeExamBrowser.Browser/Events/PopupRequestedEventHandler.cs b/SafeExamBrowser.Browser/Events/PopupRequestedEventHandler.cs new file mode 100644 index 00000000..a9bf09dc --- /dev/null +++ b/SafeExamBrowser.Browser/Events/PopupRequestedEventHandler.cs @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2019 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.Browser.Events +{ + internal delegate void PopupRequestedEventHandler(PopupRequestedEventArgs args); +} diff --git a/SafeExamBrowser.Browser/Events/ReloadRequestedEventHandler.cs b/SafeExamBrowser.Browser/Events/ReloadRequestedEventHandler.cs new file mode 100644 index 00000000..7b6fdb96 --- /dev/null +++ b/SafeExamBrowser.Browser/Events/ReloadRequestedEventHandler.cs @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2019 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.Browser.Events +{ + internal delegate void ReloadRequestedEventHandler(); +} diff --git a/SafeExamBrowser.Browser/Handlers/ContextMenuHandler.cs b/SafeExamBrowser.Browser/Handlers/ContextMenuHandler.cs index 3a7015e7..40408510 100644 --- a/SafeExamBrowser.Browser/Handlers/ContextMenuHandler.cs +++ b/SafeExamBrowser.Browser/Handlers/ContextMenuHandler.cs @@ -13,7 +13,7 @@ using BrowserSettings = SafeExamBrowser.Contracts.Configuration.Settings.Browser namespace SafeExamBrowser.Browser.Handlers { /// - /// See https://cefsharp.github.io/api/63.0.0/html/T_CefSharp_IContextMenuHandler.htm. + /// See https://cefsharp.github.io/api/67.0.0/html/T_CefSharp_IContextMenuHandler.htm. /// internal class ContextMenuHandler : IContextMenuHandler { diff --git a/SafeExamBrowser.Browser/Handlers/DownloadHandler.cs b/SafeExamBrowser.Browser/Handlers/DownloadHandler.cs index 1f08ddc4..c929c5c7 100644 --- a/SafeExamBrowser.Browser/Handlers/DownloadHandler.cs +++ b/SafeExamBrowser.Browser/Handlers/DownloadHandler.cs @@ -19,7 +19,7 @@ using BrowserSettings = SafeExamBrowser.Contracts.Configuration.Settings.Browser namespace SafeExamBrowser.Browser.Handlers { /// - /// See https://cefsharp.github.io/api/63.0.0/html/T_CefSharp_IDownloadHandler.htm. + /// See https://cefsharp.github.io/api/67.0.0/html/T_CefSharp_IDownloadHandler.htm. /// internal class DownloadHandler : IDownloadHandler { diff --git a/SafeExamBrowser.Browser/Handlers/KeyboardHandler.cs b/SafeExamBrowser.Browser/Handlers/KeyboardHandler.cs index 46061813..cce9fb8d 100644 --- a/SafeExamBrowser.Browser/Handlers/KeyboardHandler.cs +++ b/SafeExamBrowser.Browser/Handlers/KeyboardHandler.cs @@ -8,21 +8,16 @@ using System.Windows.Forms; using CefSharp; -using BrowserSettings = SafeExamBrowser.Contracts.Configuration.Settings.BrowserSettings; +using SafeExamBrowser.Browser.Events; namespace SafeExamBrowser.Browser.Handlers { /// - /// See https://cefsharp.github.io/api/63.0.0/html/T_CefSharp_IKeyboardHandler.htm. + /// See https://cefsharp.github.io/api/67.0.0/html/T_CefSharp_IKeyboardHandler.htm. /// internal class KeyboardHandler : IKeyboardHandler { - private BrowserSettings settings; - - public KeyboardHandler(BrowserSettings settings) - { - this.settings = settings; - } + public event ReloadRequestedEventHandler ReloadRequested; public bool OnKeyEvent(IWebBrowser browserControl, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey) { @@ -31,9 +26,9 @@ namespace SafeExamBrowser.Browser.Handlers public bool OnPreKeyEvent(IWebBrowser browserControl, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey, ref bool isKeyboardShortcut) { - if (settings.AllowReloading && type == KeyType.KeyUp && windowsKeyCode == (int) Keys.F5) + if (type == KeyType.KeyUp && windowsKeyCode == (int) Keys.F5) { - browserControl.Reload(); + ReloadRequested?.Invoke(); return true; } diff --git a/SafeExamBrowser.Browser/Handlers/LifeSpanHandler.cs b/SafeExamBrowser.Browser/Handlers/LifeSpanHandler.cs new file mode 100644 index 00000000..2acbcdf1 --- /dev/null +++ b/SafeExamBrowser.Browser/Handlers/LifeSpanHandler.cs @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2019 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 CefSharp; +using SafeExamBrowser.Browser.Events; + +namespace SafeExamBrowser.Browser.Handlers +{ + /// + /// See https://cefsharp.github.io/api/67.0.0/html/T_CefSharp_ILifeSpanHandler.htm. + /// + internal class LifeSpanHandler : ILifeSpanHandler + { + public event PopupRequestedEventHandler PopupRequested; + + public bool DoClose(IWebBrowser chromiumWebBrowser, IBrowser browser) + { + return false; + } + + public void OnAfterCreated(IWebBrowser chromiumWebBrowser, IBrowser browser) + { + } + + public void OnBeforeClose(IWebBrowser chromiumWebBrowser, IBrowser browser) + { + } + + public bool OnBeforePopup(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, string targetUrl, string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IPopupFeatures popupFeatures, IWindowInfo windowInfo, IBrowserSettings browserSettings, ref bool noJavascriptAccess, out IWebBrowser newBrowser) + { + var args = new PopupRequestedEventArgs { Url = targetUrl }; + + newBrowser = default(IWebBrowser); + PopupRequested?.Invoke(args); + + return true; + } + } +} diff --git a/SafeExamBrowser.Browser/Handlers/RequestHandler.cs b/SafeExamBrowser.Browser/Handlers/RequestHandler.cs index 0cbe5546..3f6a5512 100644 --- a/SafeExamBrowser.Browser/Handlers/RequestHandler.cs +++ b/SafeExamBrowser.Browser/Handlers/RequestHandler.cs @@ -14,7 +14,7 @@ using SafeExamBrowser.Contracts.Configuration; namespace SafeExamBrowser.Browser.Handlers { /// - /// See https://cefsharp.github.io/api/63.0.0/html/T_CefSharp_Handler_DefaultRequestHandler.htm. + /// See https://cefsharp.github.io/api/67.0.0/html/T_CefSharp_Handler_DefaultRequestHandler.htm. /// internal class RequestHandler : DefaultRequestHandler { diff --git a/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj b/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj index b8880ca1..551b7436 100644 --- a/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj +++ b/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj @@ -66,6 +66,9 @@ + + + Component @@ -73,6 +76,7 @@ + diff --git a/SafeExamBrowser.Client/CompositionRoot.cs b/SafeExamBrowser.Client/CompositionRoot.cs index db711b8b..38f12e9a 100644 --- a/SafeExamBrowser.Client/CompositionRoot.cs +++ b/SafeExamBrowser.Client/CompositionRoot.cs @@ -171,7 +171,7 @@ namespace SafeExamBrowser.Client private IOperation BuildBrowserOperation() { var moduleLogger = new ModuleLogger(logger, "BrowserController"); - var browserController = new BrowserApplicationController(configuration.AppConfig, configuration.Settings.Browser, moduleLogger, text, uiFactory); + var browserController = new BrowserApplicationController(configuration.AppConfig, configuration.Settings.Browser, messageBox, moduleLogger, text, uiFactory); var browserInfo = new BrowserApplicationInfo(); var operation = new BrowserOperation(browserController, browserInfo, logger, Taskbar, uiFactory); diff --git a/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.Browser.cs b/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.Browser.cs index 715a6644..b25819ab 100644 --- a/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.Browser.cs +++ b/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.Browser.cs @@ -13,6 +13,39 @@ namespace SafeExamBrowser.Configuration.ConfigurationData { internal partial class DataMapper { + private void MapAllowNavigation(Settings settings, object value) + { + if (value is bool allow) + { + settings.Browser.AllowBackwardNavigation = allow; + settings.Browser.AllowForwardNavigation = allow; + } + } + + private void MapAllowPageZoom(Settings settings, object value) + { + if (value is bool allow) + { + settings.Browser.AllowPageZoom = allow; + } + } + + private void MapAllowPopups(Settings settings, object value) + { + if (value is bool block) + { + settings.Browser.AllowPopups = !block; + } + } + + private void MapAllowReload(Settings settings, object value) + { + if (value is bool allow) + { + settings.Browser.AllowReloading = allow; + } + } + private void MapMainWindowMode(Settings settings, object value) { const int FULLSCREEN = 1; @@ -23,11 +56,11 @@ namespace SafeExamBrowser.Configuration.ConfigurationData } } - private void MapPageZoom(Settings settings, object value) + private void MapShowReloadWarning(Settings settings, object value) { - if (value is bool enabled) + if (value is bool show) { - settings.Browser.AllowPageZoom = enabled; + settings.Browser.ShowReloadWarning = show; } } diff --git a/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.cs b/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.cs index d106be85..8ad44a6d 100644 --- a/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.cs +++ b/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.cs @@ -27,12 +27,24 @@ namespace SafeExamBrowser.Configuration.ConfigurationData { switch (key) { - case Keys.Browser.EnablePageZoom: - MapPageZoom(settings, value); + case Keys.Browser.AllowNavigation: + MapAllowNavigation(settings, value); + break; + case Keys.Browser.AllowPageZoom: + MapAllowPageZoom(settings, value); + break; + case Keys.Browser.AllowPopups: + MapAllowPopups(settings, value); + break; + case Keys.Browser.AllowReload: + MapAllowReload(settings, value); break; case Keys.Browser.MainWindowMode: MapMainWindowMode(settings, value); break; + case Keys.Browser.ShowReloadWarning: + MapShowReloadWarning(settings, value); + break; case Keys.ConfigurationFile.ConfigurationPurpose: MapConfigurationMode(settings, value); break; diff --git a/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs b/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs index dd42e7a2..967b8234 100644 --- a/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs +++ b/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs @@ -20,10 +20,14 @@ namespace SafeExamBrowser.Configuration.ConfigurationData internal static class Browser { + internal const string AllowNavigation = "allowBrowsingBackForward"; + internal const string AllowPageZoom = "enableZoomPage"; + internal const string AllowPopups = "blockPopUpWindows"; + internal const string AllowReload = "browserWindowAllowReload"; internal const string CustomUserAgentDesktop = "browserUserAgentWinDesktopModeCustom"; internal const string CustomUserAgentMobile = "browserUserAgentWinTouchModeCustom"; - internal const string EnablePageZoom = "enableZoomPage"; internal const string MainWindowMode = "browserViewMode"; + internal const string ShowReloadWarning = "showReloadWarning"; internal const string UserAgentModeDesktop = "browserUserAgentWinDesktopMode"; internal const string UserAgentModeMobile = "browserUserAgentWinTouchMode"; } diff --git a/SafeExamBrowser.Contracts/Configuration/Settings/BrowserSettings.cs b/SafeExamBrowser.Contracts/Configuration/Settings/BrowserSettings.cs index 7a34172c..c949b032 100644 --- a/SafeExamBrowser.Contracts/Configuration/Settings/BrowserSettings.cs +++ b/SafeExamBrowser.Contracts/Configuration/Settings/BrowserSettings.cs @@ -17,42 +17,47 @@ namespace SafeExamBrowser.Contracts.Configuration.Settings public class BrowserSettings { /// - /// Determines whether the user should be allowed to change the URL of a browser window. + /// Determines whether the user will be allowed to change the URL of a browser window. /// public bool AllowAddressBar { get; set; } /// - /// Determines whether the user should be allowed to navigate backwards in a browser window. + /// Determines whether the user will be allowed to navigate backwards in a browser window. /// public bool AllowBackwardNavigation { get; set; } /// - /// Determines whether the user should be allowed to download configuration files. + /// Determines whether the user will be allowed to download configuration files. /// public bool AllowConfigurationDownloads { get; set; } /// - /// Determines whether the user should be allowed to open the developer console of a browser window. + /// Determines whether the user will be allowed to open the developer console of a browser window. /// public bool AllowDeveloperConsole { get; set; } /// - /// Determines whether the user should be allowed to download files (excluding configuration files). + /// Determines whether the user will be allowed to download files (excluding configuration files). /// public bool AllowDownloads { get; set; } /// - /// Determines whether the user should be allowed to navigate forwards in a browser window. + /// Determines whether the user will be allowed to navigate forwards in a browser window. /// public bool AllowForwardNavigation { get; set; } /// - /// Determines whether the user should be allowed to zoom webpages. + /// Determines whether the user will be allowed to zoom webpages. /// public bool AllowPageZoom { get; set; } /// - /// Determines whether the user should be allowed to reload webpages. + /// Determines whether popup windows will be opened or not. + /// + public bool AllowPopups { get; set; } + + /// + /// Determines whether the user will be allowed to reload webpages. /// public bool AllowReloading { get; set; } @@ -62,17 +67,22 @@ namespace SafeExamBrowser.Contracts.Configuration.Settings public string CustomUserAgent { get; set; } /// - /// Determines whether the main browser window should be rendered in fullscreen mode, i.e. without window frame. + /// Determines whether the main browser window will be rendered in fullscreen mode, i.e. without window frame. /// public bool FullScreenMode { get; set; } /// - /// The start URL with which a new browser window should be loaded. + /// Determines whether the user will need to confirm every reload attempt. + /// + public bool ShowReloadWarning { get; set; } + + /// + /// The start URL with which a new browser window will be loaded. /// public string StartUrl { get; set; } /// - /// Determines whether a custom user agent should be used for all requests, see . + /// Determines whether a custom user agent will be used for all requests, see . /// public bool UseCustomUserAgent { get; set; } } diff --git a/SafeExamBrowser.Contracts/I18n/TextKey.cs b/SafeExamBrowser.Contracts/I18n/TextKey.cs index 670fa473..c8256c81 100644 --- a/SafeExamBrowser.Contracts/I18n/TextKey.cs +++ b/SafeExamBrowser.Contracts/I18n/TextKey.cs @@ -42,6 +42,8 @@ namespace SafeExamBrowser.Contracts.I18n MessageBox_ReconfigurationErrorTitle, MessageBox_ReconfigurationQuestion, MessageBox_ReconfigurationQuestionTitle, + MessageBox_ReloadConfirmation, + MessageBox_ReloadConfirmationTitle, MessageBox_ShutdownError, MessageBox_ShutdownErrorTitle, MessageBox_SingleInstance, diff --git a/SafeExamBrowser.Contracts/Monitoring/KeyState.cs b/SafeExamBrowser.Contracts/Monitoring/KeyState.cs index 8c8b7776..d21b0737 100644 --- a/SafeExamBrowser.Contracts/Monitoring/KeyState.cs +++ b/SafeExamBrowser.Contracts/Monitoring/KeyState.cs @@ -13,7 +13,7 @@ namespace SafeExamBrowser.Contracts.Monitoring /// public enum KeyState { - None = 0, + Unknown = 0, Pressed, Released } diff --git a/SafeExamBrowser.Contracts/Monitoring/MouseButton.cs b/SafeExamBrowser.Contracts/Monitoring/MouseButton.cs index e5a9b1e8..ab904aae 100644 --- a/SafeExamBrowser.Contracts/Monitoring/MouseButton.cs +++ b/SafeExamBrowser.Contracts/Monitoring/MouseButton.cs @@ -13,7 +13,8 @@ namespace SafeExamBrowser.Contracts.Monitoring /// public enum MouseButton { - None = 0, + Unknown = 0, + Auxiliary, Left, Middle, Right diff --git a/SafeExamBrowser.I18n/Text.xml b/SafeExamBrowser.I18n/Text.xml index a1926ce7..034498ac 100644 --- a/SafeExamBrowser.I18n/Text.xml +++ b/SafeExamBrowser.I18n/Text.xml @@ -84,6 +84,12 @@ Configuration Detected + + Would you like to reload the current page? + + + Reload? + An unexpected error occurred during the shutdown procedure! Please consult the application log for more information... diff --git a/SafeExamBrowser.Monitoring/Mouse/MouseInterceptor.cs b/SafeExamBrowser.Monitoring/Mouse/MouseInterceptor.cs index d019c582..71f3c878 100644 --- a/SafeExamBrowser.Monitoring/Mouse/MouseInterceptor.cs +++ b/SafeExamBrowser.Monitoring/Mouse/MouseInterceptor.cs @@ -27,6 +27,7 @@ namespace SafeExamBrowser.Monitoring.Mouse { var block = false; + block |= button == MouseButton.Auxiliary; block |= button == MouseButton.Middle && !settings.AllowMiddleButton; block |= button == MouseButton.Right && !settings.AllowRightButton; diff --git a/SafeExamBrowser.UserInterface.Desktop/BrowserWindow.xaml b/SafeExamBrowser.UserInterface.Desktop/BrowserWindow.xaml index 3c3dc389..d5600f77 100644 --- a/SafeExamBrowser.UserInterface.Desktop/BrowserWindow.xaml +++ b/SafeExamBrowser.UserInterface.Desktop/BrowserWindow.xaml @@ -5,8 +5,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:fa="http://schemas.fontawesome.io/icons/" xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Desktop" - mc:Ignorable="d" Title="BrowserWindow" Background="#FFF0F0F0" Height="500" Width="750" MinHeight="250" MinWidth="250" - WindowState="Maximized" Icon=".\Images\SafeExamBrowser.ico"> + mc:Ignorable="d" Title="BrowserWindow" Background="#FFF0F0F0" Height="500" Width="750" MinHeight="250" MinWidth="250" Icon=".\Images\SafeExamBrowser.ico"> diff --git a/SafeExamBrowser.UserInterface.Desktop/BrowserWindow.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/BrowserWindow.xaml.cs index 0e48cfd1..14ed4800 100644 --- a/SafeExamBrowser.UserInterface.Desktop/BrowserWindow.xaml.cs +++ b/SafeExamBrowser.UserInterface.Desktop/BrowserWindow.xaml.cs @@ -153,12 +153,26 @@ namespace SafeExamBrowser.UserInterface.Desktop private void ApplySettings() { - if (IsMainWindow && settings.FullScreenMode) + if (IsMainWindow) { - MaxHeight = SystemParameters.WorkArea.Height; - ResizeMode = ResizeMode.NoResize; - WindowState = WindowState.Maximized; - WindowStyle = WindowStyle.None; + if (settings.FullScreenMode) + { + MaxHeight = SystemParameters.WorkArea.Height; + ResizeMode = ResizeMode.NoResize; + WindowState = WindowState.Maximized; + WindowStyle = WindowStyle.None; + } + else + { + WindowState = WindowState.Maximized; + } + } + else + { + Top = 0; + Left = SystemParameters.WorkArea.Width / 2; + Height = SystemParameters.WorkArea.Height; + Width = SystemParameters.WorkArea.Width / 2; } UrlTextBox.IsEnabled = settings.AllowAddressBar; diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/ApplicationButton.xaml b/SafeExamBrowser.UserInterface.Desktop/Controls/ApplicationButton.xaml index b17ee308..ffc20df2 100644 --- a/SafeExamBrowser.UserInterface.Desktop/Controls/ApplicationButton.xaml +++ b/SafeExamBrowser.UserInterface.Desktop/Controls/ApplicationButton.xaml @@ -11,17 +11,17 @@ + - - - 5 - - - + + + + + diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/KeyboardLayoutButton.xaml b/SafeExamBrowser.UserInterface.Desktop/Controls/KeyboardLayoutButton.xaml index 4945bea5..c269cf43 100644 --- a/SafeExamBrowser.UserInterface.Desktop/Controls/KeyboardLayoutButton.xaml +++ b/SafeExamBrowser.UserInterface.Desktop/Controls/KeyboardLayoutButton.xaml @@ -14,7 +14,7 @@ -