Restore SEBPatch

This commit is contained in:
2025-06-01 11:44:20 +02:00
commit 8c656e3137
1297 changed files with 142172 additions and 0 deletions

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2024 ETH Zürich, IT Services
*
* 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 CefSharp;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using SafeExamBrowser.Browser.Handlers;
namespace SafeExamBrowser.Browser.UnitTests.Handlers
{
[TestClass]
public class ContextMenuHandlerTests
{
private ContextMenuHandler sut;
[TestInitialize]
public void Initialize()
{
sut = new ContextMenuHandler();
}
[TestMethod]
public void MustClearContextMenu()
{
var menu = new Mock<IMenuModel>();
sut.OnBeforeContextMenu(default(IWebBrowser), default(IBrowser), default(IFrame), default(IContextMenuParams), menu.Object);
menu.Verify(m => m.Clear(), Times.Once);
}
[TestMethod]
public void MustBlockContextMenu()
{
var command = sut.OnContextMenuCommand(default(IWebBrowser), default(IBrowser), default(IFrame), default(IContextMenuParams), default(CefMenuCommand), default(CefEventFlags));
var run = sut.RunContextMenu(default(IWebBrowser), default(IBrowser), default(IFrame), default(IContextMenuParams), default(IMenuModel), default(IRunContextMenuCallback));
Assert.IsFalse(command);
Assert.IsFalse(run);
}
}
}

View File

@@ -0,0 +1,106 @@
/*
* Copyright (c) 2024 ETH Zürich, IT Services
*
* 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.Collections.Generic;
using System.Threading;
using CefSharp;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using SafeExamBrowser.Browser.Events;
using SafeExamBrowser.Browser.Handlers;
using SafeExamBrowser.UserInterface.Contracts.FileSystemDialog;
namespace SafeExamBrowser.Browser.UnitTests.Handlers
{
[TestClass]
public class DialogHandlerTests
{
private DialogHandler sut;
[TestInitialize]
public void Initialize()
{
sut = new DialogHandler();
}
[TestMethod]
public void MustCorrectlyCancelDialog()
{
RequestDialog(default, false);
}
[TestMethod]
public void MustCorrectlyRequestOpenFileDialog()
{
var args = RequestDialog(CefFileDialogMode.Open);
Assert.AreEqual(FileSystemElement.File, args.Element);
Assert.AreEqual(FileSystemOperation.Open, args.Operation);
}
[TestMethod]
public void MustCorrectlyRequestOpenFolderDialog()
{
var args = RequestDialog(CefFileDialogMode.OpenFolder);
Assert.AreEqual(FileSystemElement.Folder, args.Element);
Assert.AreEqual(FileSystemOperation.Open, args.Operation);
}
[TestMethod]
public void MustCorrectlyRequestSaveFileDialog()
{
var args = RequestDialog(CefFileDialogMode.Save);
Assert.AreEqual(FileSystemElement.File, args.Element);
Assert.AreEqual(FileSystemOperation.Save, args.Operation);
}
private DialogRequestedEventArgs RequestDialog(CefFileDialogMode mode, bool confirm = true)
{
var args = default(DialogRequestedEventArgs);
var callback = new Mock<IFileDialogCallback>();
var title = "Some random dialog title";
var initialPath = @"C:\Some\Random\Path";
var sync = new AutoResetEvent(false);
var threadId = default(int);
callback.Setup(c => c.Cancel()).Callback(() => sync.Set());
callback.Setup(c => c.Continue(It.IsAny<List<string>>())).Callback(() => sync.Set());
sut.DialogRequested += (a) =>
{
args = a;
args.Success = confirm;
args.FullPath = @"D:\Some\Other\File\Path.txt";
threadId = Thread.CurrentThread.ManagedThreadId;
};
var status = sut.OnFileDialog(default, default, mode, title, initialPath, default, callback.Object);
sync.WaitOne();
if (confirm)
{
callback.Verify(c => c.Continue(It.IsAny<List<string>>()), Times.Once);
callback.Verify(c => c.Cancel(), Times.Never);
}
else
{
callback.Verify(c => c.Continue(It.IsAny<List<string>>()), Times.Never);
callback.Verify(c => c.Cancel(), Times.Once);
}
Assert.IsTrue(status);
Assert.AreEqual(initialPath, args.InitialPath);
Assert.AreEqual(title, args.Title);
Assert.AreNotEqual(threadId, Thread.CurrentThread.ManagedThreadId);
return args;
}
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (c) 2024 ETH Zürich, IT Services
*
* 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.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SafeExamBrowser.Browser.Handlers;
namespace SafeExamBrowser.Browser.UnitTests.Handlers
{
[TestClass]
public class DisplayHandlerTests
{
private DisplayHandler sut;
[TestInitialize]
public void Initialize()
{
sut = new DisplayHandler();
}
[TestMethod]
public void MustUseDefaultHandling()
{
var text = default(string);
Assert.IsFalse(sut.OnAutoResize(default, default, default));
Assert.IsFalse(sut.OnConsoleMessage(default, default));
Assert.IsFalse(sut.OnCursorChange(default, default, default, default, default));
Assert.IsFalse(sut.OnTooltipChanged(default, ref text));
}
[TestMethod]
public void MustHandleFaviconChange()
{
var newUrl = "www.someurl.org/favicon.ico";
var url = default(string);
var called = false;
sut.FaviconChanged += (u) =>
{
called = true;
url = u;
};
sut.OnFaviconUrlChange(default, default, new List<string>());
Assert.AreEqual(default, url);
Assert.IsFalse(called);
sut.OnFaviconUrlChange(default, default, new List<string> { newUrl });
Assert.AreEqual(newUrl, url);
Assert.IsTrue(called);
}
[TestMethod]
public void MustHandleProgressChange()
{
var expected = 0.123456;
var actual = default(double);
sut.ProgressChanged += (p) => actual = p;
sut.OnLoadingProgressChange(default, default, expected);
Assert.AreEqual(expected, actual);
}
}
}

View File

@@ -0,0 +1,311 @@
/*
* Copyright (c) 2024 ETH Zürich, IT Services
*
* 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 System.IO;
using System.Threading;
using CefSharp;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using SafeExamBrowser.Browser.Contracts.Events;
using SafeExamBrowser.Browser.Handlers;
using SafeExamBrowser.Configuration.Contracts;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.Settings.Browser;
using SafeExamBrowser.UserInterface.Contracts.Browser.Data;
using BrowserSettings = SafeExamBrowser.Settings.Browser.BrowserSettings;
namespace SafeExamBrowser.Browser.UnitTests.Handlers
{
[TestClass]
public class DownloadHandlerTests
{
private AppConfig appConfig;
private Mock<ILogger> logger;
private BrowserSettings settings;
private WindowSettings windowSettings;
private DownloadHandler sut;
[TestInitialize]
public void Initialize()
{
appConfig = new AppConfig();
logger = new Mock<ILogger>();
settings = new BrowserSettings();
windowSettings = new WindowSettings();
sut = new DownloadHandler(appConfig, logger.Object, settings, windowSettings);
}
[TestMethod]
public void MustCorrectlyHandleConfigurationByFileExtension()
{
var item = new DownloadItem
{
SuggestedFileName = "File.seb",
Url = "https://somehost.org/some-path"
};
RequestConfigurationDownload(item);
}
[TestMethod]
public void MustCorrectlyHandleConfigurationByUrlExtension()
{
var item = new DownloadItem
{
SuggestedFileName = "Abc.xyz",
Url = "https://somehost.org/some-path-to/file.seb"
};
RequestConfigurationDownload(item);
}
[TestMethod]
public void MustCorrectlyHandleConfigurationByMimeType()
{
appConfig.ConfigurationFileMimeType = "some/mime-type";
var item = new DownloadItem
{
MimeType = appConfig.ConfigurationFileMimeType,
SuggestedFileName = "Abc.xyz",
Url = "https://somehost.org/some-path"
};
RequestConfigurationDownload(item);
}
[TestMethod]
public void MustCorrectlyHandleDeniedConfigurationFileDownload()
{
var args = default(DownloadEventArgs);
var callback = new Mock<IBeforeDownloadCallback>();
var failed = false;
var fileName = default(string);
var item = new DownloadItem
{
SuggestedFileName = "File.seb",
Url = "https://somehost.org/some-path"
};
var sync = new AutoResetEvent(false);
var threadId = default(int);
settings.AllowDownloads = false;
settings.AllowConfigurationDownloads = true;
sut.ConfigurationDownloadRequested += (f, a) =>
{
args = a;
args.AllowDownload = false;
fileName = f;
threadId = Thread.CurrentThread.ManagedThreadId;
sync.Set();
};
sut.DownloadUpdated += (state) => failed = true;
sut.OnBeforeDownload(default(IWebBrowser), default(IBrowser), item, callback.Object);
sync.WaitOne();
callback.VerifyNoOtherCalls();
Assert.IsFalse(failed);
Assert.IsFalse(args.AllowDownload);
Assert.AreEqual(item.SuggestedFileName, fileName);
Assert.AreNotEqual(Thread.CurrentThread.ManagedThreadId, threadId);
}
[TestMethod]
public void MustCorrectlyHandleFileDownload()
{
var callback = new Mock<IBeforeDownloadCallback>();
var downloadPath = default(string);
var failed = false;
var item = new DownloadItem
{
MimeType = "application/something",
SuggestedFileName = "File.txt",
Url = "https://somehost.org/somefile.abc"
};
var sync = new AutoResetEvent(false);
var threadId = default(int);
callback.Setup(c => c.Continue(It.IsAny<string>(), It.IsAny<bool>())).Callback<string, bool>((f, s) =>
{
downloadPath = f;
threadId = Thread.CurrentThread.ManagedThreadId;
sync.Set();
});
settings.AllowDownloads = true;
settings.AllowConfigurationDownloads = false;
sut.ConfigurationDownloadRequested += (f, a) => failed = true;
sut.DownloadUpdated += (state) => failed = true;
sut.OnBeforeDownload(default(IWebBrowser), default(IBrowser), item, callback.Object);
sync.WaitOne();
callback.Verify(c => c.Continue(It.Is<string>(p => p.Equals(downloadPath)), false), Times.Once);
Assert.IsFalse(failed);
Assert.AreNotEqual(Thread.CurrentThread.ManagedThreadId, threadId);
}
[TestMethod]
public void MustCorrectlyHandleFileDownloadWithCustomDirectory()
{
var callback = new Mock<IBeforeDownloadCallback>();
var failed = false;
var item = new DownloadItem
{
MimeType = "application/something",
SuggestedFileName = "File.txt",
Url = "https://somehost.org/somefile.abc"
};
var sync = new AutoResetEvent(false);
var threadId = default(int);
callback.Setup(c => c.Continue(It.IsAny<string>(), It.IsAny<bool>())).Callback(() =>
{
threadId = Thread.CurrentThread.ManagedThreadId;
sync.Set();
});
settings.AllowDownloads = true;
settings.AllowConfigurationDownloads = false;
settings.AllowCustomDownAndUploadLocation = true;
settings.DownAndUploadDirectory = @"%APPDATA%\Downloads";
sut.ConfigurationDownloadRequested += (f, a) => failed = true;
sut.DownloadUpdated += (state) => failed = true;
sut.OnBeforeDownload(default(IWebBrowser), default(IBrowser), item, callback.Object);
sync.WaitOne();
var downloadPath = Path.Combine(Environment.ExpandEnvironmentVariables(settings.DownAndUploadDirectory), item.SuggestedFileName);
callback.Verify(c => c.Continue(It.Is<string>(p => p.Equals(downloadPath)), true), Times.Once);
Assert.IsFalse(failed);
Assert.AreNotEqual(Thread.CurrentThread.ManagedThreadId, threadId);
}
[TestMethod]
public void MustDoNothingIfDownloadsNotAllowed()
{
var callback = new Mock<IBeforeDownloadCallback>();
var fail = false;
var item = new DownloadItem
{
SuggestedFileName = "File.txt",
Url = "https://somehost.org/somefile.abc"
};
settings.AllowDownloads = false;
settings.AllowConfigurationDownloads = false;
sut.ConfigurationDownloadRequested += (file, args) => fail = true;
sut.DownloadUpdated += (state) => fail = true;
sut.OnBeforeDownload(default(IWebBrowser), default(IBrowser), item, callback.Object);
callback.VerifyNoOtherCalls();
Assert.IsFalse(fail);
}
[TestMethod]
public void MustUpdateDownloadProgress()
{
var callback = new Mock<IBeforeDownloadCallback>();
var failed = false;
var item = new DownloadItem
{
MimeType = "application/something",
SuggestedFileName = "File.txt",
Url = "https://somehost.org/somefile.abc"
};
var state = default(DownloadItemState);
var sync = new AutoResetEvent(false);
var threadId = default(int);
callback.Setup(c => c.Continue(It.IsAny<string>(), It.IsAny<bool>())).Callback(() => sync.Set());
settings.AllowDownloads = true;
settings.AllowConfigurationDownloads = false;
sut.ConfigurationDownloadRequested += (f, a) => failed = true;
sut.OnBeforeDownload(default(IWebBrowser), default(IBrowser), item, callback.Object);
sync.WaitOne();
Assert.IsFalse(failed);
sut.DownloadUpdated += (s) =>
{
state = s;
threadId = Thread.CurrentThread.ManagedThreadId;
sync.Set();
};
item.PercentComplete = 10;
sut.OnDownloadUpdated(default(IWebBrowser), default(IBrowser), item, default(IDownloadItemCallback));
sync.WaitOne();
Assert.IsFalse(state.IsCancelled);
Assert.IsFalse(state.IsComplete);
Assert.AreEqual(0.1, state.Completion);
Assert.AreNotEqual(Thread.CurrentThread.ManagedThreadId, threadId);
item.PercentComplete = 20;
sut.OnDownloadUpdated(default(IWebBrowser), default(IBrowser), item, default(IDownloadItemCallback));
sync.WaitOne();
Assert.IsFalse(state.IsCancelled);
Assert.IsFalse(state.IsComplete);
Assert.AreEqual(0.2, state.Completion);
Assert.AreNotEqual(Thread.CurrentThread.ManagedThreadId, threadId);
item.PercentComplete = 50;
item.IsCancelled = true;
sut.OnDownloadUpdated(default(IWebBrowser), default(IBrowser), item, default(IDownloadItemCallback));
sync.WaitOne();
Assert.IsFalse(failed);
Assert.IsTrue(state.IsCancelled);
Assert.IsFalse(state.IsComplete);
Assert.AreEqual(0.5, state.Completion);
Assert.AreNotEqual(Thread.CurrentThread.ManagedThreadId, threadId);
}
private void RequestConfigurationDownload(DownloadItem item)
{
var args = default(DownloadEventArgs);
var callback = new Mock<IBeforeDownloadCallback>();
var failed = false;
var fileName = default(string);
var sync = new AutoResetEvent(false);
var threadId = default(int);
callback.Setup(c => c.Continue(It.IsAny<string>(), It.IsAny<bool>())).Callback(() => sync.Set());
settings.AllowDownloads = false;
settings.AllowConfigurationDownloads = true;
sut.ConfigurationDownloadRequested += (f, a) =>
{
args = a;
args.AllowDownload = true;
args.DownloadPath = @"C:\Downloads\File.seb";
fileName = f;
threadId = Thread.CurrentThread.ManagedThreadId;
};
sut.DownloadUpdated += (state) => failed = true;
sut.OnBeforeDownload(default(IWebBrowser), default(IBrowser), item, callback.Object);
sync.WaitOne();
callback.Verify(c => c.Continue(It.Is<string>(p => p.Equals(args.DownloadPath)), false), Times.Once);
Assert.IsFalse(failed);
Assert.IsTrue(args.AllowDownload);
Assert.AreEqual(item.SuggestedFileName, fileName);
Assert.AreNotEqual(Thread.CurrentThread.ManagedThreadId, threadId);
}
}
}

View File

@@ -0,0 +1,166 @@
/*
* Copyright (c) 2024 ETH Zürich, IT Services
*
* 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.Windows.Forms;
using CefSharp;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SafeExamBrowser.Browser.Handlers;
namespace SafeExamBrowser.Browser.UnitTests.Handlers
{
[TestClass]
public class KeyboardHandlerTests
{
private KeyboardHandler sut;
[TestInitialize]
public void Initialize()
{
sut = new KeyboardHandler();
}
[TestMethod]
public void MustDetectFindCommand()
{
var findRequested = false;
sut.FindRequested += () => findRequested = true;
var handled = sut.OnKeyEvent(default(IWebBrowser), default(IBrowser), KeyType.KeyUp, (int) Keys.F, default(int), CefEventFlags.ControlDown, default(bool));
Assert.IsTrue(findRequested);
Assert.IsFalse(handled);
findRequested = false;
handled = sut.OnKeyEvent(default(IWebBrowser), default(IBrowser), default(KeyType), default(int), default(int), CefEventFlags.ControlDown, default(bool));
Assert.IsFalse(findRequested);
Assert.IsFalse(handled);
}
[TestMethod]
public void MustDetectHomeNavigationCommand()
{
var homeRequested = false;
sut.HomeNavigationRequested += () => homeRequested = true;
var handled = sut.OnKeyEvent(default(IWebBrowser), default(IBrowser), KeyType.KeyUp, (int) Keys.Home, default(int), default(CefEventFlags), default(bool));
Assert.IsTrue(homeRequested);
Assert.IsFalse(handled);
homeRequested = false;
handled = sut.OnKeyEvent(default(IWebBrowser), default(IBrowser), default(KeyType), default(int), default(int), default(CefEventFlags), default(bool));
Assert.IsFalse(homeRequested);
Assert.IsFalse(handled);
}
[TestMethod]
public void MustDetectReloadCommand()
{
var isShortcut = default(bool);
var reloadRequested = false;
sut.ReloadRequested += () => reloadRequested = true;
var handled = sut.OnPreKeyEvent(default(IWebBrowser), default(IBrowser), KeyType.KeyUp, (int) Keys.F5, default(int), default(CefEventFlags), default(bool), ref isShortcut);
Assert.IsTrue(reloadRequested);
Assert.IsTrue(handled);
reloadRequested = false;
handled = sut.OnPreKeyEvent(default(IWebBrowser), default(IBrowser), default(KeyType), default(int), default(int), default(CefEventFlags), default(bool), ref isShortcut);
Assert.IsFalse(reloadRequested);
Assert.IsFalse(handled);
}
[TestMethod]
public void MustDetectZoomInCommand()
{
var zoomIn = false;
var zoomOut = false;
var zoomReset = false;
sut.ZoomInRequested += () => zoomIn = true;
sut.ZoomOutRequested += () => zoomOut = true;
sut.ZoomResetRequested += () => zoomReset = true;
var handled = sut.OnKeyEvent(default(IWebBrowser), default(IBrowser), KeyType.KeyUp, (int) Keys.Add, default(int), CefEventFlags.ControlDown, false);
Assert.IsFalse(handled);
Assert.IsTrue(zoomIn);
Assert.IsFalse(zoomOut);
Assert.IsFalse(zoomReset);
zoomIn = false;
handled = sut.OnKeyEvent(default(IWebBrowser), default(IBrowser), KeyType.KeyUp, (int) Keys.D1, default(int), CefEventFlags.ControlDown | CefEventFlags.ShiftDown, false);
Assert.IsFalse(handled);
Assert.IsTrue(zoomIn);
Assert.IsFalse(zoomOut);
Assert.IsFalse(zoomReset);
}
[TestMethod]
public void MustDetectZoomOutCommand()
{
var zoomIn = false;
var zoomOut = false;
var zoomReset = false;
sut.ZoomInRequested += () => zoomIn = true;
sut.ZoomOutRequested += () => zoomOut = true;
sut.ZoomResetRequested += () => zoomReset = true;
var handled = sut.OnKeyEvent(default(IWebBrowser), default(IBrowser), KeyType.KeyUp, (int) Keys.Subtract, default(int), CefEventFlags.ControlDown, false);
Assert.IsFalse(handled);
Assert.IsFalse(zoomIn);
Assert.IsTrue(zoomOut);
Assert.IsFalse(zoomReset);
zoomOut = false;
handled = sut.OnKeyEvent(default(IWebBrowser), default(IBrowser), KeyType.KeyUp, (int) Keys.OemMinus, default(int), CefEventFlags.ControlDown, false);
Assert.IsFalse(handled);
Assert.IsFalse(zoomIn);
Assert.IsTrue(zoomOut);
Assert.IsFalse(zoomReset);
}
[TestMethod]
public void MustDetectZoomResetCommand()
{
var zoomIn = false;
var zoomOut = false;
var zoomReset = false;
sut.ZoomInRequested += () => zoomIn = true;
sut.ZoomOutRequested += () => zoomOut = true;
sut.ZoomResetRequested += () => zoomReset = true;
var handled = sut.OnKeyEvent(default(IWebBrowser), default(IBrowser), KeyType.KeyUp, (int) Keys.D0, default(int), CefEventFlags.ControlDown, false);
Assert.IsFalse(handled);
Assert.IsFalse(zoomIn);
Assert.IsFalse(zoomOut);
Assert.IsTrue(zoomReset);
zoomReset = false;
handled = sut.OnKeyEvent(default(IWebBrowser), default(IBrowser), KeyType.KeyUp, (int) Keys.NumPad0, default(int), CefEventFlags.ControlDown, false);
Assert.IsFalse(handled);
Assert.IsFalse(zoomIn);
Assert.IsFalse(zoomOut);
Assert.IsTrue(zoomReset);
}
}
}

View File

@@ -0,0 +1,313 @@
/*
* Copyright (c) 2024 ETH Zürich, IT Services
*
* 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 CefSharp;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using SafeExamBrowser.Browser.Contracts.Filters;
using SafeExamBrowser.Browser.Handlers;
using SafeExamBrowser.Configuration.Contracts;
using SafeExamBrowser.Configuration.Contracts.Cryptography;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.Settings.Browser;
using SafeExamBrowser.Settings.Browser.Filter;
using SafeExamBrowser.Settings.Browser.Proxy;
using BrowserSettings = SafeExamBrowser.Settings.Browser.BrowserSettings;
using Request = SafeExamBrowser.Browser.Contracts.Filters.Request;
using ResourceHandler = SafeExamBrowser.Browser.Handlers.ResourceHandler;
namespace SafeExamBrowser.Browser.UnitTests.Handlers
{
[TestClass]
public class RequestHandlerTests
{
private AppConfig appConfig;
private Mock<IRequestFilter> filter;
private Mock<IKeyGenerator> keyGenerator;
private Mock<ILogger> logger;
private BrowserSettings settings;
private WindowSettings windowSettings;
private ResourceHandler resourceHandler;
private Mock<IText> text;
private TestableRequestHandler sut;
[TestInitialize]
public void Initialize()
{
appConfig = new AppConfig();
filter = new Mock<IRequestFilter>();
keyGenerator = new Mock<IKeyGenerator>();
logger = new Mock<ILogger>();
settings = new BrowserSettings();
windowSettings = new WindowSettings();
text = new Mock<IText>();
resourceHandler = new ResourceHandler(appConfig, filter.Object, keyGenerator.Object, logger.Object, default, settings, windowSettings, text.Object);
sut = new TestableRequestHandler(appConfig, filter.Object, logger.Object, resourceHandler, settings, windowSettings);
}
[TestMethod]
public void MustBlockSpecialWindowDispositions()
{
Assert.IsTrue(sut.OnOpenUrlFromTab(default, default, default, default, WindowOpenDisposition.NewBackgroundTab, default));
Assert.IsTrue(sut.OnOpenUrlFromTab(default, default, default, default, WindowOpenDisposition.NewPopup, default));
Assert.IsTrue(sut.OnOpenUrlFromTab(default, default, default, default, WindowOpenDisposition.NewWindow, default));
Assert.IsTrue(sut.OnOpenUrlFromTab(default, default, default, default, WindowOpenDisposition.SaveToDisk, default));
}
[TestMethod]
public void MustDetectQuitUrl()
{
var eventFired = false;
var quitUrl = "http://www.byebye.com";
var request = new Mock<IRequest>();
appConfig.ConfigurationFileMimeType = "application/seb";
request.SetupGet(r => r.Url).Returns(quitUrl);
settings.QuitUrl = quitUrl;
sut.QuitUrlVisited += (url) => eventFired = true;
var blocked = sut.OnBeforeBrowse(Mock.Of<IWebBrowser>(), Mock.Of<IBrowser>(), Mock.Of<IFrame>(), request.Object, false, false);
Assert.IsTrue(blocked);
Assert.IsTrue(eventFired);
blocked = false;
eventFired = false;
request.SetupGet(r => r.Url).Returns("http://www.bye.com");
blocked = sut.OnBeforeBrowse(Mock.Of<IWebBrowser>(), Mock.Of<IBrowser>(), Mock.Of<IFrame>(), request.Object, false, false);
Assert.IsFalse(blocked);
Assert.IsFalse(eventFired);
}
[TestMethod]
public void MustIgnoreTrailingSlashForQuitUrl()
{
var eventFired = false;
var quitUrl = "http://www.byebye.com";
var request = new Mock<IRequest>();
request.SetupGet(r => r.Url).Returns($"{quitUrl}/");
settings.QuitUrl = quitUrl;
sut.QuitUrlVisited += (url) => eventFired = true;
var blocked = sut.OnBeforeBrowse(Mock.Of<IWebBrowser>(), Mock.Of<IBrowser>(), Mock.Of<IFrame>(), request.Object, false, false);
Assert.IsTrue(blocked);
Assert.IsTrue(eventFired);
blocked = false;
eventFired = false;
request.SetupGet(r => r.Url).Returns(quitUrl);
settings.QuitUrl = $"{quitUrl}/";
blocked = sut.OnBeforeBrowse(Mock.Of<IWebBrowser>(), Mock.Of<IBrowser>(), Mock.Of<IFrame>(), request.Object, false, false);
Assert.IsTrue(blocked);
Assert.IsTrue(eventFired);
}
[TestMethod]
public void MustFilterMainRequests()
{
var eventFired = false;
var request = new Mock<IRequest>();
var url = "https://www.test.org";
appConfig.ConfigurationFileMimeType = "application/seb";
filter.Setup(f => f.Process(It.Is<Request>(r => r.Url.Equals(url)))).Returns(FilterResult.Block);
request.SetupGet(r => r.ResourceType).Returns(ResourceType.MainFrame);
request.SetupGet(r => r.Url).Returns(url);
settings.Filter.ProcessContentRequests = false;
settings.Filter.ProcessMainRequests = true;
sut.RequestBlocked += (u) => eventFired = true;
var blocked = sut.OnBeforeBrowse(Mock.Of<IWebBrowser>(), Mock.Of<IBrowser>(), Mock.Of<IFrame>(), request.Object, false, false);
filter.Verify(f => f.Process(It.Is<Request>(r => r.Url.Equals(url))), Times.Once);
Assert.IsTrue(blocked);
Assert.IsTrue(eventFired);
blocked = false;
eventFired = false;
request.SetupGet(r => r.ResourceType).Returns(ResourceType.SubFrame);
blocked = sut.OnBeforeBrowse(Mock.Of<IWebBrowser>(), Mock.Of<IBrowser>(), Mock.Of<IFrame>(), request.Object, false, false);
filter.Verify(f => f.Process(It.Is<Request>(r => r.Url.Equals(url))), Times.Once);
Assert.IsFalse(blocked);
Assert.IsFalse(eventFired);
}
[TestMethod]
public void MustFilterContentRequests()
{
var eventFired = false;
var request = new Mock<IRequest>();
var url = "https://www.test.org";
appConfig.ConfigurationFileMimeType = "application/seb";
filter.Setup(f => f.Process(It.Is<Request>(r => r.Url.Equals(url)))).Returns(FilterResult.Block);
request.SetupGet(r => r.ResourceType).Returns(ResourceType.SubFrame);
request.SetupGet(r => r.Url).Returns(url);
settings.Filter.ProcessContentRequests = true;
settings.Filter.ProcessMainRequests = false;
sut.RequestBlocked += (u) => eventFired = true;
var blocked = sut.OnBeforeBrowse(Mock.Of<IWebBrowser>(), Mock.Of<IBrowser>(), Mock.Of<IFrame>(), request.Object, false, false);
filter.Verify(f => f.Process(It.Is<Request>(r => r.Url.Equals(url))), Times.Once);
Assert.IsTrue(blocked);
Assert.IsFalse(eventFired);
blocked = false;
eventFired = false;
request.SetupGet(r => r.ResourceType).Returns(ResourceType.MainFrame);
blocked = sut.OnBeforeBrowse(Mock.Of<IWebBrowser>(), Mock.Of<IBrowser>(), Mock.Of<IFrame>(), request.Object, false, false);
filter.Verify(f => f.Process(It.Is<Request>(r => r.Url.Equals(url))), Times.Once);
Assert.IsFalse(blocked);
Assert.IsFalse(eventFired);
}
[TestMethod]
public void MustInitiateDataUriConfigurationFileDownload()
{
var browser = new Mock<IBrowser>();
var host = new Mock<IBrowserHost>();
var request = new Mock<IRequest>();
appConfig.ConfigurationFileExtension = ".xyz";
appConfig.ConfigurationFileMimeType = "application/seb";
appConfig.SebUriScheme = "abc";
appConfig.SebUriSchemeSecure = "abcd";
browser.Setup(b => b.GetHost()).Returns(host.Object);
request.SetupGet(r => r.Url).Returns($"{appConfig.SebUriSchemeSecure}://{appConfig.ConfigurationFileMimeType};base64,H4sIAAAAAAAAE41WbXPaRhD...");
var handled = sut.OnBeforeBrowse(Mock.Of<IWebBrowser>(), browser.Object, Mock.Of<IFrame>(), request.Object, false, false);
host.Verify(h => h.StartDownload(It.Is<string>(u => u == $"data:{appConfig.ConfigurationFileMimeType};base64,H4sIAAAAAAAAE41WbXPaRhD...")));
Assert.IsTrue(handled);
}
[TestMethod]
public void MustInitiateHttpConfigurationFileDownload()
{
var browser = new Mock<IBrowser>();
var host = new Mock<IBrowserHost>();
var request = new Mock<IRequest>();
appConfig.ConfigurationFileExtension = ".xyz";
appConfig.ConfigurationFileMimeType = "application/seb";
appConfig.SebUriScheme = "abc";
appConfig.SebUriSchemeSecure = "abcd";
browser.Setup(b => b.GetHost()).Returns(host.Object);
request.SetupGet(r => r.Url).Returns($"{appConfig.SebUriScheme}://host.com/path/file{appConfig.ConfigurationFileExtension}");
var handled = sut.OnBeforeBrowse(Mock.Of<IWebBrowser>(), browser.Object, Mock.Of<IFrame>(), request.Object, false, false);
host.Verify(h => h.StartDownload(It.Is<string>(u => u == $"{Uri.UriSchemeHttp}://host.com/path/file{appConfig.ConfigurationFileExtension}")));
Assert.IsTrue(handled);
}
[TestMethod]
public void MustInitiateHttpsConfigurationFileDownload()
{
var browser = new Mock<IBrowser>();
var host = new Mock<IBrowserHost>();
var request = new Mock<IRequest>();
appConfig.ConfigurationFileExtension = ".xyz";
appConfig.ConfigurationFileMimeType = "application/seb";
appConfig.SebUriScheme = "abc";
appConfig.SebUriSchemeSecure = "abcd";
browser.Setup(b => b.GetHost()).Returns(host.Object);
request.SetupGet(r => r.Url).Returns($"{appConfig.SebUriSchemeSecure}://host.com/path/file{appConfig.ConfigurationFileExtension}");
var handled = sut.OnBeforeBrowse(Mock.Of<IWebBrowser>(), browser.Object, Mock.Of<IFrame>(), request.Object, false, false);
host.Verify(h => h.StartDownload(It.Is<string>(u => u == $"{Uri.UriSchemeHttps}://host.com/path/file{appConfig.ConfigurationFileExtension}")));
Assert.IsTrue(handled);
}
[TestMethod]
public void MustReturnResourceHandler()
{
var disableDefaultHandling = default(bool);
var handler = sut.GetResourceRequestHandler(default, default, default, default, default, default, default, ref disableDefaultHandling);
Assert.AreSame(resourceHandler, handler);
}
[TestMethod]
public void MustUseProxyCredentials()
{
var callback = new Mock<IAuthCallback>();
var proxy1 = new ProxyConfiguration { Host = "www.test.com", Username = "Sepp", Password = "1234", Port = 10, RequiresAuthentication = true };
var proxy2 = new ProxyConfiguration { Host = "www.nope.com", Username = "Peter", Password = "4321", Port = 10, RequiresAuthentication = false };
settings.Proxy.Proxies.Add(proxy1);
settings.Proxy.Proxies.Add(proxy2);
var result = sut.GetAuthCredentials(Mock.Of<IWebBrowser>(), Mock.Of<IBrowser>(), default, true, "WWW.tEst.Com", 10, default, default, callback.Object);
callback.Verify(c => c.Cancel(), Times.Never);
callback.Verify(c => c.Continue(It.Is<string>(u => u.Equals(proxy1.Username)), It.Is<string>(p => p.Equals(proxy1.Password))), Times.Once);
callback.Verify(c => c.Continue(It.Is<string>(u => u.Equals(proxy2.Username)), It.Is<string>(p => p.Equals(proxy2.Password))), Times.Never);
Assert.IsTrue(result);
}
[TestMethod]
public void MustNotUseProxyCredentialsIfNoProxy()
{
var callback = new Mock<IAuthCallback>();
sut.GetAuthCredentials(Mock.Of<IWebBrowser>(), Mock.Of<IBrowser>(), default, false, default, default, default, default, callback.Object);
callback.Verify(c => c.Cancel(), Times.Never);
callback.Verify(c => c.Continue(It.IsAny<string>(), It.IsAny<string>()), Times.Never);
}
private class TestableRequestHandler : RequestHandler
{
internal TestableRequestHandler(AppConfig appConfig, IRequestFilter filter, ILogger logger, ResourceHandler resourceHandler, BrowserSettings settings, WindowSettings windowSettings) : base(appConfig, filter, logger, resourceHandler, settings, windowSettings)
{
}
public new bool GetAuthCredentials(IWebBrowser webBrowser, IBrowser browser, string originUrl, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback)
{
return base.GetAuthCredentials(webBrowser, browser, originUrl, isProxy, host, port, realm, scheme, callback);
}
public new IResourceRequestHandler GetResourceRequestHandler(IWebBrowser webBrowser, IBrowser browser, IFrame frame, IRequest request, bool isNavigation, bool isDownload, string requestInitiator, ref bool disableDefaultHandling)
{
return base.GetResourceRequestHandler(webBrowser, browser, frame, request, isNavigation, isDownload, requestInitiator, ref disableDefaultHandling);
}
public new bool OnBeforeBrowse(IWebBrowser webBrowser, IBrowser browser, IFrame frame, IRequest request, bool userGesture, bool isRedirect)
{
return base.OnBeforeBrowse(webBrowser, browser, frame, request, userGesture, isRedirect);
}
public new bool OnOpenUrlFromTab(IWebBrowser webBrowser, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture)
{
return base.OnOpenUrlFromTab(webBrowser, browser, frame, targetUrl, targetDisposition, userGesture);
}
}
}
}

View File

@@ -0,0 +1,363 @@
/*
* Copyright (c) 2024 ETH Zürich, IT Services
*
* 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 System.Collections.Specialized;
using System.Net.Mime;
using System.Threading;
using CefSharp;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using SafeExamBrowser.Browser.Contracts.Filters;
using SafeExamBrowser.Configuration.Contracts;
using SafeExamBrowser.Configuration.Contracts.Cryptography;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.Settings;
using SafeExamBrowser.Settings.Browser;
using SafeExamBrowser.Settings.Browser.Filter;
using BrowserSettings = SafeExamBrowser.Settings.Browser.BrowserSettings;
using Request = SafeExamBrowser.Browser.Contracts.Filters.Request;
using ResourceHandler = SafeExamBrowser.Browser.Handlers.ResourceHandler;
namespace SafeExamBrowser.Browser.UnitTests.Handlers
{
[TestClass]
public class ResourceHandlerTests
{
private AppConfig appConfig;
private Mock<IRequestFilter> filter;
private Mock<IKeyGenerator> keyGenerator;
private Mock<ILogger> logger;
private BrowserSettings settings;
private WindowSettings windowSettings;
private Mock<IText> text;
private TestableResourceHandler sut;
[TestInitialize]
public void Initialize()
{
appConfig = new AppConfig();
filter = new Mock<IRequestFilter>();
keyGenerator = new Mock<IKeyGenerator>();
logger = new Mock<ILogger>();
settings = new BrowserSettings();
windowSettings = new WindowSettings();
text = new Mock<IText>();
sut = new TestableResourceHandler(appConfig, filter.Object, keyGenerator.Object, logger.Object, SessionMode.Server, settings, windowSettings, text.Object);
}
[TestMethod]
public void MustAppendCustomHeadersForSameDomain()
{
var browser = new Mock<IWebBrowser>();
var headers = default(NameValueCollection);
var request = new Mock<IRequest>();
browser.SetupGet(b => b.Address).Returns("http://www.host.org");
keyGenerator.Setup(g => g.CalculateBrowserExamKeyHash(It.IsAny<string>(), It.IsAny<byte[]>(), It.IsAny<string>())).Returns(new Random().Next().ToString());
keyGenerator.Setup(g => g.CalculateConfigurationKeyHash(It.IsAny<string>(), It.IsAny<string>())).Returns(new Random().Next().ToString());
request.SetupGet(r => r.Headers).Returns(new NameValueCollection());
request.SetupGet(r => r.Url).Returns("http://www.host.org");
request.SetupSet(r => r.Headers = It.IsAny<NameValueCollection>()).Callback<NameValueCollection>((h) => headers = h);
settings.SendConfigurationKey = true;
settings.SendBrowserExamKey = true;
var result = sut.OnBeforeResourceLoad(browser.Object, Mock.Of<IBrowser>(), Mock.Of<IFrame>(), request.Object, Mock.Of<IRequestCallback>());
request.VerifyGet(r => r.Headers, Times.AtLeastOnce);
request.VerifySet(r => r.Headers = It.IsAny<NameValueCollection>(), Times.AtLeastOnce);
Assert.AreEqual(CefReturnValue.Continue, result);
Assert.IsNotNull(headers["X-SafeExamBrowser-ConfigKeyHash"]);
Assert.IsNotNull(headers["X-SafeExamBrowser-RequestHash"]);
}
[TestMethod]
public void MustAppendCustomHeadersForCrossDomainResourceRequestAndMainFrame()
{
var browser = new Mock<IWebBrowser>();
var headers = new NameValueCollection();
var request = new Mock<IRequest>();
browser.SetupGet(b => b.Address).Returns("http://www.otherhost.org");
keyGenerator.Setup(g => g.CalculateBrowserExamKeyHash(It.IsAny<string>(), It.IsAny<byte[]>(), It.IsAny<string>())).Returns(new Random().Next().ToString());
keyGenerator.Setup(g => g.CalculateConfigurationKeyHash(It.IsAny<string>(), It.IsAny<string>())).Returns(new Random().Next().ToString());
request.SetupGet(r => r.ResourceType).Returns(ResourceType.MainFrame);
request.SetupGet(r => r.Headers).Returns(new NameValueCollection());
request.SetupGet(r => r.Url).Returns("http://www.host.org");
request.SetupSet(r => r.Headers = It.IsAny<NameValueCollection>()).Callback<NameValueCollection>((h) => headers = h);
settings.SendConfigurationKey = true;
settings.SendBrowserExamKey = true;
var result = sut.OnBeforeResourceLoad(browser.Object, Mock.Of<IBrowser>(), Mock.Of<IFrame>(), request.Object, Mock.Of<IRequestCallback>());
request.VerifyGet(r => r.Headers, Times.AtLeastOnce);
request.VerifySet(r => r.Headers = It.IsAny<NameValueCollection>(), Times.AtLeastOnce);
Assert.AreEqual(CefReturnValue.Continue, result);
Assert.IsNotNull(headers["X-SafeExamBrowser-ConfigKeyHash"]);
Assert.IsNotNull(headers["X-SafeExamBrowser-RequestHash"]);
}
[TestMethod]
public void MustNotAppendCustomHeadersForCrossDomainResourceRequestAndSubResource()
{
var browser = new Mock<IWebBrowser>();
var headers = new NameValueCollection();
var request = new Mock<IRequest>();
browser.SetupGet(b => b.Address).Returns("http://www.otherhost.org");
request.SetupGet(r => r.ResourceType).Returns(ResourceType.SubResource);
request.SetupGet(r => r.Headers).Returns(new NameValueCollection());
request.SetupGet(r => r.Url).Returns("http://www.host.org");
request.SetupSet(r => r.Headers = It.IsAny<NameValueCollection>()).Callback<NameValueCollection>((h) => headers = h);
settings.SendConfigurationKey = true;
settings.SendBrowserExamKey = true;
var result = sut.OnBeforeResourceLoad(browser.Object, Mock.Of<IBrowser>(), Mock.Of<IFrame>(), request.Object, Mock.Of<IRequestCallback>());
request.VerifyGet(r => r.Headers, Times.Never);
request.VerifySet(r => r.Headers = It.IsAny<NameValueCollection>(), Times.Never);
Assert.AreEqual(CefReturnValue.Continue, result);
Assert.IsNull(headers["X-SafeExamBrowser-ConfigKeyHash"]);
Assert.IsNull(headers["X-SafeExamBrowser-RequestHash"]);
}
[TestMethod]
public void MustBlockMailToUrls()
{
var request = new Mock<IRequest>();
var url = $"{Uri.UriSchemeMailto}:someone@somewhere.org";
request.SetupGet(r => r.Url).Returns(url);
var result = sut.OnBeforeResourceLoad(Mock.Of<IWebBrowser>(), Mock.Of<IBrowser>(), Mock.Of<IFrame>(), request.Object, Mock.Of<IRequestCallback>());
Assert.AreEqual(CefReturnValue.Cancel, result);
}
[TestMethod]
public void MustFilterContentRequests()
{
var request = new Mock<IRequest>();
var url = "http://www.test.org";
filter.Setup(f => f.Process(It.Is<Request>(r => r.Url.Equals(url)))).Returns(FilterResult.Block);
request.SetupGet(r => r.ResourceType).Returns(ResourceType.SubFrame);
request.SetupGet(r => r.Url).Returns(url);
settings.Filter.ProcessContentRequests = true;
settings.Filter.ProcessMainRequests = true;
var resourceHandler = sut.GetResourceHandler(Mock.Of<IWebBrowser>(), Mock.Of<IBrowser>(), Mock.Of<IFrame>(), request.Object);
filter.Verify(f => f.Process(It.Is<Request>(r => r.Url.Equals(url))), Times.Once);
Assert.IsNotNull(resourceHandler);
}
[TestMethod]
public void MustLetOperatingSystemHandleUnknownProtocols()
{
Assert.IsTrue(sut.OnProtocolExecution(default, default, default, default));
}
[TestMethod]
public void MustRedirectToDisablePdfToolbar()
{
var frame = new Mock<IFrame>();
var headers = new NameValueCollection { { "Content-Type", MediaTypeNames.Application.Pdf } };
var request = new Mock<IRequest>();
var response = new Mock<IResponse>();
var url = "http://www.host.org/some-document";
request.SetupGet(r => r.ResourceType).Returns(ResourceType.MainFrame);
request.SetupGet(r => r.Url).Returns(url);
response.SetupGet(r => r.Headers).Returns(headers);
settings.AllowPdfReader = true;
settings.AllowPdfReaderToolbar = false;
var result = sut.OnResourceResponse(Mock.Of<IWebBrowser>(), Mock.Of<IBrowser>(), frame.Object, request.Object, response.Object);
frame.Verify(b => b.LoadUrl(It.Is<string>(s => s.Equals($"{url}#toolbar=0"))), Times.Once);
Assert.IsTrue(result);
frame.Reset();
request.SetupGet(r => r.Url).Returns($"{url}#toolbar=0");
result = sut.OnResourceResponse(Mock.Of<IWebBrowser>(), Mock.Of<IBrowser>(), frame.Object, request.Object, response.Object);
frame.Verify(b => b.LoadUrl(It.IsAny<string>()), Times.Never);
Assert.IsFalse(result);
}
[TestMethod]
public void MustReplaceSebScheme()
{
var request = new Mock<IRequest>();
var url = default(string);
appConfig.SebUriScheme = "abc";
appConfig.SebUriSchemeSecure = "abcs";
request.SetupGet(r => r.Headers).Returns(new NameValueCollection());
request.SetupGet(r => r.Url).Returns($"{appConfig.SebUriScheme}://www.host.org");
request.SetupSet(r => r.Url = It.IsAny<string>()).Callback<string>(u => url = u);
var result = sut.OnBeforeResourceLoad(Mock.Of<IWebBrowser>(), Mock.Of<IBrowser>(), Mock.Of<IFrame>(), request.Object, Mock.Of<IRequestCallback>());
Assert.AreEqual(CefReturnValue.Continue, result);
Assert.AreEqual("http://www.host.org/", url);
request.SetupGet(r => r.Url).Returns($"{appConfig.SebUriSchemeSecure}://www.host.org");
request.SetupSet(r => r.Url = It.IsAny<string>()).Callback<string>(u => url = u);
result = sut.OnBeforeResourceLoad(Mock.Of<IWebBrowser>(), Mock.Of<IBrowser>(), Mock.Of<IFrame>(), request.Object, Mock.Of<IRequestCallback>());
Assert.AreEqual(CefReturnValue.Continue, result);
Assert.AreEqual("https://www.host.org/", url);
}
[TestMethod]
public void MustSearchGenericLmsSessionIdentifier()
{
var @event = new AutoResetEvent(false);
var headers = new NameValueCollection();
var newUrl = default(string);
var request = new Mock<IRequest>();
var response = new Mock<IResponse>();
var userId = default(string);
headers.Add("X-LMS-USER-ID", "some-session-id-123");
request.SetupGet(r => r.Url).Returns("https://www.somelms.org");
response.SetupGet(r => r.Headers).Returns(headers);
sut.UserIdentifierDetected += (id) =>
{
userId = id;
@event.Set();
};
sut.OnResourceRedirect(Mock.Of<IWebBrowser>(), Mock.Of<IBrowser>(), Mock.Of<IFrame>(), Mock.Of<IRequest>(), response.Object, ref newUrl);
@event.WaitOne();
Assert.AreEqual("some-session-id-123", userId);
headers.Clear();
headers.Add("X-LMS-USER-ID", "other-session-id-123");
userId = default;
sut.OnResourceResponse(Mock.Of<IWebBrowser>(), Mock.Of<IBrowser>(), Mock.Of<IFrame>(), request.Object, response.Object);
@event.WaitOne();
Assert.AreEqual("other-session-id-123", userId);
}
[TestMethod]
public void MustSearchEdxSessionIdentifier()
{
var @event = new AutoResetEvent(false);
var headers = new NameValueCollection();
var newUrl = default(string);
var request = new Mock<IRequest>();
var response = new Mock<IResponse>();
var userId = default(string);
headers.Add("Set-Cookie", "edx-user-info=\"{\\\"username\\\": \\\"edx-123\\\"}\"; expires");
request.SetupGet(r => r.Url).Returns("https://www.somelms.org");
response.SetupGet(r => r.Headers).Returns(headers);
sut.UserIdentifierDetected += (id) =>
{
userId = id;
@event.Set();
};
sut.OnResourceRedirect(Mock.Of<IWebBrowser>(), Mock.Of<IBrowser>(), Mock.Of<IFrame>(), Mock.Of<IRequest>(), response.Object, ref newUrl);
@event.WaitOne();
Assert.AreEqual("edx-123", userId);
headers.Clear();
headers.Add("Set-Cookie", "edx-user-info=\"{\\\"username\\\": \\\"edx-345\\\"}\"; expires");
userId = default;
sut.OnResourceResponse(Mock.Of<IWebBrowser>(), Mock.Of<IBrowser>(), Mock.Of<IFrame>(), request.Object, response.Object);
@event.WaitOne();
Assert.AreEqual("edx-345", userId);
}
[TestMethod]
public void MustSearchMoodleSessionIdentifier()
{
var @event = new AutoResetEvent(false);
var headers = new NameValueCollection();
var newUrl = default(string);
var request = new Mock<IRequest>();
var response = new Mock<IResponse>();
var userId = default(string);
headers.Add("Location", "https://www.some-moodle-instance.org/moodle/login/index.php?testsession=123");
request.SetupGet(r => r.Url).Returns("https://www.some-moodle-instance.org");
response.SetupGet(r => r.Headers).Returns(headers);
sut.UserIdentifierDetected += (id) =>
{
userId = id;
@event.Set();
};
sut.OnResourceRedirect(Mock.Of<IWebBrowser>(), Mock.Of<IBrowser>(), Mock.Of<IFrame>(), Mock.Of<IRequest>(), response.Object, ref newUrl);
@event.WaitOne();
Assert.AreEqual("123", userId);
headers.Clear();
headers.Add("Location", "https://www.some-moodle-instance.org/moodle/login/index.php?testsession=456");
userId = default;
sut.OnResourceResponse(Mock.Of<IWebBrowser>(), Mock.Of<IBrowser>(), Mock.Of<IFrame>(), request.Object, response.Object);
@event.WaitOne();
Assert.AreEqual("456", userId);
}
private class TestableResourceHandler : ResourceHandler
{
internal TestableResourceHandler(
AppConfig appConfig,
IRequestFilter filter,
IKeyGenerator keyGenerator,
ILogger logger,
SessionMode sessionMode,
BrowserSettings settings,
WindowSettings windowSettings,
IText text) : base(appConfig, filter, keyGenerator, logger, sessionMode, settings, windowSettings, text)
{
}
public new IResourceHandler GetResourceHandler(IWebBrowser webBrowser, IBrowser browser, IFrame frame, IRequest request)
{
return base.GetResourceHandler(webBrowser, browser, frame, request);
}
public new CefReturnValue OnBeforeResourceLoad(IWebBrowser webBrowser, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback)
{
return base.OnBeforeResourceLoad(webBrowser, browser, frame, request, callback);
}
public new bool OnProtocolExecution(IWebBrowser webBrowser, IBrowser browser, IFrame frame, IRequest request)
{
return base.OnProtocolExecution(webBrowser, browser, frame, request);
}
public new void OnResourceRedirect(IWebBrowser webBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response, ref string newUrl)
{
base.OnResourceRedirect(webBrowser, browser, frame, request, response, ref newUrl);
}
public new bool OnResourceResponse(IWebBrowser webBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response)
{
return base.OnResourceResponse(webBrowser, browser, frame, request, response);
}
}
}
}