diff --git a/SafeExamBrowser.Browser.Contracts/SafeExamBrowser.Browser.Contracts.csproj b/SafeExamBrowser.Browser.Contracts/SafeExamBrowser.Browser.Contracts.csproj
index 0027d68e..fee2d426 100644
--- a/SafeExamBrowser.Browser.Contracts/SafeExamBrowser.Browser.Contracts.csproj
+++ b/SafeExamBrowser.Browser.Contracts/SafeExamBrowser.Browser.Contracts.csproj
@@ -57,7 +57,6 @@
-
diff --git a/SafeExamBrowser.Browser/BrowserApplicationInstance.cs b/SafeExamBrowser.Browser/BrowserApplicationInstance.cs
index 4a6fbdbf..2f6f127c 100644
--- a/SafeExamBrowser.Browser/BrowserApplicationInstance.cs
+++ b/SafeExamBrowser.Browser/BrowserApplicationInstance.cs
@@ -8,6 +8,7 @@
using System;
using System.Net.Http;
+using System.Threading.Tasks;
using SafeExamBrowser.Applications.Contracts;
using SafeExamBrowser.Applications.Contracts.Events;
using SafeExamBrowser.Browser.Contracts.Events;
@@ -102,7 +103,7 @@ namespace SafeExamBrowser.Browser
var keyboardHandler = new KeyboardHandler();
var lifeSpanHandler = new LifeSpanHandler();
var requestLogger = logger.CloneFor($"{nameof(RequestHandler)} {Id}");
- var requestHandler = new RequestHandler(appConfig, settings.Filter, logger, text);
+ var requestHandler = new RequestHandler(appConfig, settings.Filter, requestLogger, text);
displayHandler.FaviconChanged += DisplayHandler_FaviconChanged;
displayHandler.ProgressChanged += DisplayHandler_ProgressChanged;
@@ -112,6 +113,7 @@ namespace SafeExamBrowser.Browser
keyboardHandler.ZoomOutRequested += ZoomOutRequested;
keyboardHandler.ZoomResetRequested += ZoomResetRequested;
lifeSpanHandler.PopupRequested += LifeSpanHandler_PopupRequested;
+ requestHandler.RequestBlocked += RequestHandler_RequestBlocked;
control = new BrowserControl(contextMenuHandler, displayHandler, downloadHandler, keyboardHandler, lifeSpanHandler, requestHandler, url);
control.AddressChanged += Control_AddressChanged;
@@ -224,6 +226,17 @@ namespace SafeExamBrowser.Browser
}
}
+ private void RequestHandler_RequestBlocked(string url)
+ {
+ Task.Run(() =>
+ {
+ var message = text.Get(TextKey.MessageBox_BrowserNavigationBlocked).Replace("%%URL%%", url);
+ var title = text.Get(TextKey.MessageBox_BrowserNavigationBlockedTitle);
+
+ messageBox.Show(message, title, parent: window);
+ });
+ }
+
private void ReloadRequested()
{
if (WindowSettings.AllowReloading && WindowSettings.ShowReloadWarning)
diff --git a/SafeExamBrowser.Browser.Contracts/Events/ProgressChangedEventHandler.cs b/SafeExamBrowser.Browser/Events/ProgressChangedEventHandler.cs
similarity index 52%
rename from SafeExamBrowser.Browser.Contracts/Events/ProgressChangedEventHandler.cs
rename to SafeExamBrowser.Browser/Events/ProgressChangedEventHandler.cs
index b15d5b51..678a32a7 100644
--- a/SafeExamBrowser.Browser.Contracts/Events/ProgressChangedEventHandler.cs
+++ b/SafeExamBrowser.Browser/Events/ProgressChangedEventHandler.cs
@@ -6,10 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-namespace SafeExamBrowser.Browser.Contracts.Events
+namespace SafeExamBrowser.Browser.Events
{
- ///
- /// Event handler used to indicate the current progress value of the page load process (from 0.0 to 1.0).
- ///
- public delegate void ProgressChangedEventHandler(double value);
+ internal delegate void ProgressChangedEventHandler(double value);
}
diff --git a/SafeExamBrowser.Browser/Events/RequestBlockedEventHandler.cs b/SafeExamBrowser.Browser/Events/RequestBlockedEventHandler.cs
new file mode 100644
index 00000000..0c28057a
--- /dev/null
+++ b/SafeExamBrowser.Browser/Events/RequestBlockedEventHandler.cs
@@ -0,0 +1,12 @@
+/*
+ * 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.Events
+{
+ internal delegate void RequestBlockedEventHandler(string url);
+}
diff --git a/SafeExamBrowser.Browser/Handlers/DisplayHandler.cs b/SafeExamBrowser.Browser/Handlers/DisplayHandler.cs
index 285e7316..32cad179 100644
--- a/SafeExamBrowser.Browser/Handlers/DisplayHandler.cs
+++ b/SafeExamBrowser.Browser/Handlers/DisplayHandler.cs
@@ -10,7 +10,6 @@ using System.Collections.Generic;
using System.Linq;
using CefSharp;
using CefSharp.Structs;
-using SafeExamBrowser.Browser.Contracts.Events;
using SafeExamBrowser.Browser.Events;
namespace SafeExamBrowser.Browser.Handlers
diff --git a/SafeExamBrowser.Browser/Handlers/RequestHandler.cs b/SafeExamBrowser.Browser/Handlers/RequestHandler.cs
index 60369c30..0fcb0170 100644
--- a/SafeExamBrowser.Browser/Handlers/RequestHandler.cs
+++ b/SafeExamBrowser.Browser/Handlers/RequestHandler.cs
@@ -7,6 +7,8 @@
*/
using CefSharp;
+using SafeExamBrowser.Browser.Events;
+using SafeExamBrowser.Browser.Filters;
using SafeExamBrowser.Configuration.Contracts;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Logging.Contracts;
@@ -16,15 +18,28 @@ namespace SafeExamBrowser.Browser.Handlers
{
internal class RequestHandler : CefSharp.Handler.RequestHandler
{
+ private RequestFilter filter;
+ private ILogger logger;
private ResourceHandler resourceHandler;
+ private BrowserFilterSettings settings;
+
+ internal event RequestBlockedEventHandler RequestBlocked;
internal RequestHandler(AppConfig appConfig, BrowserFilterSettings settings, ILogger logger, IText text)
{
- this.resourceHandler = new ResourceHandler(appConfig, settings, logger, text);
+ this.filter = new RequestFilter();
+ this.logger = logger;
+ this.resourceHandler = new ResourceHandler(appConfig, settings, filter, logger, text);
+ this.settings = settings;
}
internal void Initiailize()
{
+ if (settings.FilterMainRequests || settings.FilterContentRequests)
+ {
+ InitializeFilter();
+ }
+
resourceHandler.Initialize();
}
@@ -32,5 +47,45 @@ namespace SafeExamBrowser.Browser.Handlers
{
return resourceHandler;
}
+
+ protected override bool OnBeforeBrowse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool userGesture, bool isRedirect)
+ {
+ if (Block(request))
+ {
+ RequestBlocked?.Invoke(request.Url);
+
+ return true;
+ }
+
+ return base.OnBeforeBrowse(chromiumWebBrowser, browser, frame, request, userGesture, isRedirect);
+ }
+
+ private bool Block(IRequest request)
+ {
+ if (settings.FilterMainRequests)
+ {
+ var result = filter.Process(request.Url);
+ var block = result == FilterResult.Block;
+
+ if (block)
+ {
+ logger.Info($"Blocked main request for '{request.Url}'.");
+ }
+
+ return block;
+ }
+
+ return false;
+ }
+
+ private void InitializeFilter()
+ {
+ foreach (var rule in settings.Rules)
+ {
+ filter.Load(rule);
+ }
+
+ logger.Debug($"Initialized request filter with {settings.Rules.Count} rules.");
+ }
}
}
diff --git a/SafeExamBrowser.Browser/Handlers/ResourceHandler.cs b/SafeExamBrowser.Browser/Handlers/ResourceHandler.cs
index ac86d6bc..5c725917 100644
--- a/SafeExamBrowser.Browser/Handlers/ResourceHandler.cs
+++ b/SafeExamBrowser.Browser/Handlers/ResourceHandler.cs
@@ -25,14 +25,14 @@ namespace SafeExamBrowser.Browser.Handlers
private BrowserFilterSettings settings;
private ILogger logger;
private RequestFilter filter;
- private IResourceHandler contentBlockedHandler;
- private IResourceHandler pageBlockedHandler;
+ private IResourceHandler contentHandler;
+ private IResourceHandler pageHandler;
private IText text;
- internal ResourceHandler(AppConfig appConfig, BrowserFilterSettings settings, ILogger logger, IText text)
+ internal ResourceHandler(AppConfig appConfig, BrowserFilterSettings settings, RequestFilter filter, ILogger logger, IText text)
{
this.appConfig = appConfig;
- this.filter = new RequestFilter();
+ this.filter = filter;
this.logger = logger;
this.settings = settings;
this.text = text;
@@ -40,22 +40,17 @@ namespace SafeExamBrowser.Browser.Handlers
internal void Initialize()
{
- if (settings.FilterMainRequests || settings.FilterContentRequests)
+ if (settings.FilterContentRequests)
{
- InitializeFilter();
+ InitializeResourceHandlers();
}
}
protected override IResourceHandler GetResourceHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request)
{
- if (BlockMainRequest(request))
+ if (Block(request))
{
- return pageBlockedHandler;
- }
-
- if (BlockContentRequest(request))
- {
- return contentBlockedHandler;
+ return ResourceHandlerFor(request.ResourceType);
}
return base.GetResourceHandler(chromiumWebBrowser, browser, frame, request);
@@ -73,7 +68,7 @@ namespace SafeExamBrowser.Browser.Handlers
return CefReturnValue.Cancel;
}
- ReplaceCustomScheme(request);
+ ReplaceSebScheme(request);
return base.OnBeforeResourceLoad(webBrowser, browser, frame, request, callback);
}
@@ -87,9 +82,9 @@ namespace SafeExamBrowser.Browser.Handlers
request.Headers = headers;
}
- private bool BlockContentRequest(IRequest request)
+ private bool Block(IRequest request)
{
- if (settings.FilterContentRequests && request.ResourceType != ResourceType.MainFrame)
+ if (settings.FilterContentRequests)
{
var result = filter.Process(request.Url);
var block = result == FilterResult.Block;
@@ -105,25 +100,7 @@ namespace SafeExamBrowser.Browser.Handlers
return false;
}
- private bool BlockMainRequest(IRequest request)
- {
- if (settings.FilterMainRequests && request.ResourceType == ResourceType.MainFrame)
- {
- var result = filter.Process(request.Url);
- var block = result == FilterResult.Block;
-
- if (block)
- {
- logger.Info($"Blocked main request for '{request.Url}'.");
- }
-
- return block;
- }
-
- return false;
- }
-
- private void InitializeFilter()
+ private void InitializeResourceHandlers()
{
var assembly = Assembly.GetAssembly(typeof(RequestFilter));
var contentMessage = text.Get(TextKey.Browser_BlockedContentMessage);
@@ -136,17 +113,12 @@ namespace SafeExamBrowser.Browser.Handlers
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);
- contentBlockedHandler = CefSharp.ResourceHandler.FromString(contentHtml);
- pageBlockedHandler = CefSharp.ResourceHandler.FromString(pageHtml);
-
- foreach (var rule in settings.Rules)
- {
- filter.Load(rule);
- }
-
- logger.Debug($"Initialized request filter with {settings.Rules.Count} rules.");
+ logger.Debug("Initialized resource handlers for blocked requests.");
}
private bool IsMailtoUrl(string url)
@@ -154,7 +126,7 @@ namespace SafeExamBrowser.Browser.Handlers
return url.StartsWith(Uri.UriSchemeMailto);
}
- private void ReplaceCustomScheme(IRequest request)
+ private void ReplaceSebScheme(IRequest request)
{
if (Uri.IsWellFormedUriString(request.Url, UriKind.RelativeOrAbsolute))
{
@@ -170,5 +142,17 @@ namespace SafeExamBrowser.Browser.Handlers
}
}
}
+
+ private IResourceHandler ResourceHandlerFor(ResourceType resourceType)
+ {
+ switch (resourceType)
+ {
+ case ResourceType.MainFrame:
+ case ResourceType.SubFrame:
+ return pageHandler;
+ default:
+ return contentHandler;
+ }
+ }
}
}
diff --git a/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj b/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj
index 93c88d9a..f4ad08ff 100644
--- a/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj
+++ b/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj
@@ -72,6 +72,8 @@
+
+
diff --git a/SafeExamBrowser.I18n.Contracts/TextKey.cs b/SafeExamBrowser.I18n.Contracts/TextKey.cs
index 51557657..a478c32c 100644
--- a/SafeExamBrowser.I18n.Contracts/TextKey.cs
+++ b/SafeExamBrowser.I18n.Contracts/TextKey.cs
@@ -24,6 +24,8 @@ namespace SafeExamBrowser.I18n.Contracts
LogWindow_Title,
MessageBox_ApplicationError,
MessageBox_ApplicationErrorTitle,
+ MessageBox_BrowserNavigationBlocked,
+ MessageBox_BrowserNavigationBlockedTitle,
MessageBox_CancelButton,
MessageBox_ClientConfigurationError,
MessageBox_ClientConfigurationErrorTitle,
diff --git a/SafeExamBrowser.I18n/Text.xml b/SafeExamBrowser.I18n/Text.xml
index 17a3f8a4..19896597 100644
--- a/SafeExamBrowser.I18n/Text.xml
+++ b/SafeExamBrowser.I18n/Text.xml
@@ -30,6 +30,12 @@
Application Error
+
+ Access to "%%URL%%" is not allowed according to the application configuration.
+
+
+ Page Blocked
+
Cancel