diff --git a/SafeExamBrowser.Browser/BrowserApplication.cs b/SafeExamBrowser.Browser/BrowserApplication.cs index c773e4f4..97d4f14c 100644 --- a/SafeExamBrowser.Browser/BrowserApplication.cs +++ b/SafeExamBrowser.Browser/BrowserApplication.cs @@ -78,6 +78,8 @@ namespace SafeExamBrowser.Browser public void Initialize() { + logger.Info("Starting initialization..."); + var cefSettings = InitializeCefSettings(); var success = Cef.Initialize(cefSettings, true, default(IApp)); @@ -85,6 +87,11 @@ namespace SafeExamBrowser.Browser if (success) { + if (settings.DeleteCookiesOnStartup) + { + DeleteCookies(); + } + logger.Info("Initialized browser."); } else @@ -100,6 +107,8 @@ namespace SafeExamBrowser.Browser public void Terminate() { + logger.Info("Initiating termination..."); + foreach (var instance in instances) { instance.Terminated -= Instance_Terminated; @@ -107,19 +116,15 @@ namespace SafeExamBrowser.Browser logger.Info($"Terminated browser instance {instance.Id}."); } + if (settings.DeleteCookiesOnShutdown) + { + DeleteCookies(); + } + Cef.Shutdown(); logger.Info("Terminated browser."); } - private void InitializeApplicationInfo() - { - AutoStart = true; - Icon = new BrowserIconResource(); - Id = Guid.NewGuid(); - Name = text.Get(TextKey.Browser_Name); - Tooltip = text.Get(TextKey.Browser_Tooltip); - } - private void CreateNewInstance(string url = null) { var id = ++instanceIdCounter; @@ -140,6 +145,41 @@ namespace SafeExamBrowser.Browser WindowsChanged?.Invoke(); } + private void DeleteCookies() + { + var callback = new TaskDeleteCookiesCallback(); + + callback.Task.ContinueWith(task => + { + if (!task.IsCompleted || task.Result == TaskDeleteCookiesCallback.InvalidNoOfCookiesDeleted) + { + logger.Warn("Failed to delete cookies!"); + } + else + { + logger.Debug($"Deleted {task.Result} cookies."); + } + }); + + if (Cef.GetGlobalCookieManager().DeleteCookies(callback: callback)) + { + logger.Debug("Successfully initiated cookie deletion."); + } + else + { + logger.Warn("Failed to initiate cookie deletion!"); + } + } + + private void InitializeApplicationInfo() + { + AutoStart = true; + Icon = new BrowserIconResource(); + Id = Guid.NewGuid(); + Name = text.Get(TextKey.Browser_Name); + Tooltip = text.Get(TextKey.Browser_Tooltip); + } + private CefSettings InitializeCefSettings() { var warning = logger.LogLevel == LogLevel.Warning; @@ -149,6 +189,7 @@ namespace SafeExamBrowser.Browser CachePath = appConfig.BrowserCachePath, LogFile = appConfig.BrowserLogFilePath, LogSeverity = error ? LogSeverity.Error : (warning ? LogSeverity.Warning : LogSeverity.Info), + PersistSessionCookies = !settings.DeleteCookiesOnShutdown, UserAgent = InitializeUserAgent() }; @@ -161,11 +202,12 @@ namespace SafeExamBrowser.Browser cefSettings.CefCommandLineArgs.Add("disable-pdf-extension", ""); } - logger.Debug($"Cache path: {cefSettings.CachePath}"); - logger.Debug($"Engine version: Chromium {Cef.ChromiumVersion}, CEF {Cef.CefVersion}, CefSharp {Cef.CefSharpVersion}"); - logger.Debug($"Log file: {cefSettings.LogFile}"); - logger.Debug($"Log severity: {cefSettings.LogSeverity}"); - logger.Debug($"PDF reader: {(settings.AllowPdfReader ? "Enabled" : "Disabled")}"); + logger.Debug($"Cache Path: {cefSettings.CachePath}"); + logger.Debug($"Engine Version: Chromium {Cef.ChromiumVersion}, CEF {Cef.CefVersion}, CefSharp {Cef.CefSharpVersion}"); + logger.Debug($"Log File: {cefSettings.LogFile}"); + logger.Debug($"Log Severity: {cefSettings.LogSeverity}."); + logger.Debug($"PDF Reader: {(settings.AllowPdfReader ? "Enabled" : "Disabled")}."); + logger.Debug($"Session Persistence: {(cefSettings.PersistSessionCookies ? "Enabled" : "Disabled")}."); return cefSettings; } @@ -203,6 +245,25 @@ namespace SafeExamBrowser.Browser } } + /// + /// TODO: Workaround to correctly set the user agent due to missing support for request interception for requests made by service workers. + /// Remove once CEF fully supports service workers and reactivate the functionality in ! + /// + private string InitializeUserAgent() + { + var osVersion = $"{Environment.OSVersion.Version.Major}.{Environment.OSVersion.Version.Minor}"; + var sebVersion = $"SEB/{appConfig.ProgramInformationalVersion}"; + + if (settings.UseCustomUserAgent) + { + return $"{settings.CustomUserAgent} {sebVersion}"; + } + else + { + return $"Mozilla/5.0 (Windows NT {osVersion}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{Cef.ChromiumVersion} {sebVersion}"; + } + } + private string ToScheme(ProxyProtocol protocol) { switch (protocol) @@ -231,24 +292,5 @@ namespace SafeExamBrowser.Browser instances.Remove(instances.First(i => i.Id == id)); WindowsChanged?.Invoke(); } - - /// - /// TODO: Workaround to correctly set the user agent due to missing support for request interception for requests made by service workers. - /// Remove once CEF fully supports service workers and reactivate the functionality in ! - /// - private string InitializeUserAgent() - { - var osVersion = $"{Environment.OSVersion.Version.Major}.{Environment.OSVersion.Version.Minor}"; - var sebVersion = $"SEB/{appConfig.ProgramInformationalVersion}"; - - if (settings.UseCustomUserAgent) - { - return $"{settings.CustomUserAgent} {sebVersion}"; - } - else - { - return $"Mozilla/5.0 (Windows NT {osVersion}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{Cef.ChromiumVersion} {sebVersion}"; - } - } } } diff --git a/SafeExamBrowser.Configuration/ConfigurationData/DataMapping/BrowserDataMapper.cs b/SafeExamBrowser.Configuration/ConfigurationData/DataMapping/BrowserDataMapper.cs index 24b3fc79..0681b1e6 100644 --- a/SafeExamBrowser.Configuration/ConfigurationData/DataMapping/BrowserDataMapper.cs +++ b/SafeExamBrowser.Configuration/ConfigurationData/DataMapping/BrowserDataMapper.cs @@ -61,6 +61,12 @@ namespace SafeExamBrowser.Configuration.ConfigurationData.DataMapping case Keys.Browser.AdditionalWindow.WindowWidth: MapWindowWidthAdditionalWindow(settings, value); break; + case Keys.Browser.DeleteCookiesOnShutdown: + MapDeleteCookiesOnShutdown(settings, value); + break; + case Keys.Browser.DeleteCookiesOnStartup: + MapDeleteCookiesOnStartup(settings, value); + break; case Keys.Browser.DownloadDirectory: MapDownloadDirectory(settings, value); break; @@ -231,6 +237,22 @@ namespace SafeExamBrowser.Configuration.ConfigurationData.DataMapping } } + private void MapDeleteCookiesOnShutdown(AppSettings settings, object value) + { + if (value is bool delete) + { + settings.Browser.DeleteCookiesOnShutdown = delete; + } + } + + private void MapDeleteCookiesOnStartup(AppSettings settings, object value) + { + if (value is bool delete) + { + settings.Browser.DeleteCookiesOnStartup = delete; + } + } + private void MapDownloadDirectory(AppSettings settings, object value) { if (value is string directory) diff --git a/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs b/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs index b971500c..70a17fb7 100644 --- a/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs +++ b/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs @@ -120,6 +120,8 @@ namespace SafeExamBrowser.Configuration.ConfigurationData settings.Browser.AllowPdfReader = true; settings.Browser.AllowPdfReaderToolbar = false; settings.Browser.AllowUploads = true; + settings.Browser.DeleteCookiesOnShutdown = true; + settings.Browser.DeleteCookiesOnStartup = true; settings.Browser.EnableBrowser = true; settings.Browser.MainWindow.AllowAddressBar = false; settings.Browser.MainWindow.AllowBackwardNavigation = false; diff --git a/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs b/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs index 2607beeb..c6ed1034 100644 --- a/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs +++ b/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs @@ -49,6 +49,8 @@ namespace SafeExamBrowser.Configuration.ConfigurationData internal const string AllowPdfReaderToolbar = "allowPDFReaderToolbar"; internal const string CustomUserAgentDesktop = "browserUserAgentWinDesktopModeCustom"; internal const string CustomUserAgentMobile = "browserUserAgentWinTouchModeCustom"; + internal const string DeleteCookiesOnShutdown = "examSessionClearCookiesOnEnd"; + internal const string DeleteCookiesOnStartup = "examSessionClearCookiesOnStart"; internal const string DownloadDirectory = "downloadDirectoryWin"; internal const string DownloadPdfFiles = "downloadPDFFiles"; internal const string EnableBrowser = "enableSebBrowser"; diff --git a/SafeExamBrowser.Settings/Browser/BrowserSettings.cs b/SafeExamBrowser.Settings/Browser/BrowserSettings.cs index 440d083c..c79b2e09 100644 --- a/SafeExamBrowser.Settings/Browser/BrowserSettings.cs +++ b/SafeExamBrowser.Settings/Browser/BrowserSettings.cs @@ -71,6 +71,16 @@ namespace SafeExamBrowser.Settings.Browser /// public string CustomUserAgent { get; set; } + /// + /// Determines whether all cookies are deleted when terminating the browser application. + /// + public bool DeleteCookiesOnShutdown { get; set; } + + /// + /// Determines whether all cookies are deleted when starting the browser application. + /// + public bool DeleteCookiesOnStartup { get; set; } + /// /// Defines a custom directory for file downloads. If not defined, all downloads will be saved in the current user's download directory. ///