From f0504fa6d2e9f09783b51d85073017c1260d26af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damian=20B=C3=BCchel?= Date: Fri, 13 Mar 2020 15:56:32 +0100 Subject: [PATCH] SEBWIN-362: Implemented basic load error page for browser. --- .../BrowserApplicationInstance.cs | 4 +- SafeExamBrowser.Browser/BrowserControl.cs | 18 +++++ .../Handlers/ResourceHandler.cs | 36 +++------ .../{Filters => Pages}/BlockedContent.html | 0 .../{Filters => Pages}/BlockedPage.html | 0 SafeExamBrowser.Browser/Pages/HtmlLoader.cs | 75 +++++++++++++++++++ SafeExamBrowser.Browser/Pages/LoadError.html | 14 ++++ .../SafeExamBrowser.Browser.csproj | 8 +- SafeExamBrowser.I18n.Contracts/TextKey.cs | 2 + SafeExamBrowser.I18n/Data/de.xml | 8 +- SafeExamBrowser.I18n/Data/en.xml | 6 ++ 11 files changed, 141 insertions(+), 30 deletions(-) rename SafeExamBrowser.Browser/{Filters => Pages}/BlockedContent.html (100%) rename SafeExamBrowser.Browser/{Filters => Pages}/BlockedPage.html (100%) create mode 100644 SafeExamBrowser.Browser/Pages/HtmlLoader.cs create mode 100644 SafeExamBrowser.Browser/Pages/LoadError.html diff --git a/SafeExamBrowser.Browser/BrowserApplicationInstance.cs b/SafeExamBrowser.Browser/BrowserApplicationInstance.cs index 60065a7c..292577f8 100644 --- a/SafeExamBrowser.Browser/BrowserApplicationInstance.cs +++ b/SafeExamBrowser.Browser/BrowserApplicationInstance.cs @@ -17,6 +17,7 @@ using SafeExamBrowser.Browser.Contracts.Filters; using SafeExamBrowser.Browser.Events; using SafeExamBrowser.Browser.Filters; using SafeExamBrowser.Browser.Handlers; +using SafeExamBrowser.Browser.Pages; using SafeExamBrowser.Configuration.Contracts; using SafeExamBrowser.I18n.Contracts; using SafeExamBrowser.Logging.Contracts; @@ -115,6 +116,7 @@ namespace SafeExamBrowser.Browser var displayHandler = new DisplayHandler(); var downloadLogger = logger.CloneFor($"{nameof(DownloadHandler)} #{Id}"); var downloadHandler = new DownloadHandler(appConfig, settings, downloadLogger); + var htmlLoader = new HtmlLoader(text); var keyboardHandler = new KeyboardHandler(); var lifeSpanHandler = new LifeSpanHandler(); var requestFilter = new RequestFilter(); @@ -138,7 +140,7 @@ namespace SafeExamBrowser.Browser InitializeRequestFilter(requestFilter); - control = new BrowserControl(contextMenuHandler, dialogHandler, displayHandler, downloadHandler, keyboardHandler, lifeSpanHandler, requestHandler, startUrl); + control = new BrowserControl(contextMenuHandler, dialogHandler, displayHandler, downloadHandler, htmlLoader, keyboardHandler, lifeSpanHandler, requestHandler, startUrl); control.AddressChanged += Control_AddressChanged; control.LoadingStateChanged += Control_LoadingStateChanged; control.TitleChanged += Control_TitleChanged; diff --git a/SafeExamBrowser.Browser/BrowserControl.cs b/SafeExamBrowser.Browser/BrowserControl.cs index 4a70e324..ce340caf 100644 --- a/SafeExamBrowser.Browser/BrowserControl.cs +++ b/SafeExamBrowser.Browser/BrowserControl.cs @@ -8,6 +8,7 @@ using CefSharp; using CefSharp.WinForms; +using SafeExamBrowser.Browser.Pages; using SafeExamBrowser.UserInterface.Contracts.Browser; using SafeExamBrowser.UserInterface.Contracts.Browser.Events; @@ -19,6 +20,8 @@ namespace SafeExamBrowser.Browser private IDialogHandler dialogHandler; private IDisplayHandler displayHandler; private IDownloadHandler downloadHandler; + private string errorPage; + private HtmlLoader htmlLoader; private IKeyboardHandler keyboardHandler; private ILifeSpanHandler lifeSpanHandler; private IRequestHandler requestHandler; @@ -53,6 +56,7 @@ namespace SafeExamBrowser.Browser IDialogHandler dialogHandler, IDisplayHandler displayHandler, IDownloadHandler downloadHandler, + HtmlLoader htmlLoader, IKeyboardHandler keyboardHandler, ILifeSpanHandler lifeSpanHandler, IRequestHandler requestHandler, @@ -62,6 +66,7 @@ namespace SafeExamBrowser.Browser this.dialogHandler = dialogHandler; this.displayHandler = displayHandler; this.downloadHandler = downloadHandler; + this.htmlLoader = htmlLoader; this.keyboardHandler = keyboardHandler; this.lifeSpanHandler = lifeSpanHandler; this.requestHandler = requestHandler; @@ -70,6 +75,7 @@ namespace SafeExamBrowser.Browser public void Initialize() { AddressChanged += (o, args) => addressChanged?.Invoke(args.Address); + LoadError += BrowserControl_LoadError; LoadingStateChanged += (o, args) => loadingStateChanged?.Invoke(args.IsLoading); TitleChanged += (o, args) => titleChanged?.Invoke(args.Title); @@ -80,6 +86,8 @@ namespace SafeExamBrowser.Browser LifeSpanHandler = lifeSpanHandler; MenuHandler = contextMenuHandler; RequestHandler = requestHandler; + + errorPage = htmlLoader.LoadErrorPage(); } public void NavigateBackwards() @@ -111,5 +119,15 @@ namespace SafeExamBrowser.Browser { GetBrowser().SetZoomLevel(level); } + + private void BrowserControl_LoadError(object sender, LoadErrorEventArgs e) + { + var html = string.Copy(errorPage); + + html = html.Replace("%%STATUS%%", $"{e.ErrorText} ({e.ErrorCode})"); + html = html.Replace("%%URL%%", e.FailedUrl); + + e.Frame.LoadHtml(html, true); + } } } diff --git a/SafeExamBrowser.Browser/Handlers/ResourceHandler.cs b/SafeExamBrowser.Browser/Handlers/ResourceHandler.cs index 4d547c65..7cdf0fec 100644 --- a/SafeExamBrowser.Browser/Handlers/ResourceHandler.cs +++ b/SafeExamBrowser.Browser/Handlers/ResourceHandler.cs @@ -8,14 +8,12 @@ using System; using System.Collections.Specialized; -using System.IO; using System.Net.Mime; -using System.Reflection; using System.Security.Cryptography; using System.Text; using CefSharp; using SafeExamBrowser.Browser.Contracts.Filters; -using SafeExamBrowser.Browser.Filters; +using SafeExamBrowser.Browser.Pages; using SafeExamBrowser.Configuration.Contracts; using SafeExamBrowser.I18n.Contracts; using SafeExamBrowser.Logging.Contracts; @@ -32,6 +30,7 @@ namespace SafeExamBrowser.Browser.Handlers private string browserExamKey; private IResourceHandler contentHandler; private IRequestFilter filter; + private HtmlLoader htmlLoader; private ILogger logger; private IResourceHandler pageHandler; private BrowserSettings settings; @@ -42,6 +41,7 @@ namespace SafeExamBrowser.Browser.Handlers this.appConfig = appConfig; this.algorithm = new SHA256Managed(); this.filter = filter; + this.htmlLoader = new HtmlLoader(text); this.logger = logger; this.settings = settings; this.text = text; @@ -186,9 +186,14 @@ namespace SafeExamBrowser.Browser.Handlers private IResourceHandler ResourceHandlerFor(ResourceType resourceType) { - if (contentHandler == default(IResourceHandler) || pageHandler == default(IResourceHandler)) + if (contentHandler == default(IResourceHandler)) { - InitializeResourceHandlers(); + contentHandler = CefSharp.ResourceHandler.FromString(htmlLoader.LoadBlockedContent()); + } + + if (pageHandler == default(IResourceHandler)) + { + pageHandler = CefSharp.ResourceHandler.FromString(htmlLoader.LoadBlockedPage()); } switch (resourceType) @@ -200,26 +205,5 @@ namespace SafeExamBrowser.Browser.Handlers return contentHandler; } } - - private void InitializeResourceHandlers() - { - var assembly = Assembly.GetAssembly(typeof(RequestFilter)); - var contentMessage = text.Get(TextKey.Browser_BlockedContentMessage); - var contentStream = assembly.GetManifestResourceStream($"{typeof(RequestFilter).Namespace}.BlockedContent.html"); - var pageButton = text.Get(TextKey.Browser_BlockedPageButton); - var pageMessage = text.Get(TextKey.Browser_BlockedPageMessage); - var pageTitle = text.Get(TextKey.Browser_BlockedPageTitle); - var pageStream = assembly.GetManifestResourceStream($"{typeof(RequestFilter).Namespace}.BlockedPage.html"); - var contentHtml = new StreamReader(contentStream).ReadToEnd(); - var pageHtml = new StreamReader(pageStream).ReadToEnd(); - - contentHtml = contentHtml.Replace("%%MESSAGE%%", contentMessage); - contentHandler = CefSharp.ResourceHandler.FromString(contentHtml); - - pageHtml = pageHtml.Replace("%%MESSAGE%%", pageMessage).Replace("%%TITLE%%", pageTitle).Replace("%%BACK_BUTTON%%", pageButton); - pageHandler = CefSharp.ResourceHandler.FromString(pageHtml); - - logger.Debug("Initialized resource handlers for blocked requests."); - } } } diff --git a/SafeExamBrowser.Browser/Filters/BlockedContent.html b/SafeExamBrowser.Browser/Pages/BlockedContent.html similarity index 100% rename from SafeExamBrowser.Browser/Filters/BlockedContent.html rename to SafeExamBrowser.Browser/Pages/BlockedContent.html diff --git a/SafeExamBrowser.Browser/Filters/BlockedPage.html b/SafeExamBrowser.Browser/Pages/BlockedPage.html similarity index 100% rename from SafeExamBrowser.Browser/Filters/BlockedPage.html rename to SafeExamBrowser.Browser/Pages/BlockedPage.html diff --git a/SafeExamBrowser.Browser/Pages/HtmlLoader.cs b/SafeExamBrowser.Browser/Pages/HtmlLoader.cs new file mode 100644 index 00000000..569ab635 --- /dev/null +++ b/SafeExamBrowser.Browser/Pages/HtmlLoader.cs @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2020 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 System.IO; +using System.Reflection; +using SafeExamBrowser.I18n.Contracts; + +namespace SafeExamBrowser.Browser.Pages +{ + internal class HtmlLoader + { + private IText text; + + internal HtmlLoader(IText text) + { + this.text = text; + } + + internal string LoadBlockedContent() + { + var assembly = Assembly.GetAssembly(typeof(HtmlLoader)); + var path = $"{typeof(HtmlLoader).Namespace}.BlockedContent.html"; + + using (var stream = assembly.GetManifestResourceStream(path)) + using (var reader = new StreamReader(stream)) + { + var html = reader.ReadToEnd(); + + html = html.Replace("%%MESSAGE%%", text.Get(TextKey.Browser_BlockedContentMessage)); + + return html; + } + } + + internal string LoadBlockedPage() + { + var assembly = Assembly.GetAssembly(typeof(HtmlLoader)); + var path = $"{typeof(HtmlLoader).Namespace}.BlockedPage.html"; + + using (var stream = assembly.GetManifestResourceStream(path)) + using (var reader = new StreamReader(stream)) + { + var html = reader.ReadToEnd(); + + html = html.Replace("%%BACK_BUTTON%%", text.Get(TextKey.Browser_BlockedPageButton)); + html = html.Replace("%%MESSAGE%%", text.Get(TextKey.Browser_BlockedPageMessage)); + html = html.Replace("%%TITLE%%", text.Get(TextKey.Browser_BlockedPageTitle)); + + return html; + } + } + + internal string LoadErrorPage() + { + var assembly = Assembly.GetAssembly(typeof(HtmlLoader)); + var path = $"{typeof(HtmlLoader).Namespace}.LoadError.html"; + + using (var stream = assembly.GetManifestResourceStream(path)) + using (var reader = new StreamReader(stream)) + { + var html = reader.ReadToEnd(); + + html = html.Replace("%%MESSAGE%%", text.Get(TextKey.Browser_LoadErrorPageMessage)); + html = html.Replace("%%TITLE%%", text.Get(TextKey.Browser_LoadErrorPageTitle)); + + return html; + } + } + } +} diff --git a/SafeExamBrowser.Browser/Pages/LoadError.html b/SafeExamBrowser.Browser/Pages/LoadError.html new file mode 100644 index 00000000..880682bc --- /dev/null +++ b/SafeExamBrowser.Browser/Pages/LoadError.html @@ -0,0 +1,14 @@ + + + + + %%TITLE%% + + +
+

%%TITLE%%

+

%%MESSAGE%%

+

%%STATUS%%

+
+ + \ No newline at end of file diff --git a/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj b/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj index c12cfa4e..ee4cac5a 100644 --- a/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj +++ b/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj @@ -91,6 +91,7 @@ + @@ -129,8 +130,11 @@ - - + + + + + diff --git a/SafeExamBrowser.I18n.Contracts/TextKey.cs b/SafeExamBrowser.I18n.Contracts/TextKey.cs index 2e41005c..d356628f 100644 --- a/SafeExamBrowser.I18n.Contracts/TextKey.cs +++ b/SafeExamBrowser.I18n.Contracts/TextKey.cs @@ -20,6 +20,8 @@ namespace SafeExamBrowser.I18n.Contracts Browser_BlockedPageButton, Browser_BlockedPageMessage, Browser_BlockedPageTitle, + Browser_LoadErrorPageMessage, + Browser_LoadErrorPageTitle, Browser_Name, Browser_Tooltip, BrowserWindow_DeveloperConsoleMenuItem, diff --git a/SafeExamBrowser.I18n/Data/de.xml b/SafeExamBrowser.I18n/Data/de.xml index 7c02d2bd..ac5affbc 100644 --- a/SafeExamBrowser.I18n/Data/de.xml +++ b/SafeExamBrowser.I18n/Data/de.xml @@ -18,6 +18,12 @@ Seite blockiert + + Beim Laden der Seite "%%URL%%" ist folgender Fehler aufgetreten: + + + Seiten-Ladefehler + Browser @@ -139,7 +145,7 @@ Automatisches Beenden fehlgeschlagen - Zugriff auf "%%URL%%" is gemäss der aktiven Konfiguration nicht erlaubt. + Zugriff auf "%%URL%%" ist gemäss der aktiven Konfiguration nicht erlaubt. Seite blockiert diff --git a/SafeExamBrowser.I18n/Data/en.xml b/SafeExamBrowser.I18n/Data/en.xml index ab3c2d1b..82e3149b 100644 --- a/SafeExamBrowser.I18n/Data/en.xml +++ b/SafeExamBrowser.I18n/Data/en.xml @@ -18,6 +18,12 @@ Page Blocked + + An error occurred while loading page "%%URL%%": + + + Page Load Error + Browser