diff --git a/SafeExamBrowser.Browser/BrowserApplication.cs b/SafeExamBrowser.Browser/BrowserApplication.cs index 51c0589c..c773e4f4 100644 --- a/SafeExamBrowser.Browser/BrowserApplication.cs +++ b/SafeExamBrowser.Browser/BrowserApplication.cs @@ -156,10 +156,16 @@ namespace SafeExamBrowser.Browser cefSettings.CefCommandLineArgs.Add("touch-events", "enabled"); + if (!settings.AllowPdfReader) + { + 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")}"); return cefSettings; } diff --git a/SafeExamBrowser.Browser/Handlers/ResourceHandler.cs b/SafeExamBrowser.Browser/Handlers/ResourceHandler.cs index 9564157b..477810d5 100644 --- a/SafeExamBrowser.Browser/Handlers/ResourceHandler.cs +++ b/SafeExamBrowser.Browser/Handlers/ResourceHandler.cs @@ -9,6 +9,7 @@ using System; using System.Collections.Specialized; using System.IO; +using System.Net.Mime; using System.Reflection; using System.Security.Cryptography; using System.Text; @@ -76,6 +77,22 @@ namespace SafeExamBrowser.Browser.Handlers return base.OnBeforeResourceLoad(webBrowser, browser, frame, request, callback); } + protected override bool OnResourceResponse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response) + { + var abort = true; + + if (RedirectToDisablePdfToolbar(request, response, out var url)) + { + chromiumWebBrowser.Load(url); + } + else + { + abort = base.OnResourceResponse(chromiumWebBrowser, browser, frame, request, response); + } + + return abort; + } + private void AppendCustomUserAgent(IRequest request) { var headers = new NameValueCollection(request.Headers); @@ -100,20 +117,20 @@ namespace SafeExamBrowser.Browser.Handlers private bool Block(IRequest request) { + var block = false; + if (settings.Filter.ProcessContentRequests) { var result = filter.Process(new Request { Url = request.Url }); - var block = result == FilterResult.Block; - if (block) + if (result == FilterResult.Block) { + block = true; logger.Info($"Blocked content request for '{request.Url}'."); } - - return block; } - return false; + return block; } private bool IsMailtoUrl(string url) @@ -121,6 +138,23 @@ namespace SafeExamBrowser.Browser.Handlers return url.StartsWith(Uri.UriSchemeMailto); } + private bool RedirectToDisablePdfToolbar(IRequest request, IResponse response, out string url) + { + const string DISABLE_PDF_TOOLBAR = "#toolbar=0"; + var isPdf = response.Headers["Content-Type"] == MediaTypeNames.Application.Pdf; + var hasFragment = request.Url.Contains(DISABLE_PDF_TOOLBAR); + var redirect = settings.AllowPdfReader && !settings.AllowPdfReaderToolbar && isPdf && !hasFragment; + + url = request.Url + DISABLE_PDF_TOOLBAR; + + if (redirect) + { + logger.Info($"Redirecting to '{url}' to disable PDF reader toolbar."); + } + + return redirect; + } + private void ReplaceSebScheme(IRequest request) { if (Uri.IsWellFormedUriString(request.Url, UriKind.RelativeOrAbsolute)) diff --git a/SafeExamBrowser.Configuration/ConfigurationData/DataMapping/BrowserDataMapper.cs b/SafeExamBrowser.Configuration/ConfigurationData/DataMapping/BrowserDataMapper.cs index 491ec18d..175104d1 100644 --- a/SafeExamBrowser.Configuration/ConfigurationData/DataMapping/BrowserDataMapper.cs +++ b/SafeExamBrowser.Configuration/ConfigurationData/DataMapping/BrowserDataMapper.cs @@ -36,6 +36,9 @@ namespace SafeExamBrowser.Configuration.ConfigurationData.DataMapping case Keys.Browser.AllowPageZoom: MapAllowPageZoom(settings, value); break; + case Keys.Browser.AllowPdfReaderToolbar: + MapAllowPdfReaderToolbar(settings, value); + break; case Keys.Browser.AdditionalWindow.AllowAddressBar: MapAllowAddressBarAdditionalWindow(settings, value); break; @@ -60,6 +63,9 @@ namespace SafeExamBrowser.Configuration.ConfigurationData.DataMapping case Keys.Browser.DownloadDirectory: MapDownloadDirectory(settings, value); break; + case Keys.Browser.DownloadPdfFiles: + MapDownloadPdfFiles(settings, value); + break; case Keys.Browser.EnableBrowser: MapEnableBrowser(settings, value); break; @@ -197,6 +203,14 @@ namespace SafeExamBrowser.Configuration.ConfigurationData.DataMapping } } + private void MapAllowPdfReaderToolbar(AppSettings settings, object value) + { + if (value is bool allow) + { + settings.Browser.AllowPdfReaderToolbar = allow; + } + } + private void MapAllowReload(AppSettings settings, object value) { if (value is bool allow) @@ -221,6 +235,14 @@ namespace SafeExamBrowser.Configuration.ConfigurationData.DataMapping } } + private void MapDownloadPdfFiles(AppSettings settings, object value) + { + if (value is bool download) + { + settings.Browser.AllowPdfReader = !download; + } + } + private void MapEnableBrowser(AppSettings settings, object value) { if (value is bool enable) diff --git a/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs b/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs index b21dcd16..b1ed4eee 100644 --- a/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs +++ b/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs @@ -126,6 +126,8 @@ namespace SafeExamBrowser.Configuration.ConfigurationData settings.Browser.AllowCustomDownloadLocation = false; settings.Browser.AllowDownloads = true; settings.Browser.AllowPageZoom = true; + settings.Browser.AllowPdfReader = true; + settings.Browser.AllowPdfReaderToolbar = false; settings.Browser.AllowUploads = 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 2bb3db82..ddd99bc2 100644 --- a/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs +++ b/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs @@ -46,9 +46,11 @@ namespace SafeExamBrowser.Configuration.ConfigurationData internal const string AllowDeveloperConsole = "allowDeveloperConsole"; internal const string AllowDownloadsAndUploads = "allowDownUploads"; internal const string AllowPageZoom = "enableZoomPage"; + internal const string AllowPdfReaderToolbar = "allowPDFReaderToolbar"; internal const string CustomUserAgentDesktop = "browserUserAgentWinDesktopModeCustom"; internal const string CustomUserAgentMobile = "browserUserAgentWinTouchModeCustom"; internal const string DownloadDirectory = "downloadDirectoryWin"; + internal const string DownloadPdfFiles = "downloadPDFFiles"; internal const string EnableBrowser = "enableSebBrowser"; internal const string PopupPolicy = "newBrowserWindowByLinkPolicy"; internal const string PopupBlockForeignHost = "newBrowserWindowByLinkBlockForeign"; diff --git a/SafeExamBrowser.Settings/Browser/BrowserSettings.cs b/SafeExamBrowser.Settings/Browser/BrowserSettings.cs index 2197a8d7..ca435303 100644 --- a/SafeExamBrowser.Settings/Browser/BrowserSettings.cs +++ b/SafeExamBrowser.Settings/Browser/BrowserSettings.cs @@ -41,6 +41,16 @@ namespace SafeExamBrowser.Settings.Browser /// public bool AllowPageZoom { get; set; } + /// + /// Determines whether the internal PDF reader of the browser application is enabled. If not, documents will be downloaded by default. + /// + public bool AllowPdfReader { get; set; } + + /// + /// Determines whether the toolbar of the internal PDF reader (which allows to e.g. download or print a document) will be enabled. + /// + public bool AllowPdfReaderToolbar { get; set; } + /// /// Determines whether the user will be allowed to upload files. ///