SEBWIN-362: Implemented basic load error page for browser.

This commit is contained in:
Damian Büchel 2020-03-13 15:56:32 +01:00
parent 049cf8fe19
commit f0504fa6d2
11 changed files with 141 additions and 30 deletions

View file

@ -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;

View file

@ -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);
}
}
}

View file

@ -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.");
}
}
}

View file

@ -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;
}
}
}
}

View file

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html style="height: 100%; width: 100%">
<head>
<meta charset="utf-8" />
<title>%%TITLE%%</title>
</head>
<body style="background-color: lightgray; display: table; font-family: 'Segoe UI'; height: 98%; text-align: center; width: 99%">
<div style="display: table-cell; vertical-align: middle">
<h1 style="color: red">%%TITLE%%</h1>
<p>%%MESSAGE%%</p>
<p style="font-weight: bold">%%STATUS%%</p>
</div>
</body>
</html>

View file

@ -91,6 +91,7 @@
<Compile Include="Handlers\LifeSpanHandler.cs" />
<Compile Include="Handlers\RequestHandler.cs" />
<Compile Include="Handlers\ResourceHandler.cs" />
<Compile Include="Pages\HtmlLoader.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
@ -129,8 +130,11 @@
</None>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Filters\BlockedContent.html" />
<EmbeddedResource Include="Filters\BlockedPage.html" />
<EmbeddedResource Include="Pages\BlockedContent.html" />
<EmbeddedResource Include="Pages\BlockedPage.html" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Pages\LoadError.html" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>

View file

@ -20,6 +20,8 @@ namespace SafeExamBrowser.I18n.Contracts
Browser_BlockedPageButton,
Browser_BlockedPageMessage,
Browser_BlockedPageTitle,
Browser_LoadErrorPageMessage,
Browser_LoadErrorPageTitle,
Browser_Name,
Browser_Tooltip,
BrowserWindow_DeveloperConsoleMenuItem,

View file

@ -18,6 +18,12 @@
<Entry key="Browser_BlockedPageTitle">
Seite blockiert
</Entry>
<Entry key="Browser_LoadErrorPageMessage">
Beim Laden der Seite "%%URL%%" ist folgender Fehler aufgetreten:
</Entry>
<Entry key="Browser_LoadErrorPageTitle">
Seiten-Ladefehler
</Entry>
<Entry key="Browser_Name">
Browser
</Entry>
@ -139,7 +145,7 @@
Automatisches Beenden fehlgeschlagen
</Entry>
<Entry key="MessageBox_BrowserNavigationBlocked">
Zugriff auf "%%URL%%" is gemäss der aktiven Konfiguration nicht erlaubt.
Zugriff auf "%%URL%%" ist gemäss der aktiven Konfiguration nicht erlaubt.
</Entry>
<Entry key="MessageBox_BrowserNavigationBlockedTitle">
Seite blockiert

View file

@ -18,6 +18,12 @@
<Entry key="Browser_BlockedPageTitle">
Page Blocked
</Entry>
<Entry key="Browser_LoadErrorPageMessage">
An error occurred while loading page "%%URL%%":
</Entry>
<Entry key="Browser_LoadErrorPageTitle">
Page Load Error
</Entry>
<Entry key="Browser_Name">
Browser
</Entry>