SEBWIN-310: Implemented quit URL.
This commit is contained in:
		
							parent
							
								
									4b415a5f45
								
							
						
					
					
						commit
						130dd45ff6
					
				
					 17 changed files with 213 additions and 88 deletions
				
			
		|  | @ -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.Contracts.Events | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Event handler used to indicate that a termination request has been detected. | ||||
| 	/// </summary> | ||||
| 	public delegate void TerminationRequestedEventHandler(); | ||||
| } | ||||
|  | @ -20,5 +20,10 @@ namespace SafeExamBrowser.Browser.Contracts | |||
| 		/// Event fired when the browser application detects a download request for an application configuration file. | ||||
| 		/// </summary> | ||||
| 		event DownloadRequestedEventHandler ConfigurationDownloadRequested; | ||||
| 
 | ||||
| 		/// <summary> | ||||
| 		/// Event fired when the browser application detects a request to terminate SEB. | ||||
| 		/// </summary> | ||||
| 		event TerminationRequestedEventHandler TerminationRequested; | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -57,6 +57,7 @@ | |||
|     <Compile Include="Events\DownloadEventArgs.cs" /> | ||||
|     <Compile Include="Events\DownloadFinishedCallback.cs" /> | ||||
|     <Compile Include="Events\DownloadRequestedEventHandler.cs" /> | ||||
|     <Compile Include="Events\TerminationRequestedEventHandler.cs" /> | ||||
|     <Compile Include="Filters\IRequestFilter.cs" /> | ||||
|     <Compile Include="Filters\IRule.cs" /> | ||||
|     <Compile Include="Filters\IRuleFactory.cs" /> | ||||
|  |  | |||
|  | @ -20,7 +20,6 @@ using SafeExamBrowser.Browser.Events; | |||
| using SafeExamBrowser.Configuration.Contracts; | ||||
| using SafeExamBrowser.I18n.Contracts; | ||||
| using SafeExamBrowser.Logging.Contracts; | ||||
| using SafeExamBrowser.Settings.Browser; | ||||
| using SafeExamBrowser.Settings.Browser.Proxy; | ||||
| using SafeExamBrowser.Settings.Logging; | ||||
| using SafeExamBrowser.UserInterface.Contracts; | ||||
|  | @ -49,6 +48,7 @@ namespace SafeExamBrowser.Browser | |||
| 
 | ||||
| 		public event DownloadRequestedEventHandler ConfigurationDownloadRequested; | ||||
| 		public event WindowsChangedEventHandler WindowsChanged; | ||||
| 		public event TerminationRequestedEventHandler TerminationRequested; | ||||
| 
 | ||||
| 		public BrowserApplication( | ||||
| 			AppConfig appConfig, | ||||
|  | @ -127,6 +127,7 @@ namespace SafeExamBrowser.Browser | |||
| 			instance.ConfigurationDownloadRequested += (fileName, args) => ConfigurationDownloadRequested?.Invoke(fileName, args); | ||||
| 			instance.PopupRequested += Instance_PopupRequested; | ||||
| 			instance.Terminated += Instance_Terminated; | ||||
| 			instance.TerminationRequested += () => TerminationRequested?.Invoke(); | ||||
| 
 | ||||
| 			instance.Initialize(); | ||||
| 			instances.Add(instance); | ||||
|  |  | |||
|  | @ -40,9 +40,9 @@ namespace SafeExamBrowser.Browser | |||
| 		private IMessageBox messageBox; | ||||
| 		private IModuleLogger logger; | ||||
| 		private BrowserSettings settings; | ||||
| 		private string startUrl; | ||||
| 		private IText text; | ||||
| 		private IUserInterfaceFactory uiFactory; | ||||
| 		private string url; | ||||
| 		private double zoomLevel; | ||||
| 
 | ||||
| 		private WindowSettings WindowSettings | ||||
|  | @ -59,6 +59,7 @@ namespace SafeExamBrowser.Browser | |||
| 		internal event DownloadRequestedEventHandler ConfigurationDownloadRequested; | ||||
| 		internal event PopupRequestedEventHandler PopupRequested; | ||||
| 		internal event InstanceTerminatedEventHandler Terminated; | ||||
| 		internal event TerminationRequestedEventHandler TerminationRequested; | ||||
| 
 | ||||
| 		public event IconChangedEventHandler IconChanged; | ||||
| 		public event TitleChangedEventHandler TitleChanged; | ||||
|  | @ -72,7 +73,7 @@ namespace SafeExamBrowser.Browser | |||
| 			IModuleLogger logger, | ||||
| 			IText text, | ||||
| 			IUserInterfaceFactory uiFactory, | ||||
| 			string url) | ||||
| 			string startUrl) | ||||
| 		{ | ||||
| 			this.appConfig = appConfig; | ||||
| 			this.Id = id; | ||||
|  | @ -83,7 +84,7 @@ namespace SafeExamBrowser.Browser | |||
| 			this.settings = settings; | ||||
| 			this.text = text; | ||||
| 			this.uiFactory = uiFactory; | ||||
| 			this.url = url; | ||||
| 			this.startUrl = startUrl; | ||||
| 		} | ||||
| 
 | ||||
| 		public void Activate() | ||||
|  | @ -106,12 +107,12 @@ namespace SafeExamBrowser.Browser | |||
| 		{ | ||||
| 			var contextMenuHandler = new ContextMenuHandler(); | ||||
| 			var displayHandler = new DisplayHandler(); | ||||
| 			var downloadLogger = logger.CloneFor($"{nameof(DownloadHandler)} {Id}"); | ||||
| 			var downloadLogger = logger.CloneFor($"{nameof(DownloadHandler)} #{Id}"); | ||||
| 			var downloadHandler = new DownloadHandler(appConfig, settings, downloadLogger); | ||||
| 			var keyboardHandler = new KeyboardHandler(); | ||||
| 			var lifeSpanHandler = new LifeSpanHandler(); | ||||
| 			var requestFilter = new RequestFilter(); | ||||
| 			var requestLogger = logger.CloneFor($"{nameof(RequestHandler)} {Id}"); | ||||
| 			var requestLogger = logger.CloneFor($"{nameof(RequestHandler)} #{Id}"); | ||||
| 			var requestHandler = new RequestHandler(appConfig, requestFilter, requestLogger, settings, text); | ||||
| 
 | ||||
| 			Icon = new BrowserIconResource(); | ||||
|  | @ -124,11 +125,12 @@ namespace SafeExamBrowser.Browser | |||
| 			keyboardHandler.ZoomOutRequested += ZoomOutRequested; | ||||
| 			keyboardHandler.ZoomResetRequested += ZoomResetRequested; | ||||
| 			lifeSpanHandler.PopupRequested += LifeSpanHandler_PopupRequested; | ||||
| 			requestHandler.QuitUrlVisited += RequestHandler_QuitUrlVisited; | ||||
| 			requestHandler.RequestBlocked += RequestHandler_RequestBlocked; | ||||
| 
 | ||||
| 			InitializeRequestFilter(requestFilter); | ||||
| 
 | ||||
| 			control = new BrowserControl(contextMenuHandler, displayHandler, downloadHandler, keyboardHandler, lifeSpanHandler, requestHandler, url); | ||||
| 			control = new BrowserControl(contextMenuHandler, displayHandler, downloadHandler, keyboardHandler, lifeSpanHandler, requestHandler, startUrl); | ||||
| 			control.AddressChanged += Control_AddressChanged; | ||||
| 			control.LoadingStateChanged += Control_LoadingStateChanged; | ||||
| 			control.TitleChanged += Control_TitleChanged; | ||||
|  | @ -276,6 +278,35 @@ namespace SafeExamBrowser.Browser | |||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		private void RequestHandler_QuitUrlVisited(string url) | ||||
| 		{ | ||||
| 			Task.Run(() => | ||||
| 			{ | ||||
| 				if (settings.ConfirmQuitUrl) | ||||
| 				{ | ||||
| 					var message = text.Get(TextKey.MessageBox_BrowserQuitUrlConfirmation); | ||||
| 					var title = text.Get(TextKey.MessageBox_BrowserQuitUrlConfirmationTitle); | ||||
| 					var result = messageBox.Show(message, title, MessageBoxAction.YesNo, MessageBoxIcon.Question, window); | ||||
| 					var terminate = result == MessageBoxResult.Yes; | ||||
| 
 | ||||
| 					if (terminate) | ||||
| 					{ | ||||
| 						logger.Info($"User confirmed termination via quit URL '{url}', forwarding request..."); | ||||
| 						TerminationRequested?.Invoke(); | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| 						logger.Info($"User aborted termination via quit URL '{url}'."); | ||||
| 					} | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					logger.Info($"Automatically requesting termination due to quit URL '{url}'..."); | ||||
| 					TerminationRequested?.Invoke(); | ||||
| 				} | ||||
| 			}); | ||||
| 		} | ||||
| 
 | ||||
| 		private void RequestHandler_RequestBlocked(string url) | ||||
| 		{ | ||||
| 			Task.Run(() => | ||||
|  | @ -285,7 +316,7 @@ namespace SafeExamBrowser.Browser | |||
| 
 | ||||
| 				control.TitleChanged -= Control_TitleChanged; | ||||
| 
 | ||||
| 				if (url == this.url) | ||||
| 				if (url.Equals(startUrl, StringComparison.OrdinalIgnoreCase)) | ||||
| 				{ | ||||
| 					window.UpdateTitle($"*** {title} ***"); | ||||
| 					TitleChanged?.Invoke($"*** {title} ***"); | ||||
|  |  | |||
|  | @ -8,5 +8,5 @@ | |||
| 
 | ||||
| namespace SafeExamBrowser.Browser.Events | ||||
| { | ||||
| 	internal delegate void RequestBlockedEventHandler(string url); | ||||
| 	internal delegate void UrlEventHandler(string url); | ||||
| } | ||||
|  | @ -25,7 +25,8 @@ namespace SafeExamBrowser.Browser.Handlers | |||
| 		private ResourceHandler resourceHandler; | ||||
| 		private BrowserSettings settings; | ||||
| 
 | ||||
| 		internal event RequestBlockedEventHandler RequestBlocked; | ||||
| 		internal event UrlEventHandler QuitUrlVisited; | ||||
| 		internal event UrlEventHandler RequestBlocked; | ||||
| 
 | ||||
| 		internal RequestHandler(AppConfig appConfig, IRequestFilter filter, ILogger logger, BrowserSettings settings, IText text) | ||||
| 		{ | ||||
|  | @ -60,6 +61,13 @@ namespace SafeExamBrowser.Browser.Handlers | |||
| 
 | ||||
| 		protected override bool OnBeforeBrowse(IWebBrowser webBrowser, IBrowser browser, IFrame frame, IRequest request, bool userGesture, bool isRedirect) | ||||
| 		{ | ||||
| 			if (IsQuitUrl(request)) | ||||
| 			{ | ||||
| 				QuitUrlVisited?.Invoke(request.Url); | ||||
| 
 | ||||
| 				return true; | ||||
| 			} | ||||
| 
 | ||||
| 			if (Block(request)) | ||||
| 			{ | ||||
| 				RequestBlocked?.Invoke(request.Url); | ||||
|  | @ -70,6 +78,18 @@ namespace SafeExamBrowser.Browser.Handlers | |||
| 			return base.OnBeforeBrowse(webBrowser, browser, frame, request, userGesture, isRedirect); | ||||
| 		} | ||||
| 
 | ||||
| 		private bool IsQuitUrl(IRequest request) | ||||
| 		{ | ||||
| 			var isQuitUrl = settings.QuitUrl?.Equals(request.Url, StringComparison.OrdinalIgnoreCase) == true; | ||||
| 
 | ||||
| 			if (isQuitUrl) | ||||
| 			{ | ||||
| 				logger.Debug($"Detected quit URL '{request.Url}'."); | ||||
| 			} | ||||
| 
 | ||||
| 			return isQuitUrl; | ||||
| 		} | ||||
| 
 | ||||
| 		private bool Block(IRequest request) | ||||
| 		{ | ||||
| 			if (settings.Filter.ProcessMainRequests) | ||||
|  |  | |||
|  | @ -68,7 +68,7 @@ | |||
|     <Compile Include="Events\PopupRequestedEventArgs.cs" /> | ||||
|     <Compile Include="Events\PopupRequestedEventHandler.cs" /> | ||||
|     <Compile Include="Events\ProgressChangedEventHandler.cs" /> | ||||
|     <Compile Include="Events\RequestBlockedEventHandler.cs" /> | ||||
|     <Compile Include="Events\UrlEventHandler.cs" /> | ||||
|     <Compile Include="Filters\RequestFilter.cs" /> | ||||
|     <Compile Include="Filters\Rules\RegexRule.cs" /> | ||||
|     <Compile Include="Filters\RuleFactory.cs" /> | ||||
|  |  | |||
|  | @ -232,6 +232,17 @@ namespace SafeExamBrowser.Client.UnitTests | |||
| 				It.Is<IWindow>(w => w == lockScreen.Object)), Times.Exactly(attempt - 1)); | ||||
| 		} | ||||
| 
 | ||||
| 		[TestMethod] | ||||
| 		public void Browser_MustTerminateIfRequested() | ||||
| 		{ | ||||
| 			runtimeProxy.Setup(p => p.RequestShutdown()).Returns(new CommunicationResult(true)); | ||||
| 
 | ||||
| 			sut.TryStart(); | ||||
| 			browser.Raise(b => b.TerminationRequested += null); | ||||
| 
 | ||||
| 			runtimeProxy.Verify(p => p.RequestShutdown(), Times.Once); | ||||
| 		} | ||||
| 
 | ||||
| 		[TestMethod] | ||||
| 		public void Communication_MustCorrectlyHandleMessageBoxRequest() | ||||
| 		{ | ||||
|  |  | |||
|  | @ -171,6 +171,7 @@ namespace SafeExamBrowser.Client | |||
| 			applicationMonitor.ExplorerStarted += ApplicationMonitor_ExplorerStarted; | ||||
| 			applicationMonitor.TerminationFailed += ApplicationMonitor_TerminationFailed; | ||||
| 			Browser.ConfigurationDownloadRequested += Browser_ConfigurationDownloadRequested; | ||||
| 			Browser.TerminationRequested += Browser_TerminationRequested; | ||||
| 			ClientHost.MessageBoxRequested += ClientHost_MessageBoxRequested; | ||||
| 			ClientHost.PasswordRequested += ClientHost_PasswordRequested; | ||||
| 			ClientHost.ReconfigurationDenied += ClientHost_ReconfigurationDenied; | ||||
|  | @ -321,8 +322,7 @@ namespace SafeExamBrowser.Client | |||
| 			} | ||||
| 			else if (result.OptionId == terminateOption.Id) | ||||
| 			{ | ||||
| 				logger.Info("Initiating shutdown request..."); | ||||
| 
 | ||||
| 				logger.Info("Attempting to shutdown as requested by the user..."); | ||||
| 				TryRequestShutdown(); | ||||
| 			} | ||||
| 		} | ||||
|  | @ -343,6 +343,12 @@ namespace SafeExamBrowser.Client | |||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		private void Browser_TerminationRequested() | ||||
| 		{ | ||||
| 			logger.Info("Attempting to shutdown as requested by the browser..."); | ||||
| 			TryRequestShutdown(); | ||||
| 		} | ||||
| 
 | ||||
| 		private void Browser_ConfigurationDownloadFinished(bool success, string filePath = null) | ||||
| 		{ | ||||
| 			if (success) | ||||
|  |  | |||
|  | @ -94,8 +94,8 @@ namespace SafeExamBrowser.Configuration.UnitTests.DataFormats | |||
| 
 | ||||
| 			Assert.AreEqual(true, result.RawData[Keys.Browser.AllowConfigurationDownloads]); | ||||
| 			Assert.AreEqual(0, result.RawData[Keys.ConfigurationFile.ConfigurationPurpose]); | ||||
| 			Assert.AreEqual("https://safeexambrowser.org/start", result.RawData[Keys.General.StartUrl]); | ||||
| 			Assert.AreEqual(true, result.RawData[Keys.Input.Keyboard.EnableF5]); | ||||
| 			Assert.AreEqual("https://safeexambrowser.org/start", result.RawData[Keys.Browser.StartUrl]); | ||||
| 			Assert.AreEqual(true, result.RawData[Keys.Keyboard.EnableF5]); | ||||
| 			Assert.IsInstanceOfType(result.RawData[Keys.Network.Certificates.EmbeddedCertificates], typeof(List<object>)); | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
|  | @ -133,6 +133,22 @@ namespace SafeExamBrowser.Configuration.ConfigurationData | |||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		private void MapQuitUrl(AppSettings settings, object value) | ||||
| 		{ | ||||
| 			if (value is string url) | ||||
| 			{ | ||||
| 				settings.Browser.QuitUrl = url; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		private void MapQuitUrlConfirmation(AppSettings settings, object value) | ||||
| 		{ | ||||
| 			if (value is bool confirm) | ||||
| 			{ | ||||
| 				settings.Browser.ConfirmQuitUrl = confirm; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		private void MapRequestFilter(IDictionary<string, object> rawData, AppSettings settings) | ||||
| 		{ | ||||
| 			var processMainRequests = rawData.TryGetValue(Keys.Browser.Filter.EnableMainRequestFilter, out var value) && value as bool? == true; | ||||
|  |  | |||
|  | @ -22,7 +22,8 @@ namespace SafeExamBrowser.Configuration.ConfigurationData | |||
| 				MapBrowserSettings(item.Key, item.Value, settings); | ||||
| 				MapConfigurationFileSettings(item.Key, item.Value, settings); | ||||
| 				MapGeneralSettings(item.Key, item.Value, settings); | ||||
| 				MapInputSettings(item.Key, item.Value, settings); | ||||
| 				MapKeyboardSettings(item.Key, item.Value, settings); | ||||
| 				MapMouseSettings(item.Key, item.Value, settings); | ||||
| 				MapSecuritySettings(item.Key, item.Value, settings); | ||||
| 				MapUserInterfaceSettings(item.Key, item.Value, settings); | ||||
| 			} | ||||
|  | @ -133,6 +134,15 @@ namespace SafeExamBrowser.Configuration.ConfigurationData | |||
| 				case Keys.Browser.Proxy.Settings: | ||||
| 					MapProxySettings(settings, value); | ||||
| 					break; | ||||
| 				case Keys.Browser.QuitUrl: | ||||
| 					MapQuitUrl(settings, value); | ||||
| 					break; | ||||
| 				case Keys.Browser.QuitUrlConfirmation: | ||||
| 					MapQuitUrlConfirmation(settings, value); | ||||
| 					break; | ||||
| 				case Keys.Browser.StartUrl: | ||||
| 					MapStartUrl(settings, value); | ||||
| 					break; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
|  | @ -140,6 +150,9 @@ namespace SafeExamBrowser.Configuration.ConfigurationData | |||
| 		{ | ||||
| 			switch (key) | ||||
| 			{ | ||||
| 				case Keys.ConfigurationFile.AdminPasswordHash: | ||||
| 					MapAdminPasswordHash(settings, value); | ||||
| 					break; | ||||
| 				case Keys.ConfigurationFile.ConfigurationPurpose: | ||||
| 					MapConfigurationMode(settings, value); | ||||
| 					break; | ||||
|  | @ -150,83 +163,81 @@ namespace SafeExamBrowser.Configuration.ConfigurationData | |||
| 		{ | ||||
| 			switch (key) | ||||
| 			{ | ||||
| 				case Keys.General.AdminPasswordHash: | ||||
| 					MapAdminPasswordHash(settings, value); | ||||
| 					break; | ||||
| 				case Keys.General.LogLevel: | ||||
| 					MapLogLevel(settings, value); | ||||
| 					break; | ||||
| 				case Keys.General.QuitPasswordHash: | ||||
| 					MapQuitPasswordHash(settings, value); | ||||
| 					break; | ||||
| 				case Keys.General.StartUrl: | ||||
| 					MapStartUrl(settings, value); | ||||
| 					break; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		private void MapInputSettings(string key, object value, AppSettings settings) | ||||
| 		private void MapKeyboardSettings(string key, object value, AppSettings settings) | ||||
| 		{ | ||||
| 			switch (key) | ||||
| 			{ | ||||
| 				case Keys.Input.Keyboard.EnableAltEsc: | ||||
| 				case Keys.Keyboard.EnableAltEsc: | ||||
| 					MapEnableAltEsc(settings, value); | ||||
| 					break; | ||||
| 				case Keys.Input.Keyboard.EnableAltF4: | ||||
| 				case Keys.Keyboard.EnableAltF4: | ||||
| 					MapEnableAltF4(settings, value); | ||||
| 					break; | ||||
| 				case Keys.Input.Keyboard.EnableAltTab: | ||||
| 				case Keys.Keyboard.EnableAltTab: | ||||
| 					MapEnableAltTab(settings, value); | ||||
| 					break; | ||||
| 				case Keys.Input.Keyboard.EnableCtrlEsc: | ||||
| 				case Keys.Keyboard.EnableCtrlEsc: | ||||
| 					MapEnableCtrlEsc(settings, value); | ||||
| 					break; | ||||
| 				case Keys.Input.Keyboard.EnableEsc: | ||||
| 				case Keys.Keyboard.EnableEsc: | ||||
| 					MapEnableEsc(settings, value); | ||||
| 					break; | ||||
| 				case Keys.Input.Keyboard.EnableF1: | ||||
| 				case Keys.Keyboard.EnableF1: | ||||
| 					MapEnableF1(settings, value); | ||||
| 					break; | ||||
| 				case Keys.Input.Keyboard.EnableF2: | ||||
| 				case Keys.Keyboard.EnableF2: | ||||
| 					MapEnableF2(settings, value); | ||||
| 					break; | ||||
| 				case Keys.Input.Keyboard.EnableF3: | ||||
| 				case Keys.Keyboard.EnableF3: | ||||
| 					MapEnableF3(settings, value); | ||||
| 					break; | ||||
| 				case Keys.Input.Keyboard.EnableF4: | ||||
| 				case Keys.Keyboard.EnableF4: | ||||
| 					MapEnableF4(settings, value); | ||||
| 					break; | ||||
| 				case Keys.Input.Keyboard.EnableF5: | ||||
| 				case Keys.Keyboard.EnableF5: | ||||
| 					MapEnableF5(settings, value); | ||||
| 					break; | ||||
| 				case Keys.Input.Keyboard.EnableF6: | ||||
| 				case Keys.Keyboard.EnableF6: | ||||
| 					MapEnableF6(settings, value); | ||||
| 					break; | ||||
| 				case Keys.Input.Keyboard.EnableF7: | ||||
| 				case Keys.Keyboard.EnableF7: | ||||
| 					MapEnableF7(settings, value); | ||||
| 					break; | ||||
| 				case Keys.Input.Keyboard.EnableF8: | ||||
| 				case Keys.Keyboard.EnableF8: | ||||
| 					MapEnableF8(settings, value); | ||||
| 					break; | ||||
| 				case Keys.Input.Keyboard.EnableF9: | ||||
| 				case Keys.Keyboard.EnableF9: | ||||
| 					MapEnableF9(settings, value); | ||||
| 					break; | ||||
| 				case Keys.Input.Keyboard.EnableF10: | ||||
| 				case Keys.Keyboard.EnableF10: | ||||
| 					MapEnableF10(settings, value); | ||||
| 					break; | ||||
| 				case Keys.Input.Keyboard.EnableF11: | ||||
| 				case Keys.Keyboard.EnableF11: | ||||
| 					MapEnableF11(settings, value); | ||||
| 					break; | ||||
| 				case Keys.Input.Keyboard.EnableF12: | ||||
| 				case Keys.Keyboard.EnableF12: | ||||
| 					MapEnableF12(settings, value); | ||||
| 					break; | ||||
| 				case Keys.Input.Keyboard.EnablePrintScreen: | ||||
| 				case Keys.Keyboard.EnablePrintScreen: | ||||
| 					MapEnablePrintScreen(settings, value); | ||||
| 					break; | ||||
| 				case Keys.Input.Keyboard.EnableSystemKey: | ||||
| 				case Keys.Keyboard.EnableSystemKey: | ||||
| 					MapEnableSystemKey(settings, value); | ||||
| 					break; | ||||
| 				case Keys.Input.Mouse.EnableRightMouse: | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		private void MapMouseSettings(string key, object value, AppSettings settings) | ||||
| 		{ | ||||
| 			switch (key) | ||||
| 			{ | ||||
| 				case Keys.Mouse.EnableRightMouse: | ||||
| 					MapEnableRightMouse(settings, value); | ||||
| 					break; | ||||
| 			} | ||||
|  | @ -236,6 +247,9 @@ namespace SafeExamBrowser.Configuration.ConfigurationData | |||
| 		{ | ||||
| 			switch (key) | ||||
| 			{ | ||||
| 				case Keys.Security.QuitPasswordHash: | ||||
| 					MapQuitPasswordHash(settings, value); | ||||
| 					break; | ||||
| 				case Keys.Security.ServicePolicy: | ||||
| 					MapServicePolicy(settings, value); | ||||
| 					break; | ||||
|  |  | |||
|  | @ -12,10 +12,6 @@ namespace SafeExamBrowser.Configuration.ConfigurationData | |||
| 	{ | ||||
| 		internal const int WINDOWS = 1; | ||||
| 
 | ||||
| 		internal static class AdditionalResources | ||||
| 		{ | ||||
| 		} | ||||
| 
 | ||||
| 		internal static class Applications | ||||
| 		{ | ||||
| 			internal const string Active = "active"; | ||||
|  | @ -53,6 +49,9 @@ namespace SafeExamBrowser.Configuration.ConfigurationData | |||
| 			internal const string CustomUserAgentMobile = "browserUserAgentWinTouchModeCustom"; | ||||
| 			internal const string PopupPolicy = "newBrowserWindowByLinkPolicy"; | ||||
| 			internal const string PopupBlockForeignHost = "newBrowserWindowByLinkBlockForeign"; | ||||
| 			internal const string QuitUrl = "quitURL"; | ||||
| 			internal const string QuitUrlConfirmation = "quitURLConfirm"; | ||||
| 			internal const string StartUrl = "startURL"; | ||||
| 			internal const string UserAgentModeDesktop = "browserUserAgentWinDesktopMode"; | ||||
| 			internal const string UserAgentModeMobile = "browserUserAgentWinTouchMode"; | ||||
| 
 | ||||
|  | @ -143,52 +142,43 @@ namespace SafeExamBrowser.Configuration.ConfigurationData | |||
| 
 | ||||
| 		internal static class ConfigurationFile | ||||
| 		{ | ||||
| 			internal const string AdminPasswordHash = "hashedAdminPassword"; | ||||
| 			internal const string ConfigurationPurpose = "sebConfigPurpose"; | ||||
| 			internal const string KeepClientConfigEncryption = "clientConfigKeepEncryption"; | ||||
| 		} | ||||
| 
 | ||||
| 		internal static class Exam | ||||
| 		{ | ||||
| 		} | ||||
| 
 | ||||
| 		internal static class General | ||||
| 		{ | ||||
| 			internal const string AdminPasswordHash = "hashedAdminPassword"; | ||||
| 			internal const string AllowApplicationLog = "allowApplicationLog"; | ||||
| 			internal const string LogLevel = "logLevel"; | ||||
| 			internal const string QuitPasswordHash = "hashedQuitPassword"; | ||||
| 			internal const string StartUrl = "startURL"; | ||||
| 		} | ||||
| 
 | ||||
| 		internal static class Input | ||||
| 		internal static class Keyboard | ||||
| 		{ | ||||
| 			internal static class Keyboard | ||||
| 			{ | ||||
| 				internal const string EnableAltEsc = "enableAltEsc"; | ||||
| 				internal const string EnableAltTab = "enableAltTab"; | ||||
| 				internal const string EnableAltF4 = "enableAltF4"; | ||||
| 				internal const string EnableCtrlEsc = "enableCtrlEsc"; | ||||
| 				internal const string EnableEsc = "enableEsc"; | ||||
| 				internal const string EnableF1 = "enableF1"; | ||||
| 				internal const string EnableF2 = "enableF2"; | ||||
| 				internal const string EnableF3 = "enableF3"; | ||||
| 				internal const string EnableF4 = "enableF4"; | ||||
| 				internal const string EnableF5 = "enableF5"; | ||||
| 				internal const string EnableF6 = "enableF6"; | ||||
| 				internal const string EnableF7 = "enableF7"; | ||||
| 				internal const string EnableF8 = "enableF8"; | ||||
| 				internal const string EnableF9 = "enableF9"; | ||||
| 				internal const string EnableF10 = "enableF10"; | ||||
| 				internal const string EnableF11 = "enableF11"; | ||||
| 				internal const string EnableF12 = "enableF12"; | ||||
| 				internal const string EnablePrintScreen = "enablePrintScreen"; | ||||
| 				internal const string EnableSystemKey = "enableStartMenu"; | ||||
| 			} | ||||
| 			internal const string EnableAltEsc = "enableAltEsc"; | ||||
| 			internal const string EnableAltTab = "enableAltTab"; | ||||
| 			internal const string EnableAltF4 = "enableAltF4"; | ||||
| 			internal const string EnableCtrlEsc = "enableCtrlEsc"; | ||||
| 			internal const string EnableEsc = "enableEsc"; | ||||
| 			internal const string EnableF1 = "enableF1"; | ||||
| 			internal const string EnableF2 = "enableF2"; | ||||
| 			internal const string EnableF3 = "enableF3"; | ||||
| 			internal const string EnableF4 = "enableF4"; | ||||
| 			internal const string EnableF5 = "enableF5"; | ||||
| 			internal const string EnableF6 = "enableF6"; | ||||
| 			internal const string EnableF7 = "enableF7"; | ||||
| 			internal const string EnableF8 = "enableF8"; | ||||
| 			internal const string EnableF9 = "enableF9"; | ||||
| 			internal const string EnableF10 = "enableF10"; | ||||
| 			internal const string EnableF11 = "enableF11"; | ||||
| 			internal const string EnableF12 = "enableF12"; | ||||
| 			internal const string EnablePrintScreen = "enablePrintScreen"; | ||||
| 			internal const string EnableSystemKey = "enableStartMenu"; | ||||
| 		} | ||||
| 
 | ||||
| 			internal static class Mouse | ||||
| 			{ | ||||
| 				internal const string EnableRightMouse = "enableRightMouse"; | ||||
| 			} | ||||
| 		internal static class Mouse | ||||
| 		{ | ||||
| 			internal const string EnableRightMouse = "enableRightMouse"; | ||||
| 		} | ||||
| 
 | ||||
| 		internal static class Network | ||||
|  | @ -201,14 +191,11 @@ namespace SafeExamBrowser.Configuration.ConfigurationData | |||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		internal static class Registry | ||||
| 		{ | ||||
| 		} | ||||
| 
 | ||||
| 		internal static class Security | ||||
| 		{ | ||||
| 			internal const string KioskModeCreateNewDesktop = "createNewDesktop"; | ||||
| 			internal const string KioskModeDisableExplorerShell = "killExplorerShell"; | ||||
| 			internal const string QuitPasswordHash = "hashedQuitPassword"; | ||||
| 			internal const string ServicePolicy = "sebServicePolicy"; | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
|  | @ -45,6 +45,8 @@ namespace SafeExamBrowser.I18n.Contracts | |||
| 		MessageBox_ApplicationTerminationFailureTitle, | ||||
| 		MessageBox_BrowserNavigationBlocked, | ||||
| 		MessageBox_BrowserNavigationBlockedTitle, | ||||
| 		MessageBox_BrowserQuitUrlConfirmation, | ||||
| 		MessageBox_BrowserQuitUrlConfirmationTitle, | ||||
| 		MessageBox_CancelButton, | ||||
| 		MessageBox_ClientConfigurationError, | ||||
| 		MessageBox_ClientConfigurationErrorTitle, | ||||
|  |  | |||
|  | @ -93,6 +93,12 @@ | |||
|     <Entry key="MessageBox_BrowserNavigationBlockedTitle"> | ||||
|         Page Blocked | ||||
|     </Entry> | ||||
|     <Entry key="MessageBox_BrowserQuitUrlConfirmation"> | ||||
|         The browser application has detected a quit URL! Would you like to terminate SEB now? | ||||
|     </Entry> | ||||
|     <Entry key="MessageBox_BrowserQuitUrlConfirmationTitle"> | ||||
|         Quit URL Detected | ||||
|     </Entry> | ||||
|     <Entry key="MessageBox_CancelButton"> | ||||
|         Cancel | ||||
|     </Entry> | ||||
|  |  | |||
|  | @ -36,6 +36,11 @@ namespace SafeExamBrowser.Settings.Browser | |||
| 		/// </summary> | ||||
| 		public bool AllowPageZoom { get; set; } | ||||
| 
 | ||||
| 		/// <summary> | ||||
| 		/// Determines whether the user needs to confirm the termination of SEB by <see cref="QuitUrl"/>. | ||||
| 		/// </summary> | ||||
| 		public bool ConfirmQuitUrl { get; set; } | ||||
| 
 | ||||
| 		/// <summary> | ||||
| 		/// The custom user agent to optionally be used for all requests. | ||||
| 		/// </summary> | ||||
|  | @ -61,6 +66,11 @@ namespace SafeExamBrowser.Settings.Browser | |||
| 		/// </summary> | ||||
| 		public ProxySettings Proxy { get; set; } | ||||
| 
 | ||||
| 		/// <summary> | ||||
| 		/// An URL which will initiate the termination of SEB if visited by the user. | ||||
| 		/// </summary> | ||||
| 		public string QuitUrl { get; set; } | ||||
| 
 | ||||
| 		/// <summary> | ||||
| 		/// The URL with which the main browser window will be loaded. | ||||
| 		/// </summary> | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 dbuechel
						dbuechel