diff --git a/SafeExamBrowser.Browser.Contracts/Filters/IRequestFilter.cs b/SafeExamBrowser.Browser.Contracts/Filters/IRequestFilter.cs new file mode 100644 index 00000000..4f5f0592 --- /dev/null +++ b/SafeExamBrowser.Browser.Contracts/Filters/IRequestFilter.cs @@ -0,0 +1,33 @@ +/* + * 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/. + */ + +using SafeExamBrowser.Settings.Browser; + +namespace SafeExamBrowser.Browser.Contracts.Filters +{ + /// + /// Defines the filter for browser requests. + /// + public interface IRequestFilter + { + /// + /// The default result to be returned by if no rule matches. + /// + FilterResult Default { get; set; } + + /// + /// Loads the given filter rule to be used when processing requests. + /// + void Load(IRule rule); + + /// + /// Filters the given request according to the loaded rules. + /// + FilterResult Process(Request request); + } +} diff --git a/SafeExamBrowser.Browser.Contracts/Filters/IRule.cs b/SafeExamBrowser.Browser.Contracts/Filters/IRule.cs new file mode 100644 index 00000000..636c9734 --- /dev/null +++ b/SafeExamBrowser.Browser.Contracts/Filters/IRule.cs @@ -0,0 +1,33 @@ +/* + * 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/. + */ + +using SafeExamBrowser.Settings.Browser; + +namespace SafeExamBrowser.Browser.Contracts.Filters +{ + /// + /// Defines a request filter rule. + /// + public interface IRule + { + /// + /// The filter result to be used if the rule matches a request. + /// + FilterResult Result { get; } + + /// + /// Initializes the rule for processing requests. + /// + void Initialize(FilterRuleSettings settings); + + /// + /// Indicates whether the rule applies for the given request. + /// + bool IsMatch(Request request); + } +} diff --git a/SafeExamBrowser.Browser.Contracts/Filters/IRuleFactory.cs b/SafeExamBrowser.Browser.Contracts/Filters/IRuleFactory.cs new file mode 100644 index 00000000..8f7cd076 --- /dev/null +++ b/SafeExamBrowser.Browser.Contracts/Filters/IRuleFactory.cs @@ -0,0 +1,23 @@ +/* + * 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/. + */ + +using SafeExamBrowser.Settings.Browser; + +namespace SafeExamBrowser.Browser.Contracts.Filters +{ + /// + /// Builds request filter rules. + /// + public interface IRuleFactory + { + /// + /// Creates a filter rule for the given type. + /// + IRule CreateRule(FilterRuleType type); + } +} diff --git a/SafeExamBrowser.Browser/Filters/Rules/Rule.cs b/SafeExamBrowser.Browser.Contracts/Filters/Request.cs similarity index 54% rename from SafeExamBrowser.Browser/Filters/Rules/Rule.cs rename to SafeExamBrowser.Browser.Contracts/Filters/Request.cs index 7c0a85c3..e264ed9b 100644 --- a/SafeExamBrowser.Browser/Filters/Rules/Rule.cs +++ b/SafeExamBrowser.Browser.Contracts/Filters/Request.cs @@ -6,16 +6,16 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -namespace SafeExamBrowser.Browser.Filters.Rules +namespace SafeExamBrowser.Browser.Contracts.Filters { - internal abstract class Rule + /// + /// Holds data relevant for filtering requests. + /// + public class Request { - internal Rule(string expression) - { - Initialize(expression); - } - - internal abstract bool IsMatch(string url); - protected abstract void Initialize(string expression); + /// + /// The full URL of the request. + /// + public string Url { get; set; } } } diff --git a/SafeExamBrowser.Browser.Contracts/SafeExamBrowser.Browser.Contracts.csproj b/SafeExamBrowser.Browser.Contracts/SafeExamBrowser.Browser.Contracts.csproj index fee2d426..3c68dbfa 100644 --- a/SafeExamBrowser.Browser.Contracts/SafeExamBrowser.Browser.Contracts.csproj +++ b/SafeExamBrowser.Browser.Contracts/SafeExamBrowser.Browser.Contracts.csproj @@ -56,6 +56,10 @@ + + + + @@ -64,6 +68,10 @@ {ac77745d-3b41-43e2-8e84-d40e5a4ee77f} SafeExamBrowser.Applications.Contracts + + {30b2d907-5861-4f39-abad-c4abf1b3470e} + SafeExamBrowser.Settings + \ No newline at end of file diff --git a/SafeExamBrowser.Browser.UnitTests/Filters/RequestFilterTests.cs b/SafeExamBrowser.Browser.UnitTests/Filters/RequestFilterTests.cs index 039e158d..7c35734f 100644 --- a/SafeExamBrowser.Browser.UnitTests/Filters/RequestFilterTests.cs +++ b/SafeExamBrowser.Browser.UnitTests/Filters/RequestFilterTests.cs @@ -8,6 +8,8 @@ using System; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using SafeExamBrowser.Browser.Contracts.Filters; using SafeExamBrowser.Browser.Filters; using SafeExamBrowser.Settings.Browser; @@ -27,13 +29,20 @@ namespace SafeExamBrowser.Browser.UnitTests.Filters [TestMethod] public void MustProcessBlockRulesFirst() { - var allow = new FilterRuleSettings { Expression = "*", Type = FilterType.Simplified, Result = FilterResult.Allow }; - var block = new FilterRuleSettings { Expression = "*", Type = FilterType.Simplified, Result = FilterResult.Block }; + var allow = new Mock(); + var block = new Mock(); - sut.Load(allow); - sut.Load(block); + allow.SetupGet(r => r.Result).Returns(FilterResult.Allow); + block.SetupGet(r => r.Result).Returns(FilterResult.Block); + block.Setup(r => r.IsMatch(It.IsAny())).Returns(true); - var result = sut.Process("safeexambrowser.org"); + sut.Load(allow.Object); + sut.Load(block.Object); + + var result = sut.Process(new Request()); + + allow.Verify(r => r.IsMatch(It.IsAny()), Times.Never); + block.Verify(r => r.IsMatch(It.IsAny()), Times.Once); Assert.AreEqual(FilterResult.Block, result); } @@ -41,28 +50,41 @@ namespace SafeExamBrowser.Browser.UnitTests.Filters [TestMethod] public void MustProcessAllowRulesSecond() { - var allow = new FilterRuleSettings { Expression = "*", Type = FilterType.Simplified, Result = FilterResult.Allow }; - var block = new FilterRuleSettings { Expression = "xyz", Type = FilterType.Simplified, Result = FilterResult.Block }; + var allow = new Mock(); + var block = new Mock(); - sut.Load(allow); - sut.Load(block); + allow.SetupGet(r => r.Result).Returns(FilterResult.Allow); + allow.Setup(r => r.IsMatch(It.IsAny())).Returns(true); + block.SetupGet(r => r.Result).Returns(FilterResult.Block); - var result = sut.Process("safeexambrowser.org"); + sut.Load(allow.Object); + sut.Load(block.Object); + + var result = sut.Process(new Request()); + + allow.Verify(r => r.IsMatch(It.IsAny()), Times.Once); + block.Verify(r => r.IsMatch(It.IsAny()), Times.Once); Assert.AreEqual(FilterResult.Allow, result); } [TestMethod] - public void MustReturnDefault() + public void MustReturnDefaultWithoutMatch() { - var allow = new FilterRuleSettings { Expression = "xyz", Type = FilterType.Simplified, Result = FilterResult.Allow }; - var block = new FilterRuleSettings { Expression = "xyz", Type = FilterType.Simplified, Result = FilterResult.Block }; + var allow = new Mock(); + var block = new Mock(); + + allow.SetupGet(r => r.Result).Returns(FilterResult.Allow); + block.SetupGet(r => r.Result).Returns(FilterResult.Block); sut.Default = (FilterResult) (-1); - sut.Load(allow); - sut.Load(block); + sut.Load(allow.Object); + sut.Load(block.Object); - var result = sut.Process("safeexambrowser.org"); + var result = sut.Process(new Request()); + + allow.Verify(r => r.IsMatch(It.IsAny()), Times.Once); + block.Verify(r => r.IsMatch(It.IsAny()), Times.Once); Assert.AreEqual((FilterResult) (-1), result); } @@ -71,11 +93,11 @@ namespace SafeExamBrowser.Browser.UnitTests.Filters public void MustReturnDefaultWithoutRules() { sut.Default = FilterResult.Allow; - var result = sut.Process("safeexambrowser.org"); + var result = sut.Process(new Request()); Assert.AreEqual(FilterResult.Allow, result); sut.Default = FilterResult.Block; - result = sut.Process("safeexambrowser.org"); + result = sut.Process(new Request()); Assert.AreEqual(FilterResult.Block, result); } @@ -83,14 +105,10 @@ namespace SafeExamBrowser.Browser.UnitTests.Filters [ExpectedException(typeof(NotImplementedException))] public void MustNotAllowUnsupportedResult() { - sut.Load(new FilterRuleSettings { Result = (FilterResult) (-1) }); - } + var rule = new Mock(); - [TestMethod] - [ExpectedException(typeof(NotImplementedException))] - public void MustNotAllowUnsupportedFilterType() - { - sut.Load(new FilterRuleSettings { Type = (FilterType) (-1) }); + rule.SetupGet(r => r.Result).Returns((FilterResult) (-1)); + sut.Load(rule.Object); } } } diff --git a/SafeExamBrowser.Browser.UnitTests/Filters/RuleFactoryTests.cs b/SafeExamBrowser.Browser.UnitTests/Filters/RuleFactoryTests.cs new file mode 100644 index 00000000..1373e800 --- /dev/null +++ b/SafeExamBrowser.Browser.UnitTests/Filters/RuleFactoryTests.cs @@ -0,0 +1,42 @@ +/* + * 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/. + */ + +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SafeExamBrowser.Browser.Filters; +using SafeExamBrowser.Browser.Filters.Rules; +using SafeExamBrowser.Settings.Browser; + +namespace SafeExamBrowser.Browser.UnitTests.Filters +{ + [TestClass] + public class RuleFactoryTests + { + private RuleFactory sut; + + [TestInitialize] + public void Initialize() + { + sut = new RuleFactory(); + } + + [TestMethod] + public void MustCreateCorrectRules() + { + Assert.IsInstanceOfType(sut.CreateRule(FilterRuleType.Regex), typeof(RegexRule)); + Assert.IsInstanceOfType(sut.CreateRule(FilterRuleType.Simplified), typeof(SimplifiedRule)); + } + + [TestMethod] + [ExpectedException(typeof(NotImplementedException))] + public void MustNotAllowUnsupportedFilterType() + { + sut.CreateRule((FilterRuleType) (-1)); + } + } +} diff --git a/SafeExamBrowser.Browser.UnitTests/Filters/Rules/RegexRuleTests.cs b/SafeExamBrowser.Browser.UnitTests/Filters/Rules/RegexRuleTests.cs new file mode 100644 index 00000000..7af4d3c5 --- /dev/null +++ b/SafeExamBrowser.Browser.UnitTests/Filters/Rules/RegexRuleTests.cs @@ -0,0 +1,25 @@ +/* + * 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/. + */ + +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SafeExamBrowser.Browser.Filters.Rules; + +namespace SafeExamBrowser.Browser.UnitTests.Filters.Rules +{ + [TestClass] + public class RegexRuleTests + { + private RegexRule sut; + + [TestInitialize] + public void Initialize() + { + sut = new RegexRule(); + } + } +} diff --git a/SafeExamBrowser.Browser.UnitTests/Filters/Rules/SimplifiedRuleTests.cs b/SafeExamBrowser.Browser.UnitTests/Filters/Rules/SimplifiedRuleTests.cs new file mode 100644 index 00000000..f445b077 --- /dev/null +++ b/SafeExamBrowser.Browser.UnitTests/Filters/Rules/SimplifiedRuleTests.cs @@ -0,0 +1,25 @@ +/* + * 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/. + */ + +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SafeExamBrowser.Browser.Filters.Rules; + +namespace SafeExamBrowser.Browser.UnitTests.Filters.Rules +{ + [TestClass] + public class SimplifiedRuleTests + { + private SimplifiedRule sut; + + [TestInitialize] + public void Initialize() + { + sut = new SimplifiedRule(); + } + } +} diff --git a/SafeExamBrowser.Browser.UnitTests/SafeExamBrowser.Browser.UnitTests.csproj b/SafeExamBrowser.Browser.UnitTests/SafeExamBrowser.Browser.UnitTests.csproj index ff793437..43bb803b 100644 --- a/SafeExamBrowser.Browser.UnitTests/SafeExamBrowser.Browser.UnitTests.csproj +++ b/SafeExamBrowser.Browser.UnitTests/SafeExamBrowser.Browser.UnitTests.csproj @@ -1,6 +1,6 @@  - + Debug @@ -57,20 +57,37 @@ MinimumRecommendedRules.ruleset + + ..\packages\Castle.Core.4.4.0\lib\net45\Castle.Core.dll + - ..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll + ..\packages\MSTest.TestFramework.2.0.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll - ..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll + ..\packages\MSTest.TestFramework.2.0.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll + + + ..\packages\Moq.4.13.0\lib\net45\Moq.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll + + + ..\packages\System.Threading.Tasks.Extensions.4.5.3\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll + + + + + @@ -93,8 +110,8 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - + + - + \ No newline at end of file diff --git a/SafeExamBrowser.Browser.UnitTests/app.config b/SafeExamBrowser.Browser.UnitTests/app.config new file mode 100644 index 00000000..8d5ec5ff --- /dev/null +++ b/SafeExamBrowser.Browser.UnitTests/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/SafeExamBrowser.Browser.UnitTests/packages.config b/SafeExamBrowser.Browser.UnitTests/packages.config index 2f7c5a18..d3e7023a 100644 --- a/SafeExamBrowser.Browser.UnitTests/packages.config +++ b/SafeExamBrowser.Browser.UnitTests/packages.config @@ -1,5 +1,9 @@  - - + + + + + + \ No newline at end of file diff --git a/SafeExamBrowser.Browser/BrowserApplicationInstance.cs b/SafeExamBrowser.Browser/BrowserApplicationInstance.cs index 2f6f127c..ad5de5a3 100644 --- a/SafeExamBrowser.Browser/BrowserApplicationInstance.cs +++ b/SafeExamBrowser.Browser/BrowserApplicationInstance.cs @@ -13,6 +13,7 @@ using SafeExamBrowser.Applications.Contracts; using SafeExamBrowser.Applications.Contracts.Events; using SafeExamBrowser.Browser.Contracts.Events; using SafeExamBrowser.Browser.Events; +using SafeExamBrowser.Browser.Filters; using SafeExamBrowser.Browser.Handlers; using SafeExamBrowser.Configuration.Contracts; using SafeExamBrowser.I18n.Contracts; @@ -102,8 +103,9 @@ namespace SafeExamBrowser.Browser var downloadHandler = new DownloadHandler(appConfig, settings, downloadLogger); var keyboardHandler = new KeyboardHandler(); var lifeSpanHandler = new LifeSpanHandler(); + var requestFilter = new RequestFilter(); var requestLogger = logger.CloneFor($"{nameof(RequestHandler)} {Id}"); - var requestHandler = new RequestHandler(appConfig, settings.Filter, requestLogger, text); + var requestHandler = new RequestHandler(appConfig, settings.Filter, requestFilter, requestLogger, text); displayHandler.FaviconChanged += DisplayHandler_FaviconChanged; displayHandler.ProgressChanged += DisplayHandler_ProgressChanged; @@ -115,14 +117,27 @@ namespace SafeExamBrowser.Browser lifeSpanHandler.PopupRequested += LifeSpanHandler_PopupRequested; requestHandler.RequestBlocked += RequestHandler_RequestBlocked; + if (settings.Filter.ProcessContentRequests || settings.Filter.ProcessMainRequests) + { + var factory = new RuleFactory(); + + foreach (var settings in settings.Filter.Rules) + { + var rule = factory.CreateRule(settings.Type); + + rule.Initialize(settings); + requestFilter.Load(rule); + } + + logger.Debug($"Initialized request filter with {settings.Filter.Rules.Count} rule(s)."); + } + control = new BrowserControl(contextMenuHandler, displayHandler, downloadHandler, keyboardHandler, lifeSpanHandler, requestHandler, url); control.AddressChanged += Control_AddressChanged; control.LoadingStateChanged += Control_LoadingStateChanged; control.TitleChanged += Control_TitleChanged; - requestHandler.Initiailize(); control.Initialize(); - logger.Debug("Initialized browser control."); } diff --git a/SafeExamBrowser.Browser/Filters/RequestFilter.cs b/SafeExamBrowser.Browser/Filters/RequestFilter.cs index 6cec7142..54213545 100644 --- a/SafeExamBrowser.Browser/Filters/RequestFilter.cs +++ b/SafeExamBrowser.Browser/Filters/RequestFilter.cs @@ -8,42 +8,28 @@ using System; using System.Collections.Generic; -using SafeExamBrowser.Browser.Filters.Rules; +using SafeExamBrowser.Browser.Contracts.Filters; using SafeExamBrowser.Settings.Browser; namespace SafeExamBrowser.Browser.Filters { - internal class RequestFilter + internal class RequestFilter : IRequestFilter { - private IList allowRules; - private IList blockRules; + private IList allowRules; + private IList blockRules; - internal FilterResult Default { get; set; } + public FilterResult Default { get; set; } internal RequestFilter() { - allowRules = new List(); - blockRules = new List(); + allowRules = new List(); + blockRules = new List(); Default = FilterResult.Block; } - internal void Load(FilterRuleSettings settings) + public void Load(IRule rule) { - var rule = default(Rule); - - switch (settings.Type) - { - case FilterType.Regex: - rule = new RegexRule(settings.Expression); - break; - case FilterType.Simplified: - rule = new SimpleRule(settings.Expression); - break; - default: - throw new NotImplementedException($"Filter rule of type '{settings.Type}' is not yet implemented!"); - } - - switch (settings.Result) + switch (rule.Result) { case FilterResult.Allow: allowRules.Add(rule); @@ -52,15 +38,15 @@ namespace SafeExamBrowser.Browser.Filters blockRules.Add(rule); break; default: - throw new NotImplementedException($"Filter result '{settings.Result}' is not yet implemented!"); + throw new NotImplementedException($"Filter processing for result '{rule.Result}' is not yet implemented!"); } } - internal FilterResult Process(string url) + public FilterResult Process(Request request) { foreach (var rule in blockRules) { - if (rule.IsMatch(url)) + if (rule.IsMatch(request)) { return FilterResult.Block; } @@ -68,7 +54,7 @@ namespace SafeExamBrowser.Browser.Filters foreach (var rule in allowRules) { - if (rule.IsMatch(url)) + if (rule.IsMatch(request)) { return FilterResult.Allow; } diff --git a/SafeExamBrowser.Browser/Filters/RuleFactory.cs b/SafeExamBrowser.Browser/Filters/RuleFactory.cs new file mode 100644 index 00000000..73bd2015 --- /dev/null +++ b/SafeExamBrowser.Browser/Filters/RuleFactory.cs @@ -0,0 +1,31 @@ +/* + * 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/. + */ + +using System; +using SafeExamBrowser.Browser.Contracts.Filters; +using SafeExamBrowser.Browser.Filters.Rules; +using SafeExamBrowser.Settings.Browser; + +namespace SafeExamBrowser.Browser.Filters +{ + internal class RuleFactory : IRuleFactory + { + public IRule CreateRule(FilterRuleType type) + { + switch (type) + { + case FilterRuleType.Regex: + return new RegexRule(); + case FilterRuleType.Simplified: + return new SimplifiedRule(); + default: + throw new NotImplementedException($"Filter rule of type '{type}' is not yet implemented!"); + } + } + } +} diff --git a/SafeExamBrowser.Browser/Filters/Rules/RegexRule.cs b/SafeExamBrowser.Browser/Filters/Rules/RegexRule.cs index d8bf6989..8d4712a2 100644 --- a/SafeExamBrowser.Browser/Filters/Rules/RegexRule.cs +++ b/SafeExamBrowser.Browser/Filters/Rules/RegexRule.cs @@ -7,25 +7,26 @@ */ using System.Text.RegularExpressions; +using SafeExamBrowser.Browser.Contracts.Filters; +using SafeExamBrowser.Settings.Browser; namespace SafeExamBrowser.Browser.Filters.Rules { - internal class RegexRule : Rule + internal class RegexRule : IRule { private string expression; - public RegexRule(string expression) : base(expression) + public FilterResult Result { get; private set; } + + public void Initialize(FilterRuleSettings settings) { + expression = settings.Expression; + Result = settings.Result; } - protected override void Initialize(string expression) + public bool IsMatch(Request request) { - this.expression = expression; - } - - internal override bool IsMatch(string url) - { - return Regex.IsMatch(url, expression, RegexOptions.IgnoreCase); + return Regex.IsMatch(request.Url, expression, RegexOptions.IgnoreCase); } } } diff --git a/SafeExamBrowser.Browser/Filters/Rules/SimpleRule.cs b/SafeExamBrowser.Browser/Filters/Rules/SimplifiedRule.cs similarity index 50% rename from SafeExamBrowser.Browser/Filters/Rules/SimpleRule.cs rename to SafeExamBrowser.Browser/Filters/Rules/SimplifiedRule.cs index ccf793a1..90acdf8e 100644 --- a/SafeExamBrowser.Browser/Filters/Rules/SimpleRule.cs +++ b/SafeExamBrowser.Browser/Filters/Rules/SimplifiedRule.cs @@ -7,25 +7,26 @@ */ using System.Text.RegularExpressions; +using SafeExamBrowser.Browser.Contracts.Filters; +using SafeExamBrowser.Settings.Browser; namespace SafeExamBrowser.Browser.Filters.Rules { - internal class SimpleRule : Rule + internal class SimplifiedRule : IRule { private string expression; - public SimpleRule(string expression) : base(expression) + public FilterResult Result { get; private set; } + + public void Initialize(FilterRuleSettings settings) { + expression = settings.Expression.Replace("*", @".*"); + Result = settings.Result; } - protected override void Initialize(string expression) + public bool IsMatch(Request request) { - this.expression = expression.Replace("*", @".*"); - } - - internal override bool IsMatch(string url) - { - return Regex.IsMatch(url, expression, RegexOptions.IgnoreCase); + return Regex.IsMatch(request.Url, expression, RegexOptions.IgnoreCase); } } } diff --git a/SafeExamBrowser.Browser/Handlers/RequestHandler.cs b/SafeExamBrowser.Browser/Handlers/RequestHandler.cs index 0fcb0170..c1dec50b 100644 --- a/SafeExamBrowser.Browser/Handlers/RequestHandler.cs +++ b/SafeExamBrowser.Browser/Handlers/RequestHandler.cs @@ -7,8 +7,8 @@ */ using CefSharp; +using SafeExamBrowser.Browser.Contracts.Filters; using SafeExamBrowser.Browser.Events; -using SafeExamBrowser.Browser.Filters; using SafeExamBrowser.Configuration.Contracts; using SafeExamBrowser.I18n.Contracts; using SafeExamBrowser.Logging.Contracts; @@ -18,31 +18,21 @@ namespace SafeExamBrowser.Browser.Handlers { internal class RequestHandler : CefSharp.Handler.RequestHandler { - private RequestFilter filter; + private IRequestFilter filter; private ILogger logger; private ResourceHandler resourceHandler; private BrowserFilterSettings settings; internal event RequestBlockedEventHandler RequestBlocked; - internal RequestHandler(AppConfig appConfig, BrowserFilterSettings settings, ILogger logger, IText text) + internal RequestHandler(AppConfig appConfig, BrowserFilterSettings settings, IRequestFilter filter, ILogger logger, IText text) { - this.filter = new RequestFilter(); + this.filter = filter; 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(); - } - protected override IResourceRequestHandler GetResourceRequestHandler(IWebBrowser webBrowser, IBrowser browser, IFrame frame, IRequest request, bool isNavigation, bool isDownload, string requestInitiator, ref bool disableDefaultHandling) { return resourceHandler; @@ -62,9 +52,9 @@ namespace SafeExamBrowser.Browser.Handlers private bool Block(IRequest request) { - if (settings.FilterMainRequests) + if (settings.ProcessMainRequests) { - var result = filter.Process(request.Url); + var result = filter.Process(new Request { Url = request.Url }); var block = result == FilterResult.Block; if (block) @@ -77,15 +67,5 @@ namespace SafeExamBrowser.Browser.Handlers 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 5c725917..d936a201 100644 --- a/SafeExamBrowser.Browser/Handlers/ResourceHandler.cs +++ b/SafeExamBrowser.Browser/Handlers/ResourceHandler.cs @@ -11,6 +11,7 @@ using System.Collections.Specialized; using System.IO; using System.Reflection; using CefSharp; +using SafeExamBrowser.Browser.Contracts.Filters; using SafeExamBrowser.Browser.Filters; using SafeExamBrowser.Configuration.Contracts; using SafeExamBrowser.I18n.Contracts; @@ -24,12 +25,12 @@ namespace SafeExamBrowser.Browser.Handlers private AppConfig appConfig; private BrowserFilterSettings settings; private ILogger logger; - private RequestFilter filter; + private IRequestFilter filter; private IResourceHandler contentHandler; private IResourceHandler pageHandler; private IText text; - internal ResourceHandler(AppConfig appConfig, BrowserFilterSettings settings, RequestFilter filter, ILogger logger, IText text) + internal ResourceHandler(AppConfig appConfig, BrowserFilterSettings settings, IRequestFilter filter, ILogger logger, IText text) { this.appConfig = appConfig; this.filter = filter; @@ -38,14 +39,6 @@ namespace SafeExamBrowser.Browser.Handlers this.text = text; } - internal void Initialize() - { - if (settings.FilterContentRequests) - { - InitializeResourceHandlers(); - } - } - protected override IResourceHandler GetResourceHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request) { if (Block(request)) @@ -84,9 +77,9 @@ namespace SafeExamBrowser.Browser.Handlers private bool Block(IRequest request) { - if (settings.FilterContentRequests) + if (settings.ProcessContentRequests) { - var result = filter.Process(request.Url); + var result = filter.Process(new Request { Url = request.Url }); var block = result == FilterResult.Block; if (block) @@ -100,27 +93,6 @@ namespace SafeExamBrowser.Browser.Handlers return false; } - 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."); - } - private bool IsMailtoUrl(string url) { return url.StartsWith(Uri.UriSchemeMailto); @@ -145,6 +117,11 @@ namespace SafeExamBrowser.Browser.Handlers private IResourceHandler ResourceHandlerFor(ResourceType resourceType) { + if (contentHandler == default(IResourceHandler) || pageHandler == default(IResourceHandler)) + { + InitializeResourceHandlers(); + } + switch (resourceType) { case ResourceType.MainFrame: @@ -154,5 +131,26 @@ 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/SafeExamBrowser.Browser.csproj b/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj index f4ad08ff..1a86673c 100644 --- a/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj +++ b/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj @@ -75,9 +75,9 @@ - - + + Component diff --git a/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.Browser.cs b/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.Browser.cs index 10f43543..bfccfcda 100644 --- a/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.Browser.cs +++ b/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.Browser.cs @@ -108,17 +108,17 @@ namespace SafeExamBrowser.Configuration.ConfigurationData private void MapEnableContentRequestFilter(ApplicationSettings settings, object value) { - if (value is bool filter) + if (value is bool process) { - settings.Browser.Filter.FilterContentRequests = filter; + settings.Browser.Filter.ProcessContentRequests = process; } } private void MapEnableMainRequestFilter(ApplicationSettings settings, object value) { - if (value is bool filter) + if (value is bool process) { - settings.Browser.Filter.FilterMainRequests = filter; + settings.Browser.Filter.ProcessMainRequests = process; } } @@ -148,7 +148,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData if (ruleData.TryGetValue(Keys.Browser.Filter.RuleExpressionIsRegex, out v) && v is bool regex) { - rule.Type = regex ? FilterType.Regex : FilterType.Simplified; + rule.Type = regex ? FilterRuleType.Regex : FilterRuleType.Simplified; } settings.Browser.Filter.Rules.Add(rule); diff --git a/SafeExamBrowser.Settings/Browser/BrowserFilterSettings.cs b/SafeExamBrowser.Settings/Browser/BrowserFilterSettings.cs index 698b5928..1c289b25 100644 --- a/SafeExamBrowser.Settings/Browser/BrowserFilterSettings.cs +++ b/SafeExamBrowser.Settings/Browser/BrowserFilterSettings.cs @@ -18,14 +18,14 @@ namespace SafeExamBrowser.Settings.Browser public class BrowserFilterSettings { /// - /// Defines whether all content requests for a web page should be filtered according to the defined . + /// Defines whether content requests for a web page should be filtered according to the defined . /// - public bool FilterContentRequests { get; set; } + public bool ProcessContentRequests { get; set; } /// /// Defines whether the main request for a web page should be filtered according to the defined . /// - public bool FilterMainRequests { get; set; } + public bool ProcessMainRequests { get; set; } /// /// Defines all rules to be used to filter web requests. diff --git a/SafeExamBrowser.Settings/Browser/FilterRuleSettings.cs b/SafeExamBrowser.Settings/Browser/FilterRuleSettings.cs index 4e6489c3..56d131e8 100644 --- a/SafeExamBrowser.Settings/Browser/FilterRuleSettings.cs +++ b/SafeExamBrowser.Settings/Browser/FilterRuleSettings.cs @@ -29,6 +29,6 @@ namespace SafeExamBrowser.Settings.Browser /// /// The filter type which defines how the is processed. /// - public FilterType Type { get; set; } + public FilterRuleType Type { get; set; } } } diff --git a/SafeExamBrowser.Settings/Browser/FilterType.cs b/SafeExamBrowser.Settings/Browser/FilterRuleType.cs similarity index 69% rename from SafeExamBrowser.Settings/Browser/FilterType.cs rename to SafeExamBrowser.Settings/Browser/FilterRuleType.cs index 271e4fc9..4f2ae216 100644 --- a/SafeExamBrowser.Settings/Browser/FilterType.cs +++ b/SafeExamBrowser.Settings/Browser/FilterRuleType.cs @@ -9,17 +9,17 @@ namespace SafeExamBrowser.Settings.Browser { /// - /// Defines all possible request filter types. + /// Defines all possible filter rule types. /// - public enum FilterType + public enum FilterRuleType { /// - /// The filter is based on a regular expression. + /// The filter rule is based on a regular expression. /// Regex, /// - /// The filter is based on a simplified expression with wildcards. + /// The filter rule is based on a simplified expression with wildcards. /// Simplified } diff --git a/SafeExamBrowser.Settings/SafeExamBrowser.Settings.csproj b/SafeExamBrowser.Settings/SafeExamBrowser.Settings.csproj index 61a9266f..da22b7b5 100644 --- a/SafeExamBrowser.Settings/SafeExamBrowser.Settings.csproj +++ b/SafeExamBrowser.Settings/SafeExamBrowser.Settings.csproj @@ -58,7 +58,7 @@ - +